From: nicm Date: Tue, 17 Oct 2023 09:52:08 +0000 (+0000) Subject: Update ncurses and associated libraries (form, panel, menu) to X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=c7ef0cfc17afcba97172c25e1e3a943e893bc632;p=openbsd Update ncurses and associated libraries (form, panel, menu) to 6.4-20230826 (from 5.7-20081102). Based on result from Thomas Dickey's ncu2openbsd script and then modified. Switches to the upstream tput. Major bump for the ncurses libraries and for libedit and libreadline. Help from tb, millert. ok deraadt sthen --- diff --git a/gnu/lib/libreadline/shlib_version b/gnu/lib/libreadline/shlib_version index d9961ea9fef..3066b9771e7 100644 --- a/gnu/lib/libreadline/shlib_version +++ b/gnu/lib/libreadline/shlib_version @@ -1,2 +1,2 @@ -major=4 +major=5 minor=0 diff --git a/lib/libcurses/Caps b/lib/libcurses/Caps index b24520ba66c..2bcc422accc 100644 --- a/lib/libcurses/Caps +++ b/lib/libcurses/Caps @@ -1,7 +1,8 @@ -# $OpenBSD: Caps,v 1.6 2010/01/12 23:21:58 nicm Exp $ +# $OpenBSD: Caps,v 1.7 2023/10/17 09:52:08 nicm Exp $ ############################################################################## -# Copyright (c) 1998-2002,2006 Free Software Foundation, Inc. # +# Copyright 2019-2020,2021 Thomas E. Dickey # +# Copyright 1998-2015,2016 Free Software Foundation, Inc. # # # # Permission is hereby granted, free of charge, to any person obtaining a # # copy of this software and associated documentation files (the "Software"), # @@ -31,12 +32,12 @@ # Author: Zeyd M. Ben-Halim 1992,1995 # and: Eric S. Raymond # -# $Id: Caps,v 1.6 2010/01/12 23:21:58 nicm Exp $ +# $Id: Caps,v 1.7 2023/10/17 09:52:08 nicm Exp $ # # This is the master termcap/terminfo capability table. # # This table is used to generate initializers for tables that drive tic, -# infocmp, and the library compilation code used to support the termcap +# infocmp, and the library compilation code used to support the termcap # compatibility hack. It is also used to generate the tabular portion of the # terminfo(5) man page; lines beginning with `#%' are passed through to become # the terminfo table. @@ -59,7 +60,7 @@ # # The codes following [Y-] in column 7 describe the versions of termcap which # use the given capability. This information is not used by the curses library -# proper; rather, it's there to help the terminfo maintainer avoid emitting +# proper; rather, it is there to help the terminfo maintainer avoid emitting # termcap entry translations that are more than 1023 bytes long (and tank a # lot of old termcap-using programs). The codes read as follows: # B = mentioned in the BSD man page for 4.4BSD curses @@ -99,8 +100,8 @@ # 3. List it in the standard table. You almost certainly do *not* want # to do this -- the capabilities in that one, and their order, have been # carefully chosen to be SVr4-binary-compatible when they're written out -# as a terminfo object, and breaking this would be bad. It's up the ncurses -# library what to do with the terminfo data after it's read in. +# as a terminfo object, and breaking this would be bad. It is up to the ncurses +# library what to do with the terminfo data after it is read in. # # 4. List it in the aliases table with an IGNORE target field. If you # do this, the capability will be ignored on input (though the user will @@ -109,7 +110,7 @@ # 5. List it in the extensions table. If you do this, the compiler will # silently accept the capability, but the curses library proper will never # see it (because it won't be written out as part of the terminfo object -# format). It's up to you what you have the compiler do with it. +# format). It is up to you what you have the compiler do with it. # # There are two opposite reasons to choose option 5. One is when you want # to eat the capability silently and discard it when doing translations @@ -121,14 +122,14 @@ # You'll need to write custom code, probably in postprocess_termcap() or # postprocess_terminfo(), to handle the translation. # -# CONTROLLING ENTRY LENGTH +# CONTROLLING ENTRY LENGTH # # Notes on specific elisions made to fit translations within 1023 bytes: # # Machines with IBM PC-like keyboards want to be able to define the following # keys: key_npage, key_ppage, key_home, key_ll (which is used for in termcap- # only environments for End or Home-Down), key_dc, and key_ic. This is also -# the set of keys the `joe' editor will be upset if it can't see. So don't +# the set of keys the `joe' editor will be upset if it can't see. So don't # trim those out of the set to be translated to termcap, or various users of # the termcap file will become irate. # @@ -149,7 +150,7 @@ # # It would be nice to keep f11 and f12 for Emacs use, but a couple of termcap # translations go back over critical if we do this. As 4.4BSD curses fades -# into history and GNU termcap's application base shrinks towards being GNU +# into history and GNU termcap's application base shrinks towards being GNU # Emacs only, we'll probably elide out some BSD-only capabilities in order # to buy space for non-essentials Emacs is still using. Capabilities high # on that hit list: rc, sc, uc. @@ -168,7 +169,7 @@ #%The \fBcapname\fR is the short name used in the text of the database, #%and is used by a person updating the database. #%Whenever possible, capnames are chosen to be the same as or similar to -#%the ANSI X3.64-1979 standard (now superseded by ECMA-48, which uses +#%the ANSI X3.64-1979 standard (now superseded by ECMA-48, which uses #%identical or very similar names). Semantics are also intended to match #%those of the specification. #% @@ -190,8 +191,12 @@ #%indicates that padding may be specified #%.TP #%#[1-9] -#%in the description field indicates that the string is passed through tparm with -#%parms as given (#\fIi\fP). +#%in the description field indicates that the string is passed +#%through \fBtparm\fP(3X) with parameters as given (#\fIi\fP). +#%.IP +#%If no parameters are listed in the description, +#%passing the string through \fBtparm\fP(3X) may give unexpected results, +#%e.g., if it contains percent (%%) signs. #%.TP #%(P*) #%indicates that padding may vary in proportion to the number of @@ -229,7 +234,7 @@ move_standout_mode msgr bool ms - - YBCGE safe to move while in standout mode over_strike os bool os - - YBCG- terminal can overstrike status_line_esc_ok eslok bool es - - YB-G- escape can be used on the status line dest_tabs_magic_smso xt bool xt - - YBCGE tabs destructive, magic so char (t1061) -tilde_glitch hz bool hz - - YB-GE cannot print ~'s (hazeltine) +tilde_glitch hz bool hz - - YB-GE cannot print ~'s (Hazeltine) transparent_underline ul bool ul - - YBCGE underline character overstrikes xon_xoff xon bool xo - - YB--- terminal uses xon/xoff handshaking needs_xon_xoff nxon bool nx - - ----- padding will not work, xon/xoff required @@ -273,7 +278,7 @@ num_labels nlab num Nl - - ----- number of labels on screen label_height lh num lh - - ----- rows in each label label_width lw num lw - - ----- columns in each label max_attributes ma num ma - - YBC-- maximum combined attributes terminal can handle -maximum_windows wnum num MW - - ----- maximum number of defineable windows +maximum_windows wnum num MW - - ----- maximum number of definable windows # These came in with SVr4's color support max_colors colors num Co - - ----- maximum number of colors on screen max_pairs pairs num pa - - ----- maximum number of color-pairs on the screen @@ -598,7 +603,7 @@ key_f62 kf62 str Fq KEY_F(62) - ----E F62 function key key_f63 kf63 str Fr KEY_F(63) - ----E F63 function key clr_bol el1 str cb - - ----- Clear to beginning of line clear_margins mgc str MC - - ----- clear right and left soft margins -set_left_margin smgl str ML - - ----- set left soft margin at current column. See smgl. (ML is not in BSD termcap). +set_left_margin smgl str ML - - ----- set left soft margin at current column. (ML is not in BSD termcap). set_right_margin smgr str MR - - ----- set right soft margin at current column label_format fln str Lf - - ----- label format set_clock sclk str SC - - ----- set clock, #1 hrs #2 mins #3 secs @@ -721,7 +726,7 @@ bit_image_repeat birep str Xy - - ----- Repeat bit image cell #1 #2 times bit_image_newline binel str Zz - - ----- Move to next row of the bit image bit_image_carriage_return bicr str Yv - - ----- Move to beginning of same row color_names colornm str Yw - - ----- Give name for color #1 -define_bit_image_region defbi str Yx - - ----- Define rectangualar bit image region +define_bit_image_region defbi str Yx - - ----- Define rectangular bit image region end_bit_image_region endbi str Yy - - ----- End a bit-image region set_color_band setcolor str Yz - - ----- Change to ribbon color #1 set_page_length slines str YZ - - ----- Set page length to #1 lines @@ -740,11 +745,13 @@ alt_scancode_esc scesa str S8 - - ----- Alternate escape for scancode emulatio #%.ad #% #%.in .8i -#%The XSI Curses standard added these. They are some post-4.1 -#%versions of System V curses, e.g., Solaris 2.5 and IRIX 6.x. -#%The \fBncurses\fR termcap names for them are invented; according to the -#%XSI Curses standard, they have no termcap names. If your compiled terminfo -#%entries use these, they may not be binary-compatible with System V terminfo +#%The XSI Curses standard added these hardcopy capabilities. +#%They were used in some post-4.1 versions of System V curses, +#%e.g., Solaris 2.5 and IRIX 6.x. +#%Except for \fBYI\fP, the \fBncurses\fR termcap names for them are invented. +#%According to the XSI Curses standard, they have no termcap names. +#%If your compiled terminfo entries use these, +#%they may not be binary-compatible with System V terminfo #%entries after SVr4.1; beware! #% #%.na @@ -762,7 +769,7 @@ enter_right_hl_mode erhlm str Xr - - ----- Enter right highlight mode enter_top_hl_mode ethlm str Xt - - ----- Enter top highlight mode enter_vertical_hl_mode evhlm str Xv - - ----- Enter vertical highlight mode set_a_attributes sgr1 str sA - - ----- Define second set of video attributes #1-#6 -set_pglen_inch slength str sL - - ----- YI Set page length to #1 hundredth of an inch +set_pglen_inch slength str YI - - ----- Set page length to #1 hundredth of an inch (some implementations use sL for termcap). #%.TE #%.ad # @@ -826,7 +833,7 @@ gnu_has_meta_key OTMT bool MT - - ----E has meta key # GNU termcap *does* include the following extended capability, Only the # now-obsolete Ann Arbor terminals used it. # -# gnu_change_scroll_region OTcS str cS - - ---GE alternate set scrolling region +# gnu_change_scroll_region OTcS str cS - - ---GE alternate set scrolling region # # The following comments describe capnames so ancient that I believe no # software uses them any longer. Some of these have to go because they @@ -843,9 +850,9 @@ gnu_has_meta_key OTMT bool MT - - ----E has meta key # comma-separated list of capabilities for which there are corresponding keys. # The `kn' code is accepted but ignored. # -# The `ma' capability seems to have been designed to map between the rogue(2) -# motion keys (including jkhl) and characters emitted by arrow keys on some -# primitive pre-ANSI terminals. It's so obsolete it's fossilized... +# The `ma' capability was a 4.0BSD feature used by vi version 2. +# It consists of pairs of characters corresponding to kl, kr, ku, kd, and kh. +# Besides being obsolete, that interpretation conflicts with max_attributes. # # Here is a description of memory_lock_above and memory_unlock: # "You can 'freeze' data on the screen by turning on Memory Lock in a line of @@ -871,14 +878,14 @@ horizontal_tab_delay OTdT num dT - - YB-G- padding required for ^I # vertical_tab_delay OTdV num dV - - -B--- padding required for ^V number_of_function_keys OTkn num kn - - -B-G- count of function keys other_non_function_keys OTko str ko - - -B-G- list of self-mapped keycaps -arrow_key_map OTma str ma - - YBC-- map arrow keys rogue(1) motion keys +arrow_key_map OTma str ma - - YBC-- map motion-keys for vi version 2 # memory_lock_above OTml str ml - - -B--- lock visible screen memory above the current line # memory_unlock OTmu str mu - - -B--- unlock visible screen memory above the current line has_hardware_tabs OTpt bool pt - - YB--- has 8-char tabs invoked with ^I return_does_clr_eol OTxr bool xr - - YB--- return clears the line # tek_4025_insert_line OTxx bool xx - - -BC-- Tektronix 4025 insert-line glitch # -# mytinfo described this as a termcap capability, but it's not listed in the +# mytinfo described this as a termcap capability, but it is not listed in the # 4.4BSD man pages, and not found in the 4.4BSD termcap file. The ncurses # package, like System V, behaves as though it is always true. # @@ -887,7 +894,7 @@ return_does_clr_eol OTxr bool xr - - YB--- return clears the line # University of Waterloo termcap extensions (as described in mytinfo). # The `xl' termcap file clashes with a terminfo name; this ambiguity cannot # be resolved by a type check. The descriptions are guesses from what was -# in the mytinfo tables. +# in the mytinfo tables. # # key_interrupt_char OTki str ki - - ----- string set by interrupt key (?) # key_kill_char OTkk str kk - - ----- string set by kill key (?) @@ -936,7 +943,7 @@ return_does_clr_eol OTxr bool xr - - YB--- return clears the line # Gv 186 \272 M-: double vertical line # # The compiler will translate the single-line caps and discard the others -# (via IGNORE aliases further down). We don't want to do normal pad +# (via IGNORE aliases further down). We don't want to do normal pad # translation on these, they're often single-character printable ASCII # strings that happen to be numerics. There's awk code in parametrized.sh # that detects the acs_ prefix and uses it to suppress pad translation. @@ -958,309 +965,9 @@ acs_plus OTGC str GC - - ----- single intersection # # TERMINFO EXTENSION CAPABILITIES # -# This section is almost all comments. What it's mainly for is to describe -# what capabilities need to be squeezed out to get down to the XSI Curses -# standard set. They are flagged with K. -# -# HP extensions -# -# These extensions follow ptr_non (replacing everything after it) in HP -# terminfo files. Except for memory_lock and memory_unlock, they are -# functionally identical to SVr4 extensions, but they make the binary format -# different. Grrr.... +# (see Caps-ncurses for the complete set of comments) # memory_lock meml str ml - - ----K lock memory above cursor memory_unlock memu str mu - - ----K unlock memory -#plab_norm pln str pn - - ----- program label #1 to show string #2 -#label_on smln str LO - - ----- turn on soft labels -#label_off rmln str LF - - ----- turn off soft labels -#key_f11 kf11 str F1 - - ----- F11 function key -#key_f12 kf12 str F2 - - ----- F12 function key -#key_f13 kf13 str F3 - - ----- F13 function key -#key_f14 kf14 str F4 - - ----- F14 function key -#key_f15 kf15 str F5 - - ----- F15 function key -#key_f16 kf16 str F6 - - ----- F16 function key -#key_f17 kf17 str F7 - - ----- F17 function key -#key_f18 kf18 str F8 - - ----- F18 function key -#key_f19 kf19 str F9 - - ----- F19 function key -#key_f20 kf20 str FA - - ----- F20 function key -#key_f21 kf21 str FB - - ----- F21 function key -#key_f22 kf22 str FC - - ----- F22 function key -#key_f23 kf23 str FD - - ----- F23 function key -#key_f24 kf24 str FE - - ----- F24 function key -#key_f25 kf25 str FF - - ----- F25 function key -#key_f26 kf26 str FG - - ----- F26 function key -#key_f27 kf27 str FH - - ----- F27 function key -#key_f28 kf28 str FI - - ----- F28 function key -#key_f29 kf29 str FJ - - ----- F29 function key -#key_f30 kf30 str FK - - ----- F30 function key -#key_f31 kf31 str FL - - ----- F31 function key -#key_f32 kf32 str FM - - ----- F32 function key -#key_f33 kf33 str FN - - ----- F33 function key -#key_f34 kf34 str FO - - ----- F34 function key -#key_f35 kf35 str FP - - ----- F35 function key -#key_f36 kf36 str FQ - - ----- F36 function key -#key_f37 kf37 str FR - - ----- F37 function key -#key_f38 kf38 str FS - - ----- F38 function key -#key_f39 kf39 str FT - - ----- F39 function key -#key_f40 kf40 str FU - - ----- F40 function key -#key_f41 kf41 str FV - - ----- F41 function key -#key_f42 kf42 str FW - - ----- F42 function key -#key_f43 kf43 str FX - - ----- F43 function key -#key_f44 kf44 str FY - - ----- F44 function key -#key_f45 kf45 str FZ - - ----- F45 function key -#key_f46 kf46 str Fa - - ----- F46 function key -#key_f47 kf47 str Fb - - ----- F47 function key -#key_f48 kf48 str Fc - - ----- F48 function key -#key_f49 kf49 str Fd - - ----- F49 function key -#key_f50 kf50 str Fe - - ----- F50 function key -#key_f51 kf51 str Ff - - ----- F51 function key -#key_f52 kf52 str Fg - - ----- F52 function key -#key_f53 kf53 str Fh - - ----- F53 function key -#key_f54 kf54 str Fi - - ----- F54 function key -#key_f55 kf55 str Fj - - ----- F55 function key -#key_f56 kf56 str Fk - - ----- F56 function key -#key_f57 kf57 str Fl - - ----- F57 function key -#key_f58 kf58 str Fm - - ----- F58 function key -#key_f59 kf59 str Fn - - ----- F59 function key -#key_f60 kf60 str Fo - - ----- F60 function key -#key_f61 kf61 str Fp - - ----- F61 function key -#key_f62 kf62 str Fq - - ----- F62 function key -#key_f63 kf63 str Fr - - ----- F63 function key -# -# IBM extensions -# -# These extensions follow ptr_non (replacing everything after it) in IBM -# terminfo files. -# -# The places in the box[12] capabilities correspond to acsc characters, here is -# the mapping: -# -# box1[0] = ACS_ULCORNER -# box1[1] = ACS_HLINE -# box1[2] = ACS_URCORNER -# box1[3] = ACS_VLINE -# box1[4] = ACS_LRCORNER -# box1[5] = ACS_LLCORNER -# box1[6] = ACS_TTEE -# box1[7] = ACS_RTEE -# box1[8] = ACS_BTEE -# box1[9] = ACS_LTEE -# box1[10] = ACS_PLUS -# -# The box2 characters are the double-line versions of these forms graphics. -# box_chars_1 box1 str bx - - ----K box characters primary set -#box_chars_2 box2 str by - - ----K box characters secondary set -#box_attr_1 batt1 str Bx - - ----K attributes for box1 -#box_attr_2 batt2 str By - - ----K attributes for box2 -#color_bg_0 colb0 str d0 - - ----K background color 0 -#color_bg_1 colb1 str d1 - - ----K background color 1 -#color_bg_2 colb2 str d2 - - ----K background color 2 -#color_bg_3 colb3 str d3 - - ----K background color 3 -#color_bg_4 colb4 str d4 - - ----K background color 4 -#color_bg_5 colb5 str d5 - - ----K background color 5 -#color_bg_6 colb6 str d6 - - ----K background color 6 -#color_bg_7 colb7 str d7 - - ----K background color 7 -#color_fg_0 colf0 str c0 - - ----K foreground color 0 -#color_fg_1 colf1 str c1 - - ----K foreground color 1 -#color_fg_2 colf2 str c2 - - ----K foreground color 2 -#color_fg_3 colf3 str c3 - - ----K foreground color 3 -#color_fg_4 colf4 str c4 - - ----K foreground color 4 -#color_fg_5 colf5 str c5 - - ----K foreground color 5 -#color_fg_6 colf6 str c6 - - ----K foreground color 6 -#color_fg_7 colf7 str c7 - - ----K foreground color 7 -#font_0 font0 str f0 - - ----- select font 0 -#font_1 font1 str f1 - - ----- select font 1 -#font_2 font2 str f2 - - ----- select font 2 -#font_3 font3 str f3 - - ----- select font 3 -#font_4 font4 str f4 - - ----K select font 4 -#font_5 font5 str f5 - - ----K select font 5 -#font_6 font6 str f6 - - ----K select font 6 -#font_7 font7 str f7 - - ----K select font 7 -#key_back_tab kbtab str k0 - - ----- backtab key -#key_do kdo str ki - - ----K do request key -#key_command kcmd str kd - - ----K command-request key -#key_command_pane kcpn str kW - - ----K command-pane key -#key_end kend str kw - - ----- end key -#key_help khlp str kq - - ----- help key -#key_newline knl str nl - - ----K newline key -#key_next_pane knpn str kv - - ----K next-pane key -#key_prev_cmd kppn str kp - - ----K previous-command key -#key_prev_pane kppn str kV - - ----K previous-pane key -#key_quit kquit str kQ - - ----K quit key -#key_select ksel str kU - - ----- select key -#key_scroll_left kscl str kz - - ----K scroll left -#key_scroll_right kscr str kZ - - ----K scroll right -#key_tab ktab str ko - - ----K tab key -#key_smap_in1 kmpf1 str Kv - - ----K special mapped key 1 input -#key_smap_out1 kmpt1 str KV - - ----K special mapped key 1 output -#key_smap_in2 kmpf2 str Kw - - ----K special mapped key 2 input -#key_smap_out2 kmpt2 str KW - - ----K special mapped key 2 output -#key_smap_in3 kmpf3 str Kx - - ----K special mapped key 3 input -#key_smap_out3 kmpt3 str KX - - ----K special mapped key 3 output -#key_smap_in4 kmpf4 str Ky - - ----K special mapped key 4 input -#key_smap_out4 kmpt4 str KY - - ----K special mapped key 4 output -#key_smap_in5 kmpf5 str Kz - - ----K special mapped key 5 input -#key_smap_out5 kmpt5 str KZ - - ----K special mapped key 5 output -#appl_defined_str apstr str za - - ----K application-defined string -# The key_smap_in[6789] and key_smap_out[6789] capabilities aren't described in -# the IBM manual pages, so the cap name strings are guesses. The terminfo -# names are almost certainly right, the termcap ones almost certainly wrong. -#key_smap_in6 kmpf6 str k! - - ----K special mapped key 6 input -#key_smap_out6 kmpt6 str K@ - - ----K special mapped key 6 output -#key_smap_in7 kmpf7 str k# - - ----K special mapped key 7 input -#key_smap_out7 kmpt7 str K$ - - ----K special mapped key 7 output -#key_smap_in8 kmpf8 str k% - - ----K special mapped key 8 input -#key_smap_out8 kmpt8 str K^ - - ----K special mapped key 8 output -#key_smap_in9 kmpf9 str k& - - ----K special mapped key 9 input -#key_smap_out9 kmpt9 str K* - - ----K special mapped key 9 output -# Undocumented capabilities end here -#key_sf1 ksf1 str S1 - - ----K special function key 1 -#key_sf2 ksf2 str S2 - - ----K special function key 2 -#key_sf3 ksf3 str S3 - - ----K special function key 3 -#key_sf4 ksf4 str S4 - - ----K special function key 4 -#key_sf5 ksf5 str S5 - - ----K special function key 5 -#key_sf6 ksf6 str S6 - - ----K special function key 6 -#key_sf7 ksf7 str S7 - - ----K special function key 7 -#key_sf8 ksf8 str S8 - - ----K special function key 8 -#key_sf9 ksf9 str S9 - - ----K special function key 9 -#key_sf10 ksf10 str SA - - ----K special function key 10 -# AIX version 3 documents different codes for F11, F12 and does not mention -# F13-F64. AIX version 4 uses the same naming for F0-F63 as above. -#key_f11 kf11 str k< - - ----- function key 11 -#key_f12 kf12 str k> - - ----- function key 12 -# Undocumented capabilities end here. -#key_action kact str kJ - - ----K sent by action key -# The IBM docs say these capabilities are for table-drawing, and are -# valid only for aixterm descriptions. -#enter_topline_mode topl str tp - - ----K start top-line mode -#enter_bottom_mode btml str bm - - ----K start bottom-line mode -#enter_rvert_mode rvert str rv - - ----K start right-vertical mode -#enter_lvert_mode lvert str lv - - ----K start left-vertical mode -# -############################################################################# -# -# ALIAS DECLARATIONS -# -# Here we set up aliases for translating extensions into standard terminfo. -# -#---------------------------------- Termcap aliases ------------------------- -# -# BSD aliases: -# -# This is a common error in many termcap files. We'll get notified during -# translation when this (or any other alias) fires. -# -capalias sb sr BSD scroll text down -# -# AT&T extensions: -# -# The old AT&T 5410, 5420, 5425, pc6300plus, 610, and s4 entries used a set of -# nonstandard capabilities. Its signature is the KM capability, used to name -# some sort of keymap file. EE, BO, CI, CV, XS, DS, FL and FE are in this -# set. Comments in the original, and a little cross-checking with other AT&T -# documentation, seem to establish the following mappings: -# -capalias BO mr AT&T enter_reverse_mode -capalias CI vi AT&T cursor_invisible -capalias CV ve AT&T cursor_normal -capalias DS mh AT&T enter_dim_mode -#capalias EE me AT&T exit_attribute_mode -capalias FE LF AT&T label_on -capalias FL LO AT&T label_off -capalias XS mk AT&T enter_secure_mode -# -# We comment out EE because the conflicting XENIX EE is more common in -# old entries. -# -# XENIX extensions: -# -# These are the ones we know how to translate directly: -# -capalias EE mh XENIX exit_attribute_mode -capalias GE ae XENIX exit_alt_charset_mode -capalias GS as XENIX enter_alt_charset_mode -capalias CF vi XENIX cursor_invis -capalias CO ve XENIX cursor_normal -capalias EN @7 XENIX key_end -capalias HM kh XENIX key_home -capalias LD kL XENIX key_dl -capalias PD kN XENIX key_npage -capalias PN po XENIX prtr_off -capalias PS pf XENIX prtr_on -capalias PU kP XENIX key_ppage -capalias RT @8 XENIX kent -capalias UP ku XENIX kcuu1 -capalias G6 IGNORE XENIX double-ACS_ULCORNER -capalias G7 IGNORE XENIX double-ACS_LLCORNER -capalias G5 IGNORE XENIX double-ACS_URCORNER -capalias G8 IGNORE XENIX double-ACS_LRCORNER -capalias Gr IGNORE XENIX double-ACS_LTEE -capalias Gr IGNORE XENIX double-ACS_RTEE -capalias Gu IGNORE XENIX double-ACS_BTEE -capalias Gd IGNORE XENIX double ACS_TTEE -capalias Gh IGNORE XENIX double-ACS_HLINE -capalias Gv IGNORE XENIX double-ACS_VLINE -capalias Gc IGNORE XENIX double-ACS_PLUS -capalias GG IGNORE XENIX acs-glitch -# -# IBM extensions: -# -capalias kq %1 IBM key_help -# -# Iris extensions: -# -capalias HS mh IRIS enter_dim_mode -# -# Tektronix extensions: -# -capalias KA k; Tek key_f10 -capalias KB F1 Tek key_f11 -capalias KC F2 Tek key_f12 -capalias KD F3 Tek key_f13 -capalias KE F4 Tek key_f14 -capalias KF F5 Tek key_f15 -capalias BC Sb Tek set_background -capalias FC Sf Tek set_foreground -# -# There are also the following: -# -# XENIX XENIX variable name name clash with terminfo? -# ----- ------------------- ------------------------- -# CL key_char_left -# CR key_char_right -# CW key_change_window -# HP ?? -# LF key_linefeed label_off -# NU key_next_unlocked_cell -# PL ?? -# PR ?? -# RC key_recalc remove_clock -# RF key_toggle_ref req_for_input -# WL key_word_left -# WR key_word_right -# -# If you know what any of the question-marked ones mean, please tell us. -# -#--------------------------------- Terminfo aliases ------------------------ -# -# IBM extensions: -# -infoalias font0 s0ds IBM set0_des_seq -infoalias font1 s1ds IBM set1_des_seq -infoalias font2 s2ds IBM set2_des_seq -infoalias font3 s3ds IBM set3_des_seq -infoalias kbtab kcbt IBM key_backtab -infoalias ksel kslt IBM key_select -# -# Some others are identical to SVr4/XPG4 capabilities, in particular: -# kcmd, kend, khlp, and kf11...kf63. -# ############################################################################# -# -# The following sets edit modes for GNU EMACS -# Local Variables: -# case-fold-search:nil -# truncate-lines:t -# End: diff --git a/lib/libcurses/Caps-ncurses b/lib/libcurses/Caps-ncurses new file mode 100644 index 00000000000..c198944648a --- /dev/null +++ b/lib/libcurses/Caps-ncurses @@ -0,0 +1,476 @@ +############################################################################## +# Copyright 2019-2022,2023 Thomas E. Dickey # +# # +# Permission is hereby granted, free of charge, to any person obtaining a # +# copy of this software and associated documentation files (the "Software"), # +# to deal in the Software without restriction, including without limitation # +# the rights to use, copy, modify, merge, publish, distribute, distribute # +# with modifications, sublicense, and/or sell copies of the Software, and to # +# permit persons to whom the Software is furnished to do so, subject to the # +# following conditions: # +# # +# The above copyright notice and this permission notice shall be included in # +# all copies or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # +# THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # +# DEALINGS IN THE SOFTWARE. # +# # +# Except as contained in this notice, the name(s) of the above copyright # +# holders shall not be used in advertising or otherwise to promote the sale, # +# use or other dealings in this Software without prior written # +# authorization. # +############################################################################## +# +# Author: Thomas E. Dickey +# +# $Id: Caps-ncurses,v 1.1 2023/10/17 09:52:08 nicm Exp $ +# +############################################################################# +# +# TERMINFO EXTENSION CAPABILITIES +# +# This section is all comments (selected lines are copied/uncommented into +# specific "Caps" files). The section describes what capabilities need to be +# squeezed out to get down to the XSI Curses standard set. They are flagged +# with K. +# +# HP extensions +# +# These extensions follow ptr_non (replacing everything after it) in HP +# terminfo files. Except for memory_lock and memory_unlock, they are +# functionally identical to SVr4 extensions, but they make the binary format +# different. Grrr.... +# +#memory_lock meml str ml - - ----K lock memory above cursor +#memory_unlock memu str mu - - ----K unlock memory +#plab_norm pln str pn - - ----- program label #1 to show string #2 +#label_on smln str LO - - ----- turn on soft labels +#label_off rmln str LF - - ----- turn off soft labels +#key_f11 kf11 str F1 - - ----- F11 function key +#key_f12 kf12 str F2 - - ----- F12 function key +#key_f13 kf13 str F3 - - ----- F13 function key +#key_f14 kf14 str F4 - - ----- F14 function key +#key_f15 kf15 str F5 - - ----- F15 function key +#key_f16 kf16 str F6 - - ----- F16 function key +#key_f17 kf17 str F7 - - ----- F17 function key +#key_f18 kf18 str F8 - - ----- F18 function key +#key_f19 kf19 str F9 - - ----- F19 function key +#key_f20 kf20 str FA - - ----- F20 function key +#key_f21 kf21 str FB - - ----- F21 function key +#key_f22 kf22 str FC - - ----- F22 function key +#key_f23 kf23 str FD - - ----- F23 function key +#key_f24 kf24 str FE - - ----- F24 function key +#key_f25 kf25 str FF - - ----- F25 function key +#key_f26 kf26 str FG - - ----- F26 function key +#key_f27 kf27 str FH - - ----- F27 function key +#key_f28 kf28 str FI - - ----- F28 function key +#key_f29 kf29 str FJ - - ----- F29 function key +#key_f30 kf30 str FK - - ----- F30 function key +#key_f31 kf31 str FL - - ----- F31 function key +#key_f32 kf32 str FM - - ----- F32 function key +#key_f33 kf33 str FN - - ----- F33 function key +#key_f34 kf34 str FO - - ----- F34 function key +#key_f35 kf35 str FP - - ----- F35 function key +#key_f36 kf36 str FQ - - ----- F36 function key +#key_f37 kf37 str FR - - ----- F37 function key +#key_f38 kf38 str FS - - ----- F38 function key +#key_f39 kf39 str FT - - ----- F39 function key +#key_f40 kf40 str FU - - ----- F40 function key +#key_f41 kf41 str FV - - ----- F41 function key +#key_f42 kf42 str FW - - ----- F42 function key +#key_f43 kf43 str FX - - ----- F43 function key +#key_f44 kf44 str FY - - ----- F44 function key +#key_f45 kf45 str FZ - - ----- F45 function key +#key_f46 kf46 str Fa - - ----- F46 function key +#key_f47 kf47 str Fb - - ----- F47 function key +#key_f48 kf48 str Fc - - ----- F48 function key +#key_f49 kf49 str Fd - - ----- F49 function key +#key_f50 kf50 str Fe - - ----- F50 function key +#key_f51 kf51 str Ff - - ----- F51 function key +#key_f52 kf52 str Fg - - ----- F52 function key +#key_f53 kf53 str Fh - - ----- F53 function key +#key_f54 kf54 str Fi - - ----- F54 function key +#key_f55 kf55 str Fj - - ----- F55 function key +#key_f56 kf56 str Fk - - ----- F56 function key +#key_f57 kf57 str Fl - - ----- F57 function key +#key_f58 kf58 str Fm - - ----- F58 function key +#key_f59 kf59 str Fn - - ----- F59 function key +#key_f60 kf60 str Fo - - ----- F60 function key +#key_f61 kf61 str Fp - - ----- F61 function key +#key_f62 kf62 str Fq - - ----- F62 function key +#key_f63 kf63 str Fr - - ----- F63 function key +# +# IBM extensions +# +# These extensions follow ptr_non (replacing everything after it) in IBM +# terminfo files. +# +# The places in the box[12] capabilities correspond to acsc characters, here is +# the mapping: +# +# box1[0] = ACS_ULCORNER +# box1[1] = ACS_HLINE +# box1[2] = ACS_URCORNER +# box1[3] = ACS_VLINE +# box1[4] = ACS_LRCORNER +# box1[5] = ACS_LLCORNER +# box1[6] = ACS_TTEE +# box1[7] = ACS_RTEE +# box1[8] = ACS_BTEE +# box1[9] = ACS_LTEE +# box1[10] = ACS_PLUS +# +# The box2 characters are the double-line versions of these forms graphics. +# +#box_chars_1 box1 str bx - - ----K box characters primary set +#box_chars_2 box2 str by - - ----K box characters secondary set +#box_attr_1 batt1 str Bx - - ----K attributes for box1 +#box_attr_2 batt2 str By - - ----K attributes for box2 +#color_bg_0 colb0 str d0 - - ----K background color 0 +#color_bg_1 colb1 str d1 - - ----K background color 1 +#color_bg_2 colb2 str d2 - - ----K background color 2 +#color_bg_3 colb3 str d3 - - ----K background color 3 +#color_bg_4 colb4 str d4 - - ----K background color 4 +#color_bg_5 colb5 str d5 - - ----K background color 5 +#color_bg_6 colb6 str d6 - - ----K background color 6 +#color_bg_7 colb7 str d7 - - ----K background color 7 +#color_fg_0 colf0 str c0 - - ----K foreground color 0 +#color_fg_1 colf1 str c1 - - ----K foreground color 1 +#color_fg_2 colf2 str c2 - - ----K foreground color 2 +#color_fg_3 colf3 str c3 - - ----K foreground color 3 +#color_fg_4 colf4 str c4 - - ----K foreground color 4 +#color_fg_5 colf5 str c5 - - ----K foreground color 5 +#color_fg_6 colf6 str c6 - - ----K foreground color 6 +#color_fg_7 colf7 str c7 - - ----K foreground color 7 +#font_0 font0 str f0 - - ----- select font 0 +#font_1 font1 str f1 - - ----- select font 1 +#font_2 font2 str f2 - - ----- select font 2 +#font_3 font3 str f3 - - ----- select font 3 +#font_4 font4 str f4 - - ----K select font 4 +#font_5 font5 str f5 - - ----K select font 5 +#font_6 font6 str f6 - - ----K select font 6 +#font_7 font7 str f7 - - ----K select font 7 +#key_back_tab kbtab str k0 - - ----- backtab key +#key_do kdo str ki - - ----K do request key +#key_command kcmd str kd - - ----K command-request key +#key_command_pane kcpn str kW - - ----K command-pane key +#key_end kend str kw - - ----- end key +#key_help khlp str kq - - ----- help key +#key_newline knl str nl - - ----K newline key +#key_next_pane knpn str kv - - ----K next-pane key +#key_prev_cmd kppn str kp - - ----K previous-command key +#key_prev_pane kppn str kV - - ----K previous-pane key +#key_quit kquit str kQ - - ----K quit key +#key_select ksel str kU - - ----- select key +#key_scroll_left kscl str kz - - ----K scroll left +#key_scroll_right kscr str kZ - - ----K scroll right +#key_tab ktab str ko - - ----K tab key +#key_smap_in1 kmpf1 str Kv - - ----K special mapped key 1 input +#key_smap_out1 kmpt1 str KV - - ----K special mapped key 1 output +#key_smap_in2 kmpf2 str Kw - - ----K special mapped key 2 input +#key_smap_out2 kmpt2 str KW - - ----K special mapped key 2 output +#key_smap_in3 kmpf3 str Kx - - ----K special mapped key 3 input +#key_smap_out3 kmpt3 str KX - - ----K special mapped key 3 output +#key_smap_in4 kmpf4 str Ky - - ----K special mapped key 4 input +#key_smap_out4 kmpt4 str KY - - ----K special mapped key 4 output +#key_smap_in5 kmpf5 str Kz - - ----K special mapped key 5 input +#key_smap_out5 kmpt5 str KZ - - ----K special mapped key 5 output +#appl_defined_str apstr str za - - ----K application-defined string +# The key_smap_in[6789] and key_smap_out[6789] capabilities aren't described in +# the IBM manual pages, so the cap name strings are guesses. The terminfo +# names are almost certainly right, the termcap ones almost certainly wrong. +#key_smap_in6 kmpf6 str k! - - ----K special mapped key 6 input +#key_smap_out6 kmpt6 str K@ - - ----K special mapped key 6 output +#key_smap_in7 kmpf7 str k# - - ----K special mapped key 7 input +#key_smap_out7 kmpt7 str K$ - - ----K special mapped key 7 output +#key_smap_in8 kmpf8 str k% - - ----K special mapped key 8 input +#key_smap_out8 kmpt8 str K^ - - ----K special mapped key 8 output +#key_smap_in9 kmpf9 str k& - - ----K special mapped key 9 input +#key_smap_out9 kmpt9 str K* - - ----K special mapped key 9 output +# Undocumented capabilities end here +#key_sf1 ksf1 str S1 - - ----K special function key 1 +#key_sf2 ksf2 str S2 - - ----K special function key 2 +#key_sf3 ksf3 str S3 - - ----K special function key 3 +#key_sf4 ksf4 str S4 - - ----K special function key 4 +#key_sf5 ksf5 str S5 - - ----K special function key 5 +#key_sf6 ksf6 str S6 - - ----K special function key 6 +#key_sf7 ksf7 str S7 - - ----K special function key 7 +#key_sf8 ksf8 str S8 - - ----K special function key 8 +#key_sf9 ksf9 str S9 - - ----K special function key 9 +#key_sf10 ksf10 str SA - - ----K special function key 10 +# AIX version 3 documents different codes for F11, F12 and does not mention +# F13-F64. AIX version 4 uses the same naming for F0-F63 as above. +#key_f11 kf11 str k< - - ----- function key 11 +#key_f12 kf12 str k> - - ----- function key 12 +# Undocumented capabilities end here. +#key_action kact str kJ - - ----K sent by action key +# The IBM docs say these capabilities are for table-drawing, and are +# valid only for aixterm descriptions. +#enter_topline_mode topl str tp - - ----K start top-line mode +#enter_bottom_mode btml str bm - - ----K start bottom-line mode +#enter_rvert_mode rvert str rv - - ----K start right-vertical mode +#enter_lvert_mode lvert str lv - - ----K start left-vertical mode +# +############################################################################# +# +# ALIAS DECLARATIONS +# +# Here we set up aliases for translating extensions into standard terminfo. +# +#---------------------------------- Termcap aliases ------------------------- +# +# BSD aliases: +# +# This is a common error in many termcap files. We'll get notified during +# translation when this (or any other alias) fires. +# +capalias sb sr BSD scroll text down +# +# AT&T extensions: +# +# The old AT&T 5410, 5420, 5425, pc6300plus, 610, and s4 entries used a set of +# nonstandard capabilities. Its signature is the KM capability, used to name +# some sort of keymap file. EE, BO, CI, CV, XS, DS, FL and FE are in this +# set. Comments in the original, and a little cross-checking with other AT&T +# documentation, seem to establish the following mappings: +# +capalias BO mr AT&T enter_reverse_mode +capalias CI vi AT&T cursor_invisible +capalias CV ve AT&T cursor_normal +capalias DS mh AT&T enter_dim_mode +#capalias EE me AT&T exit_attribute_mode +capalias FE LF AT&T label_on +capalias FL LO AT&T label_off +capalias XS mk AT&T enter_secure_mode +# +# We comment out EE because the conflicting XENIX EE is more common in +# old entries. +# +# XENIX extensions: +# +# These are the ones we know how to translate directly: +# +capalias EE mh XENIX exit_attribute_mode +capalias GE ae XENIX exit_alt_charset_mode +capalias GS as XENIX enter_alt_charset_mode +capalias CF vi XENIX cursor_invis +capalias CO ve XENIX cursor_normal +capalias EN @7 XENIX key_end +capalias HM kh XENIX key_home +capalias LD kL XENIX key_dl +capalias PD kN XENIX key_npage +capalias PN po XENIX prtr_off +capalias PS pf XENIX prtr_on +capalias PU kP XENIX key_ppage +capalias RT @8 XENIX kent +capalias UP ku XENIX kcuu1 +capalias G6 IGNORE XENIX double-ACS_ULCORNER +capalias G7 IGNORE XENIX double-ACS_LLCORNER +capalias G5 IGNORE XENIX double-ACS_URCORNER +capalias G8 IGNORE XENIX double-ACS_LRCORNER +capalias Gr IGNORE XENIX double-ACS_LTEE +capalias Gr IGNORE XENIX double-ACS_RTEE +capalias Gu IGNORE XENIX double-ACS_BTEE +capalias Gd IGNORE XENIX double ACS_TTEE +capalias Gh IGNORE XENIX double-ACS_HLINE +capalias Gv IGNORE XENIX double-ACS_VLINE +capalias Gc IGNORE XENIX double-ACS_PLUS +capalias GG IGNORE XENIX acs-glitch +# +# IBM extensions: +# +capalias kq %1 IBM key_help +# +# Iris extensions: +# +capalias HS mh IRIS enter_dim_mode +# +# Tektronix extensions: +# +capalias KA k; Tek key_f10 +capalias KB F1 Tek key_f11 +capalias KC F2 Tek key_f12 +capalias KD F3 Tek key_f13 +capalias KE F4 Tek key_f14 +capalias KF F5 Tek key_f15 +capalias BC Sb Tek set_background +capalias FC Sf Tek set_foreground +# +# There are also the following: +# +# XENIX XENIX variable name name clash with terminfo? +# ----- ------------------- ------------------------- +# CL key_char_left +# CR key_char_right +# CW key_change_window +# HP ?? +# LF key_linefeed label_off +# NU key_next_unlocked_cell +# PL ?? +# PR ?? +# RC key_recalc remove_clock +# RF key_toggle_ref req_for_input +# WL key_word_left +# WR key_word_right +# +# If you know what any of the question-marked ones mean, please tell us. +# +#--------------------------------- Terminfo aliases ------------------------ +# +# IBM extensions: +# +infoalias font0 s0ds IBM set0_des_seq +infoalias font1 s1ds IBM set1_des_seq +infoalias font2 s2ds IBM set2_des_seq +infoalias font3 s3ds IBM set3_des_seq +infoalias kbtab kcbt IBM key_backtab +infoalias ksel kslt IBM key_select +# +# Some others are identical to SVr4/XPG4 capabilities, in particular: +# kcmd, kend, khlp, and kf11...kf63. +# +############################################################################# +# This is a table of ncurses user-definable capabilities which applications +# developers may have used. ncurses may use the table to check consistency of +# types/parameters. Applications may have defined others (such as screen's +# LP and NF), but where a standard capability is available, those alternatives +# are not listed here. +# +used_by ncurses +userdef CO num n number of indexed colors overlaying RGB space +userdef E3 str - clears the terminal's scrollback buffer. +userdef NQ bool - terminal does not support query/response +userdef RGB bool - use direct colors with 1/3 of color-pair bits per color. +userdef RGB num n use direct colors with given number of bits per color. +userdef RGB str - use direct colors with given bit-layout. +userdef TS str - like "tsl", but uses no parameter. +userdef U8 num n terminal does/does not support VT100 SI/SO when processing UTF-8 encoding. +userdef XM str n initialize alternate xterm mouse mode +userdef grbom str - disable real bold (not intensity bright) mode. +userdef gsbom str - enable real bold (not intensity bright) mode. +userdef xm str - mouse response, no parameters +userdef xm str n mouse response, p1 = y-ordinate +userdef xm str nn mouse response, p2 = x-ordinate +userdef xm str nnn mouse response, p3 = button +userdef xm str nnns mouse response, p4 = state, e.g., pressed or released +userdef xm str nnnsn mouse response, p5 = y-ordinate starting region +userdef xm str nnnsnn mouse response, p6 = x-ordinate starting region +userdef xm str nnnsnnn mouse response, p7 = y-ordinate ending region +userdef xm str nnnsnnnn mouse response, p8 = x-ordinate ending region +# +used_by mintty +userdef Rmol str - remove overline-mode +userdef Smol str - set overline-mode +userdef blink2 str - turn on rapid blinking +userdef norm str - turn off bold and half-bright mode +userdef opaq str - turn off blank mode +userdef setal str n set underline-color +userdef smul2 str - begin double underline mode +# +used_by screen +userdef AN bool - turn on autonuke. +userdef AX bool - understands ANSI set default fg/bg color (\E[39m / \E[49m). +userdef C0 str - use the string as a conversion table for font '0', like acsc. +userdef C8 bool - terminal shows bold as high-intensity colors. +userdef CE str - switch cursor-keys back to normal mode. +userdef CS str - switch cursor-keys to application mode. +userdef E0 str - switch charset 'G0' back to standard charset. Default is '\E(B'. +userdef G0 bool - terminal can deal with ISO 2022 font selection sequences. +userdef KJ str s set the encoding of the terminal. +userdef OL num n set the screen program's output buffer limit. +userdef S0 str s switch charset 'G0' to the specified charset. Default is '\E(%.'. +userdef TF bool - add missing capabilities to screen's termcap/info entry. (Set by default). +userdef WS str nn resize display. This capability has the desired width and height as arguments. SunView(tm) example: '\E[8;%d;%dt'. +userdef XC str s describe a translation of characters to strings depending on the current font. +userdef XT bool - terminal understands special xterm sequences (OSC, mouse tracking). +userdef Z0 str - change width to 132 columns. +userdef Z1 str - change width to 80 columns. +# +used_by tmux +userdef Cr str - restore the default cursor color. +userdef Cs str s set the cursor color. +userdef Csr str n change the cursor style, overriding Ss. +userdef Ms str ss store the current buffer in the host terminal's selection (clipboard). +userdef Se str - reset the cursor style to the terminal initial state. +userdef Smulx str n modify the appearance of underlines in VTE. +userdef Ss str n change the cursor style. +userdef rmxx str - reset ECMA-48 strikeout/crossed-out attributes. +userdef smxx str - set ECMA-48 strikeout/crossed-out attributes. +# +used_by vim +userdef BD str - disables bracketed paste +userdef BE str - enables bracketed paste +userdef PE str - is sent after pasted text +userdef PS str - is sent before pasted text +userdef RV str - report terminal secondary device attributes +userdef XR str - report terminal version as a free-format string. +userdef XF bool - terminal supports xterm focus in/out +userdef rv str - response to RV, regular expression +userdef xr str - response to XR, regular expression +# +used_by xterm +userdef csl str - clear status line +userdef kDC3 str - alt delete-character +userdef kDC4 str - shift+alt delete-character +userdef kDC5 str - control delete-character +userdef kDC6 str - shift+control delete-character +userdef kDC7 str - alt+control delete-character +userdef kDN str - shift down-cursor +userdef kDN3 str - alt down-cursor +userdef kDN4 str - shift+alt down-cursor +userdef kDN5 str - control down-cursor +userdef kDN6 str - shift+control down-cursor +userdef kDN7 str - alt+control down-cursor +userdef kEND3 str - alt end +userdef kEND4 str - shift+alt end +userdef kEND5 str - control end +userdef kEND6 str - shift+control end +userdef kEND7 str - alt+control end +userdef kHOM3 str - alt home +userdef kHOM4 str - shift+alt home +userdef kHOM5 str - control home +userdef kHOM6 str - shift+control home +userdef kHOM7 str - alt+control home +userdef kIC3 str - alt insert-character +userdef kIC4 str - shift+alt insert-character +userdef kIC5 str - control insert-character +userdef kIC6 str - shift+control insert-character +userdef kIC7 str - alt+control insert-character +userdef kLFT3 str - alt left-cursor +userdef kLFT4 str - shift+alt left-cursor +userdef kLFT5 str - control left-cursor +userdef kLFT6 str - shift+control left-cursor +userdef kLFT7 str - alt+control left-cursor +userdef kNXT3 str - alt next +userdef kNXT4 str - shift+alt next +userdef kNXT5 str - control next +userdef kNXT6 str - shift+control next +userdef kNXT7 str - alt+control next +userdef kPRV3 str - alt previous +userdef kPRV4 str - shift+alt previous +userdef kPRV5 str - control previous +userdef kPRV6 str - shift+control previous +userdef kPRV7 str - alt+control previous +userdef kRIT3 str - alt right-cursor +userdef kRIT4 str - shift+alt right-cursor +userdef kRIT5 str - control right-cursor +userdef kRIT6 str - shift+control right-cursor +userdef kRIT7 str - alt+control right-cursor +userdef kUP str - shift up-cursor +userdef kUP3 str - alt up-cursor +userdef kUP4 str - shift+alt up-cursor +userdef kUP5 str - control up-cursor +userdef kUP6 str - shift+control up-cursor +userdef kUP7 str - alt+control up-cursor +userdef ka2 str - vt220-keypad extensions +userdef kb1 str - vt220-keypad extensions +userdef kb3 str - vt220-keypad extensions +userdef kc2 str - vt220-keypad extensions +userdef kxIN str - mouse response on focus-in +userdef kxOUT str - mouse response on focus-out +############################################################################# diff --git a/lib/libcurses/MKterminfo.sh b/lib/libcurses/MKterminfo.sh new file mode 100644 index 00000000000..6322b779d92 --- /dev/null +++ b/lib/libcurses/MKterminfo.sh @@ -0,0 +1,121 @@ +#!/bin/sh +# $Id: MKterminfo.sh,v 1.1 2023/10/17 09:52:08 nicm Exp $ +# +# MKterminfo.sh -- generate terminfo.5 from Caps tabular data +# +#*************************************************************************** +# Copyright 2018-2020,2022 Thomas E. Dickey * +# Copyright 1998-2003,2017 Free Software Foundation, Inc. * +# * +# Permission is hereby granted, free of charge, to any person obtaining a * +# copy of this software and associated documentation files (the * +# "Software"), to deal in the Software without restriction, including * +# without limitation the rights to use, copy, modify, merge, publish, * +# distribute, distribute with modifications, sublicense, and/or sell * +# copies of the Software, and to permit persons to whom the Software is * +# furnished to do so, subject to the following conditions: * +# * +# The above copyright notice and this permission notice shall be included * +# in all copies or substantial portions of the Software. * +# * +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * +# IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * +# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * +# THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +# * +# Except as contained in this notice, the name(s) of the above copyright * +# holders shall not be used in advertising or otherwise to promote the * +# sale, use or other dealings in this Software without prior written * +# authorization. * +#*************************************************************************** +# +# This script takes terminfo.head and terminfo.tail and splices in between +# them a table derived from the Caps data file. Besides avoiding having +# the docs fall out of sync with the table, this also lets us set up tbl +# commands for better formatting of the table. +# +# NOTE: The s in this script really are control characters. It translates +#  to \n because I couldn't get used to inserting linefeeds directly. There +# had better be no s in the table source text. +# +# keep the order independent of locale: +if test "${LANGUAGE+set}" = set; then LANGUAGE=C; export LANGUAGE; fi +if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi +if test "${LC_COLLATE+set}" = set; then LC_COLLATE=C; export LC_COLLATE; fi + +# +head="$1" +shift 1 +caps= +while test $# -gt 1 +do + caps="$caps $1" + shift 1 +done +tail="$1" +cat <$unsorted + +rm -f $sorted +rm -f $temp +saved=no +while true +do + data= + read data + test -z "$data" && break + case "$data" in #(vi + **) #(vi + echo "$data" >>$temp + saved=yes + ;; + *) + if test $saved = yes ; then + saved=no + sort $temp >>$sorted + rm -f $temp + fi + echo "$data" >>$sorted + ;; + esac +done <$unsorted +test $saved = yes && sort $temp >>$sorted + +sed -e 's/^\.\.$//' $sorted | tr "\005\006" "\012\134" + +sed -e '/^center expand;/s, expand,,' \ + -e '/^\.TS/,/^\\/s, lw[1-9][0-9]*\., l.,' \ + "$tail" diff --git a/lib/libcurses/Makefile b/lib/libcurses/Makefile index a621f369cd4..027a876ea4d 100644 --- a/lib/libcurses/Makefile +++ b/lib/libcurses/Makefile @@ -1,7 +1,6 @@ -# $OpenBSD: Makefile,v 1.74 2019/02/13 15:10:40 nicm Exp $ +# $OpenBSD: Makefile,v 1.75 2023/10/17 09:52:08 nicm Exp $ -# Uncomment this to enable tracing in libcurses -#CURSESTRACE=-DTRACE +LIB= curses # This is used to compile terminal info directly into the library FALLBACK_LIST= @@ -12,89 +11,72 @@ AWK?= /usr/bin/awk # Search in subdirs .PATH: ${.CURDIR}/base ${.CURDIR}/tinfo ${.CURDIR}/trace ${.CURDIR}/tty \ ${.CURDIR}/widechar - -LIB= curses -SRCS= codes.c comp_captab.c expanded.c fallback.c lib_gen.c lib_keyname.c \ - names.c unctrl.c -# base -SRCS+= define_key.c key_defined.c keybound.c keyok.c legacy_coding.c \ - lib_addch.c lib_addstr.c lib_beep.c lib_bkgd.c lib_box.c lib_chgat.c \ - lib_clear.c lib_clearok.c lib_clrbot.c lib_clreol.c lib_color.c \ - lib_colorset.c lib_delch.c lib_delwin.c lib_dft_fgbg.c lib_echo.c \ - lib_endwin.c lib_erase.c lib_flash.c lib_freeall.c lib_getch.c \ - lib_getstr.c lib_hline.c lib_immedok.c lib_inchstr.c lib_initscr.c \ - lib_insnstr.c lib_insch.c lib_insdel.c lib_instr.c \ - lib_isendwin.c lib_leaveok.c lib_mouse.c lib_move.c lib_mvwin.c \ - lib_newterm.c lib_newwin.c lib_nl.c lib_overlay.c lib_pad.c \ - lib_printw.c lib_redrawln.c lib_refresh.c lib_restart.c \ - lib_scanw.c lib_screen.c lib_scroll.c lib_scrollok.c \ - lib_scrreg.c lib_set_term.c lib_slk.c lib_slkatr_set.c \ - lib_slkatrof.c lib_slkatron.c lib_slkatrset.c lib_slkattr.c \ - lib_slkclear.c lib_slkcolor.c lib_slkinit.c lib_slklab.c \ - lib_slkrefr.c lib_slkset.c lib_slktouch.c lib_touch.c \ - lib_ungetch.c lib_vline.c lib_wattroff.c lib_wattron.c \ - lib_winch.c lib_window.c nc_panel.c resizeterm.c safe_sprintf.c \ - tries.c use_window.c version.c vsscanf.c wresize.c -# tinfo +SRCS= codes.c comp_captab.c comp_userdefs.c expanded.c fallback.c \ + lib_gen.c lib_keyname.c names.c unctrl.c SRCS+= access.c add_tries.c alloc_entry.c alloc_ttype.c captoinfo.c \ - comp_error.c comp_expand.c comp_hash.c comp_parse.c comp_scan.c \ - db_iterator.c doalloc.c entries.c free_ttype.c getenv_num.c \ - hashed_db.c home_terminfo.c init_keytry.c lib_acs.c lib_baudrate.c \ - lib_cur_term.c lib_data.c lib_has_cap.c lib_kernel.c lib_longname.c \ - lib_napms.c lib_options.c lib_print.c lib_raw.c lib_setup.c \ - lib_termcap.c lib_termname.c lib_tgoto.c lib_ti.c lib_tparm.c \ - lib_tputs.c lib_ttyflags.c name_match.c parse_entry.c \ - read_entry.c read_termcap.c setbuf.c strings.c \ - trim_sgr0.c use_screen.c write_entry.c -# trace -SRCS+= lib_trace.c lib_traceatr.c lib_tracebits.c lib_tracechr.c \ - lib_tracedmp.c lib_tracemse.c trace_buf.c trace_tries.c trace_xnames.c \ - varargs.c visbuf.c -# tty -SRCS+= hardscroll.c hashmap.c lib_mvcur.c lib_tstp.c lib_twait.c \ - lib_vidattr.c tty_update.c -# widechar -SRCS+= charable.c lib_add_wch.c lib_box_set.c lib_cchar.c lib_erasewchar.c \ - lib_get_wch.c lib_get_wstr.c lib_hline_set.c lib_in_wch.c \ - lib_in_wchnstr.c lib_ins_wch.c lib_inwstr.c lib_key_name.c \ - lib_pecho_wchar.c lib_slk_wset.c lib_unget_wch.c lib_vid_attr.c \ - lib_vline_set.c lib_wacs.c lib_wunctrl.c + charable.c comp_error.c comp_expand.c comp_hash.c comp_parse.c \ + comp_scan.c db_iterator.c define_key.c doalloc.c entries.c \ + free_ttype.c getenv_num.c hardscroll.c hashed_db.c hashmap.c \ + home_terminfo.c init_keytry.c key_defined.c keybound.c keyok.c \ + legacy_coding.c lib_acs.c lib_add_wch.c lib_addch.c lib_addstr.c \ + lib_baudrate.c lib_beep.c lib_bkgd.c lib_box.c lib_box_set.c \ + lib_cchar.c lib_chgat.c lib_clear.c lib_clearok.c lib_clrbot.c \ + lib_clreol.c lib_color.c lib_colorset.c lib_cur_term.c lib_data.c \ + lib_delch.c lib_delwin.c lib_dft_fgbg.c lib_echo.c lib_endwin.c \ + lib_erase.c lib_erasewchar.c lib_flash.c lib_freeall.c lib_get_wch.c \ + lib_get_wstr.c lib_getch.c lib_getstr.c lib_has_cap.c lib_hline.c \ + lib_hline_set.c lib_immedok.c lib_in_wch.c lib_in_wchnstr.c \ + lib_inchstr.c lib_initscr.c lib_ins_wch.c lib_insch.c lib_insdel.c \ + lib_insnstr.c lib_instr.c lib_inwstr.c lib_isendwin.c lib_kernel.c \ + lib_key_name.c lib_leaveok.c lib_longname.c lib_mouse.c lib_move.c \ + lib_mvcur.c lib_mvwin.c lib_napms.c lib_newterm.c lib_newwin.c \ + lib_nl.c lib_options.c lib_overlay.c lib_pad.c lib_pecho_wchar.c \ + lib_print.c lib_printw.c lib_raw.c lib_redrawln.c lib_refresh.c \ + lib_restart.c lib_scanw.c lib_screen.c lib_scroll.c lib_scrollok.c \ + lib_scrreg.c lib_set_term.c lib_setup.c lib_slk.c lib_slk_wset.c \ + lib_slkatr_set.c lib_slkatrof.c lib_slkatron.c lib_slkatrset.c \ + lib_slkattr.c lib_slkclear.c lib_slkcolor.c lib_slkinit.c \ + lib_slklab.c lib_slkrefr.c lib_slkset.c lib_slktouch.c lib_termcap.c \ + lib_termname.c lib_tgoto.c lib_ti.c lib_touch.c lib_tparm.c \ + lib_tputs.c lib_trace.c lib_tstp.c lib_ttyflags.c lib_twait.c \ + lib_unget_wch.c lib_ungetch.c lib_vid_attr.c lib_vidattr.c \ + lib_vline.c lib_vline_set.c lib_wacs.c lib_wattroff.c lib_wattron.c \ + lib_winch.c lib_window.c lib_wunctrl.c name_match.c nc_panel.c \ + new_pair.c obsolete.c parse_entry.c read_entry.c read_termcap.c \ + resizeterm.c safe_sprintf.c strings.c tries.c trim_sgr0.c \ + tty_update.c use_screen.c use_window.c version.c visbuf.c vsscanf.c \ + wresize.c write_entry.c HOSTCFLAGS?= ${CFLAGS} HOSTLDFLAGS?= ${LDFLAGS} -HOSTCFLAGS+= -I. -I${.CURDIR} ${CURSESTRACE} -CFLAGS+= -I. -I${.CURDIR} ${CURSESTRACE} - -MAN= curs_addch.3 curs_addchstr.3 curs_addstr.3 curs_attr.3 \ - curs_beep.3 curs_bkgd.3 curs_bkgrnd.3 curs_border.3 curs_border_set.3 \ - curs_clear.3 curs_color.3 \ - curs_delch.3 curs_deleteln.3 \ - curs_extend.3 \ - curs_getch.3 curs_getstr.3 curs_getyx.3 \ +HOSTCFLAGS+= -I. -I${.CURDIR} +CFLAGS+= -I. -I${.CURDIR} -D_XOPEN_SOURCE_EXTENDED -DNDEBUG + +MAN= curs_add_wch.3 curs_add_wchstr.3 curs_addch.3 curs_addchstr.3 \ + curs_addstr.3 curs_addwstr.3 curs_attr.3 curs_beep.3 curs_bkgd.3 \ + curs_bkgrnd.3 curs_border.3 curs_border_set.3 curs_clear.3 \ + curs_color.3 curs_delch.3 curs_deleteln.3 curs_extend.3 \ + curs_get_wch.3 curs_get_wstr.3 curs_getcchar.3 curs_getch.3 \ + curs_getstr.3 curs_getyx.3 curs_in_wch.3 curs_in_wchstr.3 \ curs_inch.3 curs_inchstr.3 curs_initscr.3 curs_inopts.3 \ - curs_insch.3 curs_insstr.3 curs_instr.3 \ - curs_kernel.3 \ - curs_legacy.3 \ - curs_mouse.3 curs_move.3 \ - curs_opaque.3 curs_outopts.3 curs_overlay.3 \ - curs_pad.3 curs_print.3 curs_printw.3 \ - curs_refresh.3 \ - curs_scanw.3 curs_scr_dump.3 curs_scroll.3 curs_slk.3 \ - curs_termattrs.3 curs_touch.3 \ - curs_util.3 \ - curs_window.3 \ - curs_add_wch.3 curs_add_wchstr.3 curs_addwstr.3 curs_get_wch.3 \ - curs_get_wstr.3 curs_in_wch.3 curs_in_wchstr.3 curs_ins_wch.3 \ - curs_ins_wstr.3 curs_inwstr.3 \ - default_colors.3 define_key.3 \ - key_defined.3 keybound.3 keyok.3 legacy_coding.3 \ - curses.3 \ - resizeterm.3 \ - term.5 term.7 termcap.3 terminfo.3 terminfo.5 \ + curs_ins_wch.3 curs_ins_wstr.3 curs_insch.3 curs_insstr.3 \ + curs_instr.3 curs_inwstr.3 curs_kernel.3 curs_legacy.3 \ + curs_memleaks.3 curs_mouse.3 curs_move.3 curs_opaque.3 \ + curs_outopts.3 curs_overlay.3 curs_pad.3 curs_print.3 curs_printw.3 \ + curs_refresh.3 curs_scanw.3 curs_scr_dump.3 curs_scroll.3 curs_slk.3 \ + curs_sp_funcs.3 curs_termattrs.3 curs_threads.3 curs_touch.3 \ + curs_util.3 curs_variables.3 curs_window.3 curses.3 \ + default_colors.3 define_key.3 key_defined.3 keybound.3 keyok.3 \ + legacy_coding.3 new_pair.3 resizeterm.3 scr_dump.5 term.5 term.7 \ + term_variables.3 termcap.3 terminfo.3 terminfo.5 user_caps.5 \ wresize.3 +GENERATED= codes.c comp_captab.c comp_userdefs.c expanded.c fallback.c \ + init_keytry.h keys.list lib_gen.c lib_keyname.c make_hash make_keys \ + names.c + +CAPLIST = ${.CURDIR}/Caps +USE_BIG_STRINGS = 1 -GENERATED= init_keytry.h codes.c comp_captab.c expanded.c fallback.c \ - keys.list lib_gen.c lib_keyname.c names.c unctrl.c make_hash make_keys CLEANFILES+= ${GENERATED} BUILDFIRST = ${GENERATED} @@ -103,7 +85,7 @@ includes: @cmp -s ${DESTDIR}/usr/include/ncurses.h ${.CURDIR}/curses.h || \ ${INSTALL} ${INSTALL_COPY} -m 444 -o $(BINOWN) -g $(BINGRP) \ ${.CURDIR}/curses.h ${DESTDIR}/usr/include/ncurses.h - @cd ${.CURDIR}; for i in unctrl.h term.h termcap.h; do \ + @cd ${.CURDIR}; for i in ncurses_dll.h unctrl.h term.h termcap.h; do \ cmp -s $$i ${DESTDIR}/usr/include/$$i || \ ${INSTALL} ${INSTALL_COPY} -m 444 -o $(BINOWN) -g $(BINGRP) $$i \ ${DESTDIR}/usr/include; done @@ -112,7 +94,7 @@ keys.list: ${.CURDIR}/tinfo/MKkeys_list.sh sh ${.CURDIR}/tinfo/MKkeys_list.sh ${.CURDIR}/Caps | sort > ${.TARGET} fallback.c: ${.CURDIR}/tinfo/MKfallback.sh - sh ${.CURDIR}/tinfo/MKfallback.sh $(FALLBACK_LIST) > ${.TARGET} + sh ${.CURDIR}/tinfo/MKfallback.sh /usr/share/terminfo ${.CURDIR}/../../share/termtypes/termtypes.master $(FALLBACK_LIST) > ${.TARGET} lib_gen.c: ${.CURDIR}/base/MKlib_gen.sh sh ${.CURDIR}/base/MKlib_gen.sh "${CC} -E -P -I${.CURDIR}" \ @@ -124,30 +106,39 @@ init_keytry.h: make_keys keys.list make_keys: ${.CURDIR}/tinfo/make_keys.c ${.CURDIR}/curses.priv.h names.c ${HOSTCC} ${LDSTATIC} ${HOSTCFLAGS} ${HOSTLDFLAGS} \ -o ${.TARGET} ${.CURDIR}/tinfo/make_keys.c ${LDADD} - -make_hash: ${.CURDIR}/tinfo/comp_hash.c ${.CURDIR}/curses.priv.h \ +make_hash: ${.CURDIR}/tinfo/make_hash.c \ + ${.CURDIR}/curses.priv.h \ ${.CURDIR}/hashsize.h ${HOSTCC} ${LDSTATIC} ${HOSTCFLAGS} -DMAIN_PROGRAM ${HOSTLDFLAGS} \ - -o ${.TARGET} ${.CURDIR}/tinfo/comp_hash.c ${LDADD} + -o ${.TARGET} ${.CURDIR}/tinfo/make_hash.c ${LDADD} +CAPLIST += ${.CURDIR}/Caps-ncurses + +comp_userdefs.c: make_hash \ + ${.CURDIR}/hashsize.h \ + ${.CURDIR}/tinfo/MKuserdefs.sh + sh ${.CURDIR}/tinfo/MKuserdefs.sh ${AWK} ${USE_BIG_STRINGS} ${CAPLIST} > ${.TARGET} expanded.c: ${.CURDIR}/term.h ${.CURDIR}/curses.priv.h \ ${.CURDIR}/ncurses_cfg.h ${.CURDIR}/tty/MKexpanded.sh sh ${.CURDIR}/tty/MKexpanded.sh "${CC} -E -P" ${CPPFLAGS} > ${.TARGET} comp_captab.c: make_hash - sh ${.CURDIR}/tinfo/MKcaptab.sh ${AWK} 1 \ - ${.CURDIR}/tinfo/MKcaptab.awk ${.CURDIR}/Caps > ${.TARGET} + sh ${.CURDIR}/tinfo/MKcaptab.sh ${AWK} ${USE_BIG_STRINGS} \ + ${.CURDIR}/tinfo/MKcaptab.awk ${CAPLIST} > ${.TARGET} lib_keyname.c: keys.list ${.CURDIR}/base/MKkeyname.awk - ${AWK} -f ${.CURDIR}/base/MKkeyname.awk bigstrings=1 \ + ${AWK} -f ${.CURDIR}/base/MKkeyname.awk \ + bigstrings=${USE_BIG_STRINGS} \ keys.list > ${.TARGET} names.c: ${.CURDIR}/tinfo/MKnames.awk ${AWK} -f ${.CURDIR}/tinfo/MKnames.awk \ - ${.CURDIR}/Caps > names.c + bigstrings=${USE_BIG_STRINGS} \ + ${CAPLIST} > ${.TARGET} codes.c: ${.CURDIR}/tinfo/MKcodes.awk ${AWK} -f ${.CURDIR}/tinfo/MKcodes.awk \ - bigstrings=1 ${.CURDIR}/Caps > codes.c + bigstrings=${USE_BIG_STRINGS} \ + ${CAPLIST} > ${.TARGET} unctrl.c: ${.CURDIR}/base/MKunctrl.awk echo | ${AWK} -f ${.CURDIR}/base/MKunctrl.awk bigstrings=1 > ${.TARGET} diff --git a/lib/libcurses/SigAction.h b/lib/libcurses/SigAction.h index 3a2783284d1..376a1460aa3 100644 --- a/lib/libcurses/SigAction.h +++ b/lib/libcurses/SigAction.h @@ -1,7 +1,8 @@ -/* $OpenBSD: SigAction.h,v 1.4 2010/01/12 23:21:58 nicm Exp $ */ +/* $OpenBSD: SigAction.h,v 1.5 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2003,2005 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -34,7 +35,7 @@ ****************************************************************************/ /* - * $Id: SigAction.h,v 1.4 2010/01/12 23:21:58 nicm Exp $ + * $Id: SigAction.h,v 1.5 2023/10/17 09:52:08 nicm Exp $ * * This file exists to handle non-POSIX systems which don't have , * and usually no sigaction() nor diff --git a/lib/libcurses/base/MKkeyname.awk b/lib/libcurses/base/MKkeyname.awk index 9f98264a0ca..026b1ce1b34 100644 --- a/lib/libcurses/base/MKkeyname.awk +++ b/lib/libcurses/base/MKkeyname.awk @@ -1,7 +1,8 @@ -# $OpenBSD: MKkeyname.awk,v 1.5 2010/01/12 23:22:05 nicm Exp $ -# $Id: MKkeyname.awk,v 1.5 2010/01/12 23:22:05 nicm Exp $ +# $OpenBSD: MKkeyname.awk,v 1.6 2023/10/17 09:52:08 nicm Exp $ +# $Id: MKkeyname.awk,v 1.6 2023/10/17 09:52:08 nicm Exp $ ############################################################################## -# Copyright (c) 1999-2007,2008 Free Software Foundation, Inc. # +# Copyright 2020 Thomas E. Dickey # +# Copyright 1998-2016,2017 Free Software Foundation, Inc. # # # # Permission is hereby granted, free of charge, to any person obtaining a # # copy of this software and associated documentation files (the "Software"), # @@ -32,7 +33,6 @@ BEGIN { print "" print "#include " print "#include " - print "#include " print "" first = 1; } @@ -67,18 +67,18 @@ END { print "" print "#define SIZEOF_TABLE 256" print "#define MyTable _nc_globals.keyname_table" + print "#define MyInit _nc_globals.init_keyname" print "" - print "NCURSES_EXPORT(NCURSES_CONST char *) _nc_keyname (SCREEN *sp, int c)" + print "NCURSES_EXPORT(NCURSES_CONST char *)" + print "safe_keyname (SCREEN *sp, int c)" print "{" - print " int i;" print " char name[20];" - print " char *p;" - print " size_t psize;" print " NCURSES_CONST char *result = 0;" print "" print " if (c == -1) {" print " result = \"-1\";" print " } else {" + print " int i;" if (bigstrings) { print " for (i = 0; _nc_key_names[i].offset != -1; i++) {" print " if (_nc_key_names[i].code == c) {" @@ -98,36 +98,49 @@ END { print " if (result == 0 && (c >= 0 && c < SIZEOF_TABLE)) {" print " if (MyTable == 0)" print " MyTable = typeCalloc(char *, SIZEOF_TABLE);" + print "" print " if (MyTable != 0) {" + print " int m_prefix = (sp == 0 || sp->_use_meta);" + print "" + print " /* if sense of meta() changed, discard cached data */" + print " if (MyInit != (m_prefix + 1)) {" + print " MyInit = m_prefix + 1;" + print " for (i = 0; i < SIZEOF_TABLE; ++i) {" + print " if (MyTable[i]) {" + print " FreeAndNull(MyTable[i]);" + print " }" + print " }" + print " }" + print "" + print " /* create and cache result as needed */" print " if (MyTable[c] == 0) {" print " int cc = c;" - print " p = name;" - print " psize = sizeof(name);" - print " if (cc >= 128 && (sp == 0 || sp->_use_meta)) {" - print " strlcpy(p, \"M-\", psize);" + print " char *p = name;" + print "#define P_LIMIT (sizeof(name) - (size_t) (p - name))" + print " if (cc >= 128 && m_prefix) {" + print " _nc_STRCPY(p, \"M-\", P_LIMIT);" print " p += 2;" - print " psize -= 2;" print " cc -= 128;" print " }" print " if (cc < 32)" - print " snprintf(p, psize, \"^%c\", cc + '@');" + print " _nc_SPRINTF(p, _nc_SLIMIT(P_LIMIT) \"^%c\", cc + '@');" print " else if (cc == 127)" - print " strlcpy(p, \"^?\", psize);" + print " _nc_STRCPY(p, \"^?\", P_LIMIT);" print " else" - print " snprintf(p, psize, \"%c\", cc);" + print " _nc_SPRINTF(p, _nc_SLIMIT(P_LIMIT) \"%c\", cc);" print " MyTable[c] = strdup(name);" print " }" print " result = MyTable[c];" print " }" print "#if NCURSES_EXT_FUNCS && NCURSES_XNAMES" - print " } else if (result == 0 && cur_term != 0) {" + print " } else if (result == 0 && HasTerminal(sp)) {" print " int j, k;" print " char * bound;" - print " TERMTYPE *tp = &(cur_term->type);" - print " int save_trace = _nc_tracing;" + print " TERMTYPE2 *tp = &TerminalType(TerminalOf(sp));" + print " unsigned save_trace = _nc_tracing;" print "" print " _nc_tracing = 0; /* prevent recursion via keybound() */" - print " for (j = 0; (bound = keybound(c, j)) != 0; ++j) {" + print " for (j = 0; (bound = NCURSES_SP_NAME(keybound)(NCURSES_SP_ARGx c, j)) != 0; ++j) {" print " for(k = STRCOUNT; k < (int) NUM_STRINGS(tp); k++) {" print " if (tp->Strings[k] != 0 && !strcmp(bound, tp->Strings[k])) {" print " result = ExtStrname(tp, k, strnames);" @@ -145,16 +158,17 @@ END { print " return result;" print "}" print "" - print "NCURSES_EXPORT(NCURSES_CONST char *) keyname (int c)" + print "NCURSES_EXPORT(NCURSES_CONST char *)" + print "keyname (int c)" print "{" - print "\treturn _nc_keyname(SP, c);" + print " return safe_keyname (CURRENT_SCREEN, c);" print "}" print "" print "#if NO_LEAKS" print "void _nc_keyname_leaks(void)" print "{" - print " int j;" print " if (MyTable != 0) {" + print " int j;" print " for (j = 0; j < SIZEOF_TABLE; ++j) {" print " FreeIfNeeded(MyTable[j]);" print " }" diff --git a/lib/libcurses/base/MKlib_gen.sh b/lib/libcurses/base/MKlib_gen.sh index 1c183621da8..7cf15dccac3 100644 --- a/lib/libcurses/base/MKlib_gen.sh +++ b/lib/libcurses/base/MKlib_gen.sh @@ -1,12 +1,13 @@ +# $OpenBSD: MKlib_gen.sh,v 1.5 2023/10/17 09:52:08 nicm Exp $ #!/bin/sh # # MKlib_gen.sh -- generate sources from curses.h macro definitions # -# $OpenBSD: MKlib_gen.sh,v 1.4 2010/01/12 23:22:05 nicm Exp $ -# ($Id: MKlib_gen.sh,v 1.4 2010/01/12 23:22:05 nicm Exp $) +# ($Id: MKlib_gen.sh,v 1.5 2023/10/17 09:52:08 nicm Exp $) # ############################################################################## -# Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. # +# Copyright 2018-2021,2022 Thomas E. Dickey # +# Copyright 1998-2016,2017 Free Software Foundation, Inc. # # # # Permission is hereby granted, free of charge, to any person obtaining a # # copy of this software and associated documentation files (the "Software"), # @@ -52,7 +53,7 @@ # them. # 5. cpp: macro-expand the file so the macro calls turn into C calls # 6. awk: strip the expansion junk off the front and add the new header -# 7. sed: squeeze spaces, strip off gen_ prefix, create needed #undef +# 7. sed: squeeze spaces, strip off gen_ prefix. # # keep the editing independent of locale: @@ -63,10 +64,36 @@ if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi if test "${LC_COLLATE+set}" = set; then LC_COLLATE=C; export LC_COLLATE; fi -preprocessor="$1 -DNCURSES_INTERNALS -I../include" +preprocessor="$1 -DNCURSES_WATTR_MACROS -DNCURSES_INTERNALS -I../include" AWK="$2" USE="$3" +# A patch discussed here: +# https://gcc.gnu.org/ml/gcc-patches/2014-06/msg02185.html +# +# introduces spurious #line markers into the preprocessor output. The result +# appears in gcc 5.0 and (with modification) in 5.1, making it necessary to +# determine if we are using gcc, and if so, what version because the proposed +# solution uses a nonstandard option. +# +# As illustrated in +# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60723 +# +# gcc developers chose to ignore the problems with this, and summarized those +# as "intriguing problems" in +# https://gcc.gnu.org/gcc-5/porting_to.html + +PRG=`echo "$1" | "$AWK" '{ sub(/^[ ]*/,""); sub(/[ ].*$/, ""); print; }' || exit 0` +FSF=`("$PRG" --version 2>/dev/null || exit 0) | ${FGREP-grep -F} "Free Software Foundation" | head -n 1` +ALL=`"$PRG" -dumpversion 2>/dev/null || exit 0` +ONE=`echo "$ALL" | sed -e 's/[^0-9].*$//'` +if test -n "$FSF" && test -n "$ALL" && test -n "$ONE" ; then + if test "$ONE" -ge 5 ; then + echo ".. adding -P option to work around $PRG $ALL" >&2 + preprocessor="$preprocessor -P" + fi +fi + PID=$$ ED1=sed1_${PID}.sed ED2=sed2_${PID}.sed @@ -75,13 +102,16 @@ ED4=sed4_${PID}.sed AW1=awk1_${PID}.awk AW2=awk2_${PID}.awk TMP=gen__${PID}.c -trap "rm -f $ED1 $ED2 $ED3 $ED4 $AW1 $AW2 $TMP" 0 1 2 5 15 +trap "rm -f $ED1 $ED2 $ED3 $ED4 $AW1 $AW2 $TMP; exit 1" 1 2 3 15 +trap "rm -f $ED1 $ED2 $ED3 $ED4 $AW1 $AW2 $TMP" 0 ALL=$USE if test "$USE" = implemented ; then - CALL="call_" cat >$ED1 <$ED1 <$ED3 <$ED4 <$ED4 <$ED4 <$AW2 <" + print "" + print "#undef NCURSES_NOMACROS /* _this_ file uses macros */" + print "#define NCURSES_NOMACROS 1" + print "" print "#include " print "" } /^DECLARATIONS/ {start = 1; next;} - {if (start) print \$0;} + { + if (start) { + if ( "$USE" == "generated" ) { + print \$0; + } else if ( \$0 ~ /^[{}]?\$/ ) { + print \$0; + } else if ( \$0 ~ /;/ ) { + print \$0; + } else { + calls[start] = \$0; + print \$0; + start++; + } + } + } END { if ( "$USE" != "generated" ) { - print "int main(void) { return 0; }" + print "int main(void)" + print "{" + for (n = 1; n < start; ++n) { + value = calls[n]; + if ( value !~ /P_POUNDC/ ) { + gsub(/[ \t]+/," ",value); + sub(/^[0-9a-zA-Z_]+ /,"",value); + sub(/^[*][ \t]*/,"",value); + gsub("struct[ \t]*[0-9a-zA-Z_]+[ \t]*[*]","",value); + gsub(/[0-9a-zA-Z_]+[ \t]*[*][ \t]*/,"",value); + gsub(/ (const) /," ",value); + gsub(/ (int|short|attr_t|chtype|wchar_t|NCURSES_BOOL|NCURSES_OUTC|NCURSES_OUTC_sp|va_list) /," ",value); + gsub(/ void /,"",value); + sub(/^/,"call_",value); + gsub(/ (a[0-9]|z) /, " 0 ", value); + gsub(/ int[ \t]*[(][^)]+[)][(][^)]+[)]/, "0", value); + printf "\t%s;\n", value; + } else { + print value; + } + } + print " return 0;" + print "}" } } EOF1 @@ -398,6 +496,8 @@ cat >$TMP < #undef NCURSES_NOMACROS #include +#include +#include DECLARATIONS @@ -406,7 +506,7 @@ EOF sed -n -f $ED1 \ | sed -e 's/NCURSES_EXPORT(\(.*\)) \(.*\) (\(.*\))/\1 \2(\3)/' \ | sed -f $ED2 \ -| $AWK -f $AW1 using=$USE \ +| "$AWK" -f $AW1 using="$USE" \ | sed \ -e 's/ [ ]*$//g' \ -e 's/^\([a-zA-Z_][a-zA-Z_]*[ *]*\)/\1 gen_/' \ @@ -418,7 +518,7 @@ $preprocessor $TMP 2>/dev/null \ -e 's/ / /g' \ -e 's/^ //' \ -e 's/_Bool/NCURSES_BOOL/g' \ -| $AWK -f $AW2 \ +| "$AWK" -f $AW2 \ | sed -f $ED3 \ | sed \ -e 's/^.*T_CALLED.*returnCode( \([a-z].*) \));/ return \1;/' \ diff --git a/lib/libcurses/base/MKunctrl.awk b/lib/libcurses/base/MKunctrl.awk index 506443a6512..587c65a7b73 100644 --- a/lib/libcurses/base/MKunctrl.awk +++ b/lib/libcurses/base/MKunctrl.awk @@ -1,7 +1,8 @@ -# $OpenBSD: MKunctrl.awk,v 1.4 2010/01/12 23:22:05 nicm Exp $ -# $Id: MKunctrl.awk,v 1.4 2010/01/12 23:22:05 nicm Exp $ +# $OpenBSD: MKunctrl.awk,v 1.5 2023/10/17 09:52:08 nicm Exp $ +# $Id: MKunctrl.awk,v 1.5 2023/10/17 09:52:08 nicm Exp $ ############################################################################## -# Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. # +# Copyright 2020 Thomas E. Dickey # +# Copyright 1998-2012,2017 Free Software Foundation, Inc. # # # # Permission is hereby granted, free of charge, to any person obtaining a # # copy of this software and associated documentation files (the "Software"), # @@ -37,19 +38,12 @@ BEGIN { print "#include " print "#include " print "" - print "#if USE_WIDEC_SUPPORT" - print "#if HAVE_WCTYPE_H" - print "#include " - print "#endif" - print "#endif" - print "" print "#undef unctrl" print "" } END { - print "NCURSES_EXPORT(NCURSES_CONST char *) _nc_unctrl (SCREEN *sp, chtype ch)" + print "NCURSES_EXPORT(NCURSES_CONST char *) safe_unctrl(SCREEN *sp, chtype ch)" print "{" - blob="" offset=0 if (bigstrings) { @@ -148,9 +142,10 @@ END { } else { stringname = "unctrl" } - print "\tint check = ChCharOf(ch);" + print "\tint check = (int) ChCharOf(ch);" print "\tconst char *result;" print "" + print "(void) sp;" print "\tif (check >= 0 && check < (int)SIZEOF(unctrl_table)) {" print "#if NCURSES_EXT_FUNCS" print "\t\tif ((sp != 0)" @@ -159,16 +154,6 @@ END { print "\t\t && (check < 160))" printf "\t\t\tresult = %s_c1[check - 128];\n", stringname; print "\t\telse" - print "#if USE_WIDEC_SUPPORT" - print "\t\tif ((check >= 160)" - print "\t\t && (check < 256)" - print "\t\t && ((sp != 0)" - print "\t\t && ((sp->_legacy_coding > 0)" - print "\t\t || (sp->_legacy_coding == 0" - print "\t\t && (isprint(check) || iswprint(check))))))" - printf "\t\t\tresult = %s_c1[check - 128];\n", stringname; - print "\t\telse" - print "#else" print "\t\tif ((check >= 160)" print "\t\t && (check < 256)" print "\t\t && ((sp != 0)" @@ -177,7 +162,6 @@ END { print "\t\t && isprint(check)))))" printf "\t\t\tresult = %s_c1[check - 128];\n", stringname; print "\t\telse" - print "#endif /* USE_WIDEC_SUPPORT */" print "#endif /* NCURSES_EXT_FUNCS */" printf "\t\t\tresult = %s_table[check];\n", stringname; print "\t} else {" @@ -188,6 +172,6 @@ END { print "" print "NCURSES_EXPORT(NCURSES_CONST char *) unctrl (chtype ch)" print "{" - print "\treturn _nc_unctrl(SP, ch);" + print "\treturn safe_unctrl(CURRENT_SCREEN, ch);" print "}" } diff --git a/lib/libcurses/base/define_key.c b/lib/libcurses/base/define_key.c index 001287859cb..bef1454902d 100644 --- a/lib/libcurses/base/define_key.c +++ b/lib/libcurses/base/define_key.c @@ -1,7 +1,8 @@ -/* $OpenBSD: define_key.c,v 1.5 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: define_key.c,v 1.6 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2009,2014 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,33 +30,40 @@ ****************************************************************************/ /**************************************************************************** - * Author: Thomas E. Dickey 1997-on * + * Author: Thomas E. Dickey 1997-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ #include -MODULE_ID("$Id: define_key.c,v 1.5 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: define_key.c,v 1.6 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) -define_key(const char *str, int keycode) +NCURSES_SP_NAME(define_key) (NCURSES_SP_DCLx const char *str, int keycode) { int code = ERR; - T((T_CALLED("define_key(%s,%d)"), _nc_visbuf(str), keycode)); - if (SP == 0) { + T((T_CALLED("define_key(%p, %s,%d)"), (void *) SP_PARM, _nc_visbuf(str), keycode)); + if (SP_PARM == 0 || !HasTInfoTerminal(SP_PARM)) { code = ERR; } else if (keycode > 0) { unsigned ukey = (unsigned) keycode; +#ifdef USE_TERM_DRIVER +#define CallHasKey(keycode) CallDriver_1(SP_PARM, td_kyExist, keycode) +#else +#define CallHasKey(keycode) NCURSES_SP_NAME(has_key)(NCURSES_SP_ARGx keycode) +#endif + if (str != 0) { - define_key(str, 0); - } else if (has_key(keycode)) { - while (_nc_remove_key(&(SP->_keytry), ukey)) + NCURSES_SP_NAME(define_key) (NCURSES_SP_ARGx str, 0); + } else if (CallHasKey(keycode)) { + while (_nc_remove_key(&(SP_PARM->_keytry), ukey)) code = OK; } if (str != 0) { - if (key_defined(str) == 0) { - if (_nc_add_to_try(&(SP->_keytry), str, ukey) == OK) { + if (NCURSES_SP_NAME(key_defined) (NCURSES_SP_ARGx str) == 0) { + if (_nc_add_to_try(&(SP_PARM->_keytry), str, ukey) == OK) { code = OK; } else { code = ERR; @@ -65,8 +73,16 @@ define_key(const char *str, int keycode) } } } else { - while (_nc_remove_string(&(SP->_keytry), str)) + while (_nc_remove_string(&(SP_PARM->_keytry), str)) code = OK; } returnCode(code); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +define_key(const char *str, int keycode) +{ + return NCURSES_SP_NAME(define_key) (CURRENT_SCREEN, str, keycode); +} +#endif diff --git a/lib/libcurses/base/key_defined.c b/lib/libcurses/base/key_defined.c index 65f66486dec..4aa295b1951 100644 --- a/lib/libcurses/base/key_defined.c +++ b/lib/libcurses/base/key_defined.c @@ -1,7 +1,8 @@ -/* $OpenBSD: key_defined.c,v 1.1 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: key_defined.c,v 1.2 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2003,2006 Free Software Foundation, Inc. * + * Copyright 2020,2023 Thomas E. Dickey * + * Copyright 2003-2006,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,8 +34,9 @@ ****************************************************************************/ #include +#include -MODULE_ID("$Id: key_defined.c,v 1.1 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: key_defined.c,v 1.2 2023/10/17 09:52:08 nicm Exp $") static int find_definition(TRIES * tree, const char *str) @@ -42,7 +44,7 @@ find_definition(TRIES * tree, const char *str) TRIES *ptr; int result = OK; - if (str != 0 && *str != '\0') { + if (VALID_STRING(str) && *str != '\0') { for (ptr = tree; ptr != 0; ptr = ptr->sibling) { if (UChar(*str) == UChar(ptr->ch)) { if (str[1] == '\0' && ptr->child != 0) { @@ -67,14 +69,22 @@ find_definition(TRIES * tree, const char *str) * Otherwise, return the keycode's value (neither OK/ERR). */ NCURSES_EXPORT(int) -key_defined(const char *str) +NCURSES_SP_NAME(key_defined) (NCURSES_SP_DCLx const char *str) { int code = ERR; - T((T_CALLED("key_defined(%s)"), _nc_visbuf(str))); - if (SP != 0 && str != 0) { - code = find_definition(SP->_keytry, str); + T((T_CALLED("key_defined(%p, %s)"), (void *) SP_PARM, _nc_visbuf(str))); + if (SP_PARM != 0 && str != 0) { + code = find_definition(SP_PARM->_keytry, str); } returnCode(code); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +key_defined(const char *str) +{ + return NCURSES_SP_NAME(key_defined) (CURRENT_SCREEN, str); +} +#endif diff --git a/lib/libcurses/base/keybound.c b/lib/libcurses/base/keybound.c index e8f1c34f860..3ae203e7969 100644 --- a/lib/libcurses/base/keybound.c +++ b/lib/libcurses/base/keybound.c @@ -1,7 +1,8 @@ -/* $OpenBSD: keybound.c,v 1.5 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: keybound.c,v 1.6 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1999-2005,2006 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1999-2009,2011 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,26 +30,37 @@ ****************************************************************************/ /**************************************************************************** - * Author: Thomas E. Dickey 1999-on * + * Author: Thomas E. Dickey 1999-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ #include -#include -MODULE_ID("$Id: keybound.c,v 1.5 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: keybound.c,v 1.6 2023/10/17 09:52:08 nicm Exp $") /* * Returns the count'th string definition which is associated with the * given keycode. The result is malloc'd, must be freed by the caller. */ NCURSES_EXPORT(char *) -keybound(int code, int count) +NCURSES_SP_NAME(keybound) (NCURSES_SP_DCLx int code, int count) { char *result = 0; - T((T_CALLED("keybound(%d,%d)"), code, count)); - if (SP != 0 && code >= 0) { - result = _nc_expand_try(SP->_keytry, (unsigned) code, &count, 0); + T((T_CALLED("keybound(%p, %d,%d)"), (void *) SP_PARM, code, count)); + if (SP_PARM != 0 && code >= 0) { + result = _nc_expand_try(SP_PARM->_keytry, + (unsigned) code, + &count, + (size_t) 0); } returnPtr(result); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(char *) +keybound(int code, int count) +{ + return NCURSES_SP_NAME(keybound) (CURRENT_SCREEN, code, count); +} +#endif diff --git a/lib/libcurses/base/keyok.c b/lib/libcurses/base/keyok.c index 0eb646984a4..6ee15da0bee 100644 --- a/lib/libcurses/base/keyok.c +++ b/lib/libcurses/base/keyok.c @@ -1,7 +1,8 @@ -/* $OpenBSD: keyok.c,v 1.5 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: keyok.c,v 1.6 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2006 Free Software Foundation, Inc. * + * Copyright 2019-2020,2021 Thomas E. Dickey * + * Copyright 1998-2012,2014 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,52 +30,76 @@ ****************************************************************************/ /**************************************************************************** - * Author: Thomas E. Dickey 1997-on * + * Author: Thomas E. Dickey 1997-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ #include -MODULE_ID("$Id: keyok.c,v 1.5 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: keyok.c,v 1.6 2023/10/17 09:52:08 nicm Exp $") /* * Enable (or disable) ncurses' interpretation of a keycode by adding (or * removing) the corresponding 'tries' entry. * - * Do this by storing a second tree of tries, which records the disabled keys. + * Do this by storing a second tree of tries, which records the disabled keys. * The simplest way to copy is to make a function that returns the string (with * nulls set to 0200), then use that to reinsert the string into the * corresponding tree. */ NCURSES_EXPORT(int) -keyok(int c, bool flag) +NCURSES_SP_NAME(keyok) (NCURSES_SP_DCLx int c, bool flag) { int code = ERR; - int count = 0; - char *s; - T((T_CALLED("keyok(%d,%d)"), c, flag)); - if (c >= 0) { - unsigned ch = (unsigned) c; - if (flag) { - while ((s = _nc_expand_try(SP->_key_ok, ch, &count, 0)) != 0 - && _nc_remove_key(&(SP->_key_ok), ch)) { - code = _nc_add_to_try(&(SP->_keytry), s, ch); - free(s); - count = 0; - if (code != OK) - break; - } - } else { - while ((s = _nc_expand_try(SP->_keytry, ch, &count, 0)) != 0 - && _nc_remove_key(&(SP->_keytry), ch)) { - code = _nc_add_to_try(&(SP->_key_ok), s, ch); - free(s); - count = 0; - if (code != OK) - break; + if (HasTerminal(SP_PARM)) { + T((T_CALLED("keyok(%p, %d,%d)"), (void *) SP_PARM, c, flag)); +#ifdef USE_TERM_DRIVER + code = CallDriver_2(sp, td_kyOk, c, flag); +#else + if (c >= 0) { + int count = 0; + char *s; + unsigned ch = (unsigned) c; + + if (flag) { + while ((s = _nc_expand_try(SP_PARM->_key_ok, + ch, &count, (size_t) 0)) != 0) { + if (_nc_remove_key(&(SP_PARM->_key_ok), ch)) { + code = _nc_add_to_try(&(SP_PARM->_keytry), s, ch); + free(s); + count = 0; + if (code != OK) + break; + } else { + free(s); + } + } + } else { + while ((s = _nc_expand_try(SP_PARM->_keytry, + ch, &count, (size_t) 0)) != 0) { + if (_nc_remove_key(&(SP_PARM->_keytry), ch)) { + code = _nc_add_to_try(&(SP_PARM->_key_ok), s, ch); + free(s); + count = 0; + if (code != OK) + break; + } else { + free(s); + } + } } } +#endif } returnCode(code); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +keyok(int c, bool flag) +{ + return NCURSES_SP_NAME(keyok) (CURRENT_SCREEN, c, flag); +} +#endif diff --git a/lib/libcurses/base/legacy_coding.c b/lib/libcurses/base/legacy_coding.c index f88d1b8ddc4..c0fe0cc01a9 100644 --- a/lib/libcurses/base/legacy_coding.c +++ b/lib/libcurses/base/legacy_coding.c @@ -1,7 +1,8 @@ -/* $OpenBSD: legacy_coding.c,v 1.1 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: legacy_coding.c,v 1.2 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 2005,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,22 +30,31 @@ ****************************************************************************/ /**************************************************************************** - * Author: Thomas E. Dickey * + * Author: Thomas E. Dickey 2005 * + * Juergen Pfeifer 2009 * ****************************************************************************/ #include -MODULE_ID("$Id: legacy_coding.c,v 1.1 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: legacy_coding.c,v 1.2 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) -use_legacy_coding(int level) +NCURSES_SP_NAME(use_legacy_coding) (NCURSES_SP_DCLx int level) { int result = ERR; - T((T_CALLED("use_legacy_coding(%d)"), level)); - if (level >= 0 && level <= 2 && SP != 0) { - result = SP->_legacy_coding; - SP->_legacy_coding = level; + T((T_CALLED("use_legacy_coding(%p,%d)"), (void *) SP_PARM, level)); + if (level >= 0 && level <= 2 && SP_PARM != 0) { + result = SP_PARM->_legacy_coding; + SP_PARM->_legacy_coding = level; } returnCode(result); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +use_legacy_coding(int level) +{ + return NCURSES_SP_NAME(use_legacy_coding) (CURRENT_SCREEN, level); +} +#endif diff --git a/lib/libcurses/base/lib_addch.c b/lib/libcurses/base/lib_addch.c index 055ca39306b..ee1043c3d2a 100644 --- a/lib/libcurses/base/lib_addch.c +++ b/lib/libcurses/base/lib_addch.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_addch.c,v 1.5 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_addch.c,v 1.6 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. * + * Copyright 2019-2021,2022 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -38,7 +39,7 @@ #include #include -MODULE_ID("$Id: lib_addch.c,v 1.5 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_addch.c,v 1.6 2023/10/17 09:52:08 nicm Exp $") static const NCURSES_CH_T blankchar = NewChar(BLANK_TEXT); @@ -53,7 +54,7 @@ static const NCURSES_CH_T blankchar = NewChar(BLANK_TEXT); */ /* Return bit mask for clearing color pair number if given ch has color */ -#define COLOR_MASK(ch) (~(attr_t)((ch) & A_COLOR ? A_COLOR : 0)) +#define COLOR_MASK(ch) (~(attr_t)(((ch) & A_COLOR) ? A_COLOR : 0)) static NCURSES_INLINE NCURSES_CH_T render_char(WINDOW *win, NCURSES_CH_T ch) @@ -79,12 +80,6 @@ render_char(WINDOW *win, NCURSES_CH_T ch) if ((pair = GET_WINDOW_PAIR(win)) == 0) pair = GetPair(win->_nc_bkgd); } -#if 0 - if (pair > 255) { - NCURSES_CH_T fixme = ch; - SetPair(fixme, pair); - } -#endif AddAttr(ch, (a & COLOR_MASK(AttrOf(ch)))); SetPair(ch, pair); } @@ -125,15 +120,19 @@ _nc_render(WINDOW *win, NCURSES_CH_T ch) #endif static bool -newline_forces_scroll(WINDOW *win, NCURSES_SIZE_T * ypos) +newline_forces_scroll(WINDOW *win, NCURSES_SIZE_T *ypos) { bool result = FALSE; - if (*ypos >= win->_regtop && *ypos == win->_regbottom) { - *ypos = win->_regbottom; - result = TRUE; - } else { - *ypos += 1; + if (*ypos >= win->_regtop && *ypos <= win->_regbottom) { + if (*ypos == win->_regbottom) { + *ypos = win->_regbottom; + result = TRUE; + } else if (*ypos < win->_maxy) { + *ypos = (NCURSES_SIZE_T) (*ypos + 1); + } + } else if (*ypos < win->_maxy) { + *ypos = (NCURSES_SIZE_T) (*ypos + 1); } return result; } @@ -143,7 +142,7 @@ newline_forces_scroll(WINDOW *win, NCURSES_SIZE_T * ypos) * wrapped the cursor. We don't do anything with this flag except set it when * wrapping, and clear it whenever we move the cursor. If we try to wrap at * the lower-right corner of a window, we cannot move the cursor (since that - * wouldn't be legal). So we return an error (which is what SVr4 does). + * wouldn't be legal). So we return an error (which is what SVr4 does). * Unlike SVr4, we can successfully add a character to the lower-right corner * (Solaris 2.6 does this also, however). */ @@ -178,8 +177,8 @@ fill_cells(WINDOW *win, int count) if (waddch_literal(win, blank) == ERR) break; } - win->_curx = save_x; - win->_cury = save_y; + win->_curx = (NCURSES_SIZE_T) save_x; + win->_cury = (NCURSES_SIZE_T) save_y; } #endif @@ -211,13 +210,28 @@ _nc_build_wch(WINDOW *win, ARG_CH_T ch) WINDOW_EXT(win, addch_x) = x; WINDOW_EXT(win, addch_y) = y; + /* + * If the background character is a wide-character, that may interfere with + * processing multibyte characters in this function. + */ + if (!is8bits(CharOf(CHDEREF(ch)))) { + if (WINDOW_EXT(win, addch_used) != 0) { + /* discard the incomplete multibyte character */ + WINDOW_EXT(win, addch_used) = 0; + TR(TRACE_VIRTPUT, + ("Alert discarded incomplete multibyte")); + } + return 1; + } + init_mb(state); buffer[WINDOW_EXT(win, addch_used)] = (char) CharOf(CHDEREF(ch)); WINDOW_EXT(win, addch_used) += 1; buffer[WINDOW_EXT(win, addch_used)] = '\0'; - if ((len = mbrtowc(&result, - buffer, - WINDOW_EXT(win, addch_used), &state)) > 0) { + if ((len = (int) mbrtowc(&result, + buffer, + (size_t) WINDOW_EXT(win, addch_used), + &state)) > 0) { attr_t attrs = AttrOf(CHDEREF(ch)); if_EXT_COLORS(int pair = GetPair(CHDEREF(ch))); SetChar(CHDEREF(ch), result, attrs); @@ -262,20 +276,37 @@ waddch_literal(WINDOW *win, NCURSES_CH_T ch) /* * Build up multibyte characters until we have a wide-character. */ +#if NCURSES_SP_FUNCS +#define DeriveSP() SCREEN *sp = _nc_screen_of(win); +#else +#define DeriveSP() /*nothing */ +#endif if_WIDEC({ + DeriveSP(); if (WINDOW_EXT(win, addch_used) != 0 || !Charable(ch)) { int len = _nc_build_wch(win, CHREF(ch)); if (len >= -1) { - /* handle EILSEQ */ - if (is8bits(CharOf(ch))) { - const char *s = unctrl((chtype) CharOf(ch)); - if (s[1] != 0) { - return waddstr(win, s); + attr_t attr = AttrOf(ch); + + /* handle EILSEQ (i.e., when len >= -1) */ + if (len == -1 && is8bits(CharOf(ch))) { + const char *s = NCURSES_SP_NAME(unctrl) + (NCURSES_SP_ARGx (chtype) CharOf(ch)); + + if (s[1] != '\0') { + int rc = OK; + while (*s != '\0') { + rc = waddch(win, UChar(*s) | attr); + if (rc != OK) + break; + ++s; + } + return rc; } } if (len == -1) - return waddch(win, ' '); + return waddch(win, ' ' | attr); } else { return OK; } @@ -289,23 +320,32 @@ waddch_literal(WINDOW *win, NCURSES_CH_T ch) * adjustments. */ if_WIDEC({ - int len = wcwidth(CharOf(ch)); + int len = _nc_wacs_width(CharOf(ch)); int i; int j; - wchar_t *chars; if (len == 0) { /* non-spacing */ if ((x > 0 && y >= 0) || (win->_maxx >= 0 && win->_cury >= 1)) { - if (x > 0 && y >= 0) - chars = (win->_line[y].text[x - 1].chars); - else - chars = (win->_line[y - 1].text[win->_maxx].chars); + NCURSES_CH_T *dst; + wchar_t *chars; + if (x > 0 && y >= 0) { + for (j = x - 1; j >= 0; --j) { + if (!isWidecExt(win->_line[y].text[j])) { + win->_curx = (NCURSES_SIZE_T) j; + break; + } + } + dst = &(win->_line[y].text[j]); + } else { + dst = &(win->_line[y - 1].text[win->_maxx]); + } + chars = dst->chars; for (i = 0; i < CCHARW_MAX; ++i) { if (chars[i] == 0) { TR(TRACE_VIRTPUT, - ("added non-spacing %d: %x", - x, (int) CharOf(ch))); + ("adding non-spacing %s (level %d)", + _tracech_t(CHREF(ch)), i)); chars[i] = CharOf(ch); break; } @@ -329,6 +369,8 @@ waddch_literal(WINDOW *win, NCURSES_CH_T ch) return ERR; x = win->_curx; y = win->_cury; + CHECK_POSITION(win, x, y); + line = win->_line + y; } /* * Check for cells which are orphaned by adding this character, set @@ -379,14 +421,14 @@ waddch_literal(WINDOW *win, NCURSES_CH_T ch) testwrapping: ); - TR(TRACE_VIRTPUT, ("cell (%ld, %ld..%d) = %s", - (long) win->_cury, (long) win->_curx, x - 1, - _tracech_t(CHREF(ch)))); + TR(TRACE_VIRTPUT, ("cell (%d, %d..%d) = %s", + win->_cury, win->_curx, x - 1, + _tracech_t(CHREF(line->text[win->_curx])))); if (x > win->_maxx) { return wrap_to_next_line(win); } - win->_curx = x; + win->_curx = (NCURSES_SIZE_T) x; return OK; } @@ -395,30 +437,36 @@ waddch_nosync(WINDOW *win, const NCURSES_CH_T ch) /* the workhorse function -- add a character to the given window */ { NCURSES_SIZE_T x, y; - chtype t = CharOf(ch); - const char *s = unctrl(t); + chtype t = (chtype) CharOf(ch); +#if USE_WIDEC_SUPPORT || NCURSES_SP_FUNCS || USE_REENTRANT + SCREEN *sp = _nc_screen_of(win); +#endif + const char *s = NCURSES_SP_NAME(unctrl) (NCURSES_SP_ARGx t); + int tabsize = 8; /* * If we are using the alternate character set, forget about locale. * Otherwise, if unctrl() returns a single-character or the locale - * claims the code is printable, treat it that way. + * claims the code is printable (and not also a control character), + * treat it that way. */ if ((AttrOf(ch) & A_ALTCHARSET) || ( #if USE_WIDEC_SUPPORT - (SP != 0 && SP->_legacy_coding) && + (sp != 0 && sp->_legacy_coding) && #endif s[1] == 0 ) || ( - isprint(t) + (isprint((int) t) && !iscntrl((int) t)) #if USE_WIDEC_SUPPORT - || ((SP == 0 || !SP->_legacy_coding) && + || ((sp == 0 || !sp->_legacy_coding) && (WINDOW_EXT(win, addch_used) || !_nc_is_charable(CharOf(ch)))) #endif - )) + )) { return waddch_literal(win, ch); + } /* * Handle carriage control and other codes that are not printable, or are @@ -426,11 +474,16 @@ waddch_nosync(WINDOW *win, const NCURSES_CH_T ch) */ x = win->_curx; y = win->_cury; + CHECK_POSITION(win, x, y); switch (t) { case '\t': - x += (TABSIZE - (x % TABSIZE)); - +#if USE_REENTRANT + tabsize = *ptrTabsize(sp); +#else + tabsize = TABSIZE; +#endif + x = (NCURSES_SIZE_T) (x + (tabsize - (x % tabsize))); /* * Space-fill the tab on the bottom line so that we'll get the * "correct" cursor position. @@ -480,7 +533,7 @@ waddch_nosync(WINDOW *win, const NCURSES_CH_T ch) default: while (*s) { NCURSES_CH_T sch; - SetChar(sch, *s++, AttrOf(ch)); + SetChar(sch, UChar(*s++), AttrOf(ch)); if_EXT_COLORS(SetPair(sch, GetPair(ch))); if (waddch_literal(win, sch) == ERR) return ERR; @@ -516,7 +569,7 @@ waddch(WINDOW *win, const chtype ch) NCURSES_CH_T wch; SetChar2(wch, ch); - TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("waddch(%p, %s)"), win, + TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("waddch(%p, %s)"), (void *) win, _tracechtype(ch))); if (win && (waddch_nosync(win, wch) != ERR)) { @@ -535,7 +588,8 @@ wechochar(WINDOW *win, const chtype ch) NCURSES_CH_T wch; SetChar2(wch, ch); - TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("wechochar(%p, %s)"), win, + TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("wechochar(%p, %s)"), + (void *) win, _tracechtype(ch))); if (win && (waddch_nosync(win, wch) != ERR)) { diff --git a/lib/libcurses/base/lib_addstr.c b/lib/libcurses/base/lib_addstr.c index 7f038d83e4a..c1bd4f234d4 100644 --- a/lib/libcurses/base/lib_addstr.c +++ b/lib/libcurses/base/lib_addstr.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_addstr.c,v 1.5 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_addstr.c,v 1.6 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * + * Copyright 2019-2020,2022 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -46,7 +47,7 @@ #include -MODULE_ID("$Id: lib_addstr.c,v 1.5 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_addstr.c,v 1.6 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) waddnstr(WINDOW *win, const char *astr, int n) @@ -54,17 +55,18 @@ waddnstr(WINDOW *win, const char *astr, int n) const char *str = astr; int code = ERR; - T((T_CALLED("waddnstr(%p,%s,%d)"), win, _nc_visbufn(astr, n), n)); + T((T_CALLED("waddnstr(%p,%s,%d)"), (void *) win, _nc_visbufn(astr, n), n)); if (win && (str != 0)) { TR(TRACE_VIRTPUT | TRACE_ATTRS, ("... current %s", _traceattr(WINDOW_ATTRS(win)))); code = OK; - if (n < 0) - n = (int) strlen(astr); - TR(TRACE_VIRTPUT, ("str is not null, length = %d", n)); - while ((n-- > 0) && (*str != '\0')) { + TR(TRACE_VIRTPUT, ("str is not null, length = %d", + ((n > 0) ? n : (int) strlen(str)))); + if (n < 0) + n = INT_MAX; + while ((*str != '\0') && (n-- > 0)) { NCURSES_CH_T ch; TR(TRACE_VIRTPUT, ("*str = %#o", UChar(*str))); SetChar(ch, UChar(*str++), A_NORMAL); @@ -87,9 +89,9 @@ waddchnstr(WINDOW *win, const chtype *astr, int n) int i; struct ldat *line; - T((T_CALLED("waddchnstr(%p,%p,%d)"), win, astr, n)); + T((T_CALLED("waddchnstr(%p,%p,%d)"), (void *) win, (const void *) astr, n)); - if (!win) + if (!win || !astr) returnCode(ERR); y = win->_cury; @@ -109,7 +111,7 @@ waddchnstr(WINDOW *win, const chtype *astr, int n) for (i = 0; i < n && ChCharOf(astr[i]) != '\0'; ++i) { SetChar2(line->text[i + x], astr[i]); } - CHANGED_RANGE(line, x, x + n - 1); + CHANGED_RANGE(line, x, (NCURSES_SIZE_T) (x + n - 1)); _nc_synchook(win); returnCode(code); @@ -121,8 +123,10 @@ NCURSES_EXPORT(int) _nc_wchstrlen(const cchar_t *s) { int result = 0; - while (CharOf(s[result]) != L'\0') { - result++; + if (s != 0) { + while (CharOf(s[result]) != L'\0') { + result++; + } } return result; } @@ -137,7 +141,10 @@ wadd_wchnstr(WINDOW *win, const cchar_t *astr, int n) struct ldat *line; int i, j, start, len, end; - T((T_CALLED("wadd_wchnstr(%p,%s,%d)"), win, _nc_viscbuf(astr, n), n)); + T((T_CALLED("wadd_wchnstr(%p,%s,%d)"), + (void *) win, + _nc_viscbuf(astr, n), + n)); if (!win) returnCode(ERR); @@ -180,7 +187,7 @@ wadd_wchnstr(WINDOW *win, const cchar_t *astr, int n) if (isWidecExt(astr[i])) continue; - len = wcwidth(CharOf(astr[i])); + len = _nc_wacs_width(CharOf(astr[i])); if (x + len - 1 <= win->_maxx) { line->text[x] = _nc_render(win, astr[i]); @@ -191,8 +198,10 @@ wadd_wchnstr(WINDOW *win, const cchar_t *astr, int n) } SetWidecExt(line->text[x + j], j); } + } else { + len = 1; } - x += len; + x = (NCURSES_SIZE_T) (x + len); end += len - 1; } else { break; @@ -219,17 +228,18 @@ waddnwstr(WINDOW *win, const wchar_t *str, int n) { int code = ERR; - T((T_CALLED("waddnwstr(%p,%s,%d)"), win, _nc_viswbufn(str, n), n)); + T((T_CALLED("waddnwstr(%p,%s,%d)"), (void *) win, _nc_viswbufn(str, n), n)); if (win && (str != 0)) { TR(TRACE_VIRTPUT | TRACE_ATTRS, ("... current %s", _traceattr(WINDOW_ATTRS(win)))); code = OK; - if (n < 0) - n = (int) wcslen(str); - TR(TRACE_VIRTPUT, ("str is not null, length = %d", n)); - while ((n-- > 0) && (*str != L('\0'))) { + TR(TRACE_VIRTPUT, ("str is not null, length = %d", + ((n > 0) ? n : (int) wcslen(str)))); + if (n < 0) + n = INT_MAX; + while ((*str != L('\0')) && (n-- > 0)) { NCURSES_CH_T ch; TR(TRACE_VIRTPUT, ("*str[0] = %#lx", (unsigned long) *str)); SetChar(ch, *str++, A_NORMAL); diff --git a/lib/libcurses/base/lib_beep.c b/lib/libcurses/base/lib_beep.c index 99d8dd65844..4f119e1afdd 100644 --- a/lib/libcurses/base/lib_beep.c +++ b/lib/libcurses/base/lib_beep.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_beep.c,v 1.4 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_beep.c,v 1.5 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2013,2014 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,6 +33,7 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -42,9 +44,12 @@ */ #include -#include /* beep, flash */ -MODULE_ID("$Id: lib_beep.c,v 1.4 2010/01/12 23:22:05 nicm Exp $") +#ifndef CUR +#define CUR SP_TERMTYPE +#endif + +MODULE_ID("$Id: lib_beep.c,v 1.5 2023/10/17 09:52:08 nicm Exp $") /* * beep() @@ -55,24 +60,34 @@ MODULE_ID("$Id: lib_beep.c,v 1.4 2010/01/12 23:22:05 nicm Exp $") */ NCURSES_EXPORT(int) -beep(void) +NCURSES_SP_NAME(beep) (NCURSES_SP_DCL0) { int res = ERR; - T((T_CALLED("beep()"))); + T((T_CALLED("beep(%p)"), (void *) SP_PARM)); +#ifdef USE_TERM_DRIVER + if (SP_PARM != 0) + res = CallDriver_1(SP_PARM, td_doBeepOrFlash, TRUE); +#else /* FIXME: should make sure that we are not in altchar mode */ if (cur_term == 0) { res = ERR; } else if (bell) { - TPUTS_TRACE("bell"); - res = putp(bell); - _nc_flush(); + res = NCURSES_PUTP2_FLUSH("bell", bell); } else if (flash_screen) { - TPUTS_TRACE("flash_screen"); - res = putp(flash_screen); + res = NCURSES_PUTP2_FLUSH("flash_screen", flash_screen); _nc_flush(); } +#endif returnCode(res); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +beep(void) +{ + return NCURSES_SP_NAME(beep) (CURRENT_SCREEN); +} +#endif diff --git a/lib/libcurses/base/lib_bkgd.c b/lib/libcurses/base/lib_bkgd.c index 34adf40fe2c..8de292df8d7 100644 --- a/lib/libcurses/base/lib_bkgd.c +++ b/lib/libcurses/base/lib_bkgd.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_bkgd.c,v 1.3 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_bkgd.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. * + * Copyright 2018-2020,2021 Thomas E. Dickey * + * Copyright 1998-2014,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -38,7 +39,9 @@ #include -MODULE_ID("$Id: lib_bkgd.c,v 1.3 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_bkgd.c,v 1.4 2023/10/17 09:52:08 nicm Exp $") + +static const NCURSES_CH_T blank = NewChar(BLANK_TEXT); /* * Set the window's background information. @@ -50,7 +53,7 @@ static NCURSES_INLINE void #endif wbkgrndset(WINDOW *win, const ARG_CH_T ch) { - T((T_CALLED("wbkgdset(%p,%s)"), win, _tracech_t(ch))); + T((T_CALLED("wbkgrndset(%p,%s)"), (void *) win, _tracech_t(ch))); if (win) { attr_t off = AttrOf(win->_nc_bkgd); @@ -63,7 +66,7 @@ wbkgrndset(WINDOW *win, const ARG_CH_T ch) { int pair; - if ((pair = GetPair(win->_nc_bkgd)) != 0) + if (GetPair(win->_nc_bkgd) != 0) SET_WINDOW_PAIR(win, 0); if ((pair = GetPair(CHDEREF(ch))) != 0) SET_WINDOW_PAIR(win, pair); @@ -87,12 +90,13 @@ wbkgrndset(WINDOW *win, const ARG_CH_T ch) cchar_t wch; int tmp; - wgetbkgrnd(win, &wch); + memset(&wch, 0, sizeof(wch)); + (void) wgetbkgrnd(win, &wch); tmp = _nc_to_char((wint_t) CharOf(wch)); win->_bkgd = (((tmp == EOF) ? ' ' : (chtype) tmp) | (AttrOf(wch) & ALL_BUT_COLOR) - | COLOR_PAIR(GET_WINDOW_PAIR(win))); + | (chtype) ColorPair(GET_WINDOW_PAIR(win))); } #endif } @@ -103,42 +107,147 @@ NCURSES_EXPORT(void) wbkgdset(WINDOW *win, chtype ch) { NCURSES_CH_T wch; + T((T_CALLED("wbkgdset(%p,%s)"), (void *) win, _tracechtype(ch))); SetChar2(wch, ch); wbkgrndset(win, CHREF(wch)); + returnVoid; } /* * Set the window's background information and apply it to each cell. */ -#if USE_WIDEC_SUPPORT -NCURSES_EXPORT(int) -#else static NCURSES_INLINE int -#undef wbkgrnd -#endif -wbkgrnd(WINDOW *win, const ARG_CH_T ch) +_nc_background(WINDOW *win, const ARG_CH_T ch, bool narrow) { +#undef SP_PARM +#define SP_PARM SP /* to use Charable() */ int code = ERR; - int x, y; - NCURSES_CH_T new_bkgd = CHDEREF(ch); - T((T_CALLED("wbkgd(%p,%s)"), win, _tracech_t(ch))); +#if USE_WIDEC_SUPPORT + T((T_CALLED("%s(%p,%s)"), + narrow ? "wbkgd" : "wbkgrnd", + (void *) win, + _tracecchar_t(ch))); +#define TraceChar(c) _tracecchar_t2(1, &(c)) +#else + T((T_CALLED("%s(%p,%s)"), + "wbkgd", + (void *) win, + _tracech_t(ch))); + (void) narrow; +#define TraceChar(c) _tracechar(CharOf(c)) +#endif - if (win) { - NCURSES_CH_T old_bkgrnd; - wgetbkgrnd(win, &old_bkgrnd); + if (SP == 0) { + ; + } else if (win) { + NCURSES_CH_T new_bkgd = CHDEREF(ch); + NCURSES_CH_T old_bkgd; + int y; + NCURSES_CH_T old_char; + attr_t old_attr; + int old_pair; + NCURSES_CH_T new_char; + attr_t new_attr; + int new_pair; + + /* SVr4 trims color info if non-color terminal */ + if (!SP->_pair_limit) { + RemAttr(new_bkgd, A_COLOR); + SetPair(new_bkgd, 0); + } + + /* avoid setting background-character to a null */ + if (CharOf(new_bkgd) == 0) { + NCURSES_CH_T tmp_bkgd = blank; + SetAttr(tmp_bkgd, AttrOf(new_bkgd)); + SetPair(tmp_bkgd, GetPair(new_bkgd)); + new_bkgd = tmp_bkgd; + } + + memset(&old_bkgd, 0, sizeof(old_bkgd)); + (void) wgetbkgrnd(win, &old_bkgd); + + if (!memcmp(&old_bkgd, &new_bkgd, sizeof(new_bkgd))) { + T(("...unchanged")); + returnCode(OK); + } + + old_char = old_bkgd; + RemAttr(old_char, ~A_CHARTEXT); + old_attr = AttrOf(old_bkgd); + old_pair = GetPair(old_bkgd); + + if (!(old_attr & A_COLOR)) { + old_pair = 0; + } + T(("... old background char %s, attr %s, pair %d", + TraceChar(old_char), _traceattr(old_attr), old_pair)); - wbkgrndset(win, CHREF(new_bkgd)); - wattrset(win, AttrOf(win->_nc_bkgd)); + new_char = new_bkgd; + RemAttr(new_char, ~A_CHARTEXT); + new_attr = AttrOf(new_bkgd); + new_pair = GetPair(new_bkgd); + + /* SVr4 limits background character to printable 7-bits */ + if ( +#if USE_WIDEC_SUPPORT + narrow && +#endif + !Charable(new_bkgd)) { + new_char = old_char; + } + if (!(new_attr & A_COLOR)) { + new_pair = 0; + } + T(("... new background char %s, attr %s, pair %d", + TraceChar(new_char), _traceattr(new_attr), new_pair)); + + (void) wbkgrndset(win, CHREF(new_bkgd)); + + /* SVr4 updates color pair if old/new match, otherwise just attrs */ + if ((new_pair != 0) && (new_pair == old_pair)) { + WINDOW_ATTRS(win) = new_attr; + SET_WINDOW_PAIR(win, new_pair); + } else { + WINDOW_ATTRS(win) = new_attr; + } for (y = 0; y <= win->_maxy; y++) { + int x; + for (x = 0; x <= win->_maxx; x++) { - if (CharEq(win->_line[y].text[x], old_bkgrnd)) { - win->_line[y].text[x] = win->_nc_bkgd; + NCURSES_CH_T *cp = &(win->_line[y].text[x]); + int tmp_pair = GetPair(*cp); + attr_t tmp_attr = AttrOf(*cp); + + if (CharEq(*cp, old_bkgd)) { +#if USE_WIDEC_SUPPORT + if (!narrow) { + if (Charable(new_bkgd)) { + SetChar2(*cp, CharOf(new_char)); + } else { + SetChar(*cp, L' ', AttrOf(new_char)); + } + memcpy(cp->chars, + new_char.chars, + CCHARW_MAX * sizeof(cp->chars[0])); + } else +#endif + SetChar2(*cp, CharOf(new_char)); + } + if (tmp_pair != 0) { + if (tmp_pair == old_pair) { + SetAttr(*cp, (tmp_attr & ~old_attr) | new_attr); + SetPair(*cp, new_pair); + } else { + SetAttr(*cp, + (tmp_attr & (~old_attr | A_COLOR)) + | (new_attr & ALL_BUT_COLOR)); + } } else { - NCURSES_CH_T wch = win->_line[y].text[x]; - RemAttr(wch, (~(A_ALTCHARSET | A_CHARTEXT))); - win->_line[y].text[x] = _nc_render(win, wch); + SetAttr(*cp, (tmp_attr & ~old_attr) | new_attr); + SetPair(*cp, new_pair); } } } @@ -149,10 +258,18 @@ wbkgrnd(WINDOW *win, const ARG_CH_T ch) returnCode(code); } +#if USE_WIDEC_SUPPORT +NCURSES_EXPORT(int) +wbkgrnd(WINDOW *win, const ARG_CH_T ch) +{ + return _nc_background(win, ch, FALSE); +} +#endif + NCURSES_EXPORT(int) wbkgd(WINDOW *win, chtype ch) { NCURSES_CH_T wch; SetChar2(wch, ch); - return wbkgrnd(win, CHREF(wch)); + return _nc_background(win, CHREF(wch), TRUE); } diff --git a/lib/libcurses/base/lib_box.c b/lib/libcurses/base/lib_box.c index 6676b3b58a6..220bd1f156a 100644 --- a/lib/libcurses/base/lib_box.c +++ b/lib/libcurses/base/lib_box.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_box.c,v 1.4 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_box.c,v 1.5 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2002,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2010,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -44,7 +45,7 @@ #include -MODULE_ID("$Id: lib_box.c,v 1.4 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_box.c,v 1.5 2023/10/17 09:52:08 nicm Exp $") #if USE_WIDEC_SUPPORT static NCURSES_INLINE chtype @@ -53,8 +54,9 @@ _my_render(WINDOW *win, chtype ch) NCURSES_CH_T wch; SetChar2(wch, ch); wch = _nc_render(win, wch); - return CharOf(wch) | AttrOf(wch); + return ((attr_t) CharOf(wch)) | AttrOf(wch); } + #define RENDER_WITH_DEFAULT(ch,def) w ## ch = _my_render(win, (ch == 0) ? def : ch) #else #define RENDER_WITH_DEFAULT(ch,def) w ## ch = _nc_render(win, (ch == 0) ? def : ch) @@ -72,7 +74,7 @@ wborder(WINDOW *win, chtype wls, wrs, wts, wbs, wtl, wtr, wbl, wbr; T((T_CALLED("wborder(%p,%s,%s,%s,%s,%s,%s,%s,%s)"), - win, + (void *) win, _tracechtype2(1, ls), _tracechtype2(2, rs), _tracechtype2(3, ts), @@ -115,10 +117,20 @@ wborder(WINDOW *win, win->_line[endy].lastchar = win->_line[0].lastchar = endx; for (i = 0; i <= endy; i++) { +#if USE_WIDEC_SUPPORT + if (endx > 0 && isWidecExt(win->_line[i].text[endx])) { + SetChar2(win->_line[i].text[endx - 1], ' '); + } +#endif SetChar2(win->_line[i].text[0], wls); SetChar2(win->_line[i].text[endx], wrs); win->_line[i].firstchar = 0; win->_line[i].lastchar = endx; +#if USE_WIDEC_SUPPORT + if (isWidecExt(win->_line[i].text[1])) { + SetChar2(win->_line[i].text[1], ' '); + } +#endif } SetChar2(win->_line[0].text[0], wtl); SetChar2(win->_line[0].text[endx], wtr); diff --git a/lib/libcurses/base/lib_chgat.c b/lib/libcurses/base/lib_chgat.c index 5762785c207..8b69812e505 100644 --- a/lib/libcurses/base/lib_chgat.c +++ b/lib/libcurses/base/lib_chgat.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_chgat.c,v 1.3 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_chgat.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -44,27 +45,38 @@ #include -MODULE_ID("$Id: lib_chgat.c,v 1.3 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_chgat.c,v 1.4 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) -wchgat(WINDOW *win, int n, attr_t attr, short color, const void *opts GCC_UNUSED) +wchgat(WINDOW *win, + int n, + attr_t attr, + NCURSES_PAIRS_T pair_arg, + const void *opts GCC_UNUSED) { - int i; + int code = ERR; + int color_pair = pair_arg; - T((T_CALLED("wchgat(%p,%d,%s,%d)"), win, n, _traceattr(attr), color)); + T((T_CALLED("wchgat(%p,%d,%s,%d)"), + (void *) win, + n, + _traceattr(attr), + color_pair)); + set_extended_pair(opts, color_pair); if (win) { struct ldat *line = &(win->_line[win->_cury]); + int i; - toggle_attr_on(attr, COLOR_PAIR(color)); + toggle_attr_on(attr, ColorPair(color_pair)); for (i = win->_curx; i <= win->_maxx && (n == -1 || (n-- > 0)); i++) { SetAttr(line->text[i], attr); - SetPair(line->text[i], color); + SetPair(line->text[i], color_pair); CHANGED_CELL(line, i); } - returnCode(OK); - } else - returnCode(ERR); + code = OK; + } + returnCode(code); } diff --git a/lib/libcurses/base/lib_clear.c b/lib/libcurses/base/lib_clear.c index 10dab985fbc..e5130a14356 100644 --- a/lib/libcurses/base/lib_clear.c +++ b/lib/libcurses/base/lib_clear.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_clear.c,v 1.3 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_clear.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2000,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -42,14 +43,14 @@ #include -MODULE_ID("$Id: lib_clear.c,v 1.3 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_clear.c,v 1.4 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) wclear(WINDOW *win) { int code = ERR; - T((T_CALLED("wclear(%p)"), win)); + T((T_CALLED("wclear(%p)"), (void *) win)); if ((code = werase(win)) != ERR) win->_clear = TRUE; diff --git a/lib/libcurses/base/lib_clearok.c b/lib/libcurses/base/lib_clearok.c index d0746956fa6..4c7abf5452c 100644 --- a/lib/libcurses/base/lib_clearok.c +++ b/lib/libcurses/base/lib_clearok.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_clearok.c,v 1.3 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_clearok.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2000,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -42,12 +43,12 @@ #include -MODULE_ID("$Id: lib_clearok.c,v 1.3 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_clearok.c,v 1.4 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) clearok(WINDOW *win, bool flag) { - T((T_CALLED("clearok(%p,%d)"), win, flag)); + T((T_CALLED("clearok(%p,%d)"), (void *) win, flag)); if (win) { win->_clear = flag; diff --git a/lib/libcurses/base/lib_clrbot.c b/lib/libcurses/base/lib_clrbot.c index f0b86d921f1..052045cec27 100644 --- a/lib/libcurses/base/lib_clrbot.c +++ b/lib/libcurses/base/lib_clrbot.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_clrbot.c,v 1.4 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_clrbot.c,v 1.5 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2001,2006 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2006,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -42,14 +43,14 @@ #include -MODULE_ID("$Id: lib_clrbot.c,v 1.4 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_clrbot.c,v 1.5 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) wclrtobot(WINDOW *win) { int code = ERR; - T((T_CALLED("wclrtobot(%p)"), win)); + T((T_CALLED("wclrtobot(%p)"), (void *) win)); if (win) { NCURSES_SIZE_T y; diff --git a/lib/libcurses/base/lib_clreol.c b/lib/libcurses/base/lib_clreol.c index 2b9a48bf417..d5a72b8e24f 100644 --- a/lib/libcurses/base/lib_clreol.c +++ b/lib/libcurses/base/lib_clreol.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_clreol.c,v 1.4 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_clreol.c,v 1.5 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,1999,2000,2001 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2001,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -42,14 +43,14 @@ #include -MODULE_ID("$Id: lib_clreol.c,v 1.4 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_clreol.c,v 1.5 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) wclrtoeol(WINDOW *win) { int code = ERR; - T((T_CALLED("wclrtoeol(%p)"), win)); + T((T_CALLED("wclrtoeol(%p)"), (void *) win)); if (win) { NCURSES_CH_T blank; @@ -62,7 +63,7 @@ wclrtoeol(WINDOW *win) * If we have just wrapped the cursor, the clear applies to the * new line, unless we are at the lower right corner. */ - if ((win->_flags & _WRAPPED) != 0 + if (IS_WRAPPED(win) != 0 && y < win->_maxy) { win->_flags &= ~_WRAPPED; } @@ -71,7 +72,7 @@ wclrtoeol(WINDOW *win) * There's no point in clearing if we're not on a legal * position, either. */ - if ((win->_flags & _WRAPPED) != 0 + if (IS_WRAPPED(win) || y > win->_maxy || x > win->_maxx) returnCode(ERR); diff --git a/lib/libcurses/base/lib_color.c b/lib/libcurses/base/lib_color.c index d1c4ce7f0d5..dd31003dea1 100644 --- a/lib/libcurses/base/lib_color.c +++ b/lib/libcurses/base/lib_color.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_color.c,v 1.11 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_color.c,v 1.12 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * + * Copyright 2018-2021,2022 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,6 +33,7 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* lib_color.c @@ -39,13 +41,37 @@ * Handles color emulation of SYS V curses */ -#include +#define NEW_PAIR_INTERNAL 1 -#include +#include +#include #include -MODULE_ID("$Id: lib_color.c,v 1.11 2010/01/12 23:22:05 nicm Exp $") +#ifndef CUR +#define CUR SP_TERMTYPE +#endif + +MODULE_ID("$Id: lib_color.c,v 1.12 2023/10/17 09:52:08 nicm Exp $") +#ifdef USE_TERM_DRIVER +#define CanChange InfoOf(SP_PARM).canchange +#define DefaultPalette InfoOf(SP_PARM).defaultPalette +#define HasColor InfoOf(SP_PARM).hascolor +#define InitColor InfoOf(SP_PARM).initcolor +#define MaxColors InfoOf(SP_PARM).maxcolors +#define MaxPairs InfoOf(SP_PARM).maxpairs +#define UseHlsPalette (DefaultPalette == _nc_hls_palette) +#else +#define CanChange can_change +#define DefaultPalette (hue_lightness_saturation ? hls_palette : cga_palette) +#define HasColor has_color +#define InitColor initialize_color +#define MaxColors max_colors +#define MaxPairs max_pairs +#define UseHlsPalette (hue_lightness_saturation) +#endif + +#ifndef USE_TERM_DRIVER /* * These should be screen structure members. They need to be globals for * historical reasons. So we assign them in start_color() and also in @@ -66,14 +92,13 @@ NCURSES_PUBLIC_VAR(COLORS) (void) NCURSES_EXPORT_VAR(int) COLOR_PAIRS = 0; NCURSES_EXPORT_VAR(int) COLORS = 0; #endif +#endif /* !USE_TERM_DRIVER */ #define DATA(r,g,b) {r,g,b, 0,0,0, 0} -#define TYPE_CALLOC(type,elts) typeCalloc(type, (unsigned)(elts)) - #define MAX_PALETTE 8 -#define OkColorHi(n) (((n) < COLORS) && ((n) < max_colors)) +#define OkColorHi(n) (((n) < COLORS) && ((n) < maxcolors)) #define InPalette(n) ((n) >= 0 && (n) < MAX_PALETTE) /* @@ -108,29 +133,35 @@ static const color_t hls_palette[] = DATA( 300, 50, 100), /* COLOR_CYAN */ DATA( 0, 50, 100), /* COLOR_WHITE */ }; -/* *INDENT-ON* */ +#ifdef USE_TERM_DRIVER +NCURSES_EXPORT_VAR(const color_t*) _nc_cga_palette = cga_palette; +NCURSES_EXPORT_VAR(const color_t*) _nc_hls_palette = hls_palette; +#endif + +/* *INDENT-ON* */ #if NCURSES_EXT_FUNCS /* * These are called from _nc_do_color(), which in turn is called from - * vidattr - so we have to assume that SP may be null. + * vidattr - so we have to assume that sp may be null. */ static int -default_fg(void) +default_fg(NCURSES_SP_DCL0) { - return (SP != 0) ? SP->_default_fg : COLOR_WHITE; + return (SP_PARM != 0) ? SP_PARM->_default_fg : COLOR_WHITE; } static int -default_bg(void) +default_bg(NCURSES_SP_DCL0) { - return SP != 0 ? SP->_default_bg : COLOR_BLACK; + return SP_PARM != 0 ? SP_PARM->_default_bg : COLOR_BLACK; } #else -#define default_fg() COLOR_WHITE -#define default_bg() COLOR_BLACK +#define default_fg(sp) COLOR_WHITE +#define default_bg(sp) COLOR_BLACK #endif +#ifndef USE_TERM_DRIVER /* * SVr4 curses is known to interchange color codes (1,4) and (3,6), possibly * to maintain compatibility with a pre-ANSI scheme. The same scheme is @@ -147,71 +178,148 @@ toggled_colors(int c) } return c; } +#endif static void -set_background_color(int bg, int (*outc) (int)) +set_background_color(NCURSES_SP_DCLx int bg, NCURSES_SP_OUTC outc) { +#ifdef USE_TERM_DRIVER + CallDriver_3(SP_PARM, td_color, FALSE, bg, outc); +#else if (set_a_background) { TPUTS_TRACE("set_a_background"); - tputs(TPARM_1(set_a_background, bg), 1, outc); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_1(set_a_background, bg), + 1, outc); } else { TPUTS_TRACE("set_background"); - tputs(TPARM_1(set_background, toggled_colors(bg)), 1, outc); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_1(set_background, toggled_colors(bg)), + 1, outc); } +#endif } static void -set_foreground_color(int fg, int (*outc) (int)) +set_foreground_color(NCURSES_SP_DCLx int fg, NCURSES_SP_OUTC outc) { +#ifdef USE_TERM_DRIVER + CallDriver_3(SP_PARM, td_color, TRUE, fg, outc); +#else if (set_a_foreground) { TPUTS_TRACE("set_a_foreground"); - tputs(TPARM_1(set_a_foreground, fg), 1, outc); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_1(set_a_foreground, fg), + 1, outc); } else { TPUTS_TRACE("set_foreground"); - tputs(TPARM_1(set_foreground, toggled_colors(fg)), 1, outc); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_1(set_foreground, toggled_colors(fg)), + 1, outc); } +#endif } static void -init_color_table(void) +init_color_table(NCURSES_SP_DCL0) { - const color_t *tp; + const color_t *tp = DefaultPalette; int n; - tp = (hue_lightness_saturation) ? hls_palette : cga_palette; + assert(tp != 0); + for (n = 0; n < COLORS; n++) { if (InPalette(n)) { - SP->_color_table[n] = tp[n]; + SP_PARM->_color_table[n] = tp[n]; } else { - SP->_color_table[n] = tp[n % MAX_PALETTE]; - if (hue_lightness_saturation) { - SP->_color_table[n].green = 100; + SP_PARM->_color_table[n] = tp[n % MAX_PALETTE]; + if (UseHlsPalette) { + SP_PARM->_color_table[n].green = 100; } else { - if (SP->_color_table[n].red) - SP->_color_table[n].red = 1000; - if (SP->_color_table[n].green) - SP->_color_table[n].green = 1000; - if (SP->_color_table[n].blue) - SP->_color_table[n].blue = 1000; + if (SP_PARM->_color_table[n].red) + SP_PARM->_color_table[n].red = 1000; + if (SP_PARM->_color_table[n].green) + SP_PARM->_color_table[n].green = 1000; + if (SP_PARM->_color_table[n].blue) + SP_PARM->_color_table[n].blue = 1000; + } + } + } +} + +static bool +init_direct_colors(NCURSES_SP_DCL0) +{ + static NCURSES_CONST char name[] = "RGB"; + + rgb_bits_t *result = &(SP_PARM->_direct_color); + + result->value = 0; + + if (COLORS >= 8) { + int n; + const char *s; + int width; + + /* find the number of bits needed for the maximum color value */ + for (width = 0; (1 << width) - 1 < (COLORS - 1); ++width) { + ; + } + + if (tigetflag(name) > 0) { + n = (width + 2) / 3; + result->bits.red = UChar(n); + result->bits.green = UChar(n); + result->bits.blue = UChar(width - (2 * n)); + } else if ((n = tigetnum(name)) > 0) { + result->bits.red = UChar(n); + result->bits.green = UChar(n); + result->bits.blue = UChar(n); + } else if ((s = tigetstr(name)) != 0 && VALID_STRING(s)) { + int red = n; + int green = n; + int blue = width - (2 * n); + + switch (sscanf(s, "%d/%d/%d", &red, &green, &blue)) { + default: + blue = width - (2 * n); + /* FALLTHRU */ + case 1: + green = n; + /* FALLTHRU */ + case 2: + red = n; + /* FALLTHRU */ + case 3: + /* okay */ + break; } + result->bits.red = UChar(red); + result->bits.green = UChar(green); + result->bits.blue = UChar(blue); } } + return (result->value != 0); } /* * Reset the color pair, e.g., to whatever color pair 0 is. */ static bool -reset_color_pair(void) +reset_color_pair(NCURSES_SP_DCL0) { +#ifdef USE_TERM_DRIVER + return CallDriver(SP_PARM, td_rescol); +#else bool result = FALSE; + (void) SP_PARM; if (orig_pair != 0) { - TPUTS_TRACE("orig_pair"); - putp(orig_pair); + (void) NCURSES_PUTP2("orig_pair", orig_pair); result = TRUE; } return result; +#endif } /* @@ -219,65 +327,108 @@ reset_color_pair(void) * badly-written terminal descriptions than for the relatively rare case where * someone has changed the color definitions. */ -bool -_nc_reset_colors(void) +NCURSES_EXPORT(bool) +NCURSES_SP_NAME(_nc_reset_colors) (NCURSES_SP_DCL0) { int result = FALSE; - T((T_CALLED("_nc_reset_colors()"))); - if (SP->_color_defs > 0) - SP->_color_defs = -(SP->_color_defs); - - if (reset_color_pair()) + T((T_CALLED("_nc_reset_colors(%p)"), (void *) SP_PARM)); + if (SP_PARM->_color_defs > 0) + SP_PARM->_color_defs = -(SP_PARM->_color_defs); + if (reset_color_pair(NCURSES_SP_ARG)) result = TRUE; + +#ifdef USE_TERM_DRIVER + result = CallDriver(SP_PARM, td_rescolors); +#else if (orig_colors != 0) { - TPUTS_TRACE("orig_colors"); - putp(orig_colors); + NCURSES_PUTP2("orig_colors", orig_colors); result = TRUE; } +#endif returnBool(result); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(bool) +_nc_reset_colors(void) +{ + return NCURSES_SP_NAME(_nc_reset_colors) (CURRENT_SCREEN); +} +#endif + NCURSES_EXPORT(int) -start_color(void) +NCURSES_SP_NAME(start_color) (NCURSES_SP_DCL0) { int result = ERR; - T((T_CALLED("start_color()"))); + T((T_CALLED("start_color(%p)"), (void *) SP_PARM)); - if (SP == 0) { + if (SP_PARM == 0) { result = ERR; - } else if (SP->_coloron) { + } else if (SP_PARM->_coloron) { result = OK; } else { - - if (reset_color_pair() != TRUE) { - set_foreground_color(default_fg(), _nc_outch); - set_background_color(default_bg(), _nc_outch); + int maxpairs = MaxPairs; + int maxcolors = MaxColors; + if (reset_color_pair(NCURSES_SP_ARG) != TRUE) { + set_foreground_color(NCURSES_SP_ARGx + default_fg(NCURSES_SP_ARG), + NCURSES_SP_NAME(_nc_outch)); + set_background_color(NCURSES_SP_ARGx + default_bg(NCURSES_SP_ARG), + NCURSES_SP_NAME(_nc_outch)); } +#if !NCURSES_EXT_COLORS + /* + * Without ext-colors, we cannot represent more than 256 color pairs. + */ + if (maxpairs > 256) + maxpairs = 256; +#endif - if (max_pairs > 0 && max_colors > 0) { - SP->_pair_count = max_pairs; - SP->_color_count = max_colors; + if (maxpairs > 0 && maxcolors > 0) { + SP_PARM->_pair_limit = maxpairs; + +#if NCURSES_EXT_FUNCS + /* + * If using default colors, allocate extra space in table to + * allow for default-color as a component of a color-pair. + */ + SP_PARM->_pair_limit += (1 + (2 * maxcolors)); +#if !NCURSES_EXT_COLORS + SP_PARM->_pair_limit = limit_PAIRS(SP_PARM->_pair_limit); +#endif +#endif /* NCURSES_EXT_FUNCS */ + SP_PARM->_pair_count = maxpairs; + SP_PARM->_color_count = maxcolors; #if !USE_REENTRANT - COLOR_PAIRS = max_pairs; - COLORS = max_colors; + COLOR_PAIRS = maxpairs; + COLORS = maxcolors; #endif - if ((SP->_color_pairs = TYPE_CALLOC(colorpair_t, - max_pairs)) != 0) { - if ((SP->_color_table = TYPE_CALLOC(color_t, - max_colors)) != 0) { - SP->_color_pairs[0] = PAIR_OF(default_fg(), default_bg()); - init_color_table(); - + ReservePairs(SP_PARM, 16); + if (SP_PARM->_color_pairs != 0) { + if (init_direct_colors(NCURSES_SP_ARG)) { + result = OK; + } else { + TYPE_CALLOC(color_t, maxcolors, SP_PARM->_color_table); + if (SP_PARM->_color_table != 0) { + MakeColorPair(SP_PARM->_color_pairs[0], + default_fg(NCURSES_SP_ARG), + default_bg(NCURSES_SP_ARG)); + init_color_table(NCURSES_SP_ARG); + + result = OK; + } + } + if (result == OK) { T(("started color: COLORS = %d, COLOR_PAIRS = %d", COLORS, COLOR_PAIRS)); - SP->_coloron = 1; - result = OK; - } else if (SP->_color_pairs != 0) { - FreeAndNull(SP->_color_pairs); + SP_PARM->_coloron = 1; + } else if (SP_PARM->_color_pairs != 0) { + FreeAndNull(SP_PARM->_color_pairs); } } } else { @@ -287,12 +438,20 @@ start_color(void) returnCode(result); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +start_color(void) +{ + return NCURSES_SP_NAME(start_color) (CURRENT_SCREEN); +} +#endif + /* This function was originally written by Daniel Weaver */ static void -rgb2hls(short r, short g, short b, short *h, short *l, short *s) +rgb2hls(int r, int g, int b, int *h, int *l, int *s) /* convert RGB to HLS system */ { - short min, max, t; + int min, max, t; if ((min = g < r ? g : r) > b) min = b; @@ -300,7 +459,7 @@ rgb2hls(short r, short g, short b, short *h, short *l, short *s) max = b; /* calculate lightness */ - *l = (min + max) / 20; + *l = ((min + max) / 20); if (min == max) { /* black, white and all shades of gray */ *h = 0; @@ -310,19 +469,88 @@ rgb2hls(short r, short g, short b, short *h, short *l, short *s) /* calculate saturation */ if (*l < 50) - *s = ((max - min) * 100) / (max + min); + *s = (((max - min) * 100) / (max + min)); else - *s = ((max - min) * 100) / (2000 - max - min); + *s = (((max - min) * 100) / (2000 - max - min)); /* calculate hue */ if (r == max) - t = 120 + ((g - b) * 60) / (max - min); + t = (120 + ((g - b) * 60) / (max - min)); else if (g == max) - t = 240 + ((b - r) * 60) / (max - min); + t = (240 + ((b - r) * 60) / (max - min)); else - t = 360 + ((r - g) * 60) / (max - min); + t = (360 + ((r - g) * 60) / (max - min)); + + *h = (t % 360); +} + +/* + * Change all cells which use(d) a given color pair to force a repaint. + */ +NCURSES_EXPORT(void) +_nc_change_pair(SCREEN *sp, int pair) +{ + int y, x; + + if (CurScreen(sp)->_clear) + return; +#if NO_LEAKS + if (_nc_globals.leak_checking) + return; +#endif + + for (y = 0; y <= CurScreen(sp)->_maxy; y++) { + struct ldat *ptr = &(CurScreen(sp)->_line[y]); + bool changed = FALSE; + for (x = 0; x <= CurScreen(sp)->_maxx; x++) { + if (GetPair(ptr->text[x]) == pair) { + /* Set the old cell to zero to ensure it will be + updated on the next doupdate() */ + SetChar(ptr->text[x], 0, 0); + CHANGED_CELL(ptr, x); + changed = TRUE; + } + } + if (changed) + NCURSES_SP_NAME(_nc_make_oldhash) (NCURSES_SP_ARGx y); + } +} - *h = t % 360; +NCURSES_EXPORT(void) +_nc_reserve_pairs(SCREEN *sp, int want) +{ + int have = sp->_pair_alloc; + + if (have == 0) + have = 1; + while (have <= want) + have *= 2; + if (have > sp->_pair_limit) + have = sp->_pair_limit; + + if (sp->_color_pairs == 0) { + TYPE_CALLOC(colorpair_t, have, sp->_color_pairs); + } else if (have > sp->_pair_alloc) { +#if NCURSES_EXT_COLORS + colorpair_t *next; + + if ((next = typeCalloc(colorpair_t, have)) == 0) + _nc_err_abort(MSG_NO_MEMORY); + memcpy(next, sp->_color_pairs, (size_t) sp->_pair_alloc * sizeof(*next)); + _nc_copy_pairs(sp, next, sp->_color_pairs, sp->_pair_alloc); + free(sp->_color_pairs); + sp->_color_pairs = next; +#else + TYPE_REALLOC(colorpair_t, have, sp->_color_pairs); + if (sp->_color_pairs != 0) { + memset(sp->_color_pairs + sp->_pair_alloc, 0, + sizeof(colorpair_t) * (size_t) (have - sp->_pair_alloc)); + } +#endif + } + if (sp->_color_pairs != 0) { + sp->_pair_alloc = have; + } } /* @@ -330,31 +558,85 @@ rgb2hls(short r, short g, short b, short *h, short *l, short *s) * values. */ NCURSES_EXPORT(int) -init_pair(short pair, short f, short b) +_nc_init_pair(SCREEN *sp, int pair, int f, int b) { - colorpair_t result; + static colorpair_t null_pair; + colorpair_t result = null_pair; + colorpair_t previous; + int maxcolors; - T((T_CALLED("init_pair(%d,%d,%d)"), pair, f, b)); + T((T_CALLED("init_pair(%p,%d,%d,%d)"), (void *) sp, pair, f, b)); - if ((pair < 0) || (pair >= COLOR_PAIRS) || SP == 0 || !SP->_coloron) + if (!ValidPair(sp, pair)) returnCode(ERR); + + maxcolors = MaxColors; + + ReservePairs(sp, pair); + previous = sp->_color_pairs[pair]; #if NCURSES_EXT_FUNCS - if (SP->_default_color) { - if (f < 0) + if (sp->_default_color || sp->_assumed_color) { + bool isDefault = FALSE; + bool wasDefault = FALSE; + int default_pairs = sp->_default_pairs; + + /* + * Map caller's color number, e.g., -1, 0, 1, .., 7, etc., into + * internal unsigned values which we will store in the _color_pairs[] + * table. + */ + if (isDefaultColor(f)) { f = COLOR_DEFAULT; - if (b < 0) + isDefault = TRUE; + } else if (!OkColorHi(f)) { + returnCode(ERR); + } + + if (isDefaultColor(b)) { b = COLOR_DEFAULT; - if (!OkColorHi(f) && !isDefaultColor(f)) + isDefault = TRUE; + } else if (!OkColorHi(b)) { returnCode(ERR); - if (!OkColorHi(b) && !isDefaultColor(b)) + } + + /* + * Check if the table entry that we are going to init/update used + * default colors. + */ + if (isDefaultColor(FORE_OF(previous)) + || isDefaultColor(BACK_OF(previous))) + wasDefault = TRUE; + + /* + * Keep track of the number of entries in the color pair table which + * used a default color. + */ + if (isDefault && !wasDefault) { + ++default_pairs; + } else if (wasDefault && !isDefault) { + --default_pairs; + } + + /* + * As an extension, ncurses allows the pair number to exceed the + * terminal's color_pairs value for pairs using a default color. + * + * Note that updating a pair which used a default color with one + * that does not will decrement the count - and possibly interfere + * with sequentially adding new pairs. + */ + if (pair > (sp->_pair_count + default_pairs)) { returnCode(ERR); + } + sp->_default_pairs = default_pairs; } else #endif { if ((f < 0) || !OkColorHi(f) || (b < 0) || !OkColorHi(b) - || (pair < 1)) + || (pair < 1)) { returnCode(ERR); + } } /* @@ -362,152 +644,308 @@ init_pair(short pair, short f, short b) * initialized before a screen update is performed replacing original * pair colors with the new ones). */ - result = PAIR_OF(f, b); - if (SP->_color_pairs[pair] != 0 - && SP->_color_pairs[pair] != result) { - int y, x; - - for (y = 0; y <= curscr->_maxy; y++) { - struct ldat *ptr = &(curscr->_line[y]); - bool changed = FALSE; - for (x = 0; x <= curscr->_maxx; x++) { - if (GetPair(ptr->text[x]) == pair) { - /* Set the old cell to zero to ensure it will be - updated on the next doupdate() */ - SetChar(ptr->text[x], 0, 0); - CHANGED_CELL(ptr, x); - changed = TRUE; - } - } - if (changed) - _nc_make_oldhash(y); - } + MakeColorPair(result, f, b); + if ((FORE_OF(previous) != 0 + || BACK_OF(previous) != 0) + && !isSamePair(previous, result)) { + _nc_change_pair(sp, pair); } - SP->_color_pairs[pair] = result; - if (GET_SCREEN_PAIR(SP) == pair) - SET_SCREEN_PAIR(SP, (chtype) (~0)); /* force attribute update */ + _nc_reset_color_pair(sp, pair, &result); + sp->_color_pairs[pair] = result; + _nc_set_color_pair(sp, pair, cpINIT); + + if (GET_SCREEN_PAIR(sp) == pair) + SET_SCREEN_PAIR(sp, (int) (~0)); /* force attribute update */ + +#ifdef USE_TERM_DRIVER + CallDriver_3(sp, td_initpair, pair, f, b); +#else if (initialize_pair && InPalette(f) && InPalette(b)) { - const color_t *tp = hue_lightness_saturation ? hls_palette : cga_palette; + const color_t *tp = DefaultPalette; TR(TRACE_ATTRS, ("initializing pair: pair = %d, fg=(%d,%d,%d), bg=(%d,%d,%d)", - pair, - tp[f].red, tp[f].green, tp[f].blue, - tp[b].red, tp[b].green, tp[b].blue)); - - TPUTS_TRACE("initialize_pair"); - putp(TPARM_7(initialize_pair, - pair, - tp[f].red, tp[f].green, tp[f].blue, - tp[b].red, tp[b].green, tp[b].blue)); + (int) pair, + (int) tp[f].red, (int) tp[f].green, (int) tp[f].blue, + (int) tp[b].red, (int) tp[b].green, (int) tp[b].blue)); + + NCURSES_PUTP2("initialize_pair", + TIPARM_7(initialize_pair, + pair, + (int) tp[f].red, + (int) tp[f].green, + (int) tp[f].blue, + (int) tp[b].red, + (int) tp[b].green, + (int) tp[b].blue)); } +#endif returnCode(OK); } +NCURSES_EXPORT(int) +NCURSES_SP_NAME(init_pair) (NCURSES_SP_DCLx + NCURSES_PAIRS_T pair, + NCURSES_COLOR_T f, + NCURSES_COLOR_T b) +{ + return _nc_init_pair(SP_PARM, pair, f, b); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +init_pair(NCURSES_COLOR_T pair, NCURSES_COLOR_T f, NCURSES_COLOR_T b) +{ + return NCURSES_SP_NAME(init_pair) (CURRENT_SCREEN, pair, f, b); +} +#endif + #define okRGB(n) ((n) >= 0 && (n) <= 1000) NCURSES_EXPORT(int) -init_color(short color, short r, short g, short b) +_nc_init_color(SCREEN *sp, int color, int r, int g, int b) { int result = ERR; + int maxcolors; + + T((T_CALLED("init_color(%p,%d,%d,%d,%d)"), + (void *) sp, + color, + r, g, b)); - T((T_CALLED("init_color(%d,%d,%d,%d)"), color, r, g, b)); + if (sp == 0 || sp->_direct_color.value) + returnCode(result); - if (initialize_color != NULL - && SP != 0 - && SP->_coloron + maxcolors = MaxColors; + + if (InitColor + && sp->_coloron && (color >= 0 && OkColorHi(color)) && (okRGB(r) && okRGB(g) && okRGB(b))) { - SP->_color_table[color].init = 1; - SP->_color_table[color].r = r; - SP->_color_table[color].g = g; - SP->_color_table[color].b = b; + sp->_color_table[color].init = 1; + sp->_color_table[color].r = r; + sp->_color_table[color].g = g; + sp->_color_table[color].b = b; - if (hue_lightness_saturation) { + if (UseHlsPalette) { rgb2hls(r, g, b, - &SP->_color_table[color].red, - &SP->_color_table[color].green, - &SP->_color_table[color].blue); + &sp->_color_table[color].red, + &sp->_color_table[color].green, + &sp->_color_table[color].blue); } else { - SP->_color_table[color].red = r; - SP->_color_table[color].green = g; - SP->_color_table[color].blue = b; + sp->_color_table[color].red = r; + sp->_color_table[color].green = g; + sp->_color_table[color].blue = b; } - TPUTS_TRACE("initialize_color"); - putp(TPARM_4(initialize_color, color, r, g, b)); - SP->_color_defs = max(color + 1, SP->_color_defs); +#ifdef USE_TERM_DRIVER + CallDriver_4(sp, td_initcolor, color, r, g, b); +#else + NCURSES_PUTP2("initialize_color", + TIPARM_4(initialize_color, color, r, g, b)); +#endif + sp->_color_defs = max(color + 1, sp->_color_defs); + result = OK; } returnCode(result); } +NCURSES_EXPORT(int) +NCURSES_SP_NAME(init_color) (NCURSES_SP_DCLx + NCURSES_COLOR_T color, + NCURSES_COLOR_T r, + NCURSES_COLOR_T g, + NCURSES_COLOR_T b) +{ + return _nc_init_color(SP_PARM, color, r, g, b); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +init_color(NCURSES_COLOR_T color, + NCURSES_COLOR_T r, + NCURSES_COLOR_T g, + NCURSES_COLOR_T b) +{ + return NCURSES_SP_NAME(init_color) (CURRENT_SCREEN, color, r, g, b); +} +#endif + +NCURSES_EXPORT(bool) +NCURSES_SP_NAME(can_change_color) (NCURSES_SP_DCL) +{ + int result = FALSE; + + T((T_CALLED("can_change_color(%p)"), (void *) SP_PARM)); + + if (HasTerminal(SP_PARM) && (CanChange != 0)) { + result = TRUE; + } + + returnCode(result); +} + +#if NCURSES_SP_FUNCS NCURSES_EXPORT(bool) can_change_color(void) { - T((T_CALLED("can_change_color()"))); - returnCode((can_change != 0) ? TRUE : FALSE); + return NCURSES_SP_NAME(can_change_color) (CURRENT_SCREEN); } +#endif +NCURSES_EXPORT(bool) +NCURSES_SP_NAME(has_colors) (NCURSES_SP_DCL0) +{ + int code = FALSE; + + (void) SP_PARM; + T((T_CALLED("has_colors(%p)"), (void *) SP_PARM)); + if (HasTerminal(SP_PARM)) { +#ifdef USE_TERM_DRIVER + code = HasColor; +#else + code = ((VALID_NUMERIC(max_colors) && VALID_NUMERIC(max_pairs) + && (((set_foreground != NULL) + && (set_background != NULL)) + || ((set_a_foreground != NULL) + && (set_a_background != NULL)) + || set_color_pair)) ? TRUE : FALSE); +#endif + } + returnCode(code); +} + +#if NCURSES_SP_FUNCS NCURSES_EXPORT(bool) has_colors(void) { - T((T_CALLED("has_colors()"))); - returnCode((VALID_NUMERIC(max_colors) && VALID_NUMERIC(max_pairs) - && (((set_foreground != NULL) - && (set_background != NULL)) - || ((set_a_foreground != NULL) - && (set_a_background != NULL)) - || set_color_pair)) ? TRUE : FALSE); + return NCURSES_SP_NAME(has_colors) (CURRENT_SCREEN); } +#endif -NCURSES_EXPORT(int) -color_content(short color, short *r, short *g, short *b) +static int +_nc_color_content(SCREEN *sp, int color, int *r, int *g, int *b) { - int result; + int result = ERR; - T((T_CALLED("color_content(%d,%p,%p,%p)"), color, r, g, b)); - if (color < 0 || !OkColorHi(color) || SP == 0 || !SP->_coloron) { - result = ERR; - } else { - NCURSES_COLOR_T c_r = SP->_color_table[color].red; - NCURSES_COLOR_T c_g = SP->_color_table[color].green; - NCURSES_COLOR_T c_b = SP->_color_table[color].blue; + T((T_CALLED("color_content(%p,%d,%p,%p,%p)"), + (void *) sp, + color, + (void *) r, + (void *) g, + (void *) b)); + + if (sp != 0) { + int maxcolors = MaxColors; + + if (color >= 0 && OkColorHi(color) && sp->_coloron) { + int c_r, c_g, c_b; + + if (sp->_direct_color.value) { + rgb_bits_t *work = &(sp->_direct_color); + +#define max_direct_color(name) ((1 << work->bits.name) - 1) +#define value_direct_color(max) (1000 * ((color >> bitoff) & max)) / max + + int max_r = max_direct_color(red); + int max_g = max_direct_color(green); + int max_b = max_direct_color(blue); + + int bitoff = 0; + + c_b = value_direct_color(max_b); + bitoff += work->bits.blue; + + c_g = value_direct_color(max_g); + bitoff += work->bits.green; + + c_r = value_direct_color(max_r); + + } else { + c_r = sp->_color_table[color].red; + c_g = sp->_color_table[color].green; + c_b = sp->_color_table[color].blue; + } + if (r) + *r = c_r; + if (g) + *g = c_g; + if (b) + *b = c_b; + + TR(TRACE_ATTRS, ("...color_content(%d,%d,%d,%d)", + color, c_r, c_g, c_b)); + result = OK; + } + } + if (result != OK) { if (r) - *r = c_r; + *r = 0; if (g) - *g = c_g; + *g = 0; if (b) - *b = c_b; - - TR(TRACE_ATTRS, ("...color_content(%d,%d,%d,%d)", - color, c_r, c_g, c_b)); - result = OK; + *b = 0; } returnCode(result); } NCURSES_EXPORT(int) -pair_content(short pair, short *f, short *b) +NCURSES_SP_NAME(color_content) (NCURSES_SP_DCLx + NCURSES_COLOR_T color, + NCURSES_COLOR_T *r, + NCURSES_COLOR_T *g, + NCURSES_COLOR_T *b) +{ + int my_r, my_g, my_b; + int rc = _nc_color_content(SP_PARM, color, &my_r, &my_g, &my_b); + if (rc == OK) { + *r = limit_COLOR(my_r); + *g = limit_COLOR(my_g); + *b = limit_COLOR(my_b); + } + return rc; +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +color_content(NCURSES_COLOR_T color, + NCURSES_COLOR_T *r, + NCURSES_COLOR_T *g, + NCURSES_COLOR_T *b) +{ + return NCURSES_SP_NAME(color_content) (CURRENT_SCREEN, color, r, g, b); +} +#endif + +NCURSES_EXPORT(int) +_nc_pair_content(SCREEN *sp, int pair, int *f, int *b) { int result; - T((T_CALLED("pair_content(%d,%p,%p)"), pair, f, b)); + T((T_CALLED("pair_content(%p,%d,%p,%p)"), + (void *) sp, + (int) pair, + (void *) f, + (void *) b)); - if ((pair < 0) || (pair >= COLOR_PAIRS) || SP == 0 || !SP->_coloron) { + if (!ValidPair(sp, pair)) { result = ERR; } else { - NCURSES_COLOR_T fg = ((SP->_color_pairs[pair] >> C_SHIFT) & C_MASK); - NCURSES_COLOR_T bg = (SP->_color_pairs[pair] & C_MASK); + int fg; + int bg; + ReservePairs(sp, pair); + fg = FORE_OF(sp->_color_pairs[pair]); + bg = BACK_OF(sp->_color_pairs[pair]); #if NCURSES_EXT_FUNCS - if (fg == COLOR_DEFAULT) + if (isDefaultColor(fg)) fg = -1; - if (bg == COLOR_DEFAULT) + if (isDefaultColor(bg)) bg = -1; #endif @@ -516,34 +954,71 @@ pair_content(short pair, short *f, short *b) if (b) *b = bg; - TR(TRACE_ATTRS, ("...pair_content(%d,%d,%d)", pair, fg, bg)); + TR(TRACE_ATTRS, ("...pair_content(%p,%d,%d,%d)", + (void *) sp, + (int) pair, + (int) fg, (int) bg)); result = OK; } returnCode(result); } +NCURSES_EXPORT(int) +NCURSES_SP_NAME(pair_content) (NCURSES_SP_DCLx + NCURSES_PAIRS_T pair, + NCURSES_COLOR_T *f, + NCURSES_COLOR_T *b) +{ + int my_f, my_b; + int rc = _nc_pair_content(SP_PARM, pair, &my_f, &my_b); + if (rc == OK) { + *f = limit_COLOR(my_f); + *b = limit_COLOR(my_b); + } + return rc; +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +pair_content(NCURSES_COLOR_T pair, NCURSES_COLOR_T *f, NCURSES_COLOR_T *b) +{ + return NCURSES_SP_NAME(pair_content) (CURRENT_SCREEN, pair, f, b); +} +#endif + NCURSES_EXPORT(void) -_nc_do_color(short old_pair, short pair, bool reverse, int (*outc) (int)) +NCURSES_SP_NAME(_nc_do_color) (NCURSES_SP_DCLx + int old_pair, + int pair, + int reverse, + NCURSES_SP_OUTC outc) { - NCURSES_COLOR_T fg = COLOR_DEFAULT; - NCURSES_COLOR_T bg = COLOR_DEFAULT; - NCURSES_COLOR_T old_fg, old_bg; +#ifdef USE_TERM_DRIVER + CallDriver_4(SP_PARM, td_docolor, old_pair, pair, reverse, outc); +#else + int fg = COLOR_DEFAULT; + int bg = COLOR_DEFAULT; + int old_fg = -1; + int old_bg = -1; - if (pair < 0 || pair >= COLOR_PAIRS) { + if (!ValidPair(SP_PARM, pair)) { return; } else if (pair != 0) { if (set_color_pair) { TPUTS_TRACE("set_color_pair"); - tputs(TPARM_1(set_color_pair, pair), 1, outc); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_1(set_color_pair, pair), + 1, outc); return; - } else if (SP != 0) { - pair_content((short) pair, &fg, &bg); + } else if (SP_PARM != 0) { + if (_nc_pair_content(SP_PARM, pair, &fg, &bg) == ERR) + return; } } if (old_pair >= 0 - && SP != 0 - && pair_content(old_pair, &old_fg, &old_bg) != ERR) { + && SP_PARM != 0 + && _nc_pair_content(SP_PARM, old_pair, &old_fg, &old_bg) != ERR) { if ((isDefaultColor(fg) && !isDefaultColor(old_fg)) || (isDefaultColor(bg) && !isDefaultColor(old_bg))) { #if NCURSES_EXT_FUNCS @@ -552,33 +1027,33 @@ _nc_do_color(short old_pair, short pair, bool reverse, int (*outc) (int)) * the terminal description, treat it as screen's indicator of ECMA * SGR 39 and SGR 49, and assume the two sequences are independent. */ - if (SP->_has_sgr_39_49 + if (SP_PARM->_has_sgr_39_49 && isDefaultColor(old_bg) && !isDefaultColor(old_fg)) { - tputs("\033[39m", 1, outc); - } else if (SP->_has_sgr_39_49 + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx "\033[39m", 1, outc); + } else if (SP_PARM->_has_sgr_39_49 && isDefaultColor(old_fg) && !isDefaultColor(old_bg)) { - tputs("\033[49m", 1, outc); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx "\033[49m", 1, outc); } else #endif - reset_color_pair(); + reset_color_pair(NCURSES_SP_ARG); } } else { - reset_color_pair(); - if (old_pair < 0) + reset_color_pair(NCURSES_SP_ARG); + if (old_pair < 0 && pair <= 0) return; } #if NCURSES_EXT_FUNCS if (isDefaultColor(fg)) - fg = default_fg(); + fg = default_fg(NCURSES_SP_ARG); if (isDefaultColor(bg)) - bg = default_bg(); + bg = default_bg(NCURSES_SP_ARG); #endif if (reverse) { - NCURSES_COLOR_T xx = fg; + int xx = fg; fg = bg; bg = xx; } @@ -587,9 +1062,107 @@ _nc_do_color(short old_pair, short pair, bool reverse, int (*outc) (int)) fg, bg)); if (!isDefaultColor(fg)) { - set_foreground_color(fg, outc); + set_foreground_color(NCURSES_SP_ARGx fg, outc); } if (!isDefaultColor(bg)) { - set_background_color(bg, outc); + set_background_color(NCURSES_SP_ARGx bg, outc); + } +#endif +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(void) +_nc_do_color(int old_pair, int pair, int reverse, NCURSES_OUTC outc) +{ + SetSafeOutcWrapper(outc); + NCURSES_SP_NAME(_nc_do_color) (CURRENT_SCREEN, + old_pair, + pair, + reverse, + _nc_outc_wrapper); +} +#endif + +#if NCURSES_EXT_COLORS +NCURSES_EXPORT(int) +NCURSES_SP_NAME(init_extended_pair) (NCURSES_SP_DCLx int pair, int f, int b) +{ + return _nc_init_pair(SP_PARM, pair, f, b); +} + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(init_extended_color) (NCURSES_SP_DCLx + int color, + int r, int g, int b) +{ + return _nc_init_color(SP_PARM, color, r, g, b); +} + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(extended_color_content) (NCURSES_SP_DCLx + int color, + int *r, int *g, int *b) +{ + return _nc_color_content(SP_PARM, color, r, g, b); +} + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(extended_pair_content) (NCURSES_SP_DCLx + int pair, + int *f, int *b) +{ + return _nc_pair_content(SP_PARM, pair, f, b); +} + +NCURSES_EXPORT(void) +NCURSES_SP_NAME(reset_color_pairs) (NCURSES_SP_DCL0) +{ + if (SP_PARM != 0) { + if (SP_PARM->_color_pairs) { + _nc_free_ordered_pairs(SP_PARM); + free(SP_PARM->_color_pairs); + SP_PARM->_color_pairs = 0; + SP_PARM->_pair_alloc = 0; + ReservePairs(SP_PARM, 16); + clearok(CurScreen(SP_PARM), TRUE); + touchwin(StdScreen(SP_PARM)); + } } } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +init_extended_pair(int pair, int f, int b) +{ + return NCURSES_SP_NAME(init_extended_pair) (CURRENT_SCREEN, pair, f, b); +} + +NCURSES_EXPORT(int) +init_extended_color(int color, int r, int g, int b) +{ + return NCURSES_SP_NAME(init_extended_color) (CURRENT_SCREEN, + color, + r, g, b); +} + +NCURSES_EXPORT(int) +extended_color_content(int color, int *r, int *g, int *b) +{ + return NCURSES_SP_NAME(extended_color_content) (CURRENT_SCREEN, + color, + r, g, b); +} + +NCURSES_EXPORT(int) +extended_pair_content(int pair, int *f, int *b) +{ + return NCURSES_SP_NAME(extended_pair_content) (CURRENT_SCREEN, pair, f, b); +} + +NCURSES_EXPORT(void) +reset_color_pairs(void) +{ + NCURSES_SP_NAME(reset_color_pairs) (CURRENT_SCREEN); +} +#endif /* NCURSES_SP_FUNCS */ +#endif /* NCURSES_EXT_COLORS */ diff --git a/lib/libcurses/base/lib_colorset.c b/lib/libcurses/base/lib_colorset.c index 039587de146..609ea829309 100644 --- a/lib/libcurses/base/lib_colorset.c +++ b/lib/libcurses/base/lib_colorset.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_colorset.c,v 1.5 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_colorset.c,v 1.6 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2014,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -30,7 +31,7 @@ /**************************************************************************** * Author: Juergen Pfeifer, 1998 * - * and: Thomas E. Dickey, 2005 * + * and: Thomas E. Dickey, 2005-on * ****************************************************************************/ /* @@ -43,20 +44,24 @@ #include #include -MODULE_ID("$Id: lib_colorset.c,v 1.5 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_colorset.c,v 1.6 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) -wcolor_set(WINDOW *win, short color_pair_number, void *opts) +wcolor_set(WINDOW *win, NCURSES_PAIRS_T pair_arg, void *opts) { - T((T_CALLED("wcolor_set(%p,%d)"), win, color_pair_number)); + int code = ERR; + int color_pair = pair_arg; + + T((T_CALLED("wcolor_set(%p,%d)"), (void *) win, color_pair)); + set_extended_pair(opts, color_pair); if (win - && !opts - && (color_pair_number >= 0) - && (color_pair_number < COLOR_PAIRS)) { + && (SP != 0) + && (color_pair >= 0) + && (color_pair < SP->_pair_limit)) { TR(TRACE_ATTRS, ("... current %ld", (long) GET_WINDOW_PAIR(win))); - SET_WINDOW_PAIR(win, color_pair_number); - if_EXT_COLORS(win->_color = color_pair_number); - returnCode(OK); - } else - returnCode(ERR); + SET_WINDOW_PAIR(win, color_pair); + if_EXT_COLORS(win->_color = color_pair); + code = OK; + } + returnCode(code); } diff --git a/lib/libcurses/base/lib_delch.c b/lib/libcurses/base/lib_delch.c index 42efa5cabfe..b925041ff77 100644 --- a/lib/libcurses/base/lib_delch.c +++ b/lib/libcurses/base/lib_delch.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_delch.c,v 1.3 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_delch.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000,2001 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2001,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -42,14 +43,14 @@ #include -MODULE_ID("$Id: lib_delch.c,v 1.3 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_delch.c,v 1.4 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) wdelch(WINDOW *win) { int code = ERR; - T((T_CALLED("wdelch(%p)"), win)); + T((T_CALLED("wdelch(%p)"), (void *) win)); if (win) { NCURSES_CH_T blank = win->_nc_bkgd; diff --git a/lib/libcurses/base/lib_delwin.c b/lib/libcurses/base/lib_delwin.c index 15a52a36953..58dc969f89e 100644 --- a/lib/libcurses/base/lib_delwin.c +++ b/lib/libcurses/base/lib_delwin.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_delwin.c,v 1.3 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_delwin.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2008,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +32,8 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2008 * ****************************************************************************/ /* @@ -42,21 +45,29 @@ #include -MODULE_ID("$Id: lib_delwin.c,v 1.3 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_delwin.c,v 1.4 2023/10/17 09:52:08 nicm Exp $") static bool cannot_delete(WINDOW *win) { - WINDOWLIST *p; bool result = TRUE; - for (each_window(p)) { - if (&(p->win) == win) { - result = FALSE; - } else if ((p->win._flags & _SUBWIN) != 0 - && p->win._parent == win) { - result = TRUE; - break; + if (IS_PAD(win)) { + result = FALSE; + } else { + WINDOWLIST *p; +#ifdef USE_SP_WINDOWLIST + SCREEN *sp = _nc_screen_of(win); +#endif + + for (each_window(SP_PARM, p)) { + if (&(p->win) == win) { + result = FALSE; + } else if (IS_SUBWIN(&(p->win)) + && p->win._parent == win) { + result = TRUE; + break; + } } } return result; @@ -67,19 +78,24 @@ delwin(WINDOW *win) { int result = ERR; - T((T_CALLED("delwin(%p)"), win)); + T((T_CALLED("delwin(%p)"), (void *) win)); if (_nc_try_global(curses) == 0) { if (win == 0 || cannot_delete(win)) { result = ERR; + } else if (IS_PAD(win)) { + win->_parent = NULL; + result = _nc_freewin(win); } else { - - if (win->_flags & _SUBWIN) +#if NCURSES_SP_FUNCS + SCREEN *sp = _nc_screen_of(win); +#endif + if (IS_SUBWIN(win)) { touchwin(win->_parent); - else if (curscr != 0) - touchwin(curscr); - + } else if (CurScreen(SP_PARM) != 0) { + touchwin(CurScreen(SP_PARM)); + } result = _nc_freewin(win); } _nc_unlock_global(curses); diff --git a/lib/libcurses/base/lib_dft_fgbg.c b/lib/libcurses/base/lib_dft_fgbg.c index d051dcd414d..76fb4e5c1bc 100644 --- a/lib/libcurses/base/lib_dft_fgbg.c +++ b/lib/libcurses/base/lib_dft_fgbg.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_dft_fgbg.c,v 1.8 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_dft_fgbg.c,v 1.9 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2004,2005 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2014,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,49 +30,77 @@ ****************************************************************************/ /**************************************************************************** - * Author: Thomas E. Dickey * + * Author: Thomas E. Dickey 1998-on * + * Juergen Pfeifer 2009 * ****************************************************************************/ #include -#include -MODULE_ID("$Id: lib_dft_fgbg.c,v 1.8 2010/01/12 23:22:05 nicm Exp $") +#ifndef CUR +#define CUR SP_TERMTYPE +#endif + +MODULE_ID("$Id: lib_dft_fgbg.c,v 1.9 2023/10/17 09:52:08 nicm Exp $") /* * Modify the behavior of color-pair 0 so that the library doesn't assume that * it is white on black. This is an extension to XSI curses. */ NCURSES_EXPORT(int) +NCURSES_SP_NAME(use_default_colors) (NCURSES_SP_DCL0) +{ + T((T_CALLED("use_default_colors(%p)"), (void *) SP_PARM)); + returnCode(NCURSES_SP_NAME(assume_default_colors) (NCURSES_SP_ARGx -1, -1)); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) use_default_colors(void) { - T((T_CALLED("use_default_colors()"))); - returnCode(assume_default_colors(-1, -1)); + return NCURSES_SP_NAME(use_default_colors) (CURRENT_SCREEN); } +#endif /* * Modify the behavior of color-pair 0 so that the library assumes that it * is something specific, possibly not white on black. */ NCURSES_EXPORT(int) -assume_default_colors(int fg, int bg) +NCURSES_SP_NAME(assume_default_colors) (NCURSES_SP_DCLx int fg, int bg) { - T((T_CALLED("assume_default_colors(%d,%d)"), fg, bg)); + int code = ERR; - if (!orig_pair && !orig_colors) - returnCode(ERR); + T((T_CALLED("assume_default_colors(%p,%d,%d)"), (void *) SP_PARM, fg, bg)); + if (SP_PARM != 0) { +#ifdef USE_TERM_DRIVER + code = CallDriver_2(SP_PARM, td_defaultcolors, fg, bg); +#else + if ((orig_pair || orig_colors) && !initialize_pair) { - if (initialize_pair) /* don't know how to handle this */ - returnCode(ERR); - - SP->_default_color = isDefaultColor(fg) || isDefaultColor(bg); - SP->_has_sgr_39_49 = (tigetflag("AX") == TRUE); - SP->_default_fg = isDefaultColor(fg) ? COLOR_DEFAULT : (fg & C_MASK); - SP->_default_bg = isDefaultColor(bg) ? COLOR_DEFAULT : (bg & C_MASK); - if (SP->_color_pairs != 0) { - bool save = SP->_default_color; - SP->_default_color = TRUE; - init_pair(0, (short) fg, (short) bg); - SP->_default_color = save; + SP_PARM->_default_color = isDefaultColor(fg) || isDefaultColor(bg); + SP_PARM->_has_sgr_39_49 = (tigetflag("AX") == TRUE); + SP_PARM->_default_fg = isDefaultColor(fg) ? COLOR_DEFAULT : fg; + SP_PARM->_default_bg = isDefaultColor(bg) ? COLOR_DEFAULT : bg; + if (SP_PARM->_color_pairs != 0) { + bool save = SP_PARM->_default_color; + SP_PARM->_assumed_color = TRUE; + SP_PARM->_default_color = TRUE; + NCURSES_SP_NAME(init_pair) (NCURSES_SP_ARGx 0, + (short)fg, + (short)bg); + SP_PARM->_default_color = save; + } + code = OK; + } +#endif } - returnCode(OK); + returnCode(code); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +assume_default_colors(int fg, int bg) +{ + return NCURSES_SP_NAME(assume_default_colors) (CURRENT_SCREEN, fg, bg); } +#endif diff --git a/lib/libcurses/base/lib_driver.c b/lib/libcurses/base/lib_driver.c new file mode 100644 index 00000000000..9ca13c6dde9 --- /dev/null +++ b/lib/libcurses/base/lib_driver.c @@ -0,0 +1,148 @@ +/**************************************************************************** + * Copyright 2018,2020 Thomas E. Dickey * + * Copyright 2009-2012,2014 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Juergen Pfeifer * + * * + ****************************************************************************/ + +#include + +MODULE_ID("$Id: lib_driver.c,v 1.1 2023/10/17 09:52:08 nicm Exp $") + +#ifndef EXP_WIN32_DRIVER +typedef struct DriverEntry { + const char *name; + TERM_DRIVER *driver; +} DRIVER_ENTRY; + +static DRIVER_ENTRY DriverTable[] = +{ +#ifdef _WIN32 + {"win32console", &_nc_WIN_DRIVER}, +#endif + {"tinfo", &_nc_TINFO_DRIVER} /* must be last */ +}; + +NCURSES_EXPORT(int) +_nc_get_driver(TERMINAL_CONTROL_BLOCK * TCB, const char *name, int *errret) +{ + int code = ERR; + size_t i; + TERM_DRIVER *res = (TERM_DRIVER *) 0; + TERM_DRIVER *use = 0; + + T((T_CALLED("_nc_get_driver(%p, %s, %p)"), + (void *) TCB, NonNull(name), (void *) errret)); + + assert(TCB != 0); + + for (i = 0; i < SIZEOF(DriverTable); i++) { + res = DriverTable[i].driver; + if (strcmp(DriverTable[i].name, res->td_name(TCB)) == 0) { + if (res->td_CanHandle(TCB, name, errret)) { + use = res; + break; + } + } + } + if (use != 0) { + TCB->drv = use; + code = OK; + } + returnCode(code); +} +#endif /* !EXP_WIN32_DRIVER */ + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(has_key) (SCREEN *sp, int keycode) +{ + T((T_CALLED("has_key(%p, %d)"), (void *) sp, keycode)); + returnCode(IsValidTIScreen(sp) ? CallDriver_1(sp, td_kyExist, keycode) : FALSE); +} + +NCURSES_EXPORT(int) +has_key(int keycode) +{ + return NCURSES_SP_NAME(has_key) (CURRENT_SCREEN, keycode); +} + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(_nc_mcprint) (SCREEN *sp, char *data, int len) +{ + int code = ERR; + + if (0 != TerminalOf(sp)) + code = CallDriver_2(sp, td_print, data, len); + return (code); +} + +NCURSES_EXPORT(int) +mcprint(char *data, int len) +{ + return NCURSES_SP_NAME(_nc_mcprint) (CURRENT_SCREEN, data, len); +} + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(doupdate) (SCREEN *sp) +{ + int code = ERR; + + T((T_CALLED("doupdate(%p)"), (void *) sp)); + + if (IsValidScreen(sp)) + code = CallDriver(sp, td_update); + + returnCode(code); +} + +NCURSES_EXPORT(int) +doupdate(void) +{ + return NCURSES_SP_NAME(doupdate) (CURRENT_SCREEN); +} + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(mvcur) (SCREEN *sp, int yold, int xold, int ynew, int xnew) +{ + int code = ERR; + TR(TRACE_CALLS | TRACE_MOVE, (T_CALLED("mvcur(%p,%d,%d,%d,%d)"), + (void *) sp, yold, xold, ynew, xnew)); + if (HasTerminal(sp)) { + code = CallDriver_4(sp, td_hwcur, yold, xold, ynew, xnew); + } + returnCode(code); +} + +NCURSES_EXPORT(int) +mvcur(int yold, int xold, int ynew, int xnew) +/* optimized cursor move from (yold, xold) to (ynew, xnew) */ +{ + return NCURSES_SP_NAME(mvcur) (CURRENT_SCREEN, yold, xold, ynew, xnew); +} diff --git a/lib/libcurses/base/lib_echo.c b/lib/libcurses/base/lib_echo.c index 3a73b349c9a..bb80055e6f3 100644 --- a/lib/libcurses/base/lib_echo.c +++ b/lib/libcurses/base/lib_echo.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_echo.c,v 1.3 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_echo.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright 2020,2023 Thomas E. Dickey * + * Copyright 1998-2000,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +32,8 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -44,20 +47,40 @@ #include -MODULE_ID("$Id: lib_echo.c,v 1.3 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_echo.c,v 1.4 2023/10/17 09:52:08 nicm Exp $") +NCURSES_EXPORT(int) +NCURSES_SP_NAME(echo) (NCURSES_SP_DCL0) +{ + T((T_CALLED("echo(%p)"), (void *) SP_PARM)); + if (0 == SP_PARM) + returnCode(ERR); + IsEcho(SP_PARM) = TRUE; + returnCode(OK); +} + +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) echo(void) { - T((T_CALLED("echo()"))); - SP->_echo = TRUE; + return NCURSES_SP_NAME(echo) (CURRENT_SCREEN); +} +#endif + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(noecho) (NCURSES_SP_DCL0) +{ + T((T_CALLED("noecho(%p)"), (void *) SP_PARM)); + if (0 == SP_PARM) + returnCode(ERR); + IsEcho(SP_PARM) = FALSE; returnCode(OK); } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) noecho(void) { - T((T_CALLED("noecho()"))); - SP->_echo = FALSE; - returnCode(OK); + return NCURSES_SP_NAME(noecho) (CURRENT_SCREEN); } +#endif diff --git a/lib/libcurses/base/lib_endwin.c b/lib/libcurses/base/lib_endwin.c index 281569ea043..2a011f98603 100644 --- a/lib/libcurses/base/lib_endwin.c +++ b/lib/libcurses/base/lib_endwin.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_endwin.c,v 1.4 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_endwin.c,v 1.5 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2014,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +32,8 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -41,22 +44,39 @@ */ #include -#include -MODULE_ID("$Id: lib_endwin.c,v 1.4 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_endwin.c,v 1.5 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) -endwin(void) +NCURSES_SP_NAME(endwin) (NCURSES_SP_DCL0) { - T((T_CALLED("endwin()"))); + int code = ERR; + + T((T_CALLED("endwin(%p)"), (void *) SP_PARM)); - if (SP) { - SP->_endwin = TRUE; - SP->_mouse_wrap(SP); + if (SP_PARM) { +#ifdef USE_TERM_DRIVER + TERMINAL_CONTROL_BLOCK *TCB = TCBOf(SP_PARM); + + SP_PARM->_endwin = ewSuspend; + if (TCB && TCB->drv && TCB->drv->td_scexit) + TCB->drv->td_scexit(SP_PARM); +#else + SP_PARM->_endwin = ewSuspend; + SP_PARM->_mouse_wrap(SP_PARM); _nc_screen_wrap(); _nc_mvcur_wrap(); /* wrap up cursor addressing */ - returnCode(reset_shell_mode()); +#endif + code = NCURSES_SP_NAME(reset_shell_mode) (NCURSES_SP_ARG); } - returnCode(ERR); + returnCode(code); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +endwin(void) +{ + return NCURSES_SP_NAME(endwin) (CURRENT_SCREEN); } +#endif diff --git a/lib/libcurses/base/lib_erase.c b/lib/libcurses/base/lib_erase.c index 9bc4aadf120..851c4a151bf 100644 --- a/lib/libcurses/base/lib_erase.c +++ b/lib/libcurses/base/lib_erase.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_erase.c,v 1.3 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_erase.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000,2001 Free Software Foundation, Inc. * + * Copyright 2020,2022 Thomas E. Dickey * + * Copyright 1998-2009,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -43,21 +44,25 @@ #include -MODULE_ID("$Id: lib_erase.c,v 1.3 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_erase.c,v 1.4 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) werase(WINDOW *win) { int code = ERR; - int y; - NCURSES_CH_T blank; - NCURSES_CH_T *sp, *end, *start; + NCURSES_CH_T *start; - T((T_CALLED("werase(%p)"), win)); + T((T_CALLED("werase(%p)"), (void *) win)); if (win) { + NCURSES_CH_T blank; + NCURSES_CH_T *sp; + int y; + blank = win->_nc_bkgd; for (y = 0; y <= win->_maxy; y++) { + NCURSES_CH_T *end; + start = win->_line[y].text; end = &start[win->_maxx]; diff --git a/lib/libcurses/base/lib_flash.c b/lib/libcurses/base/lib_flash.c index 9f66c4cebd4..6a146092d2d 100644 --- a/lib/libcurses/base/lib_flash.c +++ b/lib/libcurses/base/lib_flash.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_flash.c,v 1.4 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_flash.c,v 1.5 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2013,2014 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +32,8 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -41,9 +44,12 @@ */ #include -#include /* beep, flash */ -MODULE_ID("$Id: lib_flash.c,v 1.4 2010/01/12 23:22:05 nicm Exp $") +#ifndef CUR +#define CUR SP_TERMTYPE +#endif + +MODULE_ID("$Id: lib_flash.c,v 1.5 2023/10/17 09:52:08 nicm Exp $") /* * flash() @@ -54,22 +60,31 @@ MODULE_ID("$Id: lib_flash.c,v 1.4 2010/01/12 23:22:05 nicm Exp $") */ NCURSES_EXPORT(int) -flash(void) +NCURSES_SP_NAME(flash) (NCURSES_SP_DCL0) { int res = ERR; - T((T_CALLED("flash()"))); - - /* FIXME: should make sure that we are not in altchar mode */ - if (flash_screen) { - TPUTS_TRACE("flash_screen"); - res = putp(flash_screen); - _nc_flush(); - } else if (bell) { - TPUTS_TRACE("bell"); - res = putp(bell); - _nc_flush(); + T((T_CALLED("flash(%p)"), (void *) SP_PARM)); +#ifdef USE_TERM_DRIVER + if (SP_PARM != 0) + res = CallDriver_1(SP_PARM, td_doBeepOrFlash, FALSE); +#else + if (HasTerminal(SP_PARM)) { + /* FIXME: should make sure that we are not in altchar mode */ + if (flash_screen) { + res = NCURSES_PUTP2_FLUSH("flash_screen", flash_screen); + } else if (bell) { + res = NCURSES_PUTP2_FLUSH("bell", bell); + } } - +#endif returnCode(res); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +flash(void) +{ + return NCURSES_SP_NAME(flash) (CURRENT_SCREEN); +} +#endif diff --git a/lib/libcurses/base/lib_freeall.c b/lib/libcurses/base/lib_freeall.c index dd3a9449815..fbc08fbc230 100644 --- a/lib/libcurses/base/lib_freeall.c +++ b/lib/libcurses/base/lib_freeall.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_freeall.c,v 1.5 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_freeall.c,v 1.6 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2020,2021 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,7 +34,6 @@ ****************************************************************************/ #include -#include #include #if HAVE_NC_FREEALL @@ -42,50 +42,70 @@ extern int malloc_errfd; /* FIXME */ #endif -MODULE_ID("$Id: lib_freeall.c,v 1.5 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_freeall.c,v 1.6 2023/10/17 09:52:08 nicm Exp $") /* * Free all ncurses data. This is used for testing only (there's no practical * use for it as an extension). */ NCURSES_EXPORT(void) -_nc_freeall(void) +NCURSES_SP_NAME(_nc_freeall) (NCURSES_SP_DCL0) { - WINDOWLIST *p, *q; static va_list empty_va; T((T_CALLED("_nc_freeall()"))); #if NO_LEAKS - if (SP != 0) { - if (SP->_oldnum_list != 0) { - FreeAndNull(SP->_oldnum_list); + _nc_globals.leak_checking = TRUE; + if (SP_PARM != 0) { + if (SP_PARM->_oldnum_list != 0) { + FreeAndNull(SP_PARM->_oldnum_list); } - if (SP->_panelHook.destroy != 0) { - SP->_panelHook.destroy(SP->_panelHook.stdscr_pseudo_panel); + if (SP_PARM->_panelHook.destroy != 0) { + SP_PARM->_panelHook.destroy(SP_PARM->_panelHook.stdscr_pseudo_panel); } +#if NCURSES_EXT_COLORS + _nc_new_pair_leaks(SP_PARM); +#endif } #endif - if (SP != 0) { + if (SP_PARM != 0) { _nc_lock_global(curses); - while (_nc_windows != 0) { + while (WindowList(SP_PARM) != 0) { + WINDOWLIST *p, *q; bool deleted = FALSE; /* Delete only windows that're not a parent */ - for (each_window(p)) { + for (each_window(SP_PARM, p)) { + WINDOW *p_win = &(p->win); bool found = FALSE; - for (each_window(q)) { + if (IS_PAD(p_win)) + continue; + +#ifndef USE_SP_WINDOWLIST + if (p->screen != SP_PARM) + continue; +#endif + + for (each_window(SP_PARM, q)) { + WINDOW *q_win = &(q->win); + +#ifndef USE_SP_WINDOWLIST + if (q->screen != SP_PARM) + continue; +#endif + if ((p != q) - && (q->win._flags & _SUBWIN) - && (&(p->win) == q->win._parent)) { + && IS_SUBWIN(q_win) + && (p_win == q_win->_parent)) { found = TRUE; break; } } if (!found) { - if (delwin(&(p->win)) != ERR) + if (delwin(p_win) != ERR) deleted = TRUE; break; } @@ -97,15 +117,13 @@ _nc_freeall(void) if (!deleted) break; } - delscreen(SP); + delscreen(SP_PARM); _nc_unlock_global(curses); } - if (cur_term != 0) - del_curterm(cur_term); (void) _nc_printf_string(0, empty_va); #ifdef TRACE - (void) _nc_trace_buf(-1, 0); + (void) _nc_trace_buf(-1, (size_t) 0); #endif #if USE_WIDEC_SUPPORT FreeIfNeeded(_nc_wacs); @@ -123,37 +141,63 @@ _nc_freeall(void) returnVoid; } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(void) -_nc_free_and_exit(int code) +_nc_freeall(void) { - char *last_setbuf = (SP != 0) ? SP->_setbuf : 0; + NCURSES_SP_NAME(_nc_freeall) (CURRENT_SCREEN); +} +#endif - _nc_freeall(); +NCURSES_EXPORT(void) +NCURSES_SP_NAME(_nc_free_and_exit) (NCURSES_SP_DCLx int code) +{ + T((T_CALLED("_nc_free_and_exit(%d)"), code)); + NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG); + NCURSES_SP_NAME(_nc_freeall) (NCURSES_SP_ARG); #ifdef TRACE - trace(0); /* close trace file, freeing its setbuf */ + curses_trace(0); /* close trace file, freeing its setbuf */ { static va_list fake; free(_nc_varargs("?", fake)); } #endif - fclose(stdout); - FreeIfNeeded(last_setbuf); exit(code); } -#else +#else /* !HAVE_NC_FREEALL */ NCURSES_EXPORT(void) _nc_freeall(void) { } NCURSES_EXPORT(void) -_nc_free_and_exit(int code) +NCURSES_SP_NAME(_nc_free_and_exit) (NCURSES_SP_DCLx int code) { - if (SP) - delscreen(SP); - if (cur_term != 0) - del_curterm(cur_term); + if (SP_PARM) { + delscreen(SP_PARM); + } exit(code); } +#endif /* HAVE_NC_FREEALL */ + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(void) +_nc_free_and_exit(int code) +{ + NCURSES_SP_NAME(_nc_free_and_exit) (CURRENT_SCREEN, code); +} #endif + +NCURSES_EXPORT(void) +exit_curses(int code) +{ +#if NO_LEAKS +#if NCURSES_SP_FUNCS + NCURSES_SP_NAME(_nc_free_and_exit) (CURRENT_SCREEN, code); +#else + _nc_free_and_exit(code); /* deprecated... */ +#endif +#endif + exit(code); +} diff --git a/lib/libcurses/base/lib_getch.c b/lib/libcurses/base/lib_getch.c index db35bc803dc..cb9e72315d1 100644 --- a/lib/libcurses/base/lib_getch.c +++ b/lib/libcurses/base/lib_getch.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_getch.c,v 1.11 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_getch.c,v 1.12 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2015,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,6 +33,7 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -41,42 +43,91 @@ ** */ +#define NEED_KEY_EVENT #include -MODULE_ID("$Id: lib_getch.c,v 1.11 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_getch.c,v 1.12 2023/10/17 09:52:08 nicm Exp $") #include #if USE_REENTRANT -#define GetEscdelay(sp) (sp)->_ESCDELAY +#define GetEscdelay(sp) *_nc_ptr_Escdelay(sp) NCURSES_EXPORT(int) NCURSES_PUBLIC_VAR(ESCDELAY) (void) { - return SP ? GetEscdelay(SP) : 1000; + return *(_nc_ptr_Escdelay(CURRENT_SCREEN)); +} + +NCURSES_EXPORT(int *) +_nc_ptr_Escdelay(SCREEN *sp) +{ + return ptrEscdelay(sp); } #else #define GetEscdelay(sp) ESCDELAY -NCURSES_EXPORT_VAR(int) -ESCDELAY = 1000; /* max interval betw. chars in funkeys, in millisecs */ +NCURSES_EXPORT_VAR(int) ESCDELAY = 1000; #endif #if NCURSES_EXT_FUNCS NCURSES_EXPORT(int) -set_escdelay(int value) +NCURSES_SP_NAME(set_escdelay) (NCURSES_SP_DCLx int value) { int code = OK; -#if USE_REENTRANT - if (SP) { - SP->_ESCDELAY = value; - } else { + if (value < 0) { code = ERR; + } else { +#if USE_REENTRANT + if (SP_PARM) { + SET_ESCDELAY(value); + } else { + code = ERR; + } +#else + (void) SP_PARM; + ESCDELAY = value; +#endif } + return code; +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +set_escdelay(int value) +{ + int code; + if (value < 0) { + code = ERR; + } else { +#if USE_REENTRANT + code = NCURSES_SP_NAME(set_escdelay) (CURRENT_SCREEN, value); #else - ESCDELAY = value; + ESCDELAY = value; + code = OK; #endif + } return code; } #endif +#endif /* NCURSES_EXT_FUNCS */ + +#if NCURSES_EXT_FUNCS +NCURSES_EXPORT(int) +NCURSES_SP_NAME(get_escdelay) (NCURSES_SP_DCL0) +{ +#if !USE_REENTRANT + (void) SP_PARM; +#endif + return GetEscdelay(SP_PARM); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +get_escdelay(void) +{ + return NCURSES_SP_NAME(get_escdelay) (CURRENT_SCREEN); +} +#endif +#endif /* NCURSES_EXT_FUNCS */ static int _nc_use_meta(WINDOW *win) @@ -85,10 +136,15 @@ _nc_use_meta(WINDOW *win) return (sp ? sp->_use_meta : 0); } -#ifdef NCURSES_WGETCH_EVENTS -#define TWAIT_MASK 7 -#else -#define TWAIT_MASK 3 +#ifdef USE_TERM_DRIVER +# if defined(_NC_WINDOWS) && !defined(EXP_WIN32_DRIVER) +static HANDLE +_nc_get_handle(int fd) +{ + intptr_t value = _get_osfhandle(fd); + return (HANDLE) value; +} +# endif #endif /* @@ -99,28 +155,61 @@ check_mouse_activity(SCREEN *sp, int delay EVENTLIST_2nd(_nc_eventlist * evl)) { int rc; -#if USE_SYSMOUSE +#ifdef USE_TERM_DRIVER + TERMINAL_CONTROL_BLOCK *TCB = TCBOf(sp); + rc = TCBOf(sp)->drv->td_testmouse(TCBOf(sp), delay EVENTLIST_2nd(evl)); +# if defined(EXP_WIN32_DRIVER) + /* if we emulate terminfo on console, we have to use the console routine */ + if (IsTermInfoOnConsole(sp)) { + rc = _nc_console_testmouse(sp, + _nc_console_handle(sp->_ifd), + delay EVENTLIST_2nd(evl)); + } else +# elif defined(_NC_WINDOWS) + /* if we emulate terminfo on console, we have to use the console routine */ + if (IsTermInfoOnConsole(sp)) { + HANDLE fd = _nc_get_handle(sp->_ifd); + rc = _nc_mingw_testmouse(sp, fd, delay EVENTLIST_2nd(evl)); + } else +# endif + rc = TCB->drv->td_testmouse(TCB, delay EVENTLIST_2nd(evl)); +#else /* !USE_TERM_DRIVER */ +# if USE_SYSMOUSE if ((sp->_mouse_type == M_SYSMOUSE) && (sp->_sysmouse_head < sp->_sysmouse_tail)) { - return 2; - } -#endif - rc = _nc_timed_wait(sp, TWAIT_MASK, delay, (int *) 0 EVENTLIST_2nd(evl)); -#if USE_SYSMOUSE - if ((sp->_mouse_type == M_SYSMOUSE) - && (sp->_sysmouse_head < sp->_sysmouse_tail) - && (rc == 0) - && (errno == EINTR)) { - rc |= 2; + rc = TW_MOUSE; + } else +# endif + { +# if defined(EXP_WIN32_DRIVER) + rc = _nc_console_testmouse(sp, + _nc_console_handle(sp->_ifd), + delay + EVENTLIST_2nd(evl)); +# else + rc = _nc_timed_wait(sp, + TWAIT_MASK, + delay, + (int *) 0 + EVENTLIST_2nd(evl)); +# endif +# if USE_SYSMOUSE + if ((sp->_mouse_type == M_SYSMOUSE) + && (sp->_sysmouse_head < sp->_sysmouse_tail) + && (rc == 0) + && (errno == EINTR)) { + rc |= TW_MOUSE; + } +# endif } -#endif +#endif /* USE_TERM_DRIVER */ return rc; } static NCURSES_INLINE int fifo_peek(SCREEN *sp) { - int ch = sp->_fifo[peek]; + int ch = (peek >= 0) ? sp->_fifo[peek] : ERR; TR(TRACE_IEVENT, ("peeking at %d", peek)); p_inc(); @@ -130,15 +219,16 @@ fifo_peek(SCREEN *sp) static NCURSES_INLINE int fifo_pull(SCREEN *sp) { - int ch; - ch = sp->_fifo[head]; + int ch = (head >= 0) ? sp->_fifo[head] : ERR; + TR(TRACE_IEVENT, ("pulling %s from %d", _nc_tracechar(sp, ch), head)); if (peek == head) { h_inc(); peek = head; - } else + } else { h_inc(); + } #ifdef TRACE if (USE_TRACEF(TRACE_IEVENT)) { @@ -157,14 +247,9 @@ fifo_push(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl)) int mask = 0; (void) mask; - if (tail == -1) + if (tail < 0) return ERR; -#ifdef HIDE_EINTR - again: - errno = 0; -#endif - #ifdef NCURSES_WGETCH_EVENTS if (evl #if USE_GPM_SUPPORT || USE_EMX_MOUSE || USE_SYSMOUSE @@ -175,9 +260,9 @@ fifo_push(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl)) } else mask = 0; - if (mask & 4) { + if (mask & TW_EVENT) { T(("fifo_push: ungetch KEY_EVENT")); - _nc_ungetch(sp, KEY_EVENT); + safe_ungetch(sp, KEY_EVENT); return KEY_EVENT; } #elif USE_GPM_SUPPORT || USE_EMX_MOUSE || USE_SYSMOUSE @@ -187,7 +272,7 @@ fifo_push(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl)) #endif #if USE_GPM_SUPPORT || USE_EMX_MOUSE - if ((sp->_mouse_fd >= 0) && (mask & 2)) { + if ((sp->_mouse_fd >= 0) && (mask & TW_MOUSE)) { sp->_mouse_event(sp); ch = KEY_MOUSE; n = 1; @@ -205,26 +290,61 @@ fifo_push(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl)) ch = KEY_MOUSE; n = 1; } else +#endif +#ifdef USE_TERM_DRIVER + if ((sp->_mouse_type == M_TERM_DRIVER) + && (sp->_drv_mouse_head < sp->_drv_mouse_tail)) { + sp->_mouse_event(sp); + ch = KEY_MOUSE; + n = 1; + } else +#endif +#if USE_KLIBC_KBD + if (NC_ISATTY(sp->_ifd) && IsCbreak(sp)) { + ch = _read_kbd(0, 1, !IsRaw(sp)); + n = (ch == -1) ? -1 : 1; + sp->_extended_key = (ch == 0); + } else #endif { /* Can block... */ +#if defined(USE_TERM_DRIVER) + int buf; +# if defined(EXP_WIN32_DRIVER) + if (NC_ISATTY(sp->_ifd) && IsTermInfoOnConsole(sp) && IsCbreak(sp)) { + _nc_set_read_thread(TRUE); + n = _nc_console_read(sp, + _nc_console_handle(sp->_ifd), + &buf); + _nc_set_read_thread(FALSE); + } else +# elif defined(_NC_WINDOWS) + if (NC_ISATTY(sp->_ifd) && IsTermInfoOnConsole(sp) && IsCbreak(sp)) + n = _nc_mingw_console_read(sp, + _nc_get_handle(sp->_ifd), + &buf); + else +# endif /* EXP_WIN32_DRIVER */ + n = CallDriver_1(sp, td_read, &buf); + ch = buf; +#else /* !USE_TERM_DRIVER */ +#if defined(EXP_WIN32_DRIVER) + int buf; +#endif unsigned char c2 = 0; - n = read(sp->_ifd, &c2, 1); - ch = c2; - } -#ifdef HIDE_EINTR - /* - * Under System V curses with non-restarting signals, getch() returns - * with value ERR when a handled signal keeps it from completing. - * If signals restart system calls, OTOH, the signal is invisible - * except to its handler. - * - * We don't want this difference to show. This piece of code - * tries to make it look like we always have restarting signals. - */ - if (n <= 0 && errno == EINTR) - goto again; + _nc_set_read_thread(TRUE); +#if defined(EXP_WIN32_DRIVER) + n = _nc_console_read(sp, + _nc_console_handle(sp->_ifd), + &buf); + c2 = buf; +#else + n = (int) read(sp->_ifd, &c2, (size_t) 1); #endif + _nc_set_read_thread(FALSE); + ch = c2; +#endif /* USE_TERM_DRIVER */ + } if ((n == -1) || (n == 0)) { TR(TRACE_IEVENT, ("read(%d,&ch,1)=%d, errno=%d", sp->_ifd, n, errno)); @@ -255,19 +375,29 @@ fifo_clear(SCREEN *sp) tail = peek = 0; } -static int kgetch(SCREEN *EVENTLIST_2nd(_nc_eventlist * evl)); +static int kgetch(SCREEN *, bool EVENTLIST_2nd(_nc_eventlist *)); static void recur_wrefresh(WINDOW *win) { #ifdef USE_PTHREADS SCREEN *sp = _nc_screen_of(win); - if (_nc_use_pthreads && sp != SP) { + bool same_sp; + + if (_nc_use_pthreads) { + _nc_lock_global(curses); + same_sp = (sp == CURRENT_SCREEN); + _nc_unlock_global(curses); + } else { + same_sp = (sp == CURRENT_SCREEN); + } + + if (_nc_use_pthreads && !same_sp) { SCREEN *save_SP; /* temporarily switch to the window's screen to check/refresh */ _nc_lock_global(curses); - save_SP = SP; + save_SP = CURRENT_SCREEN; _nc_set_screen(sp); recur_wrefresh(win); _nc_set_screen(save_SP); @@ -275,7 +405,7 @@ recur_wrefresh(WINDOW *win) } else #endif if ((is_wintouched(win) || (win->_flags & _HASMOVED)) - && !(win->_flags & _ISPAD)) { + && !IS_PAD(win)) { wrefresh(win); } } @@ -288,12 +418,12 @@ recur_wgetnstr(WINDOW *win, char *buf) if (sp != 0) { #ifdef USE_PTHREADS - if (_nc_use_pthreads && sp != SP) { + if (_nc_use_pthreads && sp != CURRENT_SCREEN) { SCREEN *save_SP; /* temporarily switch to the window's screen to get cooked input */ _nc_lock_global(curses); - save_SP = SP; + save_SP = CURRENT_SCREEN; _nc_set_screen(sp); rc = recur_wgetnstr(win, buf); _nc_set_screen(save_SP); @@ -313,17 +443,18 @@ recur_wgetnstr(WINDOW *win, char *buf) NCURSES_EXPORT(int) _nc_wgetch(WINDOW *win, - unsigned long *result, + int *result, int use_meta EVENTLIST_2nd(_nc_eventlist * evl)) { SCREEN *sp; int ch; + int rc = 0; #ifdef NCURSES_WGETCH_EVENTS - long event_delay = -1; + int event_delay = -1; #endif - T((T_CALLED("_nc_wgetch(%p)"), win)); + T((T_CALLED("_nc_wgetch(%p)"), (void *) win)); *result = 0; @@ -350,23 +481,24 @@ _nc_wgetch(WINDOW *win, */ if (head == -1 && !sp->_notty && - !sp->_raw && - !sp->_cbreak && + !IsRaw(sp) && + !IsCbreak(sp) && !sp->_called_wgetch) { char buf[MAXCOLUMNS], *bufp; - int rc; TR(TRACE_IEVENT, ("filling queue in cooked mode")); - rc = recur_wgetnstr(win, buf); - /* ungetch in reverse order */ #ifdef NCURSES_WGETCH_EVENTS - if (rc != KEY_EVENT) + rc = recur_wgetnstr(win, buf); + if (rc != KEY_EVENT && rc != ERR) + safe_ungetch(sp, '\n'); +#else + if (recur_wgetnstr(win, buf) != ERR) + safe_ungetch(sp, '\n'); #endif - _nc_ungetch(sp, '\n'); for (bufp = buf + strlen(buf); bufp > buf; bufp--) - _nc_ungetch(sp, bufp[-1]); + safe_ungetch(sp, bufp[-1]); #ifdef NCURSES_WGETCH_EVENTS /* Return it first */ @@ -383,14 +515,13 @@ _nc_wgetch(WINDOW *win, recur_wrefresh(win); - if (win->_notimeout || (win->_delay >= 0) || (sp->_cbreak > 1)) { + if (win->_notimeout || (win->_delay >= 0) || (IsCbreak(sp) > 1)) { if (head == -1) { /* fifo is empty */ int delay; - int rc; TR(TRACE_IEVENT, ("timed delay in wgetch()")); - if (sp->_cbreak > 1) - delay = (sp->_cbreak - 1) * 100; + if (IsCbreak(sp) > 1) + delay = (IsCbreak(sp) - 1) * 100; else delay = win->_delay; @@ -404,13 +535,13 @@ _nc_wgetch(WINDOW *win, rc = check_mouse_activity(sp, delay EVENTLIST_2nd(evl)); #ifdef NCURSES_WGETCH_EVENTS - if (rc & 4) { + if (rc & TW_EVENT) { *result = KEY_EVENT; returnCode(KEY_CODE_YES); } #endif if (!rc) { - returnCode(ERR); + goto check_sigwinch; } } /* else go on to read data available */ @@ -421,7 +552,7 @@ _nc_wgetch(WINDOW *win, * This is tricky. We only want to get special-key * events one at a time. But we want to accumulate * mouse events until either (a) the mouse logic tells - * us it's picked up a complete gesture, or (b) + * us it has picked up a complete gesture, or (b) * there's a detectable time lapse after one. * * Note: if the mouse code starts failing to compose @@ -429,10 +560,9 @@ _nc_wgetch(WINDOW *win, * increase the wait with mouseinterval(). */ int runcount = 0; - int rc; do { - ch = kgetch(sp EVENTLIST_2nd(evl)); + ch = kgetch(sp, win->_notimeout EVENTLIST_2nd(evl)); if (ch == KEY_MOUSE) { ++runcount; if (sp->_mouse_inline(sp)) @@ -444,11 +574,11 @@ _nc_wgetch(WINDOW *win, (ch == KEY_MOUSE && (((rc = check_mouse_activity(sp, sp->_maxclick EVENTLIST_2nd(evl))) != 0 - && !(rc & 4)) + && !(rc & TW_EVENT)) || !sp->_mouse_parse(sp, runcount))); #ifdef NCURSES_WGETCH_EVENTS - if ((rc & 4) && !ch == KEY_EVENT) { - _nc_ungetch(sp, ch); + if ((rc & TW_EVENT) && !(ch == KEY_EVENT)) { + safe_ungetch(sp, ch); ch = KEY_EVENT; } #endif @@ -456,12 +586,12 @@ _nc_wgetch(WINDOW *win, #ifdef NCURSES_WGETCH_EVENTS /* mouse event sequence ended by an event, report event */ if (ch == KEY_EVENT) { - _nc_ungetch(sp, KEY_MOUSE); /* FIXME This interrupts a gesture... */ + safe_ungetch(sp, KEY_MOUSE); /* FIXME This interrupts a gesture... */ } else #endif { /* mouse event sequence ended by keystroke, store keystroke */ - _nc_ungetch(sp, ch); + safe_ungetch(sp, ch); ch = KEY_MOUSE; } } @@ -472,12 +602,19 @@ _nc_wgetch(WINDOW *win, } if (ch == ERR) { + check_sigwinch: #if USE_SIZECHANGE if (_nc_handle_sigwinch(sp)) { _nc_update_screensize(sp); /* resizeterm can push KEY_RESIZE */ if (cooked_key_in_fifo()) { *result = fifo_pull(sp); + /* + * Get the ERR from queue -- it is from WINCH, + * so we should take it out, the "error" is handled. + */ + if (fifo_peek(sp) == -1) + fifo_pull(sp); returnCode(*result >= KEY_MIN ? KEY_CODE_YES : OK); } } @@ -492,7 +629,7 @@ _nc_wgetch(WINDOW *win, * * If carriage return is defined as a function key in the * terminfo, e.g., kent, then Solaris may return either ^J (or ^M - * if nonl() is set) or KEY_ENTER depending on the echo() mode. + * if nonl() is set) or KEY_ENTER depending on the echo() mode. * We echo before translating carriage return based on nonl(), * since the visual result simply moves the cursor to column 0. * @@ -503,8 +640,8 @@ _nc_wgetch(WINDOW *win, * However, we provide the same visual result as Solaris, moving the * cursor to the left. */ - if (sp->_echo && !(win->_flags & _ISPAD)) { - chtype backup = (ch == KEY_BACKSPACE) ? '\b' : ch; + if (IsEcho(sp) && !IS_PAD(win)) { + chtype backup = (chtype) ((ch == KEY_BACKSPACE) ? '\b' : ch); if (backup < KEY_MIN) wechochar(win, backup); } @@ -512,7 +649,7 @@ _nc_wgetch(WINDOW *win, /* * Simulate ICRNL mode */ - if ((ch == '\r') && sp->_nl) + if ((ch == '\r') && IsNl(sp)) ch = '\n'; /* Strip 8th-bit if so desired. We do this only for characters that @@ -535,9 +672,9 @@ NCURSES_EXPORT(int) wgetch_events(WINDOW *win, _nc_eventlist * evl) { int code; - unsigned long value; + int value; - T((T_CALLED("wgetch_events(%p,%p)"), win, evl)); + T((T_CALLED("wgetch_events(%p,%p)"), (void *) win, (void *) evl)); code = _nc_wgetch(win, &value, _nc_use_meta(win) @@ -552,9 +689,9 @@ NCURSES_EXPORT(int) wgetch(WINDOW *win) { int code; - unsigned long value; + int value; - T((T_CALLED("wgetch(%p)"), win)); + T((T_CALLED("wgetch(%p)"), (void *) win)); code = _nc_wgetch(win, &value, _nc_use_meta(win) @@ -580,11 +717,11 @@ wgetch(WINDOW *win) */ static int -kgetch(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl)) +kgetch(SCREEN *sp, bool forever EVENTLIST_2nd(_nc_eventlist * evl)) { TRIES *ptr; int ch = 0; - int timeleft = GetEscdelay(sp); + int timeleft = forever ? 9999999 : GetEscdelay(sp); TR(TRACE_IEVENT, ("kgetch() called")); @@ -628,14 +765,15 @@ kgetch(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl)) break; } TR(TRACE_IEVENT, ("ptr=%p, ch=%d, value=%d", - ptr, ptr->ch, ptr->value)); + (void *) ptr, ptr->ch, ptr->value)); if (ptr->value != 0) { /* sequence terminated */ TR(TRACE_IEVENT, ("end of sequence")); - if (peek == tail) + if (peek == tail) { fifo_clear(sp); - else + } else { head = peek; + } return (ptr->value); } @@ -647,7 +785,7 @@ kgetch(SCREEN *sp EVENTLIST_2nd(_nc_eventlist * evl)) TR(TRACE_IEVENT, ("waiting for rest of sequence")); rc = check_mouse_activity(sp, timeleft EVENTLIST_2nd(evl)); #ifdef NCURSES_WGETCH_EVENTS - if (rc & 4) { + if (rc & TW_EVENT) { TR(TRACE_IEVENT, ("interrupted by a user event")); /* FIXME Should have preserved remainder timeleft for reuse... */ peek = head; /* Restart interpreting later */ diff --git a/lib/libcurses/base/lib_getstr.c b/lib/libcurses/base/lib_getstr.c index b83a0523e63..b9d8f8b7e3c 100644 --- a/lib/libcurses/base/lib_getstr.c +++ b/lib/libcurses/base/lib_getstr.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_getstr.c,v 1.3 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_getstr.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. * + * Copyright 2018-2021,2023 Thomas E. Dickey * + * Copyright 1998-2011,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -40,17 +41,17 @@ ** */ +#define NEED_KEY_EVENT #include -#include -MODULE_ID("$Id: lib_getstr.c,v 1.3 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_getstr.c,v 1.4 2023/10/17 09:52:08 nicm Exp $") /* * This wipes out the last character, no matter whether it was a tab, control * or other character, and handles reverse wraparound. */ static char * -WipeOut(WINDOW *win, int y, int x, char *first, char *last, bool echoed) +WipeOut(WINDOW *win, int y, int x, char *first, char *last, int echoed) { if (last > first) { *--last = '\0'; @@ -79,31 +80,30 @@ wgetnstr_events(WINDOW *win, { SCREEN *sp = _nc_screen_of(win); TTY buf; - bool oldnl, oldecho, oldraw, oldcbreak; + TTY_FLAGS save_flags; char erasec; char killc; char *oldstr; int ch; int y, x; - T((T_CALLED("wgetnstr(%p,%p, %d)"), win, str, maxlen)); + T((T_CALLED("wgetnstr(%p,%p,%d)"), (void *) win, (void *) str, maxlen)); - if (!win) + if (!win || !str) returnCode(ERR); - _nc_get_tty_mode(&buf); + maxlen = _nc_getstr_limit(maxlen); - oldnl = sp->_nl; - oldecho = sp->_echo; - oldraw = sp->_raw; - oldcbreak = sp->_cbreak; - nl(); - noecho(); - noraw(); - cbreak(); + NCURSES_SP_NAME(_nc_get_tty_mode) (NCURSES_SP_ARGx &buf); - erasec = erasechar(); - killc = killchar(); + save_flags = sp->_tty_flags; + NCURSES_SP_NAME(nl) (NCURSES_SP_ARG); + NCURSES_SP_NAME(noecho) (NCURSES_SP_ARG); + if (!save_flags._raw) + NCURSES_SP_NAME(cbreak) (NCURSES_SP_ARG); + + erasec = NCURSES_SP_NAME(erasechar) (NCURSES_SP_ARG); + killc = NCURSES_SP_NAME(killchar) (NCURSES_SP_ARG); oldstr = str; getyx(win, y, x); @@ -114,7 +114,7 @@ wgetnstr_events(WINDOW *win, while ((ch = wgetch_events(win, evl)) != ERR) { /* * Some terminals (the Wyse-50 is the most common) generate - * a \n from the down-arrow key. With this logic, it's the + * a \n from the down-arrow key. With this logic, it is the * user's choice whether to set kcud=\n for wgetch(); * terminating *getstr() with \n should work either way. */ @@ -122,7 +122,7 @@ wgetnstr_events(WINDOW *win, || ch == '\r' || ch == KEY_DOWN || ch == KEY_ENTER) { - if (oldecho == TRUE + if (save_flags._echo == TRUE && win->_cury == win->_maxy && win->_scroll) wechochar(win, (chtype) '\n'); @@ -138,18 +138,18 @@ wgetnstr_events(WINDOW *win, #endif if (ch == erasec || ch == KEY_LEFT || ch == KEY_BACKSPACE) { if (str > oldstr) { - str = WipeOut(win, y, x, oldstr, str, oldecho); + str = WipeOut(win, y, x, oldstr, str, save_flags._echo); } } else if (ch == killc) { while (str > oldstr) { - str = WipeOut(win, y, x, oldstr, str, oldecho); + str = WipeOut(win, y, x, oldstr, str, save_flags._echo); } } else if (ch >= KEY_MIN - || (maxlen >= 0 && str - oldstr >= maxlen)) { - beep(); + || (str - oldstr >= maxlen)) { + NCURSES_SP_NAME(beep) (NCURSES_SP_ARG); } else { *str++ = (char) ch; - if (oldecho == TRUE) { + if (save_flags._echo == TRUE) { int oldy = win->_cury; if (waddch(win, (chtype) ch) == ERR) { /* @@ -159,9 +159,9 @@ wgetnstr_events(WINDOW *win, */ win->_flags &= ~_WRAPPED; waddch(win, (chtype) ' '); - str = WipeOut(win, y, x, oldstr, str, oldecho); + str = WipeOut(win, y, x, oldstr, str, save_flags._echo); continue; - } else if (win->_flags & _WRAPPED) { + } else if (IS_WRAPPED(win)) { /* * If the last waddch forced a wrap & * scroll, adjust our reference point @@ -190,12 +190,8 @@ wgetnstr_events(WINDOW *win, /* Restore with a single I/O call, to fix minor asymmetry between * raw/noraw, etc. */ - sp->_nl = oldnl; - sp->_echo = oldecho; - sp->_raw = oldraw; - sp->_cbreak = oldcbreak; - - _nc_set_tty_mode(&buf); + sp->_tty_flags = save_flags; + NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf); *str = '\0'; if (ch == ERR) diff --git a/lib/libcurses/base/lib_hline.c b/lib/libcurses/base/lib_hline.c index 58d83488068..368a319b016 100644 --- a/lib/libcurses/base/lib_hline.c +++ b/lib/libcurses/base/lib_hline.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_hline.c,v 1.5 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_hline.c,v 1.6 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2001,2006 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +32,8 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-on * + * and: Sven Verdoolaege 2001 * ****************************************************************************/ /* @@ -42,23 +45,21 @@ #include -MODULE_ID("$Id: lib_hline.c,v 1.5 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_hline.c,v 1.6 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) whline(WINDOW *win, chtype ch, int n) { int code = ERR; - NCURSES_SIZE_T start; - NCURSES_SIZE_T end; - T((T_CALLED("whline(%p,%s,%d)"), win, _tracechtype(ch), n)); + T((T_CALLED("whline(%p,%s,%d)"), (void *) win, _tracechtype(ch), n)); if (win) { struct ldat *line = &(win->_line[win->_cury]); NCURSES_CH_T wch; + int start = win->_curx; + int end = start + n - 1; - start = win->_curx; - end = start + n - 1; if (end > win->_maxx) end = win->_maxx; @@ -70,6 +71,14 @@ whline(WINDOW *win, chtype ch, int n) SetChar2(wch, ch); wch = _nc_render(win, wch); +#if USE_WIDEC_SUPPORT + if (start > 0 && isWidecExt(line->text[start])) { + SetChar2(line->text[start - 1], ' '); + } + if (end < win->_maxx && isWidecExt(line->text[end + 1])) { + SetChar2(line->text[end + 1], ' '); + } +#endif while (end >= start) { line->text[end] = wch; end--; diff --git a/lib/libcurses/base/lib_immedok.c b/lib/libcurses/base/lib_immedok.c index 53effcbad16..ee88d9ceac8 100644 --- a/lib/libcurses/base/lib_immedok.c +++ b/lib/libcurses/base/lib_immedok.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_immedok.c,v 1.3 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_immedok.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2000,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -42,12 +43,12 @@ #include -MODULE_ID("$Id: lib_immedok.c,v 1.3 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_immedok.c,v 1.4 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(void) immedok(WINDOW *win, bool flag) { - T((T_CALLED("immedok(%p,%d)"), win, flag)); + T((T_CALLED("immedok(%p,%d)"), (void *) win, flag)); if (win) win->_immed = flag; diff --git a/lib/libcurses/base/lib_inchstr.c b/lib/libcurses/base/lib_inchstr.c index 87fddea809f..fef2646be10 100644 --- a/lib/libcurses/base/lib_inchstr.c +++ b/lib/libcurses/base/lib_inchstr.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_inchstr.c,v 1.3 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_inchstr.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000,2001 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2010,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +32,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ /* @@ -42,25 +44,28 @@ #include -MODULE_ID("$Id: lib_inchstr.c,v 1.3 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_inchstr.c,v 1.4 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) -winchnstr(WINDOW *win, chtype * str, int n) +winchnstr(WINDOW *win, chtype *str, int n) { int i = 0; - T((T_CALLED("winchnstr(%p,%p,%d)"), win, str, n)); + T((T_CALLED("winchnstr(%p,%p,%d)"), (void *) win, (void *) str, n)); - if (!str) - returnCode(0); + if (!win || !str) { + i = ERR; + } else { + int row = win->_cury; + int col = win->_curx; + NCURSES_CH_T *text = win->_line[row].text; - if (win) { - for (; (n < 0 || (i < n)) && (win->_curx + i <= win->_maxx); i++) - str[i] = - CharOf(win->_line[win->_cury].text[win->_curx + i]) | - AttrOf(win->_line[win->_cury].text[win->_curx + i]); + for (; (n < 0 || (i < n)) && (col + i <= win->_maxx); i++) { + str[i] = (((chtype) CharOf(text[col + i]) & A_CHARTEXT) | + AttrOf(text[col + i])); + } + str[i] = (chtype) 0; } - str[i] = (chtype) 0; returnCode(i); } diff --git a/lib/libcurses/base/lib_initscr.c b/lib/libcurses/base/lib_initscr.c index 6f8fa785065..53b927e3c1f 100644 --- a/lib/libcurses/base/lib_initscr.c +++ b/lib/libcurses/base/lib_initscr.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_initscr.c,v 1.3 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_initscr.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2019,2020 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,7 +32,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * - * and: Thomas E. Dickey 1996-2003 * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ /* @@ -47,15 +48,13 @@ #include /* needed for ISC */ #endif -MODULE_ID("$Id: lib_initscr.c,v 1.3 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_initscr.c,v 1.4 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(WINDOW *) initscr(void) { WINDOW *result; - NCURSES_CONST char *name; - START_TRACE(); T((T_CALLED("initscr()"))); @@ -64,11 +63,18 @@ initscr(void) /* Portable applications must not call initscr() more than once */ if (!_nc_globals.init_screen) { + const char *env; + char *name; + _nc_globals.init_screen = TRUE; - if ((name = getenv("TERM")) == 0 - || *name == '\0') - name = "unknown"; + env = getenv("TERM"); + (void) VALID_TERM_ENV(env, "unknown"); + + if ((name = strdup(env)) == NULL) { + fprintf(stderr, "Error opening allocating $TERM.\n"); + ExitProgram(EXIT_FAILURE); + } #ifdef __CYGWIN__ /* * 2002/9/21 @@ -77,9 +83,9 @@ initscr(void) * core when attempting to write to stdout. Opening /dev/tty * explicitly seems to fix the problem. */ - if (isatty(fileno(stdout))) { + if (NC_ISATTY(fileno(stdout))) { FILE *fp = fopen("/dev/tty", "w"); - if (fp != 0 && isatty(fileno(fp))) { + if (fp != 0 && NC_ISATTY(fileno(fp))) { fclose(stdout); dup2(fileno(fp), STDOUT_FILENO); stdout = fdopen(STDOUT_FILENO, "w"); @@ -88,11 +94,16 @@ initscr(void) #endif if (newterm(name, stdout, stdin) == 0) { fprintf(stderr, "Error opening terminal: %s.\n", name); - exit(EXIT_FAILURE); + ExitProgram(EXIT_FAILURE); } /* def_shell_mode - done in newterm/_nc_setupscreen */ +#if NCURSES_SP_FUNCS + NCURSES_SP_NAME(def_prog_mode) (CURRENT_SCREEN); +#else def_prog_mode(); +#endif + free(name); } result = stdscr; _nc_unlock_global(curses); diff --git a/lib/libcurses/base/lib_insch.c b/lib/libcurses/base/lib_insch.c index d0b7404c331..0920e2dcc3d 100644 --- a/lib/libcurses/base/lib_insch.c +++ b/lib/libcurses/base/lib_insch.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_insch.c,v 1.3 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_insch.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2008 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2013,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -45,24 +46,31 @@ #include #include -MODULE_ID("$Id: lib_insch.c,v 1.3 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_insch.c,v 1.4 2023/10/17 09:52:08 nicm Exp $") /* * Insert the given character, updating the current location to simplify * inserting a string. */ NCURSES_EXPORT(int) -_nc_insert_ch(WINDOW *win, chtype ch) +_nc_insert_ch(SCREEN *sp, WINDOW *win, chtype ch) { int code = OK; + int ch8 = (int) ChCharOf(ch); NCURSES_CH_T wch; int count; - NCURSES_CONST char *s; + int tabsize = ( +#if USE_REENTRANT + sp->_TABSIZE +#else + TABSIZE +#endif + ); switch (ch) { case '\t': - for (count = (TABSIZE - (win->_curx % TABSIZE)); count > 0; count--) { - if ((code = _nc_insert_ch(win, ' ')) != OK) + for (count = (tabsize - (win->_curx % tabsize)); count > 0; count--) { + if ((code = _nc_insert_ch(sp, win, ' ')) != OK) break; } break; @@ -77,8 +85,9 @@ _nc_insert_ch(WINDOW *win, chtype ch) #if USE_WIDEC_SUPPORT WINDOW_EXT(win, addch_used) == 0 && #endif - is8bits(ChCharOf(ch)) && - isprint(ChCharOf(ch))) { + (isprint(ch8) || + (ChAttrOf(ch) & A_ALTCHARSET) || + (sp != 0 && sp->_legacy_coding && !iscntrl(ch8)))) { if (win->_curx <= win->_maxx) { struct ldat *line = &(win->_line[win->_cury]); NCURSES_CH_T *end = &(line->text[win->_curx]); @@ -94,10 +103,11 @@ _nc_insert_ch(WINDOW *win, chtype ch) *temp1 = _nc_render(win, wch); win->_curx++; } - } else if (is8bits(ChCharOf(ch)) && iscntrl(ChCharOf(ch))) { - s = unctrl(ChCharOf(ch)); + } else if (iscntrl(ch8)) { + NCURSES_CONST char *s; + s = NCURSES_SP_NAME(unctrl) (NCURSES_SP_ARGx (chtype) ch8); while (*s != '\0') { - code = _nc_insert_ch(win, ChAttrOf(ch) | UChar(*s)); + code = _nc_insert_ch(sp, win, ChAttrOf(ch) | UChar(*s)); if (code != OK) break; ++s; @@ -112,13 +122,15 @@ _nc_insert_ch(WINDOW *win, chtype ch) wch = _nc_render(win, wch); count = _nc_build_wch(win, &wch); if (count > 0) { - code = wins_wch(win, &wch); + code = _nc_insert_wch(win, &wch); } else if (count == -1) { + NCURSES_CONST char *s; /* handle EILSEQ */ - if (is8bits(ch)) { - s = unctrl(ChCharOf(ch)); + s = NCURSES_SP_NAME(unctrl) (NCURSES_SP_ARGx (chtype) ch8); + if (strlen(s) > 1) { while (*s != '\0') { - code = _nc_insert_ch(win, ChAttrOf(ch) | UChar(*s)); + code = _nc_insert_ch(sp, win, + ChAttrOf(ch) | UChar(*s)); if (code != OK) break; ++s; @@ -137,17 +149,15 @@ _nc_insert_ch(WINDOW *win, chtype ch) NCURSES_EXPORT(int) winsch(WINDOW *win, chtype c) { - NCURSES_SIZE_T oy; - NCURSES_SIZE_T ox; int code = ERR; - T((T_CALLED("winsch(%p, %s)"), win, _tracechtype(c))); + T((T_CALLED("winsch(%p, %s)"), (void *) win, _tracechtype(c))); if (win != 0) { - oy = win->_cury; - ox = win->_curx; + NCURSES_SIZE_T oy = win->_cury; + NCURSES_SIZE_T ox = win->_curx; - code = _nc_insert_ch(win, c); + code = _nc_insert_ch(_nc_screen_of(win), win, c); win->_curx = ox; win->_cury = oy; diff --git a/lib/libcurses/base/lib_insdel.c b/lib/libcurses/base/lib_insdel.c index dc121093809..baa057bd9c1 100644 --- a/lib/libcurses/base/lib_insdel.c +++ b/lib/libcurses/base/lib_insdel.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_insdel.c,v 1.3 2010/01/12 23:22:05 nicm Exp $ */ +/* $OpenBSD: lib_insdel.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2001,2003 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2003,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -44,14 +45,14 @@ #include -MODULE_ID("$Id: lib_insdel.c,v 1.3 2010/01/12 23:22:05 nicm Exp $") +MODULE_ID("$Id: lib_insdel.c,v 1.4 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) winsdelln(WINDOW *win, int n) { int code = ERR; - T((T_CALLED("winsdelln(%p,%d)"), win, n)); + T((T_CALLED("winsdelln(%p,%d)"), (void *) win, n)); if (win) { if (n != 0) { diff --git a/lib/libcurses/base/lib_insnstr.c b/lib/libcurses/base/lib_insnstr.c index 3929d148699..03b00d9b3e9 100644 --- a/lib/libcurses/base/lib_insnstr.c +++ b/lib/libcurses/base/lib_insnstr.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_insnstr.c,v 1.1 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_insnstr.c,v 1.2 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2004 Free Software Foundation, Inc. * + * Copyright 2018-2020,2022 Thomas E. Dickey * + * Copyright 2004-2009,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -42,29 +43,56 @@ #include #include -MODULE_ID("$Id: lib_insnstr.c,v 1.1 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_insnstr.c,v 1.2 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) winsnstr(WINDOW *win, const char *s, int n) { int code = ERR; - NCURSES_SIZE_T oy; - NCURSES_SIZE_T ox; const unsigned char *str = (const unsigned char *) s; - const unsigned char *cp; - T((T_CALLED("winsnstr(%p,%s,%d)"), win, _nc_visbufn(s, n), n)); + T((T_CALLED("winsnstr(%p,%s,%d)"), (void *) win, _nc_visbufn(s, n), n)); if (win != 0 && str != 0) { - oy = win->_cury; - ox = win->_curx; - for (cp = str; *cp && (n <= 0 || (cp - str) < n); cp++) { - _nc_insert_ch(win, (chtype) UChar(*cp)); + SCREEN *sp = _nc_screen_of(win); +#if USE_WIDEC_SUPPORT + /* + * If the output contains "wide" (multibyte) characters, we will not + * really know the width of a character until we get the last byte + * of the character. Since the preceding byte(s) may use more columns + * on the screen than the final character, it is best to route the + * call to the wins_nwstr() function. + */ + if (sp->_screen_unicode) { + size_t nn = (n > 0) ? (size_t) n : strlen(s); + wchar_t *buffer = typeMalloc(wchar_t, nn + 1); + if (buffer != 0) { + mbstate_t state; + size_t n3; + init_mb(state); + n3 = mbstowcs(buffer, s, nn); + if (n3 != (size_t) (-1)) { + buffer[n3] = '\0'; + code = wins_nwstr(win, buffer, (int) n3); + } + free(buffer); + } + } + if (code == ERR) +#endif + { + NCURSES_SIZE_T oy = win->_cury; + NCURSES_SIZE_T ox = win->_curx; + const unsigned char *cp; + + for (cp = str; (n <= 0 || (cp - str) < n) && *cp; cp++) { + _nc_insert_ch(sp, win, (chtype) UChar(*cp)); + } + win->_curx = ox; + win->_cury = oy; + _nc_synchook(win); + code = OK; } - win->_curx = ox; - win->_cury = oy; - _nc_synchook(win); - code = OK; } returnCode(code); } diff --git a/lib/libcurses/base/lib_instr.c b/lib/libcurses/base/lib_instr.c index bf943ad4b24..572f4bbf0da 100644 --- a/lib/libcurses/base/lib_instr.c +++ b/lib/libcurses/base/lib_instr.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_instr.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_instr.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2007 Free Software Foundation, Inc. * + * Copyright 2020-2021,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -43,56 +44,65 @@ #include -MODULE_ID("$Id: lib_instr.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_instr.c,v 1.4 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) winnstr(WINDOW *win, char *str, int n) { - int i = 0, row, col; + int i = 0; - T((T_CALLED("winnstr(%p,%p,%d)"), win, str, n)); + T((T_CALLED("winnstr(%p,%p,%d)"), (void *) win, str, n)); - if (!str) - returnCode(0); - - if (win) { - getyx(win, row, col); + if (!win || !str) { + i = ERR; + } else { + int row = win->_cury; + int col = win->_curx; + NCURSES_CH_T *text = win->_line[row].text; if (n < 0) - n = win->_maxx - win->_curx + 1; + n = win->_maxx - col + 1; for (; i < n;) { #if USE_WIDEC_SUPPORT - cchar_t *cell = &(win->_line[row].text[col]); - wchar_t *wch; + cchar_t *cell = &(text[col]); attr_t attrs; - short pair; - int n2; - bool done = FALSE; - mbstate_t state; - size_t i3, n3; + NCURSES_PAIRS_T pair; char *tmp; if (!isWidecExt(*cell)) { + wchar_t *wch; + int n2; + n2 = getcchar(cell, 0, 0, 0, 0); if (n2 > 0 && (wch = typeCalloc(wchar_t, (unsigned) n2 + 1)) != 0) { + bool done = FALSE; + if (getcchar(cell, wch, &attrs, &pair, 0) == OK) { + mbstate_t state; + size_t n3; init_mb(state); - n3 = wcstombs(0, wch, 0); - if (isEILSEQ(n3) || (n3 == 0)) { - ; - } else if ((int) (n3 + i) > n) { - done = TRUE; - } else if ((tmp = typeCalloc(char, n3 + 10)) == 0) { - done = TRUE; - } else { - init_mb(state); - wcstombs(tmp, wch, n3); - for (i3 = 0; i3 < n3; ++i3) - str[i++] = tmp[i3]; - free(tmp); + n3 = wcstombs(0, wch, (size_t) 0); + if (!isEILSEQ(n3) && (n3 != 0) && (n3 <= MB_LEN_MAX)) { + size_t need = n3 + 10 + (size_t) i; + int have = (int) n3 + i; + + /* check for loop-done as well as overflow */ + if (have > n || (int) need <= 0) { + done = TRUE; + } else if ((tmp = typeCalloc(char, need)) == 0) { + done = TRUE; + } else { + size_t i3; + + init_mb(state); + wcstombs(tmp, wch, n3); + for (i3 = 0; i3 < n3; ++i3) + str[i++] = tmp[i3]; + free(tmp); + } } } free(wch); @@ -101,14 +111,14 @@ winnstr(WINDOW *win, char *str, int n) } } #else - str[i++] = (char) CharOf(win->_line[row].text[col]); + str[i++] = (char) CharOf(text[col]); #endif if (++col > win->_maxx) { break; } } + str[i] = '\0'; /* SVr4 does not seem to count the null */ } - str[i] = '\0'; /* SVr4 does not seem to count the null */ T(("winnstr returns %s", _nc_visbuf(str))); returnCode(i); } diff --git a/lib/libcurses/base/lib_isendwin.c b/lib/libcurses/base/lib_isendwin.c index 2c8421e5298..894a6806f08 100644 --- a/lib/libcurses/base/lib_isendwin.c +++ b/lib/libcurses/base/lib_isendwin.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_isendwin.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_isendwin.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2009,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +32,8 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -42,12 +45,20 @@ #include -MODULE_ID("$Id: lib_isendwin.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_isendwin.c,v 1.4 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(bool) -isendwin(void) +NCURSES_SP_NAME(isendwin) (NCURSES_SP_DCL0) { - if (SP == NULL) + if (SP_PARM == NULL) return FALSE; - return SP->_endwin; + return (SP_PARM->_endwin == ewSuspend); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(bool) +isendwin(void) +{ + return NCURSES_SP_NAME(isendwin) (CURRENT_SCREEN); } +#endif diff --git a/lib/libcurses/base/lib_leaveok.c b/lib/libcurses/base/lib_leaveok.c index 8edde4dc459..378d93e6668 100644 --- a/lib/libcurses/base/lib_leaveok.c +++ b/lib/libcurses/base/lib_leaveok.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_leaveok.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_leaveok.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2000,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -42,12 +43,12 @@ #include -MODULE_ID("$Id: lib_leaveok.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_leaveok.c,v 1.4 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) leaveok(WINDOW *win, bool flag) { - T((T_CALLED("leaveok(%p,%d)"), win, flag)); + T((T_CALLED("leaveok(%p,%d)"), (void *) win, flag)); if (win) { win->_leaveok = flag; diff --git a/lib/libcurses/base/lib_mouse.c b/lib/libcurses/base/lib_mouse.c index fe5278dd0df..efa86101646 100644 --- a/lib/libcurses/base/lib_mouse.c +++ b/lib/libcurses/base/lib_mouse.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_mouse.c,v 1.14 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_mouse.c,v 1.15 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,6 +33,7 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2008 * ****************************************************************************/ /* @@ -81,9 +83,12 @@ #include -MODULE_ID("$Id: lib_mouse.c,v 1.14 2010/01/12 23:22:06 nicm Exp $") +#ifndef CUR +#define CUR SP_TERMTYPE +#endif + +MODULE_ID("$Id: lib_mouse.c,v 1.15 2023/10/17 09:52:08 nicm Exp $") -#include #include #if USE_GPM_SUPPORT @@ -110,7 +115,7 @@ make an error #undef buttons /* symbol conflict in consio.h */ #undef mouse_info /* symbol conflict in consio.h */ #include -#if (__FreeBSD_version >= 400017) +#if defined(__DragonFly_version) || (defined(__FreeBSD__) && (__FreeBSD_version >= 400017)) #include #include #else @@ -118,41 +123,65 @@ make an error #endif #endif /* use_SYSMOUSE */ +#if USE_KLIBC_MOUSE +#include +#define pipe(handles) socketpair(AF_LOCAL, SOCK_STREAM, 0, handles) +#define DosWrite(hfile, pbuffer, cbwrite, pcbactual) \ + write(hfile, pbuffer, cbwrite) +#define DosExit(action, result ) /* do nothing */ +#define DosCreateThread(ptid, pfn, param, flag, cbStack) \ + (*(ptid) = _beginthread(pfn, NULL, cbStack, \ + (void *)param), (*(ptid) == -1)) +#endif + #define MY_TRACE TRACE_ICALLS|TRACE_IEVENT -#define MASK_RELEASE(x) NCURSES_MOUSE_MASK(x, 001) -#define MASK_PRESS(x) NCURSES_MOUSE_MASK(x, 002) -#define MASK_CLICK(x) NCURSES_MOUSE_MASK(x, 004) -#define MASK_DOUBLE_CLICK(x) NCURSES_MOUSE_MASK(x, 010) -#define MASK_TRIPLE_CLICK(x) NCURSES_MOUSE_MASK(x, 020) -#define MASK_RESERVED_EVENT(x) NCURSES_MOUSE_MASK(x, 040) +#define MASK_RELEASE(x) (mmask_t) NCURSES_MOUSE_MASK(x, 001) +#define MASK_PRESS(x) (mmask_t) NCURSES_MOUSE_MASK(x, 002) +#define MASK_CLICK(x) (mmask_t) NCURSES_MOUSE_MASK(x, 004) +#define MASK_DOUBLE_CLICK(x) (mmask_t) NCURSES_MOUSE_MASK(x, 010) +#define MASK_TRIPLE_CLICK(x) (mmask_t) NCURSES_MOUSE_MASK(x, 020) +#define MASK_RESERVED_EVENT(x) (mmask_t) NCURSES_MOUSE_MASK(x, 040) #if NCURSES_MOUSE_VERSION == 1 + #define BUTTON_CLICKED (BUTTON1_CLICKED | BUTTON2_CLICKED | BUTTON3_CLICKED | BUTTON4_CLICKED) #define BUTTON_PRESSED (BUTTON1_PRESSED | BUTTON2_PRESSED | BUTTON3_PRESSED | BUTTON4_PRESSED) #define BUTTON_RELEASED (BUTTON1_RELEASED | BUTTON2_RELEASED | BUTTON3_RELEASED | BUTTON4_RELEASED) #define BUTTON_DOUBLE_CLICKED (BUTTON1_DOUBLE_CLICKED | BUTTON2_DOUBLE_CLICKED | BUTTON3_DOUBLE_CLICKED | BUTTON4_DOUBLE_CLICKED) #define BUTTON_TRIPLE_CLICKED (BUTTON1_TRIPLE_CLICKED | BUTTON2_TRIPLE_CLICKED | BUTTON3_TRIPLE_CLICKED | BUTTON4_TRIPLE_CLICKED) + #define MAX_BUTTONS 4 + #else + #define BUTTON_CLICKED (BUTTON1_CLICKED | BUTTON2_CLICKED | BUTTON3_CLICKED | BUTTON4_CLICKED | BUTTON5_CLICKED) #define BUTTON_PRESSED (BUTTON1_PRESSED | BUTTON2_PRESSED | BUTTON3_PRESSED | BUTTON4_PRESSED | BUTTON5_PRESSED) #define BUTTON_RELEASED (BUTTON1_RELEASED | BUTTON2_RELEASED | BUTTON3_RELEASED | BUTTON4_RELEASED | BUTTON5_RELEASED) #define BUTTON_DOUBLE_CLICKED (BUTTON1_DOUBLE_CLICKED | BUTTON2_DOUBLE_CLICKED | BUTTON3_DOUBLE_CLICKED | BUTTON4_DOUBLE_CLICKED | BUTTON5_DOUBLE_CLICKED) #define BUTTON_TRIPLE_CLICKED (BUTTON1_TRIPLE_CLICKED | BUTTON2_TRIPLE_CLICKED | BUTTON3_TRIPLE_CLICKED | BUTTON4_TRIPLE_CLICKED | BUTTON5_TRIPLE_CLICKED) + +#if NCURSES_MOUSE_VERSION == 2 #define MAX_BUTTONS 5 +#else +#define MAX_BUTTONS 11 +#endif + #endif #define INVALID_EVENT -1 #define NORMAL_EVENT 0 +#define ValidEvent(ep) ((ep)->id != INVALID_EVENT) +#define Invalidate(ep) (ep)->id = INVALID_EVENT + #if USE_GPM_SUPPORT #ifndef LIBGPM_SONAME #define LIBGPM_SONAME "libgpm.so" #endif -#define GET_DLSYM(name) (my_##name = (TYPE_##name) dlsym(SP->_dlopen_gpm, #name)) +#define GET_DLSYM(name) (my_##name = (TYPE_##name) dlsym(sp->_dlopen_gpm, #name)) #endif /* USE_GPM_SUPPORT */ @@ -166,13 +195,13 @@ static void _nc_mouse_wrap(SCREEN *); #define LastEV(sp) ((sp)->_mouse_events + EV_MAX - 1) #undef NEXT -#define NEXT(ep) ((ep >= LastEV(sp)) \ - ? FirstEV(sp) \ +#define NEXT(ep) ((ep >= LastEV(SP_PARM)) \ + ? FirstEV(SP_PARM) \ : ep + 1) #undef PREV -#define PREV(ep) ((ep <= FirstEV(sp)) \ - ? LastEV(sp) \ +#define PREV(ep) ((ep <= FirstEV(SP_PARM)) \ + ? LastEV(SP_PARM) \ : ep - 1) #define IndexEV(sp, ep) (ep - FirstEV(sp)) @@ -187,7 +216,7 @@ _trace_slot(SCREEN *sp, const char *tag) { MEVENT *ep; - _tracef(tag); + _tracef("%s", tag); for (ep = FirstEV(sp); ep <= LastEV(sp); ep++) _tracef("mouse event queue slot %ld = %s", @@ -209,7 +238,7 @@ write_event(SCREEN *sp, int down, int button, int x, int y) char buf[6]; unsigned long ignore; - strncpy(buf, key_mouse, 3); /* should be "\033[M" */ + _nc_STRCPY(buf, "\033[M", sizeof(buf)); /* should be the same as key_mouse */ buf[3] = ' ' + (button - 1) + (down ? 0 : 0x40); buf[4] = ' ' + x - LEFT_COL + 1; buf[5] = ' ' + y - TOP_ROW + 1; @@ -217,7 +246,11 @@ write_event(SCREEN *sp, int down, int button, int x, int y) } static void +#if USE_KLIBC_MOUSE +mouse_server(void *param) +#else mouse_server(unsigned long param) +#endif { SCREEN *sp = (SCREEN *) param; unsigned short fWait = MOU_WAIT; @@ -243,7 +276,8 @@ mouse_server(unsigned long param) /* sit and wait on the event queue */ rc = MouReadEventQue(&mouev, &fWait, hmou); if (rc) { - snprintf(err, sizeof(err), "Error reading mouse queue, rc=%lu.\r\n", rc); + _nc_SPRINTF(err, _nc_SLIMIT(sizeof(err)) + "Error reading mouse queue, rc=%lu.\r\n", rc); break; } if (!sp->_emxmouse_activated) @@ -269,9 +303,11 @@ mouse_server(unsigned long param) finish: oldstate = mouev.fs; } - } else - snprintf(err, sizeof(err), "Error setting event mask, buttons=%d, rc=%lu.\r\n", - nbuttons, rc); + } else { + _nc_SPRINTF(err, _nc_SLIMIT(sizeof(err)) + "Error setting event mask, buttons=%d, rc=%lu.\r\n", + nbuttons, rc); + } DosWrite(2, err, strlen(err), &rc); MouClose(hmou); @@ -342,40 +378,113 @@ sysmouse_server(SCREEN *sp) static void handle_sysmouse(int sig GCC_UNUSED) { - sysmouse_server(SP); + sysmouse_server(CURRENT_SCREEN); } #endif /* USE_SYSMOUSE */ +#if !defined(USE_TERM_DRIVER) || defined(EXP_WIN32_DRIVER) +#define xterm_kmous "\033[M" + static void init_xterm_mouse(SCREEN *sp) { sp->_mouse_type = M_XTERM; + sp->_mouse_format = MF_X10; sp->_mouse_xtermcap = tigetstr("XM"); - if (!VALID_STRING(sp->_mouse_xtermcap)) - sp->_mouse_xtermcap = "\033[?1000%?%p1%{1}%=%th%el%;"; + if (VALID_STRING(sp->_mouse_xtermcap)) { + char *code = strstr(sp->_mouse_xtermcap, "[?"); + if (code != 0) { + code += 2; + while ((*code >= '0') && (*code <= '9')) { + char *next = code; + while ((*next >= '0') && (*next <= '9')) { + ++next; + } + if (!strncmp(code, "1006", (size_t) (next - code))) { + sp->_mouse_format = MF_SGR1006; + } +#ifdef EXP_XTERM_1005 + if (!strncmp(code, "1005", (size_t) (next - code))) { + sp->_mouse_format = MF_XTERM_1005; + } +#endif + if (*next == ';') { + while (*next == ';') { + ++next; + } + code = next; + } else { + break; + } + } + } + } else { + int code = tigetnum("XM"); + switch (code) { +#ifdef EXP_XTERM_1005 + case 1005: + /* see "xterm+sm+1005" */ + sp->_mouse_xtermcap = "\033[?1005;1000%?%p1%{1}%=%th%el%;"; + sp->_mouse_format = MF_XTERM_1005; + break; +#endif + case 1006: + /* see "xterm+sm+1006" */ + sp->_mouse_xtermcap = "\033[?1006;1000%?%p1%{1}%=%th%el%;"; + sp->_mouse_format = MF_SGR1006; + break; + default: + sp->_mouse_xtermcap = "\033[?1000%?%p1%{1}%=%th%el%;"; + break; + } + } } +#endif static void enable_xterm_mouse(SCREEN *sp, int enable) { + TPUTS_TRACE(enable + ? "xterm mouse initialization" + : "xterm mouse deinitialization"); #if USE_EMX_MOUSE sp->_emxmouse_activated = enable; #else - putp(TPARM_1(sp->_mouse_xtermcap, enable)); + NCURSES_PUTP2("xterm-mouse", TIPARM_1(sp->_mouse_xtermcap, enable)); #endif sp->_mouse_active = enable; } +#if defined(USE_TERM_DRIVER) +static void +enable_win32_mouse(SCREEN *sp, int enable) +{ +#if defined(EXP_WIN32_DRIVER) + enable_xterm_mouse(sp, enable); +#else + sp->_mouse_active = enable; +#endif +} +#endif + #if USE_GPM_SUPPORT static bool -allow_gpm_mouse(void) +allow_gpm_mouse(SCREEN *sp GCC_UNUSED) { bool result = FALSE; - /* GPM does printf's without checking if stdout is a terminal */ - if (isatty(fileno(stdout))) { - char *list = getenv("NCURSES_GPM_TERMS"); - char *env = getenv("TERM"); +#if USE_WEAK_SYMBOLS + /* Danger Robinson: do not use dlopen for libgpm if already loaded */ + if ((Gpm_Wgetch) != 0) { + if (!sp->_mouse_gpm_loaded) { + T(("GPM library was already dlopen'd, not by us")); + } + } else +#endif + /* GPM does printf's without checking if stdout is a terminal */ + if (NC_ISATTY(fileno(stdout))) { + const char *list = getenv("NCURSES_GPM_TERMS"); + const char *env = getenv("TERM"); if (list != 0) { if (env != 0) { result = _nc_name_match(list, env, "|:"); @@ -400,12 +509,10 @@ allow_gpm_mouse(void) static void unload_gpm_library(SCREEN *sp) { - if (SP->_dlopen_gpm != 0) { + if (sp->_dlopen_gpm != 0) { T(("unload GPM library")); sp->_mouse_gpm_loaded = FALSE; sp->_mouse_fd = -1; - dlclose(sp->_dlopen_gpm); - sp->_dlopen_gpm = 0; } } @@ -413,20 +520,36 @@ static void load_gpm_library(SCREEN *sp) { sp->_mouse_gpm_found = FALSE; - if ((sp->_dlopen_gpm = dlopen(LIBGPM_SONAME, my_RTLD)) != 0) { + + /* + * If we already had a successful dlopen, reuse it. + */ + if (sp->_dlopen_gpm != 0) { + sp->_mouse_gpm_found = TRUE; + sp->_mouse_gpm_loaded = TRUE; + } else if ((sp->_dlopen_gpm = dlopen(LIBGPM_SONAME, my_RTLD)) != 0) { +#if (defined(__GNUC__) && (__GNUC__ >= 5)) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif if (GET_DLSYM(gpm_fd) == 0 || GET_DLSYM(Gpm_Open) == 0 || GET_DLSYM(Gpm_Close) == 0 || GET_DLSYM(Gpm_GetEvent) == 0) { +#if (defined(__GNUC__) && (__GNUC__ >= 5)) || defined(__clang__) +#pragma GCC diagnostic pop +#endif T(("GPM initialization failed: %s", dlerror())); unload_gpm_library(sp); + dlclose(sp->_dlopen_gpm); + sp->_dlopen_gpm = 0; } else { sp->_mouse_gpm_found = TRUE; sp->_mouse_gpm_loaded = TRUE; } } } -#endif +#endif /* HAVE_LIBDL */ static bool enable_gpm_mouse(SCREEN *sp, bool enable) @@ -442,6 +565,8 @@ enable_gpm_mouse(SCREEN *sp, bool enable) } #endif if (sp->_mouse_gpm_loaded) { + int code; + /* GPM: initialize connection to gpm server */ sp->_mouse_gpm_connect.eventMask = GPM_DOWN | GPM_UP; sp->_mouse_gpm_connect.defaultMask = @@ -456,7 +581,16 @@ enable_gpm_mouse(SCREEN *sp, bool enable) * The former is recognized by wscons (SunOS), and the latter by * xterm. Those will not show up in ncurses' traces. */ - result = (my_Gpm_Open(&sp->_mouse_gpm_connect, 0) >= 0); + code = my_Gpm_Open(&sp->_mouse_gpm_connect, 0); + result = (code >= 0); + + /* + * GPM can return a -2 if it is trying to do something with xterm. + * Ignore that, since it conflicts with our use of stdin. + */ + if (code == -2) { + my_Gpm_Close(); + } } else { result = FALSE; } @@ -480,8 +614,6 @@ enable_gpm_mouse(SCREEN *sp, bool enable) } #endif /* USE_GPM_SUPPORT */ -#define xterm_kmous "\033[M" - static void initialize_mousetype(SCREEN *sp) { @@ -489,7 +621,7 @@ initialize_mousetype(SCREEN *sp) /* Try gpm first, because gpm may be configured to run in xterm */ #if USE_GPM_SUPPORT - if (allow_gpm_mouse()) { + if (allow_gpm_mouse(sp)) { if (!sp->_mouse_gpm_loaded) { #ifdef HAVE_LIBDL load_gpm_library(sp); @@ -516,8 +648,8 @@ initialize_mousetype(SCREEN *sp) /* OS/2 VIO */ #if USE_EMX_MOUSE if (!sp->_emxmouse_thread - && strstr(cur_term->type.term_names, "xterm") == 0 - && key_mouse) { + && strstr(SP_TERMTYPE term_names, "xterm") == 0 + && NonEmpty(key_mouse)) { int handles[2]; if (pipe(handles) < 0) { @@ -527,7 +659,7 @@ initialize_mousetype(SCREEN *sp) int rc; if (!sp->_emxmouse_buttons[0]) { - char *s = getenv("MOUSE_BUTTONS_123"); + const char *s = getenv("MOUSE_BUTTONS_123"); sp->_emxmouse_buttons[0] = 1; if (s && strlen(s) >= 3) { @@ -560,13 +692,14 @@ initialize_mousetype(SCREEN *sp) #if USE_SYSMOUSE { + static char dev_tty[] = "/dev/tty"; struct mouse_info the_mouse; char *the_device = 0; - if (isatty(sp->_ifd)) + if (NC_ISATTY(sp->_ifd)) the_device = ttyname(sp->_ifd); if (the_device == 0) - the_device = "/dev/tty"; + the_device = dev_tty; sp->_mouse_fd = open(the_device, O_RDWR); @@ -623,16 +756,19 @@ initialize_mousetype(SCREEN *sp) } #endif /* USE_SYSMOUSE */ +#ifdef USE_TERM_DRIVER + CallDriver(sp, td_initmouse); +#endif +#if !defined(USE_TERM_DRIVER) || defined(EXP_WIN32_DRIVER) /* we know how to recognize mouse events under "xterm" */ - if (key_mouse != 0) { - if (!strcmp(key_mouse, xterm_kmous) - || strstr(cur_term->type.term_names, "xterm") != 0) { - init_xterm_mouse(sp); - } - } else if (strstr(cur_term->type.term_names, "xterm") != 0) { + if (NonEmpty(key_mouse)) { + init_xterm_mouse(sp); + } else if (strstr(SP_TERMTYPE term_names, "xterm") != 0) { if (_nc_add_to_try(&(sp->_keytry), xterm_kmous, KEY_MOUSE) == OK) init_xterm_mouse(sp); } +#endif + returnVoid; } @@ -641,25 +777,28 @@ _nc_mouse_init(SCREEN *sp) /* initialize the mouse */ { bool result = FALSE; - int i; + + T((T_CALLED("_nc_mouse_init(%p)"), (void *)sp)); if (sp != 0) { if (!sp->_mouse_initialized) { + int i; + sp->_mouse_initialized = TRUE; - TR(MY_TRACE, ("_nc_mouse_init() called")); + TR(MY_TRACE, ("set _mouse_initialized")); sp->_mouse_eventp = FirstEV(sp); for (i = 0; i < EV_MAX; i++) - sp->_mouse_events[i].id = INVALID_EVENT; + Invalidate(sp->_mouse_events + i); initialize_mousetype(sp); - T(("_nc_mouse_init() set mousetype to %d", sp->_mouse_type)); + T(("set _mouse_type to %d", sp->_mouse_type)); } result = sp->_mouse_initialized; } - return result; + returnCode(result); } /* @@ -667,7 +806,7 @@ _nc_mouse_init(SCREEN *sp) * fifo_push() in lib_getch.c */ static bool -_nc_mouse_event(SCREEN *sp GCC_UNUSED) +_nc_mouse_event(SCREEN *sp) { MEVENT *eventp = sp->_mouse_eventp; bool result = FALSE; @@ -696,11 +835,16 @@ _nc_mouse_event(SCREEN *sp GCC_UNUSED) #if USE_GPM_SUPPORT case M_GPM: - { + if (sp->_mouse_fd >= 0) { /* query server for event, return TRUE if we find one */ Gpm_Event ev; - if (my_Gpm_GetEvent(&ev) == 1) { + switch (my_Gpm_GetEvent(&ev)) { + case 0: + /* Connection closed, drop the mouse. */ + sp->_mouse_fd = -1; + break; + case 1: /* there's only one mouse... */ eventp->id = NORMAL_EVENT; @@ -723,6 +867,7 @@ _nc_mouse_event(SCREEN *sp GCC_UNUSED) eventp->bstate |= BUTTON3_RELEASED; break; default: + eventp->bstate |= REPORT_MOUSE_POSITION; break; } @@ -731,8 +876,9 @@ _nc_mouse_event(SCREEN *sp GCC_UNUSED) eventp->z = 0; /* bump the next-free pointer into the circular list */ - sp->_mouse_eventp = eventp = NEXT(eventp); + sp->_mouse_eventp = NEXT(eventp); result = TRUE; + break; } } break; @@ -761,6 +907,28 @@ _nc_mouse_event(SCREEN *sp GCC_UNUSED) break; #endif /* USE_SYSMOUSE */ +#ifdef USE_TERM_DRIVER + case M_TERM_DRIVER: + while (sp->_drv_mouse_head < sp->_drv_mouse_tail) { + *eventp = sp->_drv_mouse_fifo[sp->_drv_mouse_head]; + + /* + * Point the fifo-head to the next possible location. If there + * are none, reset the indices. + */ + sp->_drv_mouse_head += 1; + if (sp->_drv_mouse_head == sp->_drv_mouse_tail) { + sp->_drv_mouse_tail = 0; + sp->_drv_mouse_head = 0; + } + + /* bump the next-free pointer into the circular list */ + sp->_mouse_eventp = eventp = NEXT(eventp); + result = TRUE; + } + break; +#endif + case M_NONE: break; } @@ -768,148 +936,446 @@ _nc_mouse_event(SCREEN *sp GCC_UNUSED) return result; /* true if we found an event */ } +#if USE_EMX_MOUSE +#define PRESS_POSITION(n) \ + do { \ + eventp->bstate = MASK_PRESS(n); \ + sp->_mouse_bstate |= MASK_PRESS(n); \ + if (button & 0x40) { \ + eventp->bstate = MASK_RELEASE(n); \ + sp->_mouse_bstate &= ~MASK_PRESS(n); \ + } \ + } while (0) +#else +#define PRESS_POSITION(n) \ + do { \ + eventp->bstate = (mmask_t) ((sp->_mouse_bstate & MASK_PRESS(n)) \ + ? REPORT_MOUSE_POSITION \ + : MASK_PRESS(n)); \ + sp->_mouse_bstate |= MASK_PRESS(n); \ + } while (0) +#endif + static bool -_nc_mouse_inline(SCREEN *sp) -/* mouse report received in the keyboard stream -- parse its info */ +handle_wheel(SCREEN *sp, MEVENT * eventp, int button, int wheel) { - int b; - bool result = FALSE; - MEVENT *eventp = sp->_mouse_eventp; + bool result = TRUE; + + switch (button & 3) { + case 0: + if (wheel) { + eventp->bstate = MASK_PRESS(4); + /* Do not record in sp->_mouse_bstate; there will be no + * corresponding release event. + */ + } else { + PRESS_POSITION(1); + } + break; + case 1: + if (wheel) { +#if NCURSES_MOUSE_VERSION >= 2 + eventp->bstate = MASK_PRESS(5); + /* See comment above for button 4 */ +#else + /* Ignore this event as it is not a true press of the button */ + eventp->bstate = REPORT_MOUSE_POSITION; +#endif + } else { + PRESS_POSITION(2); + } + break; + case 2: + PRESS_POSITION(3); + break; + default: + /* + * case 3 is sent when the mouse buttons are released. + * + * If the terminal uses xterm mode 1003, a continuous series of + * button-release events is sent as the mouse moves around the screen, + * or as the wheel mouse is rotated. + * + * Return false in this case, so that when running in X10 mode, we will + * recalculate bstate. + */ + eventp->bstate = REPORT_MOUSE_POSITION; + result = FALSE; + break; + } + return result; +} - TR(MY_TRACE, ("_nc_mouse_inline() called")); +static bool +decode_X10_bstate(SCREEN *sp, MEVENT * eventp, unsigned intro) +{ + bool result; + int button = 0; + int wheel = (intro & 96) == 96; - if (sp->_mouse_type == M_XTERM) { - unsigned char kbuf[4]; - mmask_t prev; - size_t grabbed; - int res; + eventp->bstate = 0; - /* This code requires that your xterm entry contain the kmous - * capability and that it be set to the \E[M documented in the - * Xterm Control Sequences reference. This is how we - * arrange for mouse events to be reported via a KEY_MOUSE - * return value from wgetch(). After this value is received, - * _nc_mouse_inline() gets called and is immediately - * responsible for parsing the mouse status information - * following the prefix. - * - * The following quotes from the ctrlseqs.ms document in the - * X distribution, describing the X mouse tracking feature: - * - * Parameters for all mouse tracking escape sequences - * generated by xterm encode numeric parameters in a single - * character as value+040. For example, ! is 1. - * - * On button press or release, xterm sends ESC [ M CbCxCy. - * The low two bits of Cb encode button information: 0=MB1 - * pressed, 1=MB2 pressed, 2=MB3 pressed, 3=release. The - * upper bits encode what modifiers were down when the - * button was pressed and are added together. 4=Shift, - * 8=Meta, 16=Control. Cx and Cy are the x and y coordinates - * of the mouse event. The upper left corner is (1,1). - * - * (End quote) By the time we get here, we've eaten the - * key prefix. FYI, the loop below is necessary because - * mouse click info isn't guaranteed to present as a - * single clist item. - * - * Wheel mice may return buttons 4 and 5 when the wheel is turned. - * We encode those as button presses. + if (intro >= 96) { + if (intro >= 160) { + button = (int) (intro - 152); /* buttons 8-11 */ + } else { + button = (int) (intro - 92); /* buttons 4-7 */ + } + } else { + button = (intro & 3); + } + + if (button > MAX_BUTTONS) { + eventp->bstate = REPORT_MOUSE_POSITION; + } else if (!handle_wheel(sp, eventp, (int) intro, wheel)) { + + /* + * Release events aren't reported for individual buttons, just for + * the button set as a whole. However, because there are normally + * no mouse events under xterm that intervene between press and + * release, we can infer the button actually released by looking at + * the previous event. */ - for (grabbed = 0; grabbed < 3; grabbed += (size_t) res) { + if (sp->_mouse_bstate & BUTTON_PRESSED) { + int b; + + eventp->bstate = BUTTON_RELEASED; + for (b = 1; b <= MAX_BUTTONS; ++b) { + if (!(sp->_mouse_bstate & MASK_PRESS(b))) + eventp->bstate &= ~MASK_RELEASE(b); + } + sp->_mouse_bstate = 0; + } else { + /* + * xterm will return a stream of release-events to let the + * application know where the mouse is going, if private mode + * 1002 or 1003 is enabled. + */ + eventp->bstate = REPORT_MOUSE_POSITION; + } + } + + if (intro & 4) { + eventp->bstate |= BUTTON_SHIFT; + } + if (intro & 8) { + eventp->bstate |= BUTTON_ALT; + } + if (intro & 16) { + eventp->bstate |= BUTTON_CTRL; + } + result = (eventp->bstate & REPORT_MOUSE_POSITION) ? TRUE : FALSE; + return result; +} + +/* This code requires that your xterm entry contain the kmous capability and + * that it be set to the \E[M documented in the Xterm Control Sequences + * reference. This is how we arrange for mouse events to be reported via a + * KEY_MOUSE return value from wgetch(). After this value is received, + * _nc_mouse_inline() gets called and is immediately responsible for parsing + * the mouse status information following the prefix. + * + * The following quotes from the ctlseqs.ms document in the XTerm distribution, + * describing the mouse tracking feature: + * + * Parameters for all mouse tracking escape sequences generated by xterm encode + * numeric parameters in a single character as value+040. For example, ! is + * 1. + * + * On button press or release, xterm sends ESC [ M CbCxCy. The low two bits of + * Cb encode button information: 0=MB1 pressed, 1=MB2 pressed, 2=MB3 pressed, + * 3=release. The upper bits encode what modifiers were down when the button + * was pressed and are added together. 4=Shift, 8=Meta, 16=Control. Cx and Cy + * are the x and y coordinates of the mouse event. The upper left corner is + * (1,1). + * + * (End quote) By the time we get here, we've eaten the key prefix. FYI, the + * loop below is necessary because mouse click info isn't guaranteed to present + * as a single clist item. + * + * Wheel mice may return buttons 4 and 5 when the wheel is turned. We encode + * those as button presses. + */ +static bool +decode_xterm_X10(SCREEN *sp, MEVENT * eventp) +{ +#define MAX_KBUF 3 + unsigned char kbuf[MAX_KBUF + 1]; + size_t grabbed; + int res; + bool result; + + _nc_set_read_thread(TRUE); + for (grabbed = 0; grabbed < MAX_KBUF; grabbed += (size_t) res) { - /* For VIO mouse we add extra bit 64 to disambiguate button-up. */ + /* For VIO mouse we add extra bit 64 to disambiguate button-up. */ + res = (int) read( #if USE_EMX_MOUSE - res = read(M_FD(sp) >= 0 ? M_FD(sp) : sp->_ifd, &kbuf, 3); + (M_FD(sp) >= 0) ? M_FD(sp) : sp->_ifd, #else - res = read(sp->_ifd, kbuf + grabbed, 3 - grabbed); + sp->_ifd, #endif - if (res == -1) - break; - } - kbuf[3] = '\0'; + kbuf + grabbed, (size_t) (MAX_KBUF - (int) grabbed)); + if (res == -1) + break; + } + _nc_set_read_thread(FALSE); + kbuf[MAX_KBUF] = '\0'; - TR(TRACE_IEVENT, - ("_nc_mouse_inline sees the following xterm data: '%s'", kbuf)); + TR(TRACE_IEVENT, + ("_nc_mouse_inline sees the following xterm data: '%s'", kbuf)); - /* there's only one mouse... */ - eventp->id = NORMAL_EVENT; + /* there's only one mouse... */ + eventp->id = NORMAL_EVENT; + + result = decode_X10_bstate(sp, eventp, kbuf[0]); + + eventp->x = (kbuf[1] - ' ') - 1; + eventp->y = (kbuf[2] - ' ') - 1; + + return result; +} + +#ifdef EXP_XTERM_1005 +/* + * This is identical to X10/X11 responses except that there are two UTF-8 + * characters storing the ordinates instead of two bytes. + */ +static bool +decode_xterm_1005(SCREEN *sp, MEVENT * eventp) +{ + char kbuf[80]; + size_t grabbed; + size_t limit = (sizeof(kbuf) - 1); + unsigned coords[2]; + bool result; - /* processing code goes here */ - eventp->bstate = 0; - prev = PREV(eventp)->bstate; + coords[0] = 0; + coords[1] = 0; + _nc_set_read_thread(TRUE); + for (grabbed = 0; grabbed < limit;) { + int res; + + res = (int) read( #if USE_EMX_MOUSE -#define PRESS_POSITION(n) \ - eventp->bstate = MASK_PRESS(n); \ - if (kbuf[0] & 0x40) \ - eventp->bstate = MASK_RELEASE(n) + (M_FD(sp) >= 0) ? M_FD(sp) : sp->_ifd, #else -#define PRESS_POSITION(n) \ - eventp->bstate = (mmask_t) (prev & MASK_PRESS(n) \ - ? REPORT_MOUSE_POSITION \ - : MASK_PRESS(n)) + sp->_ifd, #endif - - switch (kbuf[0] & 0x3) { - case 0x0: - if (kbuf[0] & 64) - eventp->bstate = MASK_PRESS(4); - else - PRESS_POSITION(1); + (kbuf + grabbed), (size_t) 1); + if (res == -1) break; + grabbed += (size_t) res; + if (grabbed > 1) { + size_t check = 1; + int n; - case 0x1: -#if NCURSES_MOUSE_VERSION == 2 - if (kbuf[0] & 64) - eventp->bstate = MASK_PRESS(5); - else + for (n = 0; n < 2; ++n) { + int rc; + + if (check >= grabbed) + break; + rc = _nc_conv_to_utf32(&coords[n], kbuf + check, (unsigned) + (grabbed - check)); + if (!rc) + break; + check += (size_t) rc; + } + if (n >= 2) + break; + } + } + _nc_set_read_thread(FALSE); + + TR(TRACE_IEVENT, + ("_nc_mouse_inline sees the following xterm data: %s", + _nc_visbufn(kbuf, (int) grabbed))); + + /* there's only one mouse... */ + eventp->id = NORMAL_EVENT; + + result = decode_X10_bstate(sp, eventp, UChar(kbuf[0])); + + eventp->x = (int) (coords[0] - ' ') - 1; + eventp->y = (int) (coords[1] - ' ') - 1; + + return result; +} +#endif /* EXP_XTERM_1005 */ + +/* + * ECMA-48 section 5.4 + */ +#define isInter(c) ((c) >= 0x20 && (c) <= 0x2f) +#define isParam(c) ((c) >= 0x30 && (c) <= 0x3f) +#define isFinal(c) ((c) >= 0x40 && (c) <= 0x7e) + +#define MAX_PARAMS 9 + +typedef struct { + int nerror; /* nonzero if there are unexpected chars */ + int nparam; /* number of numeric parameters */ + int params[MAX_PARAMS]; + int final; /* the final-character */ +} SGR_DATA; + +static bool +read_SGR(SCREEN *sp, SGR_DATA * result) +{ + char kbuf[80]; /* bigger than any possible mouse response */ + int grabbed = 0; + int ch = 0; + int now = -1; + int marker = 1; + + memset(result, 0, sizeof(*result)); + _nc_set_read_thread(TRUE); + + do { + int res; + + res = (int) read( +#if USE_EMX_MOUSE + (M_FD(sp) >= 0) ? M_FD(sp) : sp->_ifd, +#else + sp->_ifd, #endif - PRESS_POSITION(2); + (kbuf + grabbed), (size_t) 1); + if (res == -1) break; - - case 0x2: - PRESS_POSITION(3); + if ((grabbed + MAX_KBUF) >= (int) sizeof(kbuf)) { + result->nerror++; break; - - case 0x3: - /* - * Release events aren't reported for individual buttons, just for - * the button set as a whole. However, because there are normally - * no mouse events under xterm that intervene between press and - * release, we can infer the button actually released by looking at - * the previous event. - */ - if (prev & (BUTTON_PRESSED | BUTTON_RELEASED)) { - eventp->bstate = BUTTON_RELEASED; - for (b = 1; b <= MAX_BUTTONS; ++b) { - if (!(prev & MASK_PRESS(b))) - eventp->bstate &= ~MASK_RELEASE(b); - } - } else { + } + ch = UChar(kbuf[grabbed]); + kbuf[grabbed + 1] = 0; + switch (ch) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (marker) { + ++now; + result->nparam = (now + 1); + } + marker = 0; + result->params[now] = (result->params[now] * 10) + (ch - '0'); + break; + case ';': + if (marker) { + ++now; + result->nparam = (now + 1); + } + marker = 1; + break; + default: + if (ch < 32 || ch > 126) { /* - * XFree86 xterm will return a stream of release-events to - * let the application know where the mouse is going, if the - * private mode 1002 or 1003 is enabled. + * Technically other characters could be interspersed in the + * response. Ignore those for now. */ - eventp->bstate = REPORT_MOUSE_POSITION; + result->nerror++; + continue; + } else if (isFinal(ch)) { + if (marker) { + result->nparam++; + } + result->final = ch; + } else { + result->nerror++; } break; } - result = (eventp->bstate & REPORT_MOUSE_POSITION) ? TRUE : FALSE; + ++grabbed; + } while (!isFinal(ch)); + _nc_set_read_thread(FALSE); + + kbuf[++grabbed] = 0; + TR(TRACE_IEVENT, + ("_nc_mouse_inline sees the following xterm data: '%s'", kbuf)); + return (grabbed > 0) && (result->nerror == 0); +} - if (kbuf[0] & 4) { +static bool +decode_xterm_SGR1006(SCREEN *sp, MEVENT * eventp) +{ + SGR_DATA data; + bool result = FALSE; + if (read_SGR(sp, &data)) { + int b = data.params[0]; + int b3 = 1 + (b & 3); + int wheel = ((b & 64) == 64); + + if (b >= 132) { + b3 = MAX_BUTTONS + 1; + } else if (b >= 128) { + b3 = (b - 120); /* buttons 8-11 */ + } else if (b >= 64) { + b3 = (b - 60); /* buttons 6-7 */ + } + + eventp->id = NORMAL_EVENT; + if (data.final == 'M') { + (void) handle_wheel(sp, eventp, b, wheel); + } else if (b3 > MAX_BUTTONS) { + eventp->bstate = REPORT_MOUSE_POSITION; + } else { + mmask_t pressed = (mmask_t) NCURSES_MOUSE_MASK(b3, NCURSES_BUTTON_PRESSED); + mmask_t release = (mmask_t) NCURSES_MOUSE_MASK(b3, NCURSES_BUTTON_RELEASED); + if (sp->_mouse_bstate & pressed) { + eventp->bstate = release; + sp->_mouse_bstate &= ~pressed; + } else { + eventp->bstate = REPORT_MOUSE_POSITION; + } + } + if (b & 4) { eventp->bstate |= BUTTON_SHIFT; } - if (kbuf[0] & 8) { + if (b & 8) { eventp->bstate |= BUTTON_ALT; } - if (kbuf[0] & 16) { + if (b & 16) { eventp->bstate |= BUTTON_CTRL; } + result = (eventp->bstate & REPORT_MOUSE_POSITION) ? TRUE : FALSE; + eventp->x = (data.params[1] ? (data.params[1] - 1) : 0); + eventp->y = (data.params[2] ? (data.params[2] - 1) : 0); + } + return result; +} + +static bool +_nc_mouse_inline(SCREEN *sp) +/* mouse report received in the keyboard stream -- parse its info */ +{ + bool result = FALSE; + MEVENT *eventp = sp->_mouse_eventp; + + TR(MY_TRACE, ("_nc_mouse_inline() called")); + + if (sp->_mouse_type == M_XTERM) { + switch (sp->_mouse_format) { + case MF_X10: + result = decode_xterm_X10(sp, eventp); + break; + case MF_SGR1006: + result = decode_xterm_SGR1006(sp, eventp); + break; +#ifdef EXP_XTERM_1005 + case MF_XTERM_1005: + result = decode_xterm_1005(sp, eventp); + break; +#endif + } - eventp->x = (kbuf[1] - ' ') - 1; - eventp->y = (kbuf[2] - ' ') - 1; TR(MY_TRACE, ("_nc_mouse_inline: primitive mouse-event %s has slot %ld", _nc_tracemouse(sp, eventp), @@ -917,31 +1383,47 @@ _nc_mouse_inline(SCREEN *sp) /* bump the next-free pointer into the circular list */ sp->_mouse_eventp = NEXT(eventp); -#if 0 /* this return would be needed for QNX's mods to lib_getch.c */ - return (TRUE); -#endif + + if (!result) { + /* If this event is from a wheel-mouse, treat it like position + * reports and avoid waiting for the release-events which will + * never come. + */ + if (eventp->bstate & BUTTON_PRESSED) { + int b; + + for (b = 4; b <= MAX_BUTTONS; ++b) { + if ((eventp->bstate & MASK_PRESS(b))) { + result = TRUE; + break; + } + } + } + } } return (result); } static void -mouse_activate(SCREEN *sp, bool on) +mouse_activate(SCREEN *sp, int on) { + T((T_CALLED("mouse_activate(%p,%s)"), + (void *) SP_PARM, on ? "on" : "off")); + if (!on && !sp->_mouse_initialized) - return; + returnVoid; if (!_nc_mouse_init(sp)) - return; + returnVoid; if (on) { - + sp->_mouse_bstate = 0; switch (sp->_mouse_type) { case M_XTERM: #if NCURSES_EXT_FUNCS - keyok(KEY_MOUSE, on); + NCURSES_SP_NAME(keyok) (NCURSES_SP_ARGx KEY_MOUSE, on); #endif - TPUTS_TRACE("xterm mouse initialization"); enable_xterm_mouse(sp, 1); break; #if USE_GPM_SUPPORT @@ -957,23 +1439,31 @@ mouse_activate(SCREEN *sp, bool on) signal(SIGUSR2, handle_sysmouse); sp->_mouse_active = TRUE; break; +#endif +#ifdef USE_TERM_DRIVER + case M_TERM_DRIVER: + enable_win32_mouse(sp, TRUE); + break; #endif case M_NONE: - return; + returnVoid; + default: + T(("unexpected mouse mode")); + break; } /* Make runtime binding to cut down on object size of applications that * do not use the mouse (e.g., 'clear'). */ - sp->_mouse_event = _nc_mouse_event; + /* *INDENT-EQLS* */ + sp->_mouse_event = _nc_mouse_event; sp->_mouse_inline = _nc_mouse_inline; - sp->_mouse_parse = _nc_mouse_parse; + sp->_mouse_parse = _nc_mouse_parse; sp->_mouse_resume = _nc_mouse_resume; - sp->_mouse_wrap = _nc_mouse_wrap; + sp->_mouse_wrap = _nc_mouse_wrap; } else { switch (sp->_mouse_type) { case M_XTERM: - TPUTS_TRACE("xterm mouse deinitialization"); enable_xterm_mouse(sp, 0); break; #if USE_GPM_SUPPORT @@ -986,12 +1476,21 @@ mouse_activate(SCREEN *sp, bool on) signal(SIGUSR2, SIG_IGN); sp->_mouse_active = FALSE; break; +#endif +#ifdef USE_TERM_DRIVER + case M_TERM_DRIVER: + enable_win32_mouse(sp, FALSE); + break; #endif case M_NONE: - return; + returnVoid; + default: + T(("unexpected mouse mode")); + break; } } - _nc_flush(); + NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG); + returnVoid; } /************************************************************************** @@ -1005,10 +1504,13 @@ _nc_mouse_parse(SCREEN *sp, int runcount) /* parse a run of atomic mouse events into a gesture */ { MEVENT *eventp = sp->_mouse_eventp; - MEVENT *ep, *runp, *next, *prev = PREV(eventp); + MEVENT *next, *ep; + MEVENT *first_valid = NULL; + MEVENT *first_invalid = NULL; int n; int b; bool merge; + bool endLoop; TR(MY_TRACE, ("_nc_mouse_parse(%d) called", runcount)); @@ -1025,7 +1527,8 @@ _nc_mouse_parse(SCREEN *sp, int runcount) * * It's possible that the run may not resolve to a single event (for * example, if the user quadruple-clicks). If so, leading events - * in the run are ignored. + * in the run are ignored if user does not call getmouse in a loop (getting + * them from newest to older). * * Note that this routine is independent of the format of the specific * format of the pointing-device's reports. We can use it to parse @@ -1033,79 +1536,110 @@ _nc_mouse_parse(SCREEN *sp, int runcount) * button basis, as long as the device-dependent mouse code puts stuff * on the queue in MEVENT format. */ - if (runcount == 1) { - TR(MY_TRACE, - ("_nc_mouse_parse: returning simple mouse event %s at slot %ld", - _nc_tracemouse(sp, prev), - (long) IndexEV(sp, prev))); - return (prev->id >= NORMAL_EVENT) - ? ((prev->bstate & sp->_mouse_mask) ? TRUE : FALSE) - : FALSE; - } - /* find the start of the run */ - runp = eventp; - for (n = runcount; n > 0; n--) { - runp = PREV(runp); + /* + * Reset all events that were not set, in case the user sometimes calls + * getmouse only once and other times until there are no more events in + * queue. + * + * This also allows reaching the beginning of the run. + */ + ep = eventp; + for (n = runcount; n < EV_MAX; n++) { + Invalidate(ep); + ep = NEXT(ep); } #ifdef TRACE if (USE_TRACEF(TRACE_IEVENT)) { _trace_slot(sp, "before mouse press/release merge:"); _tracef("_nc_mouse_parse: run starts at %ld, ends at %ld, count %d", - RunParams(sp, eventp, runp), + RunParams(sp, eventp, ep), runcount); _nc_unlock_global(tracef); } #endif /* TRACE */ /* first pass; merge press/release pairs */ - do { - merge = FALSE; - for (ep = runp; (next = NEXT(ep)) != eventp; ep = next) { + endLoop = FALSE; + while (!endLoop) { + next = NEXT(ep); + if (next == eventp) { + /* Will end the loop, but compact before */ + endLoop = TRUE; + } else { #define MASK_CHANGED(x) (!(ep->bstate & MASK_PRESS(x)) \ == !(next->bstate & MASK_RELEASE(x))) - if (ep->x == next->x && ep->y == next->y + if (ValidEvent(ep) && ValidEvent(next) + && ep->x == next->x && ep->y == next->y && (ep->bstate & BUTTON_PRESSED) - && MASK_CHANGED(1) - && MASK_CHANGED(2) - && MASK_CHANGED(3) - && MASK_CHANGED(4) -#if NCURSES_MOUSE_VERSION == 2 - && MASK_CHANGED(5) -#endif - ) { + && (!(next->bstate & BUTTON_PRESSED))) { + bool changed = TRUE; + for (b = 1; b <= MAX_BUTTONS; ++b) { - if ((sp->_mouse_mask & MASK_CLICK(b)) - && (ep->bstate & MASK_PRESS(b))) { - ep->bstate &= ~MASK_PRESS(b); - ep->bstate |= MASK_CLICK(b); - merge = TRUE; + if (!MASK_CHANGED(b)) { + changed = FALSE; + break; + } + } + + if (changed) { + merge = FALSE; + for (b = 1; b <= MAX_BUTTONS; ++b) { + if ((sp->_mouse_mask2 & MASK_CLICK(b)) + && (ep->bstate & MASK_PRESS(b))) { + next->bstate &= ~MASK_RELEASE(b); + next->bstate |= MASK_CLICK(b); + merge = TRUE; + } + } + if (merge) { + Invalidate(ep); } } - if (merge) - next->id = INVALID_EVENT; } } - } while - (merge); + /* Compact valid events */ + if (!ValidEvent(ep)) { + if ((first_valid != NULL) && (first_invalid == NULL)) { + first_invalid = ep; + } + } else { + if (first_valid == NULL) { + first_valid = ep; + } else if (first_invalid != NULL) { + *first_invalid = *ep; + Invalidate(ep); + first_invalid = NEXT(first_invalid); + } + } + + ep = next; + } + + if (first_invalid != NULL) { + eventp = first_invalid; + } #ifdef TRACE if (USE_TRACEF(TRACE_IEVENT)) { _trace_slot(sp, "before mouse click merge:"); - _tracef("_nc_mouse_parse: run starts at %ld, ends at %ld, count %d", - RunParams(sp, eventp, runp), - runcount); - _nc_unlock_global(tracef); + if (first_valid == NULL) { + _tracef("_nc_mouse_parse: no valid event"); + } else { + _tracef("_nc_mouse_parse: run starts at %ld, ends at %ld, count %d", + RunParams(sp, eventp, first_valid), + runcount); + _nc_unlock_global(tracef); + } } #endif /* TRACE */ /* - * Second pass; merge click runs. At this point, click events are - * each followed by one invalid event. We merge click events - * forward in the queue. + * Second pass; merge click runs. We merge click events forward in the + * queue. For example, double click can be changed to triple click. * * NOTE: There is a problem with this design! If the application * allows enough click events to pile up in the circular queue so @@ -1118,87 +1652,103 @@ _nc_mouse_parse(SCREEN *sp, int runcount) * but the timer element would have to have sub-second resolution, * which would get us into portability trouble. */ - do { - MEVENT *follower; - - merge = FALSE; - for (ep = runp; (next = NEXT(ep)) != eventp; ep = next) - if (ep->id != INVALID_EVENT) { - if (next->id != INVALID_EVENT) - continue; - follower = NEXT(next); - if (follower->id == INVALID_EVENT) - continue; - - /* merge click events forward */ - if ((ep->bstate & BUTTON_CLICKED) - && (follower->bstate & BUTTON_CLICKED)) { - for (b = 1; b <= MAX_BUTTONS; ++b) { - if ((sp->_mouse_mask & MASK_DOUBLE_CLICK(b)) - && (follower->bstate & MASK_CLICK(b))) { - follower->bstate &= ~MASK_CLICK(b); - follower->bstate |= MASK_DOUBLE_CLICK(b); - merge = TRUE; - } + first_invalid = NULL; + endLoop = (first_valid == NULL); + ep = first_valid; + while (!endLoop) { + next = NEXT(ep); + + if (next == eventp) { + /* Will end the loop, but check event type and compact before */ + endLoop = TRUE; + } else if (!ValidEvent(next)) { + continue; + } else { + /* merge click events forward */ + if ((ep->bstate & BUTTON_CLICKED) + && (next->bstate & BUTTON_CLICKED)) { + merge = FALSE; + for (b = 1; b <= MAX_BUTTONS; ++b) { + if ((sp->_mouse_mask2 & MASK_DOUBLE_CLICK(b)) + && (ep->bstate & MASK_CLICK(b)) + && (next->bstate & MASK_CLICK(b))) { + next->bstate &= ~MASK_CLICK(b); + next->bstate |= MASK_DOUBLE_CLICK(b); + merge = TRUE; } - if (merge) - ep->id = INVALID_EVENT; } + if (merge) { + Invalidate(ep); + } + } - /* merge double-click events forward */ - if ((ep->bstate & BUTTON_DOUBLE_CLICKED) - && (follower->bstate & BUTTON_CLICKED)) { - for (b = 1; b <= MAX_BUTTONS; ++b) { - if ((sp->_mouse_mask & MASK_TRIPLE_CLICK(b)) - && (follower->bstate & MASK_CLICK(b))) { - follower->bstate &= ~MASK_CLICK(b); - follower->bstate |= MASK_TRIPLE_CLICK(b); - merge = TRUE; - } + /* merge double-click events forward */ + if ((ep->bstate & BUTTON_DOUBLE_CLICKED) + && (next->bstate & BUTTON_CLICKED)) { + merge = FALSE; + for (b = 1; b <= MAX_BUTTONS; ++b) { + if ((sp->_mouse_mask2 & MASK_TRIPLE_CLICK(b)) + && (ep->bstate & MASK_DOUBLE_CLICK(b)) + && (next->bstate & MASK_CLICK(b))) { + next->bstate &= ~MASK_CLICK(b); + next->bstate |= MASK_TRIPLE_CLICK(b); + merge = TRUE; } - if (merge) - ep->id = INVALID_EVENT; } + if (merge) { + Invalidate(ep); + } + } + } + + /* Discard event if it does not match event mask */ + if (!(ep->bstate & sp->_mouse_mask2)) { + Invalidate(ep); + } + + /* Compact valid events */ + if (!ValidEvent(ep)) { + if (ep == first_valid) { + first_valid = next; + } else if (first_invalid == NULL) { + first_invalid = ep; } - } while - (merge); + } else if (first_invalid != NULL) { + *first_invalid = *ep; + Invalidate(ep); + first_invalid = NEXT(first_invalid); + } -#ifdef TRACE - if (USE_TRACEF(TRACE_IEVENT)) { - _trace_slot(sp, "before mouse event queue compaction:"); - _tracef("_nc_mouse_parse: run starts at %ld, ends at %ld, count %d", - RunParams(sp, eventp, runp), - runcount); - _nc_unlock_global(tracef); + ep = next; } -#endif /* TRACE */ - /* - * Now try to throw away trailing events flagged invalid, or that - * don't match the current event mask. - */ - for (; runcount; prev = PREV(eventp), runcount--) - if (prev->id == INVALID_EVENT || !(prev->bstate & sp->_mouse_mask)) { - sp->_mouse_eventp = eventp = prev; - } + if (first_invalid == NULL) { + first_invalid = eventp; + } + sp->_mouse_eventp = first_invalid; + #ifdef TRACE - if (USE_TRACEF(TRACE_IEVENT)) { - _trace_slot(sp, "after mouse event queue compaction:"); - _tracef("_nc_mouse_parse: run starts at %ld, ends at %ld, count %d", - RunParams(sp, eventp, runp), - runcount); - _nc_unlock_global(tracef); + if (first_valid != NULL) { + if (USE_TRACEF(TRACE_IEVENT)) { + _trace_slot(sp, "after mouse event queue compaction:"); + _tracef("_nc_mouse_parse: run starts at %ld, ends at %ld, count %d", + RunParams(sp, first_invalid, first_valid), + runcount); + _nc_unlock_global(tracef); + } + for (ep = first_valid; ep != first_invalid; ep = NEXT(ep)) { + if (ValidEvent(ep)) + TR(MY_TRACE, + ("_nc_mouse_parse: returning composite mouse event %s at slot %ld", + _nc_tracemouse(sp, ep), + (long) IndexEV(sp, ep))); + } } - for (ep = runp; ep != eventp; ep = NEXT(ep)) - if (ep->id != INVALID_EVENT) - TR(MY_TRACE, - ("_nc_mouse_parse: returning composite mouse event %s at slot %ld", - _nc_tracemouse(sp, ep), - (long) IndexEV(sp, ep))); #endif /* TRACE */ /* after all this, do we have a valid event? */ - return (PREV(eventp)->id != INVALID_EVENT); + ep = PREV(first_invalid); + return ValidEvent(ep) && ((ep->bstate & sp->_mouse_mask) != 0); } static void @@ -1223,6 +1773,11 @@ _nc_mouse_wrap(SCREEN *sp) case M_SYSMOUSE: mouse_activate(sp, FALSE); break; +#endif +#ifdef USE_TERM_DRIVER + case M_TERM_DRIVER: + mouse_activate(sp, FALSE); + break; #endif case M_NONE: break; @@ -1255,6 +1810,13 @@ _nc_mouse_resume(SCREEN *sp) mouse_activate(sp, TRUE); break; #endif + +#ifdef USE_TERM_DRIVER + case M_TERM_DRIVER: + mouse_activate(sp, TRUE); + break; +#endif + case M_NONE: break; } @@ -1266,80 +1828,116 @@ _nc_mouse_resume(SCREEN *sp) * **************************************************************************/ -static int -_nc_getmouse(SCREEN *sp, MEVENT * aevent) +NCURSES_EXPORT(int) +NCURSES_SP_NAME(getmouse) (NCURSES_SP_DCLx MEVENT * aevent) { - T((T_CALLED("getmouse(%p)"), aevent)); + int result = ERR; + MEVENT *eventp; - if ((aevent != 0) && (sp != 0) && (sp->_mouse_type != M_NONE)) { - MEVENT *eventp = sp->_mouse_eventp; + T((T_CALLED("getmouse(%p,%p)"), (void *) SP_PARM, (void *) aevent)); + + if ((aevent != 0) && + (SP_PARM != 0) && + (SP_PARM->_mouse_type != M_NONE) && + (eventp = SP_PARM->_mouse_eventp) != 0) { /* compute the current-event pointer */ MEVENT *prev = PREV(eventp); - /* copy the event we find there */ - *aevent = *prev; + /* + * Discard events not matching mask (there could be still some if + * _nc_mouse_parse was not called, e.g., when _nc_mouse_inline returns + * false). + */ + while (ValidEvent(prev) && (!(prev->bstate & SP_PARM->_mouse_mask2))) { + Invalidate(prev); + prev = PREV(prev); + } + if (ValidEvent(prev)) { + /* copy the event we find there */ + *aevent = *prev; - TR(TRACE_IEVENT, ("getmouse: returning event %s from slot %ld", - _nc_tracemouse(sp, prev), - (long) IndexEV(sp, prev))); + TR(TRACE_IEVENT, ("getmouse: returning event %s from slot %ld", + _nc_tracemouse(SP_PARM, prev), + (long) IndexEV(SP_PARM, prev))); - prev->id = INVALID_EVENT; /* so the queue slot becomes free */ - returnCode(OK); + Invalidate(prev); /* so the queue slot becomes free */ + SP_PARM->_mouse_eventp = prev; + result = OK; + } else { + /* Reset the provided event */ + aevent->bstate = 0; + Invalidate(aevent); + aevent->x = 0; + aevent->y = 0; + aevent->z = 0; + } } - returnCode(ERR); + returnCode(result); } +#if NCURSES_SP_FUNCS /* grab a copy of the current mouse event */ NCURSES_EXPORT(int) getmouse(MEVENT * aevent) { - return _nc_getmouse(SP, aevent); + return NCURSES_SP_NAME(getmouse) (CURRENT_SCREEN, aevent); } +#endif -static int -_nc_ungetmouse(SCREEN *sp, MEVENT * aevent) +NCURSES_EXPORT(int) +NCURSES_SP_NAME(ungetmouse) (NCURSES_SP_DCLx MEVENT * aevent) { int result = ERR; + MEVENT *eventp; - T((T_CALLED("ungetmouse(%p)"), aevent)); + T((T_CALLED("ungetmouse(%p,%p)"), (void *) SP_PARM, (void *) aevent)); - if (aevent != 0 && sp != 0) { - MEVENT *eventp = sp->_mouse_eventp; + if (aevent != 0 && + SP_PARM != 0 && + (eventp = SP_PARM->_mouse_eventp) != 0) { /* stick the given event in the next-free slot */ *eventp = *aevent; /* bump the next-free pointer into the circular list */ - sp->_mouse_eventp = NEXT(eventp); + SP_PARM->_mouse_eventp = NEXT(eventp); /* push back the notification event on the keyboard queue */ - result = _nc_ungetch(sp, KEY_MOUSE); + result = NCURSES_SP_NAME(ungetch) (NCURSES_SP_ARGx KEY_MOUSE); } returnCode(result); } +#if NCURSES_SP_FUNCS /* enqueue a synthesized mouse event to be seen by the next wgetch() */ NCURSES_EXPORT(int) ungetmouse(MEVENT * aevent) { - return _nc_ungetmouse(SP, aevent); + return NCURSES_SP_NAME(ungetmouse) (CURRENT_SCREEN, aevent); } +#endif NCURSES_EXPORT(mmask_t) -mousemask(mmask_t newmask, mmask_t * oldmask) +NCURSES_SP_NAME(mousemask) (NCURSES_SP_DCLx mmask_t newmask, mmask_t * oldmask) /* set the mouse event mask */ { mmask_t result = 0; - T((T_CALLED("mousemask(%#lx,%p)"), (unsigned long) newmask, oldmask)); + T((T_CALLED("mousemask(%p,%#lx,%p)"), + (void *) SP_PARM, + (unsigned long) newmask, + (void *) oldmask)); - if (SP != 0) { + if (SP_PARM != 0) { if (oldmask) - *oldmask = SP->_mouse_mask; + *oldmask = SP_PARM->_mouse_mask; + + if (newmask || SP_PARM->_mouse_initialized) { + _nc_mouse_init(SP_PARM); + + if (SP_PARM->_mouse_type != M_NONE) { + int b; - if (newmask || SP->_mouse_initialized) { - _nc_mouse_init(SP); - if (SP->_mouse_type != M_NONE) { result = newmask & (REPORT_MOUSE_POSITION | BUTTON_ALT @@ -1351,22 +1949,46 @@ mousemask(mmask_t newmask, mmask_t * oldmask) | BUTTON_DOUBLE_CLICKED | BUTTON_TRIPLE_CLICKED); - mouse_activate(SP, (bool) (result != 0)); + mouse_activate(SP_PARM, (bool) (result != 0)); + + SP_PARM->_mouse_mask = result; + SP_PARM->_mouse_mask2 = result; - SP->_mouse_mask = result; + /* + * Make a mask corresponding to the states we will need to + * retain (temporarily) while building up the state that the + * user asked for. + */ + for (b = 1; b <= MAX_BUTTONS; ++b) { + if (SP_PARM->_mouse_mask2 & MASK_TRIPLE_CLICK(b)) + SP_PARM->_mouse_mask2 |= MASK_DOUBLE_CLICK(b); + if (SP_PARM->_mouse_mask2 & MASK_DOUBLE_CLICK(b)) + SP_PARM->_mouse_mask2 |= MASK_CLICK(b); + if (SP_PARM->_mouse_mask2 & MASK_CLICK(b)) + SP_PARM->_mouse_mask2 |= (MASK_PRESS(b) | + MASK_RELEASE(b)); + } } } } - returnBits(result); + returnMMask(result); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(mmask_t) +mousemask(mmask_t newmask, mmask_t * oldmask) +{ + return NCURSES_SP_NAME(mousemask) (CURRENT_SCREEN, newmask, oldmask); +} +#endif + NCURSES_EXPORT(bool) wenclose(const WINDOW *win, int y, int x) /* check to see if given window encloses given screen location */ { bool result = FALSE; - T((T_CALLED("wenclose(%p,%d,%d)"), win, y, x)); + T((T_CALLED("wenclose(%p,%d,%d)"), (const void *) win, y, x)); if (win != 0) { y -= win->_yoffset; @@ -1379,17 +2001,17 @@ wenclose(const WINDOW *win, int y, int x) } NCURSES_EXPORT(int) -mouseinterval(int maxclick) +NCURSES_SP_NAME(mouseinterval) (NCURSES_SP_DCLx int maxclick) /* set the maximum mouse interval within which to recognize a click */ { int oldval; - T((T_CALLED("mouseinterval(%d)"), maxclick)); + T((T_CALLED("mouseinterval(%p,%d)"), (void *) SP_PARM, maxclick)); - if (SP != 0) { - oldval = SP->_maxclick; + if (SP_PARM != 0) { + oldval = SP_PARM->_maxclick; if (maxclick >= 0) - SP->_maxclick = maxclick; + SP_PARM->_maxclick = maxclick; } else { oldval = DEFAULT_MAXCLICK; } @@ -1397,20 +2019,46 @@ mouseinterval(int maxclick) returnCode(oldval); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +mouseinterval(int maxclick) +{ + return NCURSES_SP_NAME(mouseinterval) (CURRENT_SCREEN, maxclick); +} +#endif + /* This may be used by other routines to ask for the existence of mouse support */ -NCURSES_EXPORT(int) -_nc_has_mouse(void) +NCURSES_EXPORT(bool) +_nc_has_mouse(SCREEN *sp) +{ + return (((0 == sp) || (sp->_mouse_type == M_NONE)) ? FALSE : TRUE); +} + +NCURSES_EXPORT(bool) +NCURSES_SP_NAME(has_mouse) (NCURSES_SP_DCL0) +{ + return _nc_has_mouse(SP_PARM); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(bool) +has_mouse(void) { - return (SP->_mouse_type == M_NONE ? 0 : 1); + return _nc_has_mouse(CURRENT_SCREEN); } +#endif NCURSES_EXPORT(bool) wmouse_trafo(const WINDOW *win, int *pY, int *pX, bool to_screen) { bool result = FALSE; - T((T_CALLED("wmouse_trafo(%p,%p,%p,%d)"), win, pY, pX, to_screen)); + T((T_CALLED("wmouse_trafo(%p,%p,%p,%d)"), + (const void *) win, + (void *) pY, + (void *) pX, + to_screen)); if (win && pY && pX) { int y = *pY; diff --git a/lib/libcurses/base/lib_move.c b/lib/libcurses/base/lib_move.c index a2f2f793b72..0a4a07ef147 100644 --- a/lib/libcurses/base/lib_move.c +++ b/lib/libcurses/base/lib_move.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_move.c,v 1.4 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_move.c,v 1.5 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2004 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2004,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -43,12 +44,12 @@ #include -MODULE_ID("$Id: lib_move.c,v 1.4 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_move.c,v 1.5 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) wmove(WINDOW *win, int y, int x) { - T((T_CALLED("wmove(%p,%d,%d)"), win, y, x)); + T((T_CALLED("wmove(%p,%d,%d)"), (void *) win, y, x)); if (LEGALYX(win, y, x)) { win->_curx = (NCURSES_SIZE_T) x; diff --git a/lib/libcurses/base/lib_mvwin.c b/lib/libcurses/base/lib_mvwin.c index 3a6e9d54fb3..ee78e9bb9c9 100644 --- a/lib/libcurses/base/lib_mvwin.c +++ b/lib/libcurses/base/lib_mvwin.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_mvwin.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_mvwin.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2001,2006 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +32,8 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer * ****************************************************************************/ /* @@ -42,14 +45,18 @@ #include -MODULE_ID("$Id: lib_mvwin.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_mvwin.c,v 1.4 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) mvwin(WINDOW *win, int by, int bx) { - T((T_CALLED("mvwin(%p,%d,%d)"), win, by, bx)); +#if NCURSES_SP_FUNCS + SCREEN *sp = _nc_screen_of(win); +#endif + + T((T_CALLED("mvwin(%p,%d,%d)"), (void *) win, by, bx)); - if (!win || (win->_flags & _ISPAD)) + if (!win || IS_PAD(win)) returnCode(ERR); /* @@ -58,7 +65,7 @@ mvwin(WINDOW *win, int by, int bx) */ #if 0 /* Copying subwindows is allowed, but it is expensive... */ - if (win->_flags & _SUBWIN) { + if (IS_SUBWIN(win)) { int err = ERR; WINDOW *parent = win->_parent; if (parent) { /* Now comes the complicated and costly part, you should really @@ -98,8 +105,8 @@ mvwin(WINDOW *win, int by, int bx) } #endif - if (by + win->_maxy > screen_lines - 1 - || bx + win->_maxx > screen_columns - 1 + if (by + win->_maxy > screen_lines(SP_PARM) - 1 + || bx + win->_maxx > screen_columns(SP_PARM) - 1 || by < 0 || bx < 0) returnCode(ERR); @@ -110,7 +117,7 @@ mvwin(WINDOW *win, int by, int bx) * new location. This ensures that if the caller has refreshed another * window at the same location, that this one will be displayed. */ - win->_begy = by; - win->_begx = bx; + win->_begy = (NCURSES_SIZE_T) by; + win->_begx = (NCURSES_SIZE_T) bx; returnCode(touchwin(win)); } diff --git a/lib/libcurses/base/lib_newterm.c b/lib/libcurses/base/lib_newterm.c index 18e26bfeea4..e38faa56f4d 100644 --- a/lib/libcurses/base/lib_newterm.c +++ b/lib/libcurses/base/lib_newterm.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_newterm.c,v 1.13 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_newterm.c,v 1.14 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2020,2022 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,6 +33,7 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -43,14 +45,19 @@ #include -#if SVR4_TERMIO && !defined(_POSIX_SOURCE) -#define _POSIX_SOURCE +#ifndef CUR +#define CUR SP_TERMTYPE #endif -#include /* clear_screen, cup & friends, cur_term */ #include -MODULE_ID("$Id: lib_newterm.c,v 1.13 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_newterm.c,v 1.14 2023/10/17 09:52:08 nicm Exp $") + +#ifdef USE_TERM_DRIVER +#define NumLabels InfoOf(SP_PARM).numlabels +#else +#define NumLabels num_labels +#endif #ifndef ONLCR /* Allows compilation under the QNX 4.2 OS */ #define ONLCR 0 @@ -65,29 +72,38 @@ MODULE_ID("$Id: lib_newterm.c,v 1.13 2010/01/12 23:22:06 nicm Exp $") * is supposed to behave as if it calls newterm, we do it here. */ static NCURSES_INLINE int -_nc_initscr(void) +_nc_initscr(NCURSES_SP_DCL0) { int result = ERR; + TERMINAL *term = TerminalOf(SP_PARM); /* for extended XPG4 conformance requires cbreak() at this point */ /* (SVr4 curses does this anyway) */ - if (cbreak() == OK) { + T((T_CALLED("_nc_initscr(%p) ->term %p"), (void *) SP_PARM, (void *) term)); + if (NCURSES_SP_NAME(cbreak) (NCURSES_SP_ARG) == OK) { TTY buf; - buf = cur_term->Nttyb; + buf = term->Nttyb; #ifdef TERMIOS - buf.c_lflag &= ~(ECHO | ECHONL); - buf.c_iflag &= ~(ICRNL | INLCR | IGNCR); - buf.c_oflag &= ~(ONLCR); + buf.c_lflag &= (unsigned) ~(ECHO | ECHONL); + buf.c_iflag &= (unsigned) ~(ICRNL | INLCR | IGNCR); + buf.c_oflag &= (unsigned) ~(ONLCR); #elif HAVE_SGTTY_H buf.sg_flags &= ~(ECHO | CRMOD); +#elif defined(EXP_WIN32_DRIVER) + buf.dwFlagIn = CONMODE_IN_DEFAULT; + buf.dwFlagOut = CONMODE_OUT_DEFAULT | VT_FLAG_OUT; + if (WINCONSOLE.isTermInfoConsole) { + buf.dwFlagIn |= VT_FLAG_IN; + } #else memset(&buf, 0, sizeof(buf)); #endif - if ((result = _nc_set_tty_mode(&buf)) == OK) - cur_term->Nttyb = buf; + result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf); + if (result == OK) + term->Nttyb = buf; } - return result; + returnCode(result); } /* @@ -97,13 +113,30 @@ _nc_initscr(void) * initialized. */ NCURSES_EXPORT(void) +NCURSES_SP_NAME(filter) (NCURSES_SP_DCL0) +{ + START_TRACE(); + T((T_CALLED("filter(%p)"), (void *) SP_PARM)); +#if NCURSES_SP_FUNCS + if (IsPreScreen(SP_PARM)) { + SP_PARM->_filtered = TRUE; + } +#else + _nc_prescreen.filter_mode = TRUE; +#endif + returnVoid; +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(void) filter(void) { START_TRACE(); - T((T_CALLED("filter"))); + T((T_CALLED("filter()"))); _nc_prescreen.filter_mode = TRUE; returnVoid; } +#endif #if NCURSES_EXT_FUNCS /* @@ -111,62 +144,128 @@ filter(void) * requiring it to also be filtered. */ NCURSES_EXPORT(void) +NCURSES_SP_NAME(nofilter) (NCURSES_SP_DCL0) +{ + START_TRACE(); + T((T_CALLED("nofilter(%p)"), (void *) SP_PARM)); +#if NCURSES_SP_FUNCS + if (IsPreScreen(SP_PARM)) { + SP_PARM->_filtered = FALSE; + } +#else + _nc_prescreen.filter_mode = FALSE; +#endif + returnVoid; +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(void) nofilter(void) { START_TRACE(); - T((T_CALLED("nofilter"))); + T((T_CALLED("nofilter()"))); _nc_prescreen.filter_mode = FALSE; returnVoid; } #endif +#endif /* NCURSES_EXT_FUNCS */ NCURSES_EXPORT(SCREEN *) -newterm(NCURSES_CONST char *name, FILE *ofp, FILE *ifp) +NCURSES_SP_NAME(newterm) (NCURSES_SP_DCLx + const char *name, + FILE *ofp, + FILE *ifp) { - int value; int errret; - SCREEN *current; SCREEN *result = 0; + SCREEN *current; TERMINAL *its_term; + FILE *_ofp = ofp ? ofp : stdout; + FILE *_ifp = ifp ? ifp : stdin; + TERMINAL *new_term = 0; START_TRACE(); - T((T_CALLED("newterm(\"%s\",%p,%p)"), name, ofp, ifp)); + T((T_CALLED("newterm(%p, \"%s\", %p,%p)"), + (void *) SP_PARM, + (name ? name : ""), + (void *) ofp, + (void *) ifp)); + +#if NCURSES_SP_FUNCS + assert(SP_PARM != 0); + if (SP_PARM == 0) + returnSP(SP_PARM); +#endif _nc_init_pthreads(); _nc_lock_global(curses); - current = SP; - its_term = (SP ? SP->_term : 0); + current = CURRENT_SCREEN; + its_term = (current ? current->_term : 0); + +#if defined(EXP_WIN32_DRIVER) + _setmode(fileno(_ifp), _O_BINARY); + _setmode(fileno(_ofp), _O_BINARY); +#endif + INIT_TERM_DRIVER(); /* this loads the capability entry, then sets LINES and COLS */ - if (setupterm(name, fileno(ofp), &errret) != ERR) { - int slk_format = _nc_globals.slk_format; + if ( + TINFO_SETUP_TERM(&new_term, name, + fileno(_ofp), &errret, FALSE) != ERR) { + int slk_format; + int filter_mode; + + _nc_set_screen(0); +#ifdef USE_TERM_DRIVER + assert(new_term != 0); +#endif + +#if NCURSES_SP_FUNCS + slk_format = SP_PARM->slk_format; + filter_mode = SP_PARM->_filtered; +#else + slk_format = _nc_globals.slk_format; + filter_mode = _nc_prescreen.filter_mode; +#endif /* * This actually allocates the screen structure, and saves the original * terminal settings. */ - _nc_set_screen(0); - - /* allow user to set maximum escape delay from the environment */ - if ((value = _nc_getenv_num("ESCDELAY")) >= 0) { - set_escdelay(value); - } - - if (_nc_setupscreen(LINES, - COLS, - ofp, - _nc_prescreen.filter_mode, - slk_format) == ERR) { + if (NCURSES_SP_NAME(_nc_setupscreen) ( +#if NCURSES_SP_FUNCS + &SP_PARM, +#endif + *(ptrLines(SP_PARM)), + *(ptrCols(SP_PARM)), + _ofp, + filter_mode, + slk_format) == ERR) { _nc_set_screen(current); result = 0; } else { - assert(SP != 0); + int value; + int cols; + +#ifdef USE_TERM_DRIVER + TERMINAL_CONTROL_BLOCK *TCB; +#elif !NCURSES_SP_FUNCS + _nc_set_screen(CURRENT_SCREEN); +#endif + assert(SP_PARM != 0); + cols = *(ptrCols(SP_PARM)); +#ifdef USE_TERM_DRIVER + _nc_set_screen(SP_PARM); + TCB = (TERMINAL_CONTROL_BLOCK *) new_term; + TCB->csp = SP_PARM; +#endif /* * In setupterm() we did a set_curterm(), but it was before we set - * SP. So the "current" screen's terminal pointer was overwritten - * with a different terminal. Later, in _nc_setupscreen(), we set - * SP and the terminal pointer in the new screen. + * CURRENT_SCREEN. So the "current" screen's terminal pointer was + * overwritten with a different terminal. Later, in + * _nc_setupscreen(), we set CURRENT_SCREEN and the terminal + * pointer in the new screen. * * Restore the terminal-pointer for the pre-existing screen, if * any. @@ -174,37 +273,58 @@ newterm(NCURSES_CONST char *name, FILE *ofp, FILE *ifp) if (current) current->_term = its_term; +#ifdef USE_TERM_DRIVER + SP_PARM->_term = new_term; +#else + new_term = SP_PARM->_term; +#endif + + /* allow user to set maximum escape delay from the environment */ + if ((value = _nc_getenv_num("ESCDELAY")) >= 0) { +#if NCURSES_EXT_FUNCS + NCURSES_SP_NAME(set_escdelay) (NCURSES_SP_ARGx value); +#else + ESCDELAY = value; +#endif + } + /* if the terminal type has real soft labels, set those up */ - if (slk_format && num_labels > 0 && SLK_STDFMT(slk_format)) - _nc_slk_initialize(stdscr, COLS); + if (slk_format && NumLabels > 0 && SLK_STDFMT(slk_format)) + _nc_slk_initialize(StdScreen(SP_PARM), cols); - SP->_ifd = fileno(ifp); - typeahead(fileno(ifp)); + SP_PARM->_ifd = fileno(_ifp); + NCURSES_SP_NAME(typeahead) (NCURSES_SP_ARGx fileno(_ifp)); #ifdef TERMIOS - SP->_use_meta = ((cur_term->Ottyb.c_cflag & CSIZE) == CS8 && - !(cur_term->Ottyb.c_iflag & ISTRIP)); + SP_PARM->_use_meta = ((new_term->Ottyb.c_cflag & CSIZE) == CS8 && + !(new_term->Ottyb.c_iflag & ISTRIP)) || + USE_KLIBC_KBD; #else - SP->_use_meta = FALSE; + SP_PARM->_use_meta = FALSE; #endif - SP->_endwin = FALSE; - + SP_PARM->_endwin = ewInitial; +#ifndef USE_TERM_DRIVER /* * Check whether we can optimize scrolling under dumb terminals in * case we do not have any of these capabilities, scrolling * optimization will be useless. */ - SP->_scrolling = ((scroll_forward && scroll_reverse) || - ((parm_rindex || - parm_insert_line || - insert_line) && - (parm_index || - parm_delete_line || - delete_line))); + SP_PARM->_scrolling = ((scroll_forward && scroll_reverse) || + ((parm_rindex || + parm_insert_line || + insert_line) && + (parm_index || + parm_delete_line || + delete_line))); +#endif - baudrate(); /* sets a field in the SP structure */ + NCURSES_SP_NAME(baudrate) (NCURSES_SP_ARG); /* sets a field in the screen structure */ - SP->_keytry = 0; + SP_PARM->_keytry = 0; + /* compute movement costs so we can do better move optimization */ +#ifdef USE_TERM_DRIVER + TCBOf(SP_PARM)->drv->td_scinit(SP_PARM); +#else /* ! USE_TERM_DRIVER */ /* * Check for mismatched graphic-rendition capabilities. Most SVr4 * terminfo trees contain entries that have rmul or rmso equated to @@ -215,23 +335,43 @@ newterm(NCURSES_CONST char *name, FILE *ofp, FILE *ifp) * shouldn't be looking at this detail. */ #define SGR0_TEST(mode) (mode != 0) && (exit_attribute_mode == 0 || strcmp(mode, exit_attribute_mode)) - SP->_use_rmso = SGR0_TEST(exit_standout_mode); - SP->_use_rmul = SGR0_TEST(exit_underline_mode); + SP_PARM->_use_rmso = SGR0_TEST(exit_standout_mode); + SP_PARM->_use_rmul = SGR0_TEST(exit_underline_mode); +#if USE_ITALIC + SP_PARM->_use_ritm = SGR0_TEST(exit_italics_mode); +#endif /* compute movement costs so we can do better move optimization */ _nc_mvcur_init(); /* initialize terminal to a sane state */ _nc_screen_init(); +#endif /* USE_TERM_DRIVER */ /* Initialize the terminal line settings. */ - _nc_initscr(); + _nc_initscr(NCURSES_SP_ARG); _nc_signal_handler(TRUE); - - result = SP; + result = SP_PARM; } } _nc_unlock_global(curses); returnSP(result); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(SCREEN *) +newterm(const char *name, FILE *ofp, FILE *ifp) +{ + SCREEN *rc; + + _nc_init_pthreads(); + _nc_lock_global(prescreen); + START_TRACE(); + rc = NCURSES_SP_NAME(newterm) (CURRENT_SCREEN_PRE, name, ofp, ifp); + _nc_forget_prescr(); + _nc_unlock_global(prescreen); + + return rc; +} +#endif diff --git a/lib/libcurses/base/lib_newwin.c b/lib/libcurses/base/lib_newwin.c index 64fca59d06a..041355bb2a3 100644 --- a/lib/libcurses/base/lib_newwin.c +++ b/lib/libcurses/base/lib_newwin.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_newwin.c,v 1.6 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_newwin.c,v 1.7 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,6 +33,7 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -44,7 +46,7 @@ #include #include -MODULE_ID("$Id: lib_newwin.c,v 1.6 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_newwin.c,v 1.7 2023/10/17 09:52:08 nicm Exp $") #define window_is(name) ((sp)->_##name == win) @@ -63,6 +65,17 @@ remove_window_from_screen(WINDOW *win) { SCREEN *sp; +#ifdef USE_SP_WINDOWLIST + if ((sp = _nc_screen_of(win)) != 0) { + if (window_is(curscr)) { + remove_window(curscr); + } else if (window_is(stdscr)) { + remove_window(stdscr); + } else if (window_is(newscr)) { + remove_window(newscr); + } + } +#else for (each_screen(sp)) { if (window_is(curscr)) { remove_window(curscr); @@ -75,29 +88,37 @@ remove_window_from_screen(WINDOW *win) break; } } +#endif } NCURSES_EXPORT(int) _nc_freewin(WINDOW *win) { - WINDOWLIST *p, *q; - int i; int result = ERR; +#ifdef USE_SP_WINDOWLIST + SCREEN *sp = _nc_screen_of(win); /* pretend this is parameter */ +#endif - T((T_CALLED("_nc_freewin(%p)"), win)); + T((T_CALLED("_nc_freewin(%p)"), (void *) win)); if (win != 0) { - if (_nc_try_global(curses) == 0) { + + if (_nc_nonsp_try_global(curses) == 0) { + WINDOWLIST *p, *q; + q = 0; - for (each_window(p)) { + for (each_window(sp, p)) { + if (&(p->win) == win) { remove_window_from_screen(win); if (q == 0) - _nc_windows = p->next; + WindowList(sp) = p->next; else q->next = p->next; - if (!(win->_flags & _SUBWIN)) { + if (!IS_SUBWIN(win)) { + int i; + for (i = 0; i <= win->_maxy; i++) FreeIfNeeded(win->_line[i].text); } @@ -105,35 +126,43 @@ _nc_freewin(WINDOW *win) free(p); result = OK; - T(("...deleted win=%p", win)); + T(("...deleted win=%p", (void *) win)); break; } q = p; } - _nc_unlock_global(curses); + _nc_nonsp_unlock_global(curses); } } returnCode(result); } NCURSES_EXPORT(WINDOW *) -newwin(int num_lines, int num_columns, int begy, int begx) +NCURSES_SP_NAME(newwin) (NCURSES_SP_DCLx + int num_lines, int num_columns, int begy, int begx) { WINDOW *win; NCURSES_CH_T *ptr; int i; - T((T_CALLED("newwin(%d,%d,%d,%d)"), num_lines, num_columns, begy, begx)); + T((T_CALLED("newwin(%p, %d,%d,%d,%d)"), (void *) SP_PARM, num_lines, num_columns, + begy, begx)); - if (begy < 0 || begx < 0 || num_lines < 0 || num_columns < 0) + if (begy < 0 + || begx < 0 + || num_lines < 0 + || num_columns < 0 + || SP_PARM == 0) returnWin(0); if (num_lines == 0) - num_lines = SP->_lines_avail - begy; + num_lines = SP_PARM->_lines_avail - begy; if (num_columns == 0) - num_columns = screen_columns - begx; + num_columns = screen_columns(SP_PARM) - begx; - if ((win = _nc_makenew(num_lines, num_columns, begy, begx, 0)) == 0) + win = NCURSES_SP_NAME(_nc_makenew) (NCURSES_SP_ARGx + num_lines, num_columns, begy, begx, 0); + if (win == 0) returnWin(0); for (i = 0; i < num_lines; i++) { @@ -151,14 +180,30 @@ newwin(int num_lines, int num_columns, int begy, int begx) returnWin(win); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(WINDOW *) +newwin(int num_lines, int num_columns, int begy, int begx) +{ + WINDOW *win; + _nc_sp_lock_global(curses); + win = NCURSES_SP_NAME(newwin) (CURRENT_SCREEN, + num_lines, num_columns, begy, begx); + _nc_sp_unlock_global(curses); + return (win); +} +#endif + NCURSES_EXPORT(WINDOW *) derwin(WINDOW *orig, int num_lines, int num_columns, int begy, int begx) { WINDOW *win; int i; int flags = _SUBWIN; +#if NCURSES_SP_FUNCS + SCREEN *sp = _nc_screen_of(orig); +#endif - T((T_CALLED("derwin(%p,%d,%d,%d,%d)"), orig, num_lines, num_columns, + T((T_CALLED("derwin(%p,%d,%d,%d,%d)"), (void *) orig, num_lines, num_columns, begy, begx)); /* @@ -176,11 +221,13 @@ derwin(WINDOW *orig, int num_lines, int num_columns, int begy, int begx) if (num_columns == 0) num_columns = orig->_maxx + 1 - begx; - if (orig->_flags & _ISPAD) + if (IS_PAD(orig)) flags |= _ISPAD; - if ((win = _nc_makenew(num_lines, num_columns, orig->_begy + begy, - orig->_begx + begx, flags)) == 0) + win = NCURSES_SP_NAME(_nc_makenew) (NCURSES_SP_ARGx num_lines, num_columns, + orig->_begy + begy, + orig->_begx + begx, flags); + if (win == 0) returnWin(0); win->_pary = begy; @@ -199,30 +246,41 @@ derwin(WINDOW *orig, int num_lines, int num_columns, int begy, int begx) NCURSES_EXPORT(WINDOW *) subwin(WINDOW *w, int l, int c, int y, int x) { - T((T_CALLED("subwin(%p, %d, %d, %d, %d)"), w, l, c, y, x)); - T(("parent has begy = %ld, begx = %ld", (long) w->_begy, (long) w->_begx)); + WINDOW *result = 0; + + T((T_CALLED("subwin(%p, %d, %d, %d, %d)"), (void *) w, l, c, y, x)); + if (w != 0) { + T(("parent has begy = %ld, begx = %ld", (long) w->_begy, (long) w->_begx)); - returnWin(derwin(w, l, c, y - w->_begy, x - w->_begx)); + result = derwin(w, l, c, y - w->_begy, x - w->_begx); + } + returnWin(result); } static bool dimension_limit(int value) { - NCURSES_SIZE_T test = value; + NCURSES_SIZE_T test = (NCURSES_SIZE_T) value; return (test == value && value > 0); } NCURSES_EXPORT(WINDOW *) -_nc_makenew(int num_lines, int num_columns, int begy, int begx, int flags) +NCURSES_SP_NAME(_nc_makenew) (NCURSES_SP_DCLx + int num_lines, + int num_columns, + int begy, + int begx, + int flags) { int i; WINDOWLIST *wp; WINDOW *win; - bool is_pad = (flags & _ISPAD); + bool is_padwin = (flags & _ISPAD); - T((T_CALLED("_nc_makenew(%d,%d,%d,%d)"), num_lines, num_columns, begy, begx)); + T((T_CALLED("_nc_makenew(%p,%d,%d,%d,%d)"), + (void *) SP_PARM, num_lines, num_columns, begy, begx)); - if (SP == 0) + if (SP_PARM == 0) returnWin(0); if (!dimension_limit(num_lines) || !dimension_limit(num_columns)) @@ -238,22 +296,24 @@ _nc_makenew(int num_lines, int num_columns, int begy, int begx, int flags) returnWin(0); } - _nc_lock_global(curses); + _nc_nonsp_lock_global(curses); win->_curx = 0; win->_cury = 0; - win->_maxy = num_lines - 1; - win->_maxx = num_columns - 1; - win->_begy = begy; - win->_begx = begx; - win->_yoffset = SP->_topstolen; + win->_maxy = (NCURSES_SIZE_T) (num_lines - 1); + win->_maxx = (NCURSES_SIZE_T) (num_columns - 1); + win->_begy = (NCURSES_SIZE_T) begy; + win->_begx = (NCURSES_SIZE_T) begx; + win->_yoffset = SP_PARM->_topstolen; - win->_flags = flags; + win->_flags = (short) flags; WINDOW_ATTRS(win) = A_NORMAL; SetChar(win->_nc_bkgd, BLANK_TEXT, BLANK_ATTR); - win->_clear = is_pad ? FALSE : (num_lines == screen_lines - && num_columns == screen_columns); + win->_clear = (is_padwin + ? FALSE + : (num_lines == screen_lines(SP_PARM) + && num_columns == screen_columns(SP_PARM))); win->_idlok = FALSE; win->_idcok = TRUE; win->_scroll = FALSE; @@ -267,7 +327,7 @@ _nc_makenew(int num_lines, int num_columns, int begy, int begx, int flags) win->_parent = 0; win->_regtop = 0; - win->_regbottom = num_lines - 1; + win->_regbottom = (NCURSES_SIZE_T) (num_lines - 1); win->_pad._pad_y = -1; win->_pad._pad_x = -1; @@ -297,28 +357,28 @@ _nc_makenew(int num_lines, int num_columns, int begy, int begx, int flags) * So that's how we want ncurses to behave. */ win->_line[i].firstchar = 0; - win->_line[i].lastchar = num_columns - 1; + win->_line[i].lastchar = (NCURSES_SIZE_T) (num_columns - 1); if_USE_SCROLL_HINTS(win->_line[i].oldindex = i); } - if (!is_pad && (begx + num_columns == screen_columns)) { + if (!is_padwin && (begx + num_columns == screen_columns(SP_PARM))) { win->_flags |= _ENDLINE; - if (begx == 0 && num_lines == screen_lines && begy == 0) + if (begx == 0 && num_lines == screen_lines(SP_PARM) && begy == 0) win->_flags |= _FULLWIN; - if (begy + num_lines == screen_lines) + if (begy + num_lines == screen_lines(SP_PARM)) win->_flags |= _SCROLLWIN; } - wp->next = _nc_windows; - wp->screen = SP; - _nc_windows = wp; + wp->next = WindowList(SP_PARM); + wp->screen = SP_PARM; + WindowList(SP_PARM) = wp; - T((T_CREATE("window %p"), win)); + T((T_CREATE("window %p"), (void *) win)); - _nc_unlock_global(curses); + _nc_nonsp_unlock_global(curses); returnWin(win); } @@ -327,14 +387,22 @@ _nc_makenew(int num_lines, int num_columns, int begy, int begx, int flags) * internally, and it is useful to allow those to be invoked without switching * SCREEN's, e.g., for multi-threaded applications. */ -NCURSES_EXPORT(SCREEN *) -_nc_screen_of(WINDOW *win) +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(WINDOW *) +_nc_curscr_of(SCREEN *sp) { - SCREEN *sp = 0; + return (sp == 0) ? NULL : CurScreen(sp); +} - if (win != 0) { - WINDOWLIST *wp = (WINDOWLIST *) win; - sp = wp->screen; - } - return (sp); +NCURSES_EXPORT(WINDOW *) +_nc_newscr_of(SCREEN *sp) +{ + return (sp == 0) ? NULL : NewScreen(sp); } + +NCURSES_EXPORT(WINDOW *) +_nc_stdscr_of(SCREEN *sp) +{ + return (sp == 0) ? NULL : StdScreen(sp); +} +#endif diff --git a/lib/libcurses/base/lib_nl.c b/lib/libcurses/base/lib_nl.c index 74ac920ed53..d92cf3552c5 100644 --- a/lib/libcurses/base/lib_nl.c +++ b/lib/libcurses/base/lib_nl.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_nl.c,v 1.6 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_nl.c,v 1.7 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,1999,2000 Free Software Foundation, Inc. * + * Copyright 2020,2023 Thomas E. Dickey * + * Copyright 1998-2000,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +32,8 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -44,38 +47,52 @@ #include -MODULE_ID("$Id: lib_nl.c,v 1.6 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_nl.c,v 1.7 2023/10/17 09:52:08 nicm Exp $") #ifdef __EMX__ #include #endif NCURSES_EXPORT(int) -nl(void) +NCURSES_SP_NAME(nl) (NCURSES_SP_DCL0) { - T((T_CALLED("nl()"))); - - SP->_nl = TRUE; - + T((T_CALLED("nl(%p)"), (void *) SP_PARM)); + if (0 == SP_PARM) + returnCode(ERR); + IsNl(SP_PARM) = TRUE; #ifdef __EMX__ _nc_flush(); - _fsetmode(NC_OUTPUT, "t"); + _fsetmode(NC_OUTPUT(SP_PARM), "t"); #endif - returnCode(OK); } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) -nonl(void) +nl(void) { - T((T_CALLED("nonl()"))); - - SP->_nl = FALSE; + return NCURSES_SP_NAME(nl) (CURRENT_SCREEN); +} +#endif +NCURSES_EXPORT(int) +NCURSES_SP_NAME(nonl) (NCURSES_SP_DCL0) +{ + T((T_CALLED("nonl(%p)"), (void *) SP_PARM)); + if (0 == SP_PARM) + returnCode(ERR); + IsNl(SP_PARM) = FALSE; #ifdef __EMX__ _nc_flush(); - _fsetmode(NC_OUTPUT, "b"); + _fsetmode(NC_OUTPUT(SP_PARM), "b"); #endif - returnCode(OK); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +nonl(void) +{ + return NCURSES_SP_NAME(nonl) (CURRENT_SCREEN); +} +#endif diff --git a/lib/libcurses/base/lib_overlay.c b/lib/libcurses/base/lib_overlay.c index a61ebf3f1fc..2f4c305f06a 100644 --- a/lib/libcurses/base/lib_overlay.c +++ b/lib/libcurses/base/lib_overlay.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_overlay.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_overlay.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2013,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -42,21 +43,19 @@ #include -MODULE_ID("$Id: lib_overlay.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_overlay.c,v 1.4 2023/10/17 09:52:08 nicm Exp $") static int overlap(const WINDOW *const src, WINDOW *const dst, int const flag) { int rc = ERR; - int sx1, sy1, sx2, sy2; - int dx1, dy1, dx2, dy2; - int sminrow, smincol; - int dminrow, dmincol; - int dmaxrow, dmaxcol; - T((T_CALLED("overlap(%p,%p,%d)"), src, dst, flag)); + T((T_CALLED("overlap(%p,%p,%d)"), (const void *) src, (void *) dst, flag)); if (src != 0 && dst != 0) { + int sx1, sy1, sx2, sy2; + int dx1, dy1, dx2, dy2; + _nc_lock_global(curses); T(("src : begy %ld, begx %ld, maxy %ld, maxx %ld", @@ -81,12 +80,12 @@ overlap(const WINDOW *const src, WINDOW *const dst, int const flag) dy2 = dy1 + dst->_maxy; if (dx2 >= sx1 && dx1 <= sx2 && dy2 >= sy1 && dy1 <= sy2) { - sminrow = max(sy1, dy1) - sy1; - smincol = max(sx1, dx1) - sx1; - dminrow = max(sy1, dy1) - dy1; - dmincol = max(sx1, dx1) - dx1; - dmaxrow = min(sy2, dy2) - dy1; - dmaxcol = min(sx2, dx2) - dx1; + int sminrow = max(sy1, dy1) - sy1; + int smincol = max(sx1, dx1) - sx1; + int dminrow = max(sy1, dy1) - dy1; + int dmincol = max(sx1, dx1) - dx1; + int dmaxrow = min(sy2, dy2) - dy1; + int dmaxcol = min(sx2, dx2) - dx1; rc = copywin(src, dst, sminrow, smincol, @@ -112,7 +111,7 @@ overlap(const WINDOW *const src, WINDOW *const dst, int const flag) NCURSES_EXPORT(int) overlay(const WINDOW *win1, WINDOW *win2) { - T((T_CALLED("overlay(%p,%p)"), win1, win2)); + T((T_CALLED("overlay(%p,%p)"), (const void *) win1, (void *) win2)); returnCode(overlap(win1, win2, TRUE)); } @@ -129,7 +128,7 @@ overlay(const WINDOW *win1, WINDOW *win2) NCURSES_EXPORT(int) overwrite(const WINDOW *win1, WINDOW *win2) { - T((T_CALLED("overwrite(%p,%p)"), win1, win2)); + T((T_CALLED("overwrite(%p,%p)"), (const void *) win1, (void *) win2)); returnCode(overlap(win1, win2, FALSE)); } @@ -141,15 +140,21 @@ copywin(const WINDOW *src, WINDOW *dst, int over) { int rc = ERR; - int sx, sy, dx, dy; - bool touched; - attr_t bk; - attr_t mask; T((T_CALLED("copywin(%p, %p, %d, %d, %d, %d, %d, %d, %d)"), - src, dst, sminrow, smincol, dminrow, dmincol, dmaxrow, dmaxcol, over)); + (const void *) src, + (void *) dst, + sminrow, smincol, + dminrow, dmincol, + dmaxrow, dmaxcol, over)); + + if (src != 0 + && dst != 0 + && dmaxrow >= dminrow + && dmaxcol >= dmincol) { + attr_t bk; + attr_t mask; - if (src && dst) { _nc_lock_global(curses); bk = AttrOf(dst->_nc_bkgd); @@ -163,17 +168,28 @@ copywin(const WINDOW *src, WINDOW *dst, /* make sure rectangle fits in destination */ if (dmaxrow <= dst->_maxy && dmaxcol <= dst->_maxx) { + int sx, sy, dx, dy; + bool copied = FALSE; T(("rectangle fits in destination")); for (dy = dminrow, sy = sminrow; dy <= dmaxrow; sy++, dy++) { + bool touched; + + if (dy < 0 || sy < 0) + continue; touched = FALSE; for (dx = dmincol, sx = smincol; dx <= dmaxcol; sx++, dx++) { + + if (dx < 0 || sx < 0) + continue; + copied = TRUE; + if (over) { if ((CharOf(src->_line[sy].text[sx]) != L(' ')) && (!CharEq(dst->_line[dy].text[dx], @@ -199,7 +215,8 @@ copywin(const WINDOW *src, WINDOW *dst, } } T(("finished copywin")); - rc = OK; + if (copied) + rc = OK; } } _nc_unlock_global(curses); diff --git a/lib/libcurses/base/lib_pad.c b/lib/libcurses/base/lib_pad.c index 50463e24a23..18c10fbf0fb 100644 --- a/lib/libcurses/base/lib_pad.c +++ b/lib/libcurses/base/lib_pad.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_pad.c,v 1.5 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_pad.c,v 1.6 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2004,2006 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2010,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +32,8 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -42,21 +45,22 @@ #include -MODULE_ID("$Id: lib_pad.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_pad.c,v 1.6 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(WINDOW *) -newpad(int l, int c) +NCURSES_SP_NAME(newpad) (NCURSES_SP_DCLx int l, int c) { WINDOW *win; NCURSES_CH_T *ptr; int i; - T((T_CALLED("newpad(%d, %d)"), l, c)); + T((T_CALLED("newpad(%p,%d, %d)"), (void *) SP_PARM, l, c)); if (l <= 0 || c <= 0) returnWin(0); - if ((win = _nc_makenew(l, c, 0, 0, _ISPAD)) == NULL) + win = NCURSES_SP_NAME(_nc_makenew) (NCURSES_SP_ARGx l, c, 0, 0, _ISPAD); + if (win == NULL) returnWin(0); for (i = 0; i < l; i++) { @@ -72,6 +76,14 @@ newpad(int l, int c) returnWin(win); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(WINDOW *) +newpad(int l, int c) +{ + return NCURSES_SP_NAME(newpad) (CURRENT_SCREEN, l, c); +} +#endif + NCURSES_EXPORT(WINDOW *) subpad(WINDOW *orig, int l, int c, int begy, int begx) { @@ -80,7 +92,7 @@ subpad(WINDOW *orig, int l, int c, int begy, int begx) T((T_CALLED("subpad(%d, %d)"), l, c)); if (orig) { - if (!(orig->_flags & _ISPAD) + if (!IS_PAD(orig) || ((win = derwin(orig, l, c, begy, begx)) == NULL)) returnWin(0); } @@ -96,10 +108,14 @@ prefresh(WINDOW *win, int smaxrow, int smaxcol) { +#if NCURSES_SP_FUNCS + SCREEN *sp = _nc_screen_of(win); +#endif + T((T_CALLED("prefresh()"))); if (pnoutrefresh(win, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol) != ERR - && doupdate() != ERR) { + && NCURSES_SP_NAME(doupdate) (NCURSES_SP_ARG) != ERR) { returnCode(OK); } returnCode(ERR); @@ -114,10 +130,11 @@ pnoutrefresh(WINDOW *win, int smaxrow, int smaxcol) { - NCURSES_SIZE_T i, j; - NCURSES_SIZE_T m, n; - NCURSES_SIZE_T pmaxrow; - NCURSES_SIZE_T pmaxcol; + int i, j; + int m, n; + int pmaxrow; + int pmaxcol; + SCREEN *sp; #if USE_SCROLL_HINTS const int my_len = 2; /* parameterize the threshold for hardscroll */ @@ -126,14 +143,16 @@ pnoutrefresh(WINDOW *win, #endif T((T_CALLED("pnoutrefresh(%p, %d, %d, %d, %d, %d, %d)"), - win, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol)); + (void *) win, pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol)); if (win == 0) returnCode(ERR); - if (!(win->_flags & _ISPAD)) + if (!IS_PAD(win)) returnCode(ERR); + sp = _nc_screen_of(win); + /* negative values are interpreted as zero */ if (pminrow < 0) pminrow = 0; @@ -164,14 +183,20 @@ pnoutrefresh(WINDOW *win, pmaxcol = pmincol + smaxcol - smincol; } - if (smaxrow >= screen_lines - || smaxcol >= screen_columns + if (smaxrow >= screen_lines(sp) + || smaxcol >= screen_columns(sp) || sminrow > smaxrow || smincol > smaxcol) returnCode(ERR); T(("pad being refreshed")); +#ifdef TRACE + if (USE_TRACEF(TRACE_UPDATE)) { + _tracedump("...pad", win); + _nc_unlock_global(tracef); + } +#endif /* TRACE */ #if USE_SCROLL_HINTS if (win->_pad._pad_y >= 0) { displaced = pminrow - win->_pad._pad_y @@ -196,13 +221,13 @@ pnoutrefresh(WINDOW *win, * merely change the costs of various update cases. */ #if USE_SCROLL_HINTS - wide = (smincol < my_len && smaxcol > (newscr->_maxx - my_len)); + wide = (smincol < my_len && smaxcol > (NewScreen(sp)->_maxx - my_len)); #endif for (i = pminrow, m = sminrow + win->_yoffset; - i <= pmaxrow && m <= newscr->_maxy; + i <= pmaxrow && m <= NewScreen(sp)->_maxy; i++, m++) { - register struct ldat *nline = &newscr->_line[m]; + register struct ldat *nline = &NewScreen(sp)->_line[m]; register struct ldat *oline = &win->_line[i]; for (j = pmincol, n = smincol; j <= pmaxcol; j++, n++) { NCURSES_CH_T ch = oline->text[j]; @@ -231,9 +256,9 @@ pnoutrefresh(WINDOW *win, || nind > smaxrow) { nind = _NEWINDEX; } else if (displaced) { - register struct ldat *pline = &curscr->_line[nind]; + register struct ldat *pline = &CurScreen(sp)->_line[nind]; for (j = 0; j <= my_len; j++) { - int k = newscr->_maxx - j; + int k = NewScreen(sp)->_maxx - j; if (pline->text[j] != nline->text[j] || pline->text[k] != nline->text[k]) { nind = _NEWINDEX; @@ -263,27 +288,29 @@ pnoutrefresh(WINDOW *win, win->_line[i].oldindex = _NEWINDEX; #endif - win->_begx = smincol; - win->_begy = sminrow; + win->_begx = (NCURSES_SIZE_T) smincol; + win->_begy = (NCURSES_SIZE_T) sminrow; if (win->_clear) { win->_clear = FALSE; - newscr->_clear = TRUE; + NewScreen(sp)->_clear = TRUE; } /* * Use the pad's current position, if it will be visible. - * If not, don't do anything; it's not an error. + * If not, don't do anything; it is not an error. */ if (win->_leaveok == FALSE && win->_cury >= pminrow && win->_curx >= pmincol && win->_cury <= pmaxrow && win->_curx <= pmaxcol) { - newscr->_cury = win->_cury - pminrow + win->_begy + win->_yoffset; - newscr->_curx = win->_curx - pmincol + win->_begx; + NewScreen(sp)->_cury = (NCURSES_SIZE_T) (win->_cury - pminrow + + win->_begy + win->_yoffset); + NewScreen(sp)->_curx = (NCURSES_SIZE_T) (win->_curx - pmincol + + win->_begx); } - newscr->_leaveok = win->_leaveok; + NewScreen(sp)->_leaveok = win->_leaveok; win->_flags &= ~_HASMOVED; /* @@ -291,12 +318,12 @@ pnoutrefresh(WINDOW *win, * We will use this on subsequent calls to this function to derive * values to stuff into 'oldindex[]' -- for scrolling optimization. */ - win->_pad._pad_y = pminrow; - win->_pad._pad_x = pmincol; - win->_pad._pad_top = sminrow; - win->_pad._pad_left = smincol; - win->_pad._pad_bottom = smaxrow; - win->_pad._pad_right = smaxcol; + win->_pad._pad_y = (NCURSES_SIZE_T) pminrow; + win->_pad._pad_x = (NCURSES_SIZE_T) pmincol; + win->_pad._pad_top = (NCURSES_SIZE_T) sminrow; + win->_pad._pad_left = (NCURSES_SIZE_T) smincol; + win->_pad._pad_bottom = (NCURSES_SIZE_T) smaxrow; + win->_pad._pad_right = (NCURSES_SIZE_T) smaxcol; returnCode(OK); } @@ -304,12 +331,12 @@ pnoutrefresh(WINDOW *win, NCURSES_EXPORT(int) pechochar(WINDOW *pad, const chtype ch) { - T((T_CALLED("pechochar(%p, %s)"), pad, _tracechtype(ch))); + T((T_CALLED("pechochar(%p, %s)"), (void *) pad, _tracechtype(ch))); if (pad == 0) returnCode(ERR); - if (!(pad->_flags & _ISPAD)) + if (!IS_PAD(pad)) returnCode(wechochar(pad, ch)); waddch(pad, ch); diff --git a/lib/libcurses/base/lib_printw.c b/lib/libcurses/base/lib_printw.c index 165d6ae719c..68f226bb565 100644 --- a/lib/libcurses/base/lib_printw.c +++ b/lib/libcurses/base/lib_printw.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_printw.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_printw.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2005 Free Software Foundation, Inc. * + * Copyright 2018-2019,2020 Thomas E. Dickey * + * Copyright 1998-2012,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,7 +30,7 @@ ****************************************************************************/ /**************************************************************************** - * Author: Thomas E. Dickey 1997 * + * Author: Thomas E. Dickey 1997-on * ****************************************************************************/ /* @@ -41,85 +42,91 @@ #include -MODULE_ID("$Id: lib_printw.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_printw.c,v 1.4 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) -printw(const char *fmt,...) +printw(const char *fmt, ...) { va_list argp; int code; #ifdef TRACE - va_start(argp, fmt); + va_list argq; + va_start(argq, fmt); T((T_CALLED("printw(%s%s)"), - _nc_visbuf(fmt), _nc_varargs(fmt, argp))); - va_end(argp); + _nc_visbuf(fmt), _nc_varargs(fmt, argq))); + va_end(argq); #endif va_start(argp, fmt); - code = vwprintw(stdscr, fmt, argp); + code = vw_printw(stdscr, fmt, argp); va_end(argp); returnCode(code); } NCURSES_EXPORT(int) -wprintw(WINDOW *win, const char *fmt,...) +wprintw(WINDOW *win, const char *fmt, ...) { va_list argp; int code; #ifdef TRACE - va_start(argp, fmt); + va_list argq; + va_start(argq, fmt); T((T_CALLED("wprintw(%p,%s%s)"), - win, _nc_visbuf(fmt), _nc_varargs(fmt, argp))); - va_end(argp); + (void *) win, _nc_visbuf(fmt), _nc_varargs(fmt, argq))); + va_end(argq); #endif va_start(argp, fmt); - code = vwprintw(win, fmt, argp); + code = vw_printw(win, fmt, argp); va_end(argp); returnCode(code); } NCURSES_EXPORT(int) -mvprintw(int y, int x, const char *fmt,...) +mvprintw(int y, int x, const char *fmt, ...) { - va_list argp; int code; #ifdef TRACE - va_start(argp, fmt); + va_list argq; + va_start(argq, fmt); T((T_CALLED("mvprintw(%d,%d,%s%s)"), - y, x, _nc_visbuf(fmt), _nc_varargs(fmt, argp))); - va_end(argp); + y, x, _nc_visbuf(fmt), _nc_varargs(fmt, argq))); + va_end(argq); #endif if ((code = move(y, x)) != ERR) { + va_list argp; + va_start(argp, fmt); - code = vwprintw(stdscr, fmt, argp); + code = vw_printw(stdscr, fmt, argp); va_end(argp); } returnCode(code); } NCURSES_EXPORT(int) -mvwprintw(WINDOW *win, int y, int x, const char *fmt,...) +mvwprintw(WINDOW *win, int y, int x, const char *fmt, ...) { - va_list argp; int code; #ifdef TRACE - va_start(argp, fmt); + va_list argq; + va_start(argq, fmt); T((T_CALLED("mvwprintw(%d,%d,%p,%s%s)"), - y, x, win, _nc_visbuf(fmt), _nc_varargs(fmt, argp))); - va_end(argp); + y, x, (void *) win, _nc_visbuf(fmt), _nc_varargs(fmt, argq))); + va_end(argq); #endif if ((code = wmove(win, y, x)) != ERR) { + va_list argp; + va_start(argp, fmt); - code = vwprintw(win, fmt, argp); + code = vw_printw(win, fmt, argp); va_end(argp); } returnCode(code); @@ -130,10 +137,32 @@ vwprintw(WINDOW *win, const char *fmt, va_list argp) { char *buf; int code = ERR; +#if NCURSES_SP_FUNCS + SCREEN *sp = _nc_screen_of(win); +#endif + + T((T_CALLED("vwprintw(%p,%s,va_list)"), (void *) win, _nc_visbuf(fmt))); + + buf = NCURSES_SP_NAME(_nc_printf_string) (NCURSES_SP_ARGx fmt, argp); + if (buf != 0) { + code = waddstr(win, buf); + } + returnCode(code); +} + +NCURSES_EXPORT(int) +vw_printw(WINDOW *win, const char *fmt, va_list argp) +{ + char *buf; + int code = ERR; +#if NCURSES_SP_FUNCS + SCREEN *sp = _nc_screen_of(win); +#endif - T((T_CALLED("vwprintw(%p,%s,va_list)"), win, _nc_visbuf(fmt))); + T((T_CALLED("vw_printw(%p,%s,va_list)"), (void *) win, _nc_visbuf(fmt))); - if ((buf = _nc_printf_string(fmt, argp)) != 0) { + buf = NCURSES_SP_NAME(_nc_printf_string) (NCURSES_SP_ARGx fmt, argp); + if (buf != 0) { code = waddstr(win, buf); } returnCode(code); diff --git a/lib/libcurses/base/lib_redrawln.c b/lib/libcurses/base/lib_redrawln.c index e84667ca819..a10e1cae9ff 100644 --- a/lib/libcurses/base/lib_redrawln.c +++ b/lib/libcurses/base/lib_redrawln.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_redrawln.c,v 1.4 2019/11/15 14:45:37 fcambus Exp $ */ +/* $OpenBSD: lib_redrawln.c,v 1.5 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -41,7 +42,7 @@ #include -MODULE_ID("$Id: lib_redrawln.c,v 1.4 2019/11/15 14:45:37 fcambus Exp $") +MODULE_ID("$Id: lib_redrawln.c,v 1.5 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) wredrawln(WINDOW *win, int beg, int num) @@ -49,37 +50,40 @@ wredrawln(WINDOW *win, int beg, int num) int i; int end; size_t len; + SCREEN *sp; - T((T_CALLED("wredrawln(%p,%d,%d)"), win, beg, num)); + T((T_CALLED("wredrawln(%p,%d,%d)"), (void *) win, beg, num)); if (win == 0) returnCode(ERR); + sp = _nc_screen_of(win); + if (beg < 0) beg = 0; if (touchline(win, beg, num) == ERR) returnCode(ERR); - if (touchline(curscr, beg + win->_begy, num) == ERR) + if (touchline(CurScreen(sp), beg + win->_begy, num) == ERR) returnCode(ERR); end = beg + num; - if (end > curscr->_maxy + 1 - win->_begy) - end = curscr->_maxy + 1 - win->_begy; + if (end > CurScreen(sp)->_maxy + 1 - win->_begy) + end = CurScreen(sp)->_maxy + 1 - win->_begy; if (end > win->_maxy + 1) end = win->_maxy + 1; - len = (win->_maxx + 1); - if (len > (size_t) (curscr->_maxx + 1 - win->_begx)) - len = (size_t) (curscr->_maxx + 1 - win->_begx); - len *= sizeof(curscr->_line[0].text[0]); + len = (size_t) (win->_maxx + 1); + if (len > (size_t) (CurScreen(sp)->_maxx + 1 - win->_begx)) + len = (size_t) (CurScreen(sp)->_maxx + 1 - win->_begx); + len *= sizeof(CurScreen(sp)->_line[0].text[0]); for (i = beg; i < end; i++) { int crow = i + win->_begy; - memset(curscr->_line[crow].text + win->_begx, 0, len); - _nc_make_oldhash(crow); + memset(CurScreen(sp)->_line[crow].text + win->_begx, 0, len); + NCURSES_SP_NAME(_nc_make_oldhash) (NCURSES_SP_ARGx crow); } returnCode(OK); diff --git a/lib/libcurses/base/lib_refresh.c b/lib/libcurses/base/lib_refresh.c index d0571b99212..95f9c985bed 100644 --- a/lib/libcurses/base/lib_refresh.c +++ b/lib/libcurses/base/lib_refresh.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_refresh.c,v 1.5 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_refresh.c,v 1.6 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * + * Copyright 2020-2021,2023 Thomas E. Dickey * + * Copyright 1998-2010,2011 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,6 +33,7 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer * ****************************************************************************/ /* @@ -43,24 +45,27 @@ #include -MODULE_ID("$Id: lib_refresh.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_refresh.c,v 1.6 2023/10/17 09:52:08 nicm Exp $") NCURSES_EXPORT(int) wrefresh(WINDOW *win) { int code; +#if NCURSES_SP_FUNCS + SCREEN *SP_PARM = _nc_screen_of(win); +#endif - T((T_CALLED("wrefresh(%p)"), win)); + T((T_CALLED("wrefresh(%p)"), (void *) win)); if (win == 0) { code = ERR; - } else if (win == curscr) { - curscr->_clear = TRUE; - code = doupdate(); + } else if (win == CurScreen(SP_PARM)) { + CurScreen(SP_PARM)->_clear = TRUE; + code = NCURSES_SP_NAME(doupdate) (NCURSES_SP_ARG); } else if ((code = wnoutrefresh(win)) == OK) { if (win->_clear) - newscr->_clear = TRUE; - code = doupdate(); + NewScreen(SP_PARM)->_clear = TRUE; + code = NCURSES_SP_NAME(doupdate) (NCURSES_SP_ARG); /* * Reset the clearok() flag in case it was set for the special * case in hardscroll.c (if we don't reset it here, we'll get 2 @@ -75,16 +80,35 @@ wrefresh(WINDOW *win) NCURSES_EXPORT(int) wnoutrefresh(WINDOW *win) { - NCURSES_SIZE_T limit_x; - NCURSES_SIZE_T src_row, src_col; - NCURSES_SIZE_T begx; - NCURSES_SIZE_T begy; - NCURSES_SIZE_T dst_row, dst_col; + int limit_x; + int src_row, src_col; + int begx; + int begy; + int dst_row, dst_col; #if USE_SCROLL_HINTS bool wide; #endif +#if NCURSES_SP_FUNCS + SCREEN *SP_PARM = _nc_screen_of(win); +#endif + + T((T_CALLED("wnoutrefresh(%p)"), (void *) win)); - T((T_CALLED("wnoutrefresh(%p)"), win)); + if (win == NULL) + returnCode(ERR); + + /* + * Handle pads as a special case. + */ + if (IS_PAD(win)) { + returnCode(pnoutrefresh(win, + win->_pad._pad_y, + win->_pad._pad_x, + win->_pad._pad_top, + win->_pad._pad_left, + win->_pad._pad_bottom, + win->_pad._pad_right)); + } #ifdef TRACE if (USE_TRACEF(TRACE_UPDATE)) { _tracedump("...win", win); @@ -92,19 +116,12 @@ wnoutrefresh(WINDOW *win) } #endif /* TRACE */ - /* - * This function will break badly if we try to refresh a pad. - */ - if ((win == 0) - || (win->_flags & _ISPAD)) - returnCode(ERR); - /* put them here so "win == 0" won't break our code */ begx = win->_begx; begy = win->_begy; - newscr->_nc_bkgd = win->_nc_bkgd; - WINDOW_ATTRS(newscr) = WINDOW_ATTRS(win); + NewScreen(SP_PARM)->_nc_bkgd = win->_nc_bkgd; + WINDOW_ATTRS(NewScreen(SP_PARM)) = WINDOW_ATTRS(win); /* merge in change information from all subwindows of this window */ wsyncdown(win); @@ -124,7 +141,7 @@ wnoutrefresh(WINDOW *win) * windows). Note that changing this formula will not break any code, * merely change the costs of various update cases. */ - wide = (begx <= 1 && win->_maxx >= (newscr->_maxx - 1)); + wide = (begx <= 1 && win->_maxx >= (NewScreen(SP_PARM)->_maxx - 1)); #endif win->_flags &= ~_HASMOVED; @@ -139,14 +156,14 @@ wnoutrefresh(WINDOW *win) /* limit(dst_col) */ limit_x = win->_maxx; /* limit(src_col) */ - if (limit_x > newscr->_maxx - begx) - limit_x = newscr->_maxx - begx; + if (limit_x > NewScreen(SP_PARM)->_maxx - begx) + limit_x = NewScreen(SP_PARM)->_maxx - begx; for (src_row = 0, dst_row = begy + win->_yoffset; - src_row <= win->_maxy && dst_row <= newscr->_maxy; + src_row <= win->_maxy && dst_row <= NewScreen(SP_PARM)->_maxy; src_row++, dst_row++) { - register struct ldat *nline = &newscr->_line[dst_row]; - register struct ldat *oline = &win->_line[src_row]; + struct ldat *nline = &(NewScreen(SP_PARM)->_line[dst_row]); + struct ldat *oline = &win->_line[src_row]; if (oline->firstchar != _NOCHANGE) { int last_src = oline->lastchar; @@ -158,7 +175,7 @@ wnoutrefresh(WINDOW *win) dst_col = src_col + begx; if_WIDEC({ - register int j; + int j; /* * Ensure that we will copy complete multi-column characters @@ -193,13 +210,12 @@ wnoutrefresh(WINDOW *win) }); if_WIDEC({ - static cchar_t blank = BLANK; int last_dst = begx + ((last_src < win->_maxx) ? last_src : win->_maxx); int fix_left = dst_col; int fix_right = last_dst; - register int j; + int j; /* * Check for boundary cases where we may overwrite part of a @@ -227,7 +243,8 @@ wnoutrefresh(WINDOW *win) * this character. Find the end of the character. */ ++j; - while (j <= newscr->_maxx && isWidecExt(nline->text[j])) { + while (j <= NewScreen(SP_PARM)->_maxx && + isWidecExt(nline->text[j])) { fix_right = j++; } } @@ -238,6 +255,7 @@ wnoutrefresh(WINDOW *win) */ if (fix_left < dst_col || fix_right > last_dst) { for (j = fix_left; j <= fix_right; ++j) { + static cchar_t blank = BLANK; nline->text[j] = blank; CHANGED_CELL(nline, j); } @@ -271,18 +289,19 @@ wnoutrefresh(WINDOW *win) if (win->_clear) { win->_clear = FALSE; - newscr->_clear = TRUE; + NewScreen(SP_PARM)->_clear = TRUE; } if (!win->_leaveok) { - newscr->_cury = win->_cury + win->_begy + win->_yoffset; - newscr->_curx = win->_curx + win->_begx; + NewScreen(SP_PARM)->_cury = (NCURSES_SIZE_T) (win->_cury + + win->_begy + win->_yoffset); + NewScreen(SP_PARM)->_curx = (NCURSES_SIZE_T) (win->_curx + win->_begx); } - newscr->_leaveok = win->_leaveok; + NewScreen(SP_PARM)->_leaveok = win->_leaveok; #ifdef TRACE if (USE_TRACEF(TRACE_UPDATE)) { - _tracedump("newscr", newscr); + _tracedump("newscr", NewScreen(SP_PARM)); _nc_unlock_global(tracef); } #endif /* TRACE */ diff --git a/lib/libcurses/base/lib_restart.c b/lib/libcurses/base/lib_restart.c index b017010bc8f..c4a01059147 100644 --- a/lib/libcurses/base/lib_restart.c +++ b/lib/libcurses/base/lib_restart.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_restart.c,v 1.5 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_restart.c,v 1.6 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020,2023 Thomas E. Dickey * + * Copyright 1998-2012,2015 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,6 +33,7 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2008 * ****************************************************************************/ /* @@ -42,53 +44,60 @@ #include -#if SVR4_TERMIO && !defined(_POSIX_SOURCE) -#define _POSIX_SOURCE -#endif - -#include /* lines, columns, cur_term */ - -MODULE_ID("$Id: lib_restart.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_restart.c,v 1.6 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) -restartterm(NCURSES_CONST char *termp, int filenum, int *errret) +NCURSES_SP_NAME(restartterm) (NCURSES_SP_DCLx + NCURSES_CONST char *termp, + int filenum, + int *errret) { int result; +#ifdef USE_TERM_DRIVER + TERMINAL *new_term = 0; +#endif - T((T_CALLED("restartterm(%s,%d,%p)"), termp, filenum, errret)); + START_TRACE(); + T((T_CALLED("restartterm(%p,%s,%d,%p)"), + (void *) SP_PARM, + termp, + filenum, + (void *) errret)); - if (setupterm(termp, filenum, errret) != OK) { + if (TINFO_SETUP_TERM(&new_term, termp, filenum, errret, FALSE) != OK) { result = ERR; - } else if (SP != 0) { - int saveecho = SP->_echo; - int savecbreak = SP->_cbreak; - int saveraw = SP->_raw; - int savenl = SP->_nl; + } else if (SP_PARM != 0) { + TTY_FLAGS save_flags = SP_PARM->_tty_flags; - if (saveecho) - echo(); - else - noecho(); +#ifdef USE_TERM_DRIVER + SP_PARM->_term = new_term; +#endif + if (save_flags._echo) { + NCURSES_SP_NAME(echo) (NCURSES_SP_ARG); + } else { + NCURSES_SP_NAME(noecho) (NCURSES_SP_ARG); + } - if (savecbreak) { - cbreak(); - noraw(); - } else if (saveraw) { - nocbreak(); - raw(); + if (save_flags._cbreak) { + NCURSES_SP_NAME(cbreak) (NCURSES_SP_ARG); + NCURSES_SP_NAME(noraw) (NCURSES_SP_ARG); + } else if (save_flags._raw) { + NCURSES_SP_NAME(nocbreak) (NCURSES_SP_ARG); + NCURSES_SP_NAME(raw) (NCURSES_SP_ARG); } else { - nocbreak(); - noraw(); + NCURSES_SP_NAME(nocbreak) (NCURSES_SP_ARG); + NCURSES_SP_NAME(noraw) (NCURSES_SP_ARG); + } + if (save_flags._nl) { + NCURSES_SP_NAME(nl) (NCURSES_SP_ARG); + } else { + NCURSES_SP_NAME(nonl) (NCURSES_SP_ARG); } - if (savenl) - nl(); - else - nonl(); - reset_prog_mode(); + NCURSES_SP_NAME(reset_prog_mode) (NCURSES_SP_ARG); #if USE_SIZECHANGE - _nc_update_screensize(SP); + _nc_update_screensize(SP_PARM); #endif result = OK; @@ -97,3 +106,12 @@ restartterm(NCURSES_CONST char *termp, int filenum, int *errret) } returnCode(result); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +restartterm(NCURSES_CONST char *termp, int filenum, int *errret) +{ + START_TRACE(); + return NCURSES_SP_NAME(restartterm) (CURRENT_SCREEN, termp, filenum, errret); +} +#endif diff --git a/lib/libcurses/base/lib_scanw.c b/lib/libcurses/base/lib_scanw.c index 852573c83c5..1612f614d10 100644 --- a/lib/libcurses/base/lib_scanw.c +++ b/lib/libcurses/base/lib_scanw.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_scanw.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_scanw.c,v 1.4 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000,2001 Free Software Foundation, Inc. * + * Copyright 2018-2019,2020 Thomas E. Dickey * + * Copyright 1998-2009,2011 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -42,21 +43,40 @@ #include -MODULE_ID("$Id: lib_scanw.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_scanw.c,v 1.4 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) -vwscanw(WINDOW *win, NCURSES_CONST char *fmt, va_list argp) +vwscanw(WINDOW *win, const char *fmt, va_list argp) { char buf[BUFSIZ]; + int code = ERR; - if (wgetnstr(win, buf, sizeof(buf) - 1) == ERR) - return (ERR); + if (wgetnstr(win, buf, (int) sizeof(buf) - 1) != ERR) { + if ((code = vsscanf(buf, fmt, argp)) == EOF) { + code = ERR; + } + } - return (vsscanf(buf, fmt, argp)); + return code; } NCURSES_EXPORT(int) -scanw(NCURSES_CONST char *fmt,...) +vw_scanw(WINDOW *win, const char *fmt, va_list argp) +{ + char buf[BUFSIZ]; + int code = ERR; + + if (wgetnstr(win, buf, (int) sizeof(buf) - 1) != ERR) { + if ((code = vsscanf(buf, fmt, argp)) == EOF) { + code = ERR; + } + } + + return code; +} + +NCURSES_EXPORT(int) +scanw(const char *fmt, ...) { int code; va_list ap; @@ -64,45 +84,45 @@ scanw(NCURSES_CONST char *fmt,...) T(("scanw(\"%s\",...) called", fmt)); va_start(ap, fmt); - code = vwscanw(stdscr, fmt, ap); + code = vw_scanw(stdscr, fmt, ap); va_end(ap); return (code); } NCURSES_EXPORT(int) -wscanw(WINDOW *win, NCURSES_CONST char *fmt,...) +wscanw(WINDOW *win, const char *fmt, ...) { int code; va_list ap; - T(("wscanw(%p,\"%s\",...) called", win, fmt)); + T(("wscanw(%p,\"%s\",...) called", (void *) win, fmt)); va_start(ap, fmt); - code = vwscanw(win, fmt, ap); + code = vw_scanw(win, fmt, ap); va_end(ap); return (code); } NCURSES_EXPORT(int) -mvscanw(int y, int x, NCURSES_CONST char *fmt,...) +mvscanw(int y, int x, const char *fmt, ...) { int code; va_list ap; va_start(ap, fmt); - code = (move(y, x) == OK) ? vwscanw(stdscr, fmt, ap) : ERR; + code = (move(y, x) == OK) ? vw_scanw(stdscr, fmt, ap) : ERR; va_end(ap); return (code); } NCURSES_EXPORT(int) -mvwscanw(WINDOW *win, int y, int x, NCURSES_CONST char *fmt,...) +mvwscanw(WINDOW *win, int y, int x, const char *fmt, ...) { int code; va_list ap; va_start(ap, fmt); - code = (wmove(win, y, x) == OK) ? vwscanw(win, fmt, ap) : ERR; + code = (wmove(win, y, x) == OK) ? vw_scanw(win, fmt, ap) : ERR; va_end(ap); return (code); } diff --git a/lib/libcurses/base/lib_screen.c b/lib/libcurses/base/lib_screen.c index de9e4dc8196..1bf2dee491a 100644 --- a/lib/libcurses/base/lib_screen.c +++ b/lib/libcurses/base/lib_screen.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_screen.c,v 1.4 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_screen.c,v 1.5 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2019-2021,2023 Thomas E. Dickey * + * Copyright 1998-2017,2018 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,35 +33,523 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996 on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ #include -MODULE_ID("$Id: lib_screen.c,v 1.4 2010/01/12 23:22:06 nicm Exp $") +#include + +#ifndef CUR +#define CUR SP_TERMTYPE +#endif + +MODULE_ID("$Id: lib_screen.c,v 1.5 2023/10/17 09:52:09 nicm Exp $") #define MAX_SIZE 0x3fff /* 16k is big enough for a window or pad */ +#define MARKER '\\' +#define APPEND '+' +#define GUTTER '|' +#define L_CURL '{' +#define R_CURL '}' + +#if USE_STRING_HACKS && HAVE_SNPRINTF +#define ARG_SLIMIT(name) size_t name, +#else +#define ARG_SLIMIT(name) /* nothing */ +#endif + +#define CUR_SLIMIT _nc_SLIMIT(limit - (size_t) (target - base)) +#define TOP_SLIMIT _nc_SLIMIT(sizeof(buffer)) + +/* + * Use 0x888888 as the magic number for new-format files, since it cannot be + * mistaken for the _cury/_curx pair of 16-bit numbers which start the old + * format. It happens to be unused in the file 5.22 database (2015/03/07). + */ +static const char my_magic[] = +{'\210', '\210', '\210', '\210', 0}; + +#if NCURSES_EXT_PUTWIN +typedef enum { + pINT /* int */ + ,pSHORT /* short */ + ,pBOOL /* bool */ + ,pATTR /* attr_t */ + ,pCHAR /* chtype */ + ,pSIZE /* NCURSES_SIZE_T */ +#if NCURSES_WIDECHAR + ,pCCHAR /* cchar_t */ +#endif +} PARAM_TYPE; + +typedef struct { + const char name[11]; + attr_t attr; +} SCR_ATTRS; + +typedef struct { + const char name[17]; + PARAM_TYPE type; + size_t offset; +} SCR_PARAMS; + +#define DATA(name) { { #name }, A_##name } +static const SCR_ATTRS scr_attrs[] = +{ + DATA(NORMAL), + DATA(STANDOUT), + DATA(UNDERLINE), + DATA(REVERSE), + DATA(BLINK), + DATA(DIM), + DATA(BOLD), + DATA(ALTCHARSET), + DATA(INVIS), + DATA(PROTECT), + DATA(HORIZONTAL), + DATA(LEFT), + DATA(LOW), + DATA(RIGHT), + DATA(TOP), + DATA(VERTICAL), + +#ifdef A_ITALIC + DATA(ITALIC), +#endif +}; +#undef DATA + +#define DATA(name, type) { { #name }, type, offsetof(WINDOW, name) } + +static const SCR_PARAMS scr_params[] = +{ + DATA(_cury, pSIZE), + DATA(_curx, pSIZE), + DATA(_maxy, pSIZE), + DATA(_maxx, pSIZE), + DATA(_begy, pSIZE), + DATA(_begx, pSIZE), + DATA(_flags, pSHORT), + DATA(_attrs, pATTR), + DATA(_bkgd, pCHAR), + DATA(_notimeout, pBOOL), + DATA(_clear, pBOOL), + DATA(_leaveok, pBOOL), + DATA(_scroll, pBOOL), + DATA(_idlok, pBOOL), + DATA(_idcok, pBOOL), + DATA(_immed, pBOOL), + DATA(_sync, pBOOL), + DATA(_use_keypad, pBOOL), + DATA(_delay, pINT), + DATA(_regtop, pSIZE), + DATA(_regbottom, pSIZE), + DATA(_pad._pad_y, pSIZE), + DATA(_pad._pad_x, pSIZE), + DATA(_pad._pad_top, pSIZE), + DATA(_pad._pad_left, pSIZE), + DATA(_pad._pad_bottom, pSIZE), + DATA(_pad._pad_right, pSIZE), + DATA(_yoffset, pSIZE), +#if NCURSES_WIDECHAR + DATA(_bkgrnd, pCCHAR), +#if NCURSES_EXT_COLORS + DATA(_color, pINT), +#endif +#endif +}; +#undef DATA + +static const NCURSES_CH_T blank = NewChar(BLANK_TEXT); + +/* + * Allocate and read a line of text. Caller must free it. + */ +static char * +read_txt(FILE *fp) +{ + size_t limit = 1024; + char *result = malloc(limit); + char *buffer; + + if (result != 0) { + int ch = 0; + size_t used = 0; + + clearerr(fp); + result[used] = '\0'; + do { + if (used + 2 >= limit) { + limit += 1024; + buffer = realloc(result, limit); + if (buffer == 0) { + free(result); + result = 0; + break; + } + result = buffer; + } + ch = fgetc(fp); + if (ch == EOF) + break; + result[used++] = (char) ch; + result[used] = '\0'; + } while (ch != '\n'); + + if (ch == '\n') { + result[--used] = '\0'; + TR(TRACE_IEVENT, ("READ:%s", result)); + } else if (used == 0) { + free(result); + result = 0; + } + } + return result; +} + +static char * +decode_attr(char *source, attr_t *target, int *color) +{ + bool found = FALSE; + + TR(TRACE_IEVENT, ("decode_attr '%s'", source)); + + while (*source) { + if (source[0] == MARKER && source[1] == L_CURL) { + source += 2; + found = TRUE; + } else if (source[0] == R_CURL) { + source++; + found = FALSE; + } else if (found) { + size_t n; + char *next = source; + + if (source[0] == GUTTER) { + ++next; + } else if (*next == 'C') { + int value = 0; + unsigned pair; + next++; + while (isdigit(UChar(*next))) { + value = value * 10 + (*next++ - '0'); + } + *target &= ~A_COLOR; + pair = (unsigned) ((value > 256) + ? COLOR_PAIR(255) + : COLOR_PAIR(value)); + *target |= pair; + *color = value; + } else { + while (isalnum(UChar(*next))) { + ++next; + } + for (n = 0; n < SIZEOF(scr_attrs); ++n) { + if ((size_t) (next - source) == strlen(scr_attrs[n].name)) { + if (scr_attrs[n].attr) { + *target |= scr_attrs[n].attr; + } else { + *target = A_NORMAL; + } + break; + } + } + } + source = next; + } else { + break; + } + } + return source; +} + +static char * +decode_char(char *source, int *target) +{ + int limit = 0; + int base = 16; + const char digits[] = "0123456789abcdef"; + + TR(TRACE_IEVENT, ("decode_char '%s'", source)); + *target = ' '; + switch (*source) { + case MARKER: + switch (*++source) { + case APPEND: + break; + case MARKER: + *target = MARKER; + ++source; + break; + case 's': + *target = ' '; + ++source; + break; + case '0': + case '1': + case '2': + case '3': + base = 8; + limit = 3; + break; + case 'u': + limit = 4; + ++source; + break; + case 'U': + limit = 8; + ++source; + break; + } + if (limit) { + *target = 0; + while (limit-- > 0) { + char *find = strchr(digits, *source++); + int ch = (find != 0) ? (int) (find - digits) : -1; + *target *= base; + if (ch >= 0 && ch < base) { + *target += ch; + } + } + } + break; + default: + *target = *source++; + break; + } + return source; +} + +static char * +decode_chtype(char *source, chtype fillin, chtype *target) +{ + attr_t attr = ChAttrOf(fillin); + int color = PAIR_NUMBER((int) attr); + int value; + + TR(TRACE_IEVENT, ("decode_chtype '%s'", source)); + source = decode_attr(source, &attr, &color); + source = decode_char(source, &value); + *target = (ChCharOf(value) | attr | (chtype) COLOR_PAIR(color)); + /* FIXME - ignore combining characters */ + return source; +} + +#if NCURSES_WIDECHAR +static char * +decode_cchar(char *source, cchar_t *fillin, cchar_t *target) +{ + int color; + attr_t attr = fillin->attr; + wchar_t chars[CCHARW_MAX]; + int append = 0; + int value = 0; + + TR(TRACE_IEVENT, ("decode_cchar '%s'", source)); + *target = blank; +#if NCURSES_EXT_COLORS + color = fillin->ext_color; +#else + color = (int) PAIR_NUMBER(attr); +#endif + source = decode_attr(source, &attr, &color); + memset(chars, 0, sizeof(chars)); + source = decode_char(source, &value); + chars[0] = (wchar_t) value; + /* handle combining characters */ + while (source[0] == MARKER && source[1] == APPEND) { + source += 2; + source = decode_char(source, &value); + if (++append < CCHARW_MAX) { + chars[append] = (wchar_t) value; + } + } + setcchar(target, chars, attr, (short) color, &color); + return source; +} +#endif + +static int +read_win(WINDOW *win, FILE *fp) +{ + int code = ERR; + size_t n; + int color; +#if NCURSES_WIDECHAR + NCURSES_CH_T prior; +#endif + chtype prior2; + + memset(win, 0, sizeof(WINDOW)); + for (;;) { + char *name; + char *value; + char *txt = read_txt(fp); + + if (txt == 0) + break; + if (!strcmp(txt, "rows:")) { + free(txt); + code = OK; + break; + } + if ((value = strchr(txt, '=')) == 0) { + free(txt); + continue; + } + *value++ = '\0'; + name = !strcmp(txt, "flag") ? value : txt; + for (n = 0; n < SIZEOF(scr_params); ++n) { + if (!strcmp(name, scr_params[n].name)) { + void *data = (void *) ((char *) win + scr_params[n].offset); + + switch (scr_params[n].type) { + case pATTR: + (void) decode_attr(value, data, &color); + break; + case pBOOL: + *(bool *) data = TRUE; + break; + case pCHAR: + prior2 = ' '; + decode_chtype(value, prior2, data); + break; + case pINT: + *(int *) data = atoi(value); + break; + case pSHORT: + *(short *) data = (short) atoi(value); + break; + case pSIZE: + *(NCURSES_SIZE_T *) data = (NCURSES_SIZE_T) atoi(value); + break; +#if NCURSES_WIDECHAR + case pCCHAR: + prior = blank; + decode_cchar(value, &prior, data); + break; +#endif + } + break; + } + } + free(txt); + } + return code; +} + +static int +read_row(char *source, NCURSES_CH_T *prior, NCURSES_CH_T *target, int length) +{ + while (*source != '\0' && length > 0) { +#if NCURSES_WIDECHAR + int len; + + source = decode_cchar(source, prior, target); + len = _nc_wacs_width(target->chars[0]); + if (len > 1) { + int n; + + SetWidecExt(CHDEREF(target), 0); + for (n = 1; n < len; ++n) { + target[n] = target[0]; + SetWidecExt(CHDEREF(target), n); + } + target += (len - 1); + length -= (len - 1); + } +#else + source = decode_chtype(source, *prior, target); +#endif + *prior = *target; + ++target; + --length; + } + while (length-- > 0) { + *target++ = blank; + } + /* FIXME - see what error conditions should apply if I need to return ERR */ + return 0; +} +#endif /* NCURSES_EXT_PUTWIN */ + +/* + * Originally, getwin/putwin used fread/fwrite, because they used binary data. + * The new format uses printable ASCII, which does not have as predictable + * sizes. Consequently, we use buffered I/O, e.g., fgetc/fprintf, which need + * special handling if we want to read screen dumps from an older library. + */ +static int +read_block(void *target, size_t length, FILE *fp) +{ + int result = 0; + char *buffer = target; + + clearerr(fp); + while (length-- != 0) { + int ch = fgetc(fp); + if (ch == EOF) { + result = -1; + break; + } + *buffer++ = (char) ch; + } + return result; +} + NCURSES_EXPORT(WINDOW *) -getwin(FILE *filep) +NCURSES_SP_NAME(getwin) (NCURSES_SP_DCLx FILE *filep) { WINDOW tmp, *nwin; - int n; + bool old_format = FALSE; - T((T_CALLED("getwin(%p)"), filep)); + T((T_CALLED("getwin(%p)"), (void *) filep)); - clearerr(filep); - (void) fread(&tmp, sizeof(WINDOW), 1, filep); - if (ferror(filep) - || tmp._maxy == 0 - || tmp._maxy > MAX_SIZE - || tmp._maxx == 0 - || tmp._maxx > MAX_SIZE) + if (filep == 0) { returnWin(0); + } - if (tmp._flags & _ISPAD) { - nwin = newpad(tmp._maxy + 1, tmp._maxx + 1); + /* + * Read the first 4 bytes to determine first if this is an old-format + * screen-dump, or new-format. + */ + if (read_block(&tmp, (size_t) 4, filep) < 0) { + returnWin(0); + } + /* + * If this is a new-format file, and we do not support it, give up. + */ + if (!memcmp(&tmp, my_magic, (size_t) 4)) { +#if NCURSES_EXT_PUTWIN + if (read_win(&tmp, filep) < 0) +#endif + returnWin(0); + } else if (read_block(((char *) &tmp) + 4, sizeof(WINDOW) - 4, filep) < 0) { + returnWin(0); } else { - nwin = newwin(tmp._maxy + 1, tmp._maxx + 1, 0, 0); + old_format = TRUE; + } + + /* + * Check the window-size: + */ + if (tmp._maxy == 0 || + tmp._maxy > MAX_SIZE || + tmp._maxx == 0 || + tmp._maxx > MAX_SIZE) { + returnWin(0); + } + + if (IS_PAD(&tmp)) { + nwin = NCURSES_SP_NAME(newpad) (NCURSES_SP_ARGx + tmp._maxy + 1, + tmp._maxx + 1); + } else { + nwin = NCURSES_SP_NAME(newwin) (NCURSES_SP_ARGx + tmp._maxy + 1, + tmp._maxx + 1, 0, 0); } /* @@ -69,6 +558,9 @@ getwin(FILE *filep) * made sense is probably gone. */ if (nwin != 0) { + int n; + size_t linesize = sizeof(NCURSES_CH_T) * (size_t) (tmp._maxx + 1); + nwin->_curx = tmp._curx; nwin->_cury = tmp._cury; nwin->_maxy = tmp._maxy; @@ -95,43 +587,348 @@ getwin(FILE *filep) nwin->_regtop = tmp._regtop; nwin->_regbottom = tmp._regbottom; - if (tmp._flags & _ISPAD) + if (IS_PAD(&tmp)) nwin->_pad = tmp._pad; - for (n = 0; n <= nwin->_maxy; n++) { - clearerr(filep); - (void) fread(nwin->_line[n].text, - sizeof(NCURSES_CH_T), - (size_t) (nwin->_maxx + 1), - filep); - if (ferror(filep)) { + if (old_format) { + T(("reading old-format screen dump")); + for (n = 0; n <= nwin->_maxy; n++) { + if (read_block(nwin->_line[n].text, linesize, filep) < 0) { + delwin(nwin); + returnWin(0); + } + } + } +#if NCURSES_EXT_PUTWIN + else { + char *txt = 0; + bool success = TRUE; + NCURSES_CH_T prior = blank; + + T(("reading new-format screen dump")); + for (n = 0; n <= nwin->_maxy; n++) { + long row; + char *next; + + if ((txt = read_txt(filep)) == 0) { + T(("...failed to read string for row %d", n + 1)); + success = FALSE; + break; + } + row = strtol(txt, &next, 10); + if (row != (n + 1) || *next != ':') { + T(("...failed to read row-number %d", n + 1)); + success = FALSE; + break; + } + + if (read_row(++next, &prior, nwin->_line[n].text, tmp._maxx + + 1) < 0) { + T(("...failed to read cells for row %d", n + 1)); + success = FALSE; + break; + } + free(txt); + txt = 0; + } + + if (!success) { + free(txt); delwin(nwin); returnWin(0); } } +#endif touchwin(nwin); } returnWin(nwin); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(WINDOW *) +getwin(FILE *filep) +{ + return NCURSES_SP_NAME(getwin) (CURRENT_SCREEN, filep); +} +#endif + +#if NCURSES_EXT_PUTWIN +static void +encode_attr(char *target, ARG_SLIMIT(limit) + attr_t source, + attr_t prior, + int source_color, + int prior_color) +{ +#if USE_STRING_HACKS && HAVE_SNPRINTF + char *base = target; +#endif + source &= ~A_CHARTEXT; + prior &= ~A_CHARTEXT; + + *target = '\0'; + if ((source != prior) || (source_color != prior_color)) { + size_t n; + bool first = TRUE; + + *target++ = MARKER; + *target++ = L_CURL; + + for (n = 0; n < SIZEOF(scr_attrs); ++n) { + if ((source & scr_attrs[n].attr) != 0 || + ((source & ALL_BUT_COLOR) == 0 && + (scr_attrs[n].attr == A_NORMAL))) { + if (first) { + first = FALSE; + } else { + *target++ = '|'; + } + _nc_STRCPY(target, scr_attrs[n].name, limit); + target += strlen(target); + } + } + if (source_color != prior_color) { + if (!first) + *target++ = '|'; + _nc_SPRINTF(target, CUR_SLIMIT "C%d", source_color); + target += strlen(target); + } + + *target++ = R_CURL; + *target = '\0'; + } +} + +static void +encode_cell(char *target, ARG_SLIMIT(limit) CARG_CH_T source, CARG_CH_T previous) +{ +#if USE_STRING_HACKS && HAVE_SNPRINTF + char *base = target; +#endif +#if NCURSES_WIDECHAR + size_t n; + int source_pair = GetPair(*source); + int previous_pair = GetPair(*previous); + + *target = '\0'; + if ((previous->attr != source->attr) || (previous_pair != source_pair)) { + encode_attr(target, CUR_SLIMIT + source->attr, + previous->attr, + source_pair, + previous_pair); + } + target += strlen(target); +#if NCURSES_EXT_COLORS + if (previous->ext_color != source->ext_color) { + _nc_SPRINTF(target, CUR_SLIMIT + "%c%cC%d%c", MARKER, L_CURL, source->ext_color, R_CURL); + } +#endif + for (n = 0; n < SIZEOF(source->chars); ++n) { + unsigned uch = (unsigned) source->chars[n]; + if (uch == 0) + continue; + if (n) { + *target++ = MARKER; + *target++ = APPEND; + } + *target++ = MARKER; + if (uch > 0xffff) { + _nc_SPRINTF(target, CUR_SLIMIT "U%08x", uch); + } else if (uch > 0xff) { + _nc_SPRINTF(target, CUR_SLIMIT "u%04x", uch); + } else if (uch < 32 || uch >= 127) { + _nc_SPRINTF(target, CUR_SLIMIT "%03o", uch & 0xff); + } else { + switch (uch) { + case ' ': + _nc_STRCPY(target, "s", limit); + break; + case MARKER: + *target++ = MARKER; + *target = '\0'; + break; + default: + --target; + _nc_SPRINTF(target, CUR_SLIMIT "%c", uch); + break; + } + } + target += strlen(target); + } +#else + chtype ch = CharOfD(source); + + *target = '\0'; + if (AttrOfD(previous) != AttrOfD(source)) { + encode_attr(target, CUR_SLIMIT + AttrOfD(source), + AttrOfD(previous), + GetPair(source), + GetPair(previous)); + } + target += strlen(target); + *target++ = MARKER; + if (ch < 32 || ch >= 127) { + _nc_SPRINTF(target, CUR_SLIMIT "%03o", UChar(ch)); + } else { + switch (ch) { + case ' ': + _nc_STRCPY(target, "s", limit); + break; + case MARKER: + *target++ = MARKER; + *target = '\0'; + break; + default: + --target; + _nc_SPRINTF(target, CUR_SLIMIT "%c", UChar(ch)); + break; + } + } +#endif +} +#endif + NCURSES_EXPORT(int) putwin(WINDOW *win, FILE *filep) { int code = ERR; - int n; - T((T_CALLED("putwin(%p,%p)"), win, filep)); + T((T_CALLED("putwin(%p,%p)"), (void *) win, (void *) filep)); +#if NCURSES_EXT_PUTWIN + if (win != 0) { + const char *version = curses_version(); + char buffer[1024]; + NCURSES_CH_T last_cell; + int y; + + memset(&last_cell, 0, sizeof(last_cell)); + + clearerr(filep); + + /* + * Our magic number is technically nonprinting, but aside from that, + * all of the file is printable ASCII. + */ +#define PUTS(s) if (fputs(s, filep) == EOF || ferror(filep)) returnCode(code) + PUTS(my_magic); + PUTS(version); + PUTS("\n"); + for (y = 0; y < (int) SIZEOF(scr_params); ++y) { + const char *name = scr_params[y].name; + const char *data = (char *) win + scr_params[y].offset; + const void *dp = (const void *) data; + attr_t attr; + + *buffer = '\0'; + if (!strncmp(name, "_pad.", (size_t) 5) && !IS_PAD(win)) { + continue; + } + switch (scr_params[y].type) { + case pATTR: + attr = (*(const attr_t *) dp) & ~A_CHARTEXT; + encode_attr(buffer, TOP_SLIMIT + (*(const attr_t *) dp) & ~A_CHARTEXT, + A_NORMAL, + COLOR_PAIR((int) attr), + 0); + break; + case pBOOL: + if (!(*(const bool *) data)) { + continue; + } + _nc_STRCPY(buffer, name, sizeof(buffer)); + name = "flag"; + break; + case pCHAR: + attr = (*(const attr_t *) dp); + encode_attr(buffer, TOP_SLIMIT + * (const attr_t *) dp, + A_NORMAL, + COLOR_PAIR((int) attr), + 0); + break; + case pINT: + if (!(*(const int *) dp)) + continue; + _nc_SPRINTF(buffer, TOP_SLIMIT + "%d", *(const int *) dp); + break; + case pSHORT: + if (!(*(const short *) dp)) + continue; + _nc_SPRINTF(buffer, TOP_SLIMIT + "%d", *(const short *) dp); + break; + case pSIZE: + if (!(*(const NCURSES_SIZE_T *) dp)) + continue; + _nc_SPRINTF(buffer, TOP_SLIMIT + "%d", *(const NCURSES_SIZE_T *) dp); + break; +#if NCURSES_WIDECHAR + case pCCHAR: + encode_cell(buffer, TOP_SLIMIT + (CARG_CH_T) dp, CHREF(last_cell)); + break; +#endif + } + /* + * Only write non-default data. + */ + if (*buffer != '\0') { + if (fprintf(filep, "%s=%s\n", name, buffer) <= 0 + || ferror(filep)) + returnCode(code); + } + } + /* Write row-data */ + fprintf(filep, "rows:\n"); + for (y = 0; y <= win->_maxy; y++) { + NCURSES_CH_T *data = win->_line[y].text; + int x; + if (fprintf(filep, "%d:", y + 1) <= 0 + || ferror(filep)) + returnCode(code); + for (x = 0; x <= win->_maxx; x++) { +#if NCURSES_WIDECHAR + int len = _nc_wacs_width(data[x].chars[0]); + encode_cell(buffer, TOP_SLIMIT CHREF(data[x]), CHREF(last_cell)); + last_cell = data[x]; + PUTS(buffer); + if (len > 1) + x += (len - 1); +#else + encode_cell(buffer, TOP_SLIMIT CHREF(data[x]), CHREF(last_cell)); + last_cell = data[x]; + PUTS(buffer); +#endif + } + PUTS("\n"); + } + code = OK; + } +#else + /* + * This is the original putwin(): + * A straight binary dump is simple, but its format can depend on whether + * ncurses is compiled with wide-character support, and also may depend + * on the version of ncurses, e.g., if the WINDOW structure is extended. + */ if (win != 0) { size_t len = (size_t) (win->_maxx + 1); + int y; clearerr(filep); - if (fwrite(win, sizeof(WINDOW), 1, filep) != 1 + if (fwrite(win, sizeof(WINDOW), (size_t) 1, filep) != 1 || ferror(filep)) returnCode(code); - for (n = 0; n <= win->_maxy; n++) { - if (fwrite(win->_line[n].text, + for (y = 0; y <= win->_maxy; y++) { + if (fwrite(win->_line[y].text, sizeof(NCURSES_CH_T), len, filep) != len || ferror(filep)) { returnCode(code); @@ -139,84 +936,147 @@ putwin(WINDOW *win, FILE *filep) } code = OK; } +#endif returnCode(code); } +/* + * Replace a window covering the whole screen, i.e., newscr or curscr. + */ +static WINDOW * +replace_window(WINDOW *target, FILE *source) +{ + WINDOW *result = getwin(source); +#if NCURSES_EXT_FUNCS + if (result != NULL) { + if (getmaxx(result) != getmaxx(target) + || getmaxy(result) != getmaxy(target)) { + int code = wresize(result, + 1 + getmaxy(target), + 1 + getmaxx(target)); + if (code != OK) { + delwin(result); + result = NULL; + } + } + } +#endif + delwin(target); + return result; +} + NCURSES_EXPORT(int) -scr_restore(const char *file) +NCURSES_SP_NAME(scr_restore) (NCURSES_SP_DCLx const char *file) { FILE *fp = 0; + int code = ERR; - T((T_CALLED("scr_restore(%s)"), _nc_visbuf(file))); + T((T_CALLED("scr_restore(%p,%s)"), (void *) SP_PARM, _nc_visbuf(file))); - if (_nc_access(file, R_OK) < 0 - || (fp = fopen(file, "rb")) == 0) { - returnCode(ERR); - } else { - delwin(newscr); - SP->_newscr = getwin(fp); + if (_nc_access(file, R_OK) >= 0 + && (fp = safe_fopen(file, BIN_R)) != 0) { + NewScreen(SP_PARM) = replace_window(NewScreen(SP_PARM), fp); #if !USE_REENTRANT - newscr = SP->_newscr; + newscr = NewScreen(SP_PARM); #endif (void) fclose(fp); - returnCode(OK); + if (NewScreen(SP_PARM) != 0) { + code = OK; + } } + returnCode(code); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +scr_restore(const char *file) +{ + return NCURSES_SP_NAME(scr_restore) (CURRENT_SCREEN, file); +} +#endif + NCURSES_EXPORT(int) scr_dump(const char *file) { + int result; FILE *fp = 0; T((T_CALLED("scr_dump(%s)"), _nc_visbuf(file))); if (_nc_access(file, W_OK) < 0 - || (fp = fopen(file, "wb")) == 0) { - returnCode(ERR); + || (fp = safe_fopen(file, BIN_W)) == 0) { + result = ERR; } else { (void) putwin(newscr, fp); (void) fclose(fp); - returnCode(OK); + result = OK; } + returnCode(result); } NCURSES_EXPORT(int) -scr_init(const char *file) +NCURSES_SP_NAME(scr_init) (NCURSES_SP_DCLx const char *file) { - FILE *fp = 0; + int code = ERR; - T((T_CALLED("scr_init(%s)"), _nc_visbuf(file))); + T((T_CALLED("scr_init(%p,%s)"), (void *) SP_PARM, _nc_visbuf(file))); - if (exit_ca_mode && non_rev_rmcup) - returnCode(ERR); + if (SP_PARM != 0 && +#ifdef USE_TERM_DRIVER + InfoOf(SP_PARM).caninit +#else + !(exit_ca_mode && non_rev_rmcup) +#endif + ) { + FILE *fp = 0; - if (_nc_access(file, R_OK) < 0 - || (fp = fopen(file, "rb")) == 0) { - returnCode(ERR); - } else { - delwin(curscr); - SP->_curscr = getwin(fp); + if (_nc_access(file, R_OK) >= 0 + && (fp = safe_fopen(file, BIN_R)) != 0) { + CurScreen(SP_PARM) = replace_window(CurScreen(SP_PARM), fp); #if !USE_REENTRANT - curscr = SP->_curscr; + curscr = CurScreen(SP_PARM); #endif - (void) fclose(fp); - returnCode(OK); + (void) fclose(fp); + if (CurScreen(SP_PARM) != 0) { + code = OK; + } + } } + returnCode(code); } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) -scr_set(const char *file) +scr_init(const char *file) { - T((T_CALLED("scr_set(%s)"), _nc_visbuf(file))); + return NCURSES_SP_NAME(scr_init) (CURRENT_SCREEN, file); +} +#endif - if (scr_init(file) == ERR) { - returnCode(ERR); - } else { - delwin(newscr); - SP->_newscr = dupwin(curscr); +NCURSES_EXPORT(int) +NCURSES_SP_NAME(scr_set) (NCURSES_SP_DCLx const char *file) +{ + int code = ERR; + + T((T_CALLED("scr_set(%p,%s)"), (void *) SP_PARM, _nc_visbuf(file))); + + if (NCURSES_SP_NAME(scr_init) (NCURSES_SP_ARGx file) == OK) { + delwin(NewScreen(SP_PARM)); + NewScreen(SP_PARM) = dupwin(curscr); #if !USE_REENTRANT - newscr = SP->_newscr; + newscr = NewScreen(SP_PARM); #endif - returnCode(OK); + if (NewScreen(SP_PARM) != 0) { + code = OK; + } } + returnCode(code); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +scr_set(const char *file) +{ + return NCURSES_SP_NAME(scr_set) (CURRENT_SCREEN, file); +} +#endif diff --git a/lib/libcurses/base/lib_scroll.c b/lib/libcurses/base/lib_scroll.c index c3fc784958c..964eb03bc1b 100644 --- a/lib/libcurses/base/lib_scroll.c +++ b/lib/libcurses/base/lib_scroll.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_scroll.c,v 1.4 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_scroll.c,v 1.5 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2004,2006 Free Software Foundation, Inc. * + * Copyright 2019,2020 Thomas E. Dickey * + * Copyright 1998-2010,2011 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -45,22 +46,22 @@ #include -MODULE_ID("$Id: lib_scroll.c,v 1.4 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_scroll.c,v 1.5 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(void) _nc_scroll_window(WINDOW *win, int const n, - NCURSES_SIZE_T const top, - NCURSES_SIZE_T const bottom, + int const top, + int const bottom, NCURSES_CH_T blank) { int limit; int line; int j; - size_t to_copy = (size_t) (sizeof(NCURSES_CH_T) * (win->_maxx + 1)); + size_t to_copy = (sizeof(NCURSES_CH_T) * (size_t) (win->_maxx + 1)); TR(TRACE_MOVE, ("_nc_scroll_window(%p, %d, %ld, %ld)", - win, n, (long) top, (long) bottom)); + (void *) win, n, (long) top, (long) bottom)); if (top < 0 || bottom < top @@ -79,11 +80,13 @@ _nc_scroll_window(WINDOW *win, * setup cost. So there is no point in trying to be excessively * clever -- esr. */ +#define BottomLimit(n) ((n) >= 0 && (n) >= top) +#define TopLimit(n) ((n) <= win->_maxy && (n) <= bottom) /* shift n lines downwards */ if (n < 0) { limit = top - n; - for (line = bottom; line >= limit && line >= 0; line--) { + for (line = bottom; line >= limit && BottomLimit(line); line--) { TR(TRACE_MOVE, ("...copying %d to %d", line + n, line)); memcpy(win->_line[line].text, win->_line[line + n].text, @@ -91,7 +94,7 @@ _nc_scroll_window(WINDOW *win, if_USE_SCROLL_HINTS(win->_line[line].oldindex = win->_line[line + n].oldindex); } - for (line = top; line < limit && line <= win->_maxy; line++) { + for (line = top; line < limit && TopLimit(line); line++) { TR(TRACE_MOVE, ("...filling %d", line)); for (j = 0; j <= win->_maxx; j++) win->_line[line].text[j] = blank; @@ -102,14 +105,14 @@ _nc_scroll_window(WINDOW *win, /* shift n lines upwards */ if (n > 0) { limit = bottom - n; - for (line = top; line <= limit && line <= win->_maxy; line++) { + for (line = top; line <= limit && TopLimit(line); line++) { memcpy(win->_line[line].text, win->_line[line + n].text, to_copy); if_USE_SCROLL_HINTS(win->_line[line].oldindex = win->_line[line + n].oldindex); } - for (line = bottom; line > limit && line >= 0; line--) { + for (line = bottom; line > limit && BottomLimit(line); line--) { for (j = 0; j <= win->_maxx; j++) win->_line[line].text[j] = blank; if_USE_SCROLL_HINTS(win->_line[line].oldindex = _NEWINDEX); @@ -137,7 +140,7 @@ _nc_scroll_window(WINDOW *win, NCURSES_EXPORT(int) wscrl(WINDOW *win, int n) { - T((T_CALLED("wscrl(%p,%d)"), win, n)); + T((T_CALLED("wscrl(%p,%d)"), (void *) win, n)); if (!win || !win->_scroll) { TR(TRACE_MOVE, ("...scrollok is false")); diff --git a/lib/libcurses/base/lib_scrollok.c b/lib/libcurses/base/lib_scrollok.c index a3bfc155ddf..9b483ee9c5f 100644 --- a/lib/libcurses/base/lib_scrollok.c +++ b/lib/libcurses/base/lib_scrollok.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_scrollok.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_scrollok.c,v 1.4 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2000,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -42,12 +43,12 @@ #include -MODULE_ID("$Id: lib_scrollok.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_scrollok.c,v 1.4 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) scrollok(WINDOW *win, bool flag) { - T((T_CALLED("scrollok(%p,%d)"), win, flag)); + T((T_CALLED("scrollok(%p,%d)"), (void *) win, flag)); if (win) { win->_scroll = flag; diff --git a/lib/libcurses/base/lib_scrreg.c b/lib/libcurses/base/lib_scrreg.c index d70a0ac88a9..2f4ee87b1a0 100644 --- a/lib/libcurses/base/lib_scrreg.c +++ b/lib/libcurses/base/lib_scrreg.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_scrreg.c,v 1.4 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_scrreg.c,v 1.5 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2000,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -42,12 +43,12 @@ #include -MODULE_ID("$Id: lib_scrreg.c,v 1.4 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_scrreg.c,v 1.5 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) wsetscrreg(WINDOW *win, int top, int bottom) { - T((T_CALLED("wsetscrreg(%p,%d,%d)"), win, top, bottom)); + T((T_CALLED("wsetscrreg(%p,%d,%d)"), (void *) win, top, bottom)); if (win && top >= 0 && top <= win->_maxy && diff --git a/lib/libcurses/base/lib_set_term.c b/lib/libcurses/base/lib_set_term.c index 0c821fdb98d..2d98ef46583 100644 --- a/lib/libcurses/base/lib_set_term.c +++ b/lib/libcurses/base/lib_set_term.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_set_term.c,v 1.14 2021/03/10 20:16:08 millert Exp $ */ +/* $OpenBSD: lib_set_term.c,v 1.15 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2021,2022 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,6 +33,7 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -41,12 +43,31 @@ ** */ -#include +#define NEW_PAIR_INTERNAL 1 -#include /* cur_term */ +#include #include +#include + +#if USE_GPM_SUPPORT +#ifdef HAVE_LIBDL +/* use dynamic loader to avoid linkage dependency */ +#include +#endif +#endif + +#undef CUR +#define CUR SP_TERMTYPE -MODULE_ID("$Id: lib_set_term.c,v 1.14 2021/03/10 20:16:08 millert Exp $") +MODULE_ID("$Id: lib_set_term.c,v 1.15 2023/10/17 09:52:09 nicm Exp $") + +#ifdef USE_TERM_DRIVER +#define MaxColors InfoOf(sp).maxcolors +#define NumLabels InfoOf(sp).numlabels +#else +#define MaxColors max_colors +#define NumLabels num_labels +#endif NCURSES_EXPORT(SCREEN *) set_term(SCREEN *screenp) @@ -54,25 +75,25 @@ set_term(SCREEN *screenp) SCREEN *oldSP; SCREEN *newSP; - T((T_CALLED("set_term(%p)"), screenp)); + T((T_CALLED("set_term(%p)"), (void *) screenp)); _nc_lock_global(curses); - oldSP = SP; + oldSP = CURRENT_SCREEN; _nc_set_screen(screenp); - newSP = SP; + newSP = screenp; if (newSP != 0) { - set_curterm(newSP->_term); + TINFO_SET_CURTERM(newSP, newSP->_term); #if !USE_REENTRANT - curscr = newSP->_curscr; - newscr = newSP->_newscr; - stdscr = newSP->_stdscr; + curscr = CurScreen(newSP); + newscr = NewScreen(newSP); + stdscr = StdScreen(newSP); COLORS = newSP->_color_count; COLOR_PAIRS = newSP->_pair_count; #endif } else { - set_curterm(0); + TINFO_SET_CURTERM(oldSP, 0); #if !USE_REENTRANT curscr = 0; newscr = 0; @@ -84,7 +105,7 @@ set_term(SCREEN *screenp) _nc_unlock_global(curses); - T((T_RETURN("%p"), oldSP)); + T((T_RETURN("%p"), (void *) oldSP)); return (oldSP); } @@ -108,7 +129,7 @@ delink_screen(SCREEN *sp) for (each_screen(temp)) { if (temp == sp) { if (last) - last = sp->_next_screen; + last->_next_screen = sp->_next_screen; else _nc_screen_chain = sp->_next_screen; result = TRUE; @@ -125,19 +146,41 @@ delink_screen(SCREEN *sp) NCURSES_EXPORT(void) delscreen(SCREEN *sp) { - int i; - T((T_CALLED("delscreen(%p)"), sp)); + T((T_CALLED("delscreen(%p)"), (void *) sp)); _nc_lock_global(curses); if (delink_screen(sp)) { + WINDOWLIST *wl; + bool is_current = (sp == CURRENT_SCREEN); + +#ifdef USE_SP_RIPOFF + if (safe_ripoff_sp && safe_ripoff_sp != safe_ripoff_stack) { + ripoff_t *rop; + for (rop = safe_ripoff_stack; + rop != safe_ripoff_sp && (rop - safe_ripoff_stack) < N_RIPS; + rop++) { + if (rop->win) { + (void) delwin(rop->win); + rop->win = 0; + } + } + } +#endif - (void) _nc_freewin(sp->_curscr); - (void) _nc_freewin(sp->_newscr); - (void) _nc_freewin(sp->_stdscr); + /* delete all of the windows in this screen */ + rescan: + for (each_window(sp, wl)) { + if (_nc_freewin(&(wl->win)) == OK) { + goto rescan; + } + } if (sp->_slk != 0) { + if (sp->_slk->ent != 0) { + int i; + for (i = 0; i < sp->_slk->labcnt; ++i) { FreeIfNeeded(sp->_slk->ent[i].ent_text); FreeIfNeeded(sp->_slk->ent[i].form_text); @@ -156,9 +199,11 @@ delscreen(SCREEN *sp) FreeIfNeeded(sp->_current_attr); + _nc_free_ordered_pairs(sp); FreeIfNeeded(sp->_color_table); FreeIfNeeded(sp->_color_pairs); + FreeIfNeeded(sp->_oldnum_list); FreeIfNeeded(sp->oldhash); FreeIfNeeded(sp->newhash); FreeIfNeeded(sp->hashtab); @@ -166,19 +211,20 @@ delscreen(SCREEN *sp) FreeIfNeeded(sp->_acs_map); FreeIfNeeded(sp->_screen_acs_map); - /* - * If the associated output stream has been closed, we can discard the - * set-buffer. Limit the error check to EBADF, since fflush may fail - * for other reasons than trying to operate upon a closed stream. - */ - if (sp->_ofp != 0 - && sp->_setbuf != 0 - && fflush(sp->_ofp) != 0 - && errno == EBADF) { - free(sp->_setbuf); + NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG); + NCURSES_SP_NAME(del_curterm) (NCURSES_SP_ARGx sp->_term); + FreeIfNeeded(sp->out_buffer); + if (_nc_find_prescr() == sp) { + _nc_forget_prescr(); } - - del_curterm(sp->_term); +#if USE_GPM_SUPPORT +#ifdef HAVE_LIBDL + if (sp->_dlopen_gpm != 0) { + dlclose(sp->_dlopen_gpm); + sp->_dlopen_gpm = 0; + } +#endif +#endif /* USE_GPM_SUPPORT */ free(sp); /* @@ -186,7 +232,7 @@ delscreen(SCREEN *sp) * application might try to use (except cur_term, which may have * multiple references in different screens). */ - if (sp == SP) { + if (is_current) { #if !USE_REENTRANT curscr = 0; newscr = 0; @@ -195,6 +241,14 @@ delscreen(SCREEN *sp) COLOR_PAIRS = 0; #endif _nc_set_screen(0); +#if USE_WIDEC_SUPPORT + if (SP == 0) { + FreeIfNeeded(_nc_wacs); + _nc_wacs = 0; + } +#endif + } else { + set_term(CURRENT_SCREEN); } } _nc_unlock_global(curses); @@ -231,16 +285,17 @@ no_mouse_wrap(SCREEN *sp GCC_UNUSED) } #if NCURSES_EXT_FUNCS && USE_COLORFGBG -static char * -extract_fgbg(char *src, int *result) +static const char * +extract_fgbg(const char *src, int *result) { - char *dst = 0; - long value = strtol(src, &dst, 0); + const char *dst = 0; + char *tmp = 0; + long value = strtol(src, &tmp, 0); - if (dst == 0) { + if ((dst = tmp) == 0) { dst = src; } else if (value >= 0) { - *result = value; + *result = (int) value; } while (*dst != 0 && *dst != ';') dst++; @@ -250,85 +305,155 @@ extract_fgbg(char *src, int *result) } #endif +#define ReturnScreenError() do { _nc_set_screen(0); \ + returnCode(ERR); } while (0) + /* OS-independent screen initializations */ NCURSES_EXPORT(int) -_nc_setupscreen(int slines GCC_UNUSED, - int scolumns GCC_UNUSED, - FILE *output, - bool filtered, - int slk_format) +NCURSES_SP_NAME(_nc_setupscreen) ( +#if NCURSES_SP_FUNCS + SCREEN **spp, +#endif + int slines, + int scolumns, + FILE *output, + int filtered, + int slk_format) { +#ifndef USE_TERM_DRIVER + static const TTY null_TTY; /* all zeros iff uninitialized */ +#endif char *env; int bottom_stolen = 0; + SCREEN *sp; +#ifndef USE_TERM_DRIVER bool support_cookies = USE_XMC_SUPPORT; - ripoff_t *rop; +#endif T((T_CALLED("_nc_setupscreen(%d, %d, %p, %d, %d)"), - slines, scolumns, output, filtered, slk_format)); + slines, scolumns, (void *) output, filtered, slk_format)); + + assert(CURRENT_SCREEN == 0); /* has been reset in newterm() ! */ + +#if NCURSES_SP_FUNCS + assert(spp != 0); + sp = *spp; + + if (!sp) { + sp = _nc_alloc_screen_sp(); + T(("_nc_alloc_screen_sp %p", (void *) sp)); + *spp = sp; + } + if (sp == NULL) { + ReturnScreenError(); + } + if ((sp->_acs_map = typeCalloc(chtype, ACS_LEN)) == NULL) { + ReturnScreenError(); + } + if ((sp->_screen_acs_map = typeCalloc(bool, ACS_LEN)) == NULL) { + free(sp->_acs_map); + ReturnScreenError(); + } - assert(SP == 0); /* has been reset in newterm() ! */ + T(("created SP %p", (void *) sp)); + sp->_next_screen = _nc_screen_chain; + _nc_screen_chain = sp; + + if ((sp->_current_attr = typeCalloc(NCURSES_CH_T, 1)) == 0) { + ReturnScreenError(); + } +#else if (!_nc_alloc_screen() || ((SP->_acs_map = typeCalloc(chtype, ACS_LEN)) == 0) || ((SP->_screen_acs_map = typeCalloc(bool, ACS_LEN)) == 0)) { returnCode(ERR); } - T(("created SP %p", SP)); - SP->_next_screen = _nc_screen_chain; - _nc_screen_chain = SP; + T(("created SP %p", (void *) SP)); + + sp = SP; /* fixup so SET_LINES and SET_COLS works */ + sp->_next_screen = _nc_screen_chain; + _nc_screen_chain = sp; - if ((SP->_current_attr = typeCalloc(NCURSES_CH_T, 1)) == 0) + if ((sp->_current_attr = typeCalloc(NCURSES_CH_T, 1)) == 0) { returnCode(ERR); + } +#endif /* * We should always check the screensize, just in case. */ - _nc_get_screensize(SP, &slines, &scolumns); + _nc_set_screen(sp); + sp->_term = cur_term; +#ifdef USE_TERM_DRIVER + TCBOf(sp)->csp = sp; + _nc_get_screensize(sp, sp->_term, &slines, &scolumns); +#else + _nc_get_screensize(sp, &slines, &scolumns); +#endif SET_LINES(slines); SET_COLS(scolumns); - T((T_CREATE("screen %s %dx%d"), termname(), LINES, COLS)); - SP->_filtered = filtered; + T((T_CREATE("screen %s %dx%d"), + NCURSES_SP_NAME(termname) (NCURSES_SP_ARG), slines, scolumns)); + + sp->_filtered = filtered; /* implement filter mode */ if (filtered) { slines = 1; SET_LINES(slines); - clear_screen = 0; - cursor_down = parm_down_cursor = 0; - cursor_address = 0; - cursor_up = parm_up_cursor = 0; - row_address = 0; - - cursor_home = carriage_return; - T(("filter screensize %dx%d", LINES, COLS)); +#ifdef USE_TERM_DRIVER + CallDriver(sp, td_setfilter); +#else + /* *INDENT-EQLS* */ + clear_screen = ABSENT_STRING; + cursor_address = ABSENT_STRING; + cursor_down = ABSENT_STRING; + cursor_up = ABSENT_STRING; + parm_down_cursor = ABSENT_STRING; + parm_up_cursor = ABSENT_STRING; + row_address = ABSENT_STRING; + cursor_home = carriage_return; + + if (back_color_erase) + clr_eos = ABSENT_STRING; + +#endif + T(("filter screensize %dx%d", slines, scolumns)); } #ifdef __DJGPP__ T(("setting output mode to binary")); fflush(output); setmode(output, O_BINARY); #endif - _nc_set_buffer(output, TRUE); - SP->_term = cur_term; - SP->_lines = slines; - SP->_lines_avail = slines; - SP->_columns = scolumns; - SP->_cursrow = -1; - SP->_curscol = -1; - SP->_nl = TRUE; - SP->_raw = FALSE; - SP->_cbreak = 0; - SP->_echo = TRUE; - SP->_fifohead = -1; - SP->_endwin = TRUE; - SP->_ofp = output; - SP->_cursor = -1; /* cannot know real cursor shape */ - - SetNoPadding(SP); +#if defined(EXP_WIN32_DRIVER) + T(("setting output mode to binary")); + fflush(output); + _setmode(fileno(output), _O_BINARY); +#endif + sp->_lines = (NCURSES_SIZE_T) slines; + sp->_lines_avail = (NCURSES_SIZE_T) slines; + sp->_columns = (NCURSES_SIZE_T) scolumns; + + fflush(output); + sp->_ofd = output ? fileno(output) : -1; + sp->_ofp = output; +#if defined(EXP_WIN32_DRIVER) + if (output) + _setmode(fileno(output), _O_BINARY); +#endif + sp->out_limit = (size_t) ((2 + slines) * (6 + scolumns)); + if ((sp->out_buffer = malloc(sp->out_limit)) == 0) + sp->out_limit = 0; + sp->out_inuse = 0; + + SP_PRE_INIT(sp); + SetNoPadding(sp); #if NCURSES_EXT_FUNCS - SP->_default_color = FALSE; - SP->_has_sgr_39_49 = FALSE; + sp->_default_color = FALSE; + sp->_has_sgr_39_49 = FALSE; /* * Set our assumption of the terminal's default foreground and background @@ -350,11 +475,11 @@ _nc_setupscreen(int slines GCC_UNUSED, * or black-on-white display under control of the application than not). */ #ifdef USE_ASSUMED_COLOR - SP->_default_fg = COLOR_WHITE; - SP->_default_bg = COLOR_BLACK; + sp->_default_fg = COLOR_WHITE; + sp->_default_bg = COLOR_BLACK; #else - SP->_default_fg = C_MASK; - SP->_default_bg = C_MASK; + sp->_default_fg = COLOR_DEFAULT; + sp->_default_bg = COLOR_DEFAULT; #endif /* @@ -366,14 +491,14 @@ _nc_setupscreen(int slines GCC_UNUSED, char sep1, sep2; int count = sscanf(env, "%d%c%d%c", &fg, &sep1, &bg, &sep2); if (count >= 1) { - SP->_default_fg = (fg >= 0 && fg < max_colors) ? fg : C_MASK; + sp->_default_fg = ((fg >= 0 && fg < MaxColors) ? fg : COLOR_DEFAULT); if (count >= 3) { - SP->_default_bg = (bg >= 0 && bg < max_colors) ? bg : C_MASK; + sp->_default_bg = ((bg >= 0 && bg < MaxColors) ? bg : COLOR_DEFAULT); } TR(TRACE_CHARPUT | TRACE_MOVE, ("from environment assumed fg=%d, bg=%d", - SP->_default_fg, - SP->_default_bg)); + sp->_default_fg, + sp->_default_bg)); } } #if USE_COLORFGBG @@ -384,50 +509,53 @@ _nc_setupscreen(int slines GCC_UNUSED, * decide later if it is worth having default attributes as well. */ if (getenv("COLORFGBG") != 0) { - char *p = getenv("COLORFGBG"); + const char *p = getenv("COLORFGBG"); TR(TRACE_CHARPUT | TRACE_MOVE, ("decoding COLORFGBG %s", p)); - p = extract_fgbg(p, &(SP->_default_fg)); - p = extract_fgbg(p, &(SP->_default_bg)); + p = extract_fgbg(p, &(sp->_default_fg)); + p = extract_fgbg(p, &(sp->_default_bg)); if (*p) /* assume rxvt was compiled with xpm support */ - p = extract_fgbg(p, &(SP->_default_bg)); + extract_fgbg(p, &(sp->_default_bg)); TR(TRACE_CHARPUT | TRACE_MOVE, ("decoded fg=%d, bg=%d", - SP->_default_fg, SP->_default_bg)); - if (SP->_default_fg >= max_colors) { + sp->_default_fg, sp->_default_bg)); + if (sp->_default_fg >= MaxColors) { if (set_a_foreground != ABSENT_STRING && !strcmp(set_a_foreground, "\033[3%p1%dm")) { - set_a_foreground = "\033[3%?%p1%{8}%>%t9%e%p1%d%;m"; + set_a_foreground = strdup("\033[3%?%p1%{8}%>%t9%e%p1%d%;m"); } else { - SP->_default_fg %= max_colors; + sp->_default_fg %= MaxColors; } } - if (SP->_default_bg >= max_colors) { + if (sp->_default_bg >= MaxColors) { if (set_a_background != ABSENT_STRING && !strcmp(set_a_background, "\033[4%p1%dm")) { - set_a_background = "\033[4%?%p1%{8}%>%t9%e%p1%d%;m"; + set_a_background = strdup("\033[4%?%p1%{8}%>%t9%e%p1%d%;m"); } else { - SP->_default_bg %= max_colors; + sp->_default_bg %= MaxColors; } } } #endif #endif /* NCURSES_EXT_FUNCS */ - SP->_maxclick = DEFAULT_MAXCLICK; - SP->_mouse_event = no_mouse_event; - SP->_mouse_inline = no_mouse_inline; - SP->_mouse_parse = no_mouse_parse; - SP->_mouse_resume = no_mouse_resume; - SP->_mouse_wrap = no_mouse_wrap; - SP->_mouse_fd = -1; + sp->_maxclick = DEFAULT_MAXCLICK; + sp->_mouse_event = no_mouse_event; + sp->_mouse_inline = no_mouse_inline; + sp->_mouse_parse = no_mouse_parse; + sp->_mouse_resume = no_mouse_resume; + sp->_mouse_wrap = no_mouse_wrap; + sp->_mouse_fd = -1; /* * If we've no magic cookie support, we suppress attributes that xmc would * affect, i.e., the attributes that affect the rendition of a space. */ - SP->_ok_attributes = termattrs(); - if (has_colors()) { - SP->_ok_attributes |= A_COLOR; + sp->_ok_attributes = NCURSES_SP_NAME(termattrs) (NCURSES_SP_ARG); + if (NCURSES_SP_NAME(has_colors) (NCURSES_SP_ARG)) { + sp->_ok_attributes |= A_COLOR; } +#ifdef USE_TERM_DRIVER + _nc_cookie_init(sp); +#else #if USE_XMC_SUPPORT /* * If we have no magic-cookie support compiled-in, or if it is suppressed @@ -446,16 +574,7 @@ _nc_setupscreen(int slines GCC_UNUSED, if (magic_cookie_glitch > 0) { /* tvi, wyse */ - SP->_xmc_triggers = SP->_ok_attributes & ( - A_STANDOUT | - A_UNDERLINE | - A_REVERSE | - A_BLINK | - A_DIM | - A_BOLD | - A_INVIS | - A_PROTECT - ); + sp->_xmc_triggers = sp->_ok_attributes & XMC_CONFLICT; #if 0 /* * We "should" treat colors as an attribute. The wyse350 (and its @@ -463,12 +582,12 @@ _nc_setupscreen(int slines GCC_UNUSED, * cookies. */ if (has_colors()) { - SP->_xmc_triggers |= A_COLOR; + sp->_xmc_triggers |= A_COLOR; } #endif - SP->_xmc_suppress = SP->_xmc_triggers & (chtype) ~(A_BOLD); + sp->_xmc_suppress = sp->_xmc_triggers & (chtype) ~(A_BOLD); - T(("magic cookie attributes %s", _traceattr(SP->_xmc_suppress))); + T(("magic cookie attributes %s", _traceattr(sp->_xmc_suppress))); /* * Supporting line-drawing may be possible. But make the regular * video attributes work first. @@ -508,7 +627,7 @@ _nc_setupscreen(int slines GCC_UNUSED, /* initialize normal acs before wide, since we use mapping in the latter */ #if !USE_WIDEC_SUPPORT - if (_nc_unicode_locale() && _nc_locale_breaks_acs(cur_term)) { + if (_nc_unicode_locale() && _nc_locale_breaks_acs(sp->_term)) { acs_chars = NULL; ena_acs = NULL; enter_alt_charset_mode = NULL; @@ -516,135 +635,240 @@ _nc_setupscreen(int slines GCC_UNUSED, set_attributes = NULL; } #endif - _nc_init_acs(); +#endif + + NCURSES_SP_NAME(_nc_init_acs) (NCURSES_SP_ARG); #if USE_WIDEC_SUPPORT - _nc_init_wacs(); + sp->_screen_unicode = _nc_unicode_locale(); + if (_nc_wacs == 0) { + _nc_init_wacs(); + } + if (_nc_wacs == 0) { + ReturnScreenError(); + } - SP->_screen_acs_fix = (_nc_unicode_locale() - && _nc_locale_breaks_acs(cur_term)); + sp->_screen_acs_fix = (sp->_screen_unicode + && _nc_locale_breaks_acs(sp->_term)); #endif env = _nc_get_locale(); - SP->_legacy_coding = ((env == 0) + sp->_legacy_coding = ((env == 0) || !strcmp(env, "C") || !strcmp(env, "POSIX")); - T(("legacy-coding %d", SP->_legacy_coding)); + T(("legacy-coding %d", sp->_legacy_coding)); - _nc_idcok = TRUE; - _nc_idlok = FALSE; + sp->_nc_sp_idcok = TRUE; + sp->_nc_sp_idlok = FALSE; - SP->oldhash = 0; - SP->newhash = 0; + sp->oldhash = 0; + sp->newhash = 0; T(("creating newscr")); - if ((SP->_newscr = newwin(slines, scolumns, 0, 0)) == 0) - returnCode(ERR); - + NewScreen(sp) = NCURSES_SP_NAME(newwin) (NCURSES_SP_ARGx slines, scolumns, + 0, 0); + if (NewScreen(sp) == 0) { + ReturnScreenError(); + } T(("creating curscr")); - if ((SP->_curscr = newwin(slines, scolumns, 0, 0)) == 0) - returnCode(ERR); - + CurScreen(sp) = NCURSES_SP_NAME(newwin) (NCURSES_SP_ARGx slines, scolumns, + 0, 0); + if (CurScreen(sp) == 0) { + ReturnScreenError(); + } #if !USE_REENTRANT - newscr = SP->_newscr; - curscr = SP->_curscr; + newscr = NewScreen(sp); + curscr = CurScreen(sp); #endif #if USE_SIZECHANGE - SP->_resize = resizeterm; - SP->_ungetch = _nc_ungetch; -#endif - - newscr->_clear = TRUE; - curscr->_clear = FALSE; - - def_shell_mode(); - def_prog_mode(); - - for (rop = ripoff_stack; - rop != ripoff_sp && (rop - ripoff_stack) < N_RIPS; - rop++) { - - /* If we must simulate soft labels, grab off the line to be used. - We assume that we must simulate, if it is none of the standard - formats (4-4 or 3-2-3) for which there may be some hardware - support. */ - if (rop->hook == _nc_slk_initialize) - if (!(num_labels <= 0 || !SLK_STDFMT(slk_format))) - continue; - if (rop->hook) { - int count; - WINDOW *w; - - count = (rop->line < 0) ? -rop->line : rop->line; - T(("ripping off %i lines at %s", count, - ((rop->line < 0) - ? "bottom" - : "top"))); - - w = newwin(count, scolumns, - ((rop->line < 0) - ? SP->_lines_avail - count - : 0), - 0); - if (w) { - rop->win = w; - rop->hook(w, scolumns); - } else { - returnCode(ERR); + sp->_resize = NCURSES_SP_NAME(resizeterm); + sp->_ungetch = safe_ungetch; +#endif + + NewScreen(sp)->_clear = TRUE; + CurScreen(sp)->_clear = FALSE; + + /* + * Get the current tty-modes. setupterm() may already have done this, + * unless we use the term-driver. + */ +#ifndef USE_TERM_DRIVER + if (cur_term != 0 && + !memcmp(&cur_term->Ottyb, &null_TTY, sizeof(TTY))) +#endif + { + NCURSES_SP_NAME(def_shell_mode) (NCURSES_SP_ARG); + NCURSES_SP_NAME(def_prog_mode) (NCURSES_SP_ARG); + } + + if (safe_ripoff_sp && safe_ripoff_sp != safe_ripoff_stack) { + ripoff_t *rop; + + for (rop = safe_ripoff_stack; + rop != safe_ripoff_sp && (rop - safe_ripoff_stack) < N_RIPS; + rop++) { + + /* If we must simulate soft labels, grab off the line to be used. + We assume that we must simulate, if it is none of the standard + formats (4-4 or 3-2-3) for which there may be some hardware + support. */ + if (rop->hook == _nc_slk_initialize) { + if (!TerminalOf(sp)) { + continue; + } + if (!(NumLabels <= 0 || !SLK_STDFMT(slk_format))) { + continue; + } + } + if (rop->hook) { + int count; + WINDOW *w; + + count = (rop->line < 0) ? -rop->line : rop->line; + T(("ripping off %i lines at %s", count, + ((rop->line < 0) + ? "bottom" + : "top"))); + + w = NCURSES_SP_NAME(newwin) (NCURSES_SP_ARGx + count, scolumns, + ((rop->line < 0) + ? sp->_lines_avail - count + : 0), + 0); + if (w) { + rop->win = w; + rop->hook(w, scolumns); + } else { + ReturnScreenError(); + } + if (rop->line < 0) { + bottom_stolen += count; + } else { + sp->_topstolen = (NCURSES_SIZE_T) (sp->_topstolen + count); + } + sp->_lines_avail = (NCURSES_SIZE_T) (sp->_lines_avail - count); } - if (rop->line < 0) - bottom_stolen += count; - else - SP->_topstolen += count; - SP->_lines_avail -= count; } + /* reset the stack */ + safe_ripoff_sp = safe_ripoff_stack; } - /* reset the stack */ - ripoff_sp = ripoff_stack; T(("creating stdscr")); - assert((SP->_lines_avail + SP->_topstolen + bottom_stolen) == slines); - if ((SP->_stdscr = newwin(SP->_lines_avail, scolumns, 0, 0)) == 0) - returnCode(ERR); - - SET_LINES(SP->_lines_avail); + (void) bottom_stolen; + assert((sp->_lines_avail + sp->_topstolen + bottom_stolen) == slines); + if ((StdScreen(sp) = NCURSES_SP_NAME(newwin) (NCURSES_SP_ARGx + sp->_lines_avail, + scolumns, 0, 0)) == 0) { + ReturnScreenError(); + } + SET_LINES(sp->_lines_avail); #if !USE_REENTRANT - stdscr = SP->_stdscr; + stdscr = StdScreen(sp); #endif - + sp->_prescreen = FALSE; returnCode(OK); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +_nc_setupscreen(int slines GCC_UNUSED, + int scolumns GCC_UNUSED, + FILE *output, + int filtered, + int slk_format) +{ + SCREEN *sp = 0; + int rc = NCURSES_SP_NAME(_nc_setupscreen) (&sp, + slines, + scolumns, + output, + filtered, + slk_format); + if (rc != OK) + _nc_set_screen(0); + return rc; +} +#endif + /* * The internal implementation interprets line as the number of lines to rip * off from the top or bottom. */ NCURSES_EXPORT(int) -_nc_ripoffline(int line, int (*init) (WINDOW *, int)) +NCURSES_SP_NAME(_nc_ripoffline) (NCURSES_SP_DCLx + int line, + int (*init) (WINDOW *, int)) { - T((T_CALLED("_nc_ripoffline(%d, %p)"), line, init)); - - if (line != 0) { + int code = ERR; + TR_FUNC_BFR(1); - if (ripoff_sp == 0) - ripoff_sp = ripoff_stack; - if (ripoff_sp >= ripoff_stack + N_RIPS) - returnCode(ERR); + START_TRACE(); + T((T_CALLED("ripoffline(%p,%d,%s)"), + (void *) SP_PARM, line, + TR_FUNC_ARG(0, init))); - ripoff_sp->line = line; - ripoff_sp->hook = init; - ripoff_sp++; +#if NCURSES_SP_FUNCS + if (SP_PARM != 0 && SP_PARM->_prescreen) +#endif + { + if (line == 0) { + code = OK; + } else { + if (safe_ripoff_sp == 0) { + safe_ripoff_sp = safe_ripoff_stack; + } + if (safe_ripoff_sp < safe_ripoff_stack + N_RIPS) { + safe_ripoff_sp->line = line; + safe_ripoff_sp->hook = init; + (safe_ripoff_sp)++; + T(("ripped-off %d:%d chunks", + (int) (safe_ripoff_sp - safe_ripoff_stack), N_RIPS)); + code = OK; + } + } } - returnCode(OK); + returnCode(code); } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) -ripoffline(int line, int (*init) (WINDOW *, int)) +_nc_ripoffline(int line, int (*init) (WINDOW *, int)) { + int rc; + + _nc_init_pthreads(); + _nc_lock_global(prescreen); START_TRACE(); - T((T_CALLED("ripoffline(%d,%p)"), line, init)); + rc = NCURSES_SP_NAME(_nc_ripoffline) (CURRENT_SCREEN_PRE, line, init); + _nc_unlock_global(prescreen); - if (line == 0) - returnCode(OK); + return rc; +} +#endif - returnCode(_nc_ripoffline((line < 0) ? -1 : 1, init)); +NCURSES_EXPORT(int) +NCURSES_SP_NAME(ripoffline) (NCURSES_SP_DCLx + int line, + int (*init) (WINDOW *, int)) +{ + START_TRACE(); + return NCURSES_SP_NAME(_nc_ripoffline) (NCURSES_SP_ARGx + (line < 0) ? -1 : 1, + init); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +ripoffline(int line, int (*init) (WINDOW *, int)) +{ + int rc; + + _nc_init_pthreads(); + _nc_lock_global(prescreen); + START_TRACE(); + rc = NCURSES_SP_NAME(ripoffline) (CURRENT_SCREEN_PRE, line, init); + _nc_unlock_global(prescreen); + + return rc; +} +#endif diff --git a/lib/libcurses/base/lib_slk.c b/lib/libcurses/base/lib_slk.c index c9abb8038f0..a615c06b775 100644 --- a/lib/libcurses/base/lib_slk.c +++ b/lib/libcurses/base/lib_slk.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_slk.c,v 1.5 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_slk.c,v 1.6 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2008 Free Software Foundation, Inc. * + * Copyright 2020,2022 Thomas E. Dickey * + * Copyright 1998-2010,2011 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -43,26 +44,94 @@ */ #include - #include -#include /* num_labels, label_*, plab_norm */ -MODULE_ID("$Id: lib_slk.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") +#ifndef CUR +#define CUR SP_TERMTYPE +#endif + +MODULE_ID("$Id: lib_slk.c,v 1.6 2023/10/17 09:52:09 nicm Exp $") + +#ifdef USE_TERM_DRIVER +#define NumLabels InfoOf(SP_PARM).numlabels +#define NoColorVideo InfoOf(SP_PARM).nocolorvideo +#define LabelWidth InfoOf(SP_PARM).labelwidth +#define LabelHeight InfoOf(SP_PARM).labelheight +#else +#define NumLabels num_labels +#define NoColorVideo no_color_video +#define LabelWidth label_width +#define LabelHeight label_height +#endif /* * Free any memory related to soft labels, return an error. */ static int -slk_failed(void) +slk_failed(NCURSES_SP_DCL0) { - if (SP->_slk) { - FreeIfNeeded(SP->_slk->ent); - free(SP->_slk); - SP->_slk = (SLK *) 0; + if ((0 != SP_PARM) && SP_PARM->_slk) { + FreeIfNeeded(SP_PARM->_slk->ent); + free(SP_PARM->_slk); + SP_PARM->_slk = (SLK *) 0; } return ERR; } +NCURSES_EXPORT(int) +_nc_format_slks(NCURSES_SP_DCLx int cols) +{ + int gap, i, x; + int max_length; + + if (!SP_PARM || !SP_PARM->_slk) + return ERR; + + max_length = SP_PARM->_slk->maxlen; + if (SP_PARM->slk_format >= 3) { /* PC style */ + gap = (cols - 3 * (3 + 4 * max_length)) / 2; + + if (gap < 1) + gap = 1; + + for (i = x = 0; i < SP_PARM->_slk->maxlab; i++) { + SP_PARM->_slk->ent[i].ent_x = x; + x += max_length; + x += (i == 3 || i == 7) ? gap : 1; + } + } else { + if (SP_PARM->slk_format == 2) { /* 4-4 */ + gap = cols - (int) (SP_PARM->_slk->maxlab * max_length) - 6; + + if (gap < 1) + gap = 1; + for (i = x = 0; i < SP_PARM->_slk->maxlab; i++) { + SP_PARM->_slk->ent[i].ent_x = x; + x += max_length; + x += (i == 3) ? gap : 1; + } + } else { + if (SP_PARM->slk_format == 1) { /* 1 -> 3-2-3 */ + gap = (cols - (SP_PARM->_slk->maxlab * max_length) - 5) + / 2; + + if (gap < 1) + gap = 1; + for (i = x = 0; i < SP_PARM->_slk->maxlab; i++) { + SP_PARM->_slk->ent[i].ent_x = x; + x += max_length; + x += (i == 2 || i == 4) ? gap : 1; + } + } else { + return slk_failed(NCURSES_SP_ARG); + } + } + } + SP_PARM->_slk->dirty = TRUE; + + return OK; +} + /* * Initialize soft labels. * Called from newterm() @@ -70,108 +139,92 @@ slk_failed(void) NCURSES_EXPORT(int) _nc_slk_initialize(WINDOW *stwin, int cols) { - int i, x; + int i; int res = OK; - unsigned max_length; + size_t max_length; + SCREEN *sp; + int numlab; T((T_CALLED("_nc_slk_initialize()"))); - if (SP->_slk) { /* we did this already, so simply return */ + assert(stwin); + + sp = _nc_screen_of(stwin); + if (0 == sp) + returnCode(ERR); + + assert(TerminalOf(SP_PARM)); + + numlab = NumLabels; + + if (SP_PARM->_slk) { /* we did this already, so simply return */ returnCode(OK); - } else if ((SP->_slk = typeCalloc(SLK, 1)) == 0) + } else if ((SP_PARM->_slk = typeCalloc(SLK, 1)) == 0) returnCode(ERR); - SP->_slk->ent = NULL; + if (!SP_PARM->slk_format) + SP_PARM->slk_format = _nc_globals.slk_format; /* * If we use colors, vidputs() will suppress video attributes that conflict * with colors. In that case, we're still guaranteed that "reverse" would * work. */ - if ((no_color_video & 1) == 0) - SetAttr(SP->_slk->attr, A_STANDOUT); + if ((NoColorVideo & 1) == 0) + SetAttr(SP_PARM->_slk->attr, A_STANDOUT); else - SetAttr(SP->_slk->attr, A_REVERSE); - - SP->_slk->maxlab = ((num_labels > 0) - ? num_labels - : MAX_SKEY(_nc_globals.slk_format)); - SP->_slk->maxlen = ((num_labels > 0) - ? label_width * label_height - : MAX_SKEY_LEN(_nc_globals.slk_format)); - SP->_slk->labcnt = ((SP->_slk->maxlab < MAX_SKEY(_nc_globals.slk_format)) - ? MAX_SKEY(_nc_globals.slk_format) - : SP->_slk->maxlab); - - if (SP->_slk->maxlen <= 0 - || SP->_slk->labcnt <= 0 - || (SP->_slk->ent = typeCalloc(slk_ent, - (unsigned) SP->_slk->labcnt)) == NULL) - returnCode(slk_failed()); - - max_length = SP->_slk->maxlen; - for (i = 0; i < SP->_slk->labcnt; i++) { - size_t used = max_length + 1; + SetAttr(SP_PARM->_slk->attr, A_REVERSE); - if ((SP->_slk->ent[i].ent_text = (char *) _nc_doalloc(0, used)) == 0) - returnCode(slk_failed()); - memset(SP->_slk->ent[i].ent_text, 0, used); + SP_PARM->_slk->maxlab = (short) ((numlab > 0) + ? numlab + : MAX_SKEY(SP_PARM->slk_format)); + SP_PARM->_slk->maxlen = (short) ((numlab > 0) + ? LabelWidth * LabelHeight + : MAX_SKEY_LEN(SP_PARM->slk_format)); + SP_PARM->_slk->labcnt = (short) ((SP_PARM->_slk->maxlab < MAX_SKEY(SP_PARM->slk_format)) + ? MAX_SKEY(SP_PARM->slk_format) + : SP_PARM->_slk->maxlab); - if ((SP->_slk->ent[i].form_text = (char *) _nc_doalloc(0, used)) == 0) - returnCode(slk_failed()); - memset(SP->_slk->ent[i].form_text, 0, used); - - memset(SP->_slk->ent[i].form_text, ' ', max_length); - SP->_slk->ent[i].visible = (char) (i < SP->_slk->maxlab); + if (SP_PARM->_slk->maxlen <= 0 + || SP_PARM->_slk->labcnt <= 0 + || (SP_PARM->_slk->ent = typeCalloc(slk_ent, + (size_t) SP_PARM->_slk->labcnt)) + == NULL) { + free(SP_PARM->_slk->ent); + returnCode(slk_failed(NCURSES_SP_ARG)); } - if (_nc_globals.slk_format >= 3) { /* PC style */ - int gap = (cols - 3 * (3 + 4 * max_length)) / 2; - if (gap < 1) - gap = 1; + max_length = (size_t) SP_PARM->_slk->maxlen; + for (i = 0; i < SP_PARM->_slk->labcnt; i++) { + size_t used = max_length + 1; - for (i = x = 0; i < SP->_slk->maxlab; i++) { - SP->_slk->ent[i].ent_x = x; - x += max_length; - x += (i == 3 || i == 7) ? gap : 1; - } - } else { - if (_nc_globals.slk_format == 2) { /* 4-4 */ - int gap = cols - (SP->_slk->maxlab * max_length) - 6; + SP_PARM->_slk->ent[i].ent_text = (char *) _nc_doalloc(0, used); + if (SP_PARM->_slk->ent[i].ent_text == 0) + returnCode(slk_failed(NCURSES_SP_ARG)); + memset(SP_PARM->_slk->ent[i].ent_text, 0, used); - if (gap < 1) - gap = 1; - for (i = x = 0; i < SP->_slk->maxlab; i++) { - SP->_slk->ent[i].ent_x = x; - x += max_length; - x += (i == 3) ? gap : 1; - } - } else { - if (_nc_globals.slk_format == 1) { /* 1 -> 3-2-3 */ - int gap = (cols - (SP->_slk->maxlab * max_length) - 5) - / 2; + SP_PARM->_slk->ent[i].form_text = (char *) _nc_doalloc(0, used); + if (SP_PARM->_slk->ent[i].form_text == 0) + returnCode(slk_failed(NCURSES_SP_ARG)); - if (gap < 1) - gap = 1; - for (i = x = 0; i < SP->_slk->maxlab; i++) { - SP->_slk->ent[i].ent_x = x; - x += max_length; - x += (i == 2 || i == 4) ? gap : 1; - } - } else - returnCode(slk_failed()); + if (used > 1) { + memset(SP_PARM->_slk->ent[i].form_text, ' ', used - 1); } + SP_PARM->_slk->ent[i].form_text[used - 1] = '\0'; + + SP_PARM->_slk->ent[i].visible = (char) (i < SP_PARM->_slk->maxlab); } - SP->_slk->dirty = TRUE; - if ((SP->_slk->win = stwin) == NULL) { - returnCode(slk_failed()); + + res = _nc_format_slks(NCURSES_SP_ARGx cols); + + if ((SP_PARM->_slk->win = stwin) == NULL) { + returnCode(slk_failed(NCURSES_SP_ARG)); } /* We now reset the format so that the next newterm has again * per default no SLK keys and may call slk_init again to * define a new layout. (juergen 03-Mar-1999) */ - SP->slk_format = _nc_globals.slk_format; _nc_globals.slk_format = 0; returnCode(res); } @@ -180,14 +233,24 @@ _nc_slk_initialize(WINDOW *stwin, int cols) * Restore the soft labels on the screen. */ NCURSES_EXPORT(int) -slk_restore(void) +NCURSES_SP_NAME(slk_restore) (NCURSES_SP_DCL0) { - T((T_CALLED("slk_restore()"))); + T((T_CALLED("slk_restore(%p)"), (void *) SP_PARM)); + + if (0 == SP_PARM) + returnCode(ERR); + if (SP_PARM->_slk == NULL) + returnCode(ERR); + SP_PARM->_slk->hidden = FALSE; + SP_PARM->_slk->dirty = TRUE; - if (SP->_slk == NULL) - return (ERR); - SP->_slk->hidden = FALSE; - SP->_slk->dirty = TRUE; + returnCode(NCURSES_SP_NAME(slk_refresh) (NCURSES_SP_ARG)); +} - returnCode(slk_refresh()); +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +slk_restore(void) +{ + return NCURSES_SP_NAME(slk_restore) (CURRENT_SCREEN); } +#endif diff --git a/lib/libcurses/base/lib_slkatr_set.c b/lib/libcurses/base/lib_slkatr_set.c index 523eadfdf3e..a9ba3fbd5bf 100644 --- a/lib/libcurses/base/lib_slkatr_set.c +++ b/lib/libcurses/base/lib_slkatr_set.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_slkatr_set.c,v 1.4 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_slkatr_set.c,v 1.5 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2014,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -30,7 +31,7 @@ /**************************************************************************** * Author: Juergen Pfeifer, 1998 * - * and: Thomas E. Dickey 2005 * + * and: Thomas E. Dickey 2005-on * ****************************************************************************/ /* @@ -40,22 +41,43 @@ */ #include -MODULE_ID("$Id: lib_slkatr_set.c,v 1.4 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_slkatr_set.c,v 1.5 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) -slk_attr_set(const attr_t attr, short color_pair_number, void *opts) +NCURSES_SP_NAME(slk_attr_set) (NCURSES_SP_DCLx + const attr_t attr, + NCURSES_PAIRS_T pair_arg, + void *opts) { - T((T_CALLED("slk_attr_set(%s,%d)"), _traceattr(attr), color_pair_number)); - - if (SP != 0 && SP->_slk != 0 && !opts && - color_pair_number >= 0 && color_pair_number < COLOR_PAIRS) { - TR(TRACE_ATTRS, ("... current %s", _tracech_t(CHREF(SP->_slk->attr)))); - SetAttr(SP->_slk->attr, attr); - if (color_pair_number > 0) { - SetPair(SP->_slk->attr, color_pair_number); + int code = ERR; + int color_pair = pair_arg; + + T((T_CALLED("slk_attr_set(%p,%s,%d)"), + (void *) SP_PARM, + _traceattr(attr), + color_pair)); + + set_extended_pair(opts, color_pair); + if (SP_PARM != 0 + && SP_PARM->_slk != 0 + && color_pair >= 0 + && color_pair < SP_PARM->_pair_limit) { + TR(TRACE_ATTRS, ("... current %s", _tracech_t(CHREF(SP_PARM->_slk->attr)))); + SetAttr(SP_PARM->_slk->attr, attr); + if (color_pair > 0) { + SetPair(SP_PARM->_slk->attr, color_pair); } - TR(TRACE_ATTRS, ("new attribute is %s", _tracech_t(CHREF(SP->_slk->attr)))); - returnCode(OK); - } else - returnCode(ERR); + TR(TRACE_ATTRS, ("new attribute is %s", _tracech_t(CHREF(SP_PARM->_slk->attr)))); + code = OK; + } + returnCode(code); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +slk_attr_set(const attr_t attr, NCURSES_COLOR_T pair_arg, void *opts) +{ + return NCURSES_SP_NAME(slk_attr_set) (CURRENT_SCREEN, attr, + pair_arg, opts); } +#endif diff --git a/lib/libcurses/base/lib_slkatrof.c b/lib/libcurses/base/lib_slkatrof.c index e760fa62001..fa90dbc8c6b 100644 --- a/lib/libcurses/base/lib_slkatrof.c +++ b/lib/libcurses/base/lib_slkatrof.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_slkatrof.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_slkatrof.c,v 1.4 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2005,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -40,21 +41,29 @@ */ #include -MODULE_ID("$Id: lib_slkatrof.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_slkatrof.c,v 1.4 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) -slk_attroff(const chtype attr) +NCURSES_SP_NAME(slk_attroff) (NCURSES_SP_DCLx const chtype attr) { - T((T_CALLED("slk_attroff(%s)"), _traceattr(attr))); + T((T_CALLED("slk_attroff(%p,%s)"), (void *) SP_PARM, _traceattr(attr))); - if (SP != 0 && SP->_slk != 0) { - TR(TRACE_ATTRS, ("... current %s", _tracech_t(CHREF(SP->_slk->attr)))); - RemAttr(SP->_slk->attr, attr); + if (SP_PARM != 0 && SP_PARM->_slk != 0) { + TR(TRACE_ATTRS, ("... current %s", _tracech_t(CHREF(SP_PARM->_slk->attr)))); + RemAttr(SP_PARM->_slk->attr, attr); if ((attr & A_COLOR) != 0) { - SetPair(SP->_slk->attr, 0); + SetPair(SP_PARM->_slk->attr, 0); } - TR(TRACE_ATTRS, ("new attribute is %s", _tracech_t(CHREF(SP->_slk->attr)))); + TR(TRACE_ATTRS, ("new attribute is %s", _tracech_t(CHREF(SP_PARM->_slk->attr)))); returnCode(OK); } else returnCode(ERR); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +slk_attroff(const chtype attr) +{ + return NCURSES_SP_NAME(slk_attroff) (CURRENT_SCREEN, attr); +} +#endif diff --git a/lib/libcurses/base/lib_slkatron.c b/lib/libcurses/base/lib_slkatron.c index deef29f7326..c4e982b3cdc 100644 --- a/lib/libcurses/base/lib_slkatron.c +++ b/lib/libcurses/base/lib_slkatron.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_slkatron.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_slkatron.c,v 1.4 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -40,21 +41,29 @@ */ #include -MODULE_ID("$Id: lib_slkatron.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_slkatron.c,v 1.4 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) -slk_attron(const chtype attr) +NCURSES_SP_NAME(slk_attron) (NCURSES_SP_DCLx const chtype attr) { - T((T_CALLED("slk_attron(%s)"), _traceattr(attr))); + T((T_CALLED("slk_attron(%p,%s)"), (void *) SP_PARM, _traceattr(attr))); - if (SP != 0 && SP->_slk != 0) { - TR(TRACE_ATTRS, ("... current %s", _tracech_t(CHREF(SP->_slk->attr)))); - AddAttr(SP->_slk->attr, attr); + if (SP_PARM != 0 && SP_PARM->_slk != 0) { + TR(TRACE_ATTRS, ("... current %s", _tracech_t(CHREF(SP_PARM->_slk->attr)))); + AddAttr(SP_PARM->_slk->attr, attr); if ((attr & A_COLOR) != 0) { - SetPair(SP->_slk->attr, PAIR_NUMBER(attr)); + SetPair(SP_PARM->_slk->attr, PairNumber(attr)); } - TR(TRACE_ATTRS, ("new attribute is %s", _tracech_t(CHREF(SP->_slk->attr)))); + TR(TRACE_ATTRS, ("new attribute is %s", _tracech_t(CHREF(SP_PARM->_slk->attr)))); returnCode(OK); } else returnCode(ERR); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +slk_attron(const chtype attr) +{ + return NCURSES_SP_NAME(slk_attron) (CURRENT_SCREEN, attr); +} +#endif diff --git a/lib/libcurses/base/lib_slkatrset.c b/lib/libcurses/base/lib_slkatrset.c index 17dc4a2097f..707ed3f00bb 100644 --- a/lib/libcurses/base/lib_slkatrset.c +++ b/lib/libcurses/base/lib_slkatrset.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_slkatrset.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_slkatrset.c,v 1.4 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2005,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -40,16 +41,24 @@ */ #include -MODULE_ID("$Id: lib_slkatrset.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_slkatrset.c,v 1.4 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) -slk_attrset(const chtype attr) +NCURSES_SP_NAME(slk_attrset) (NCURSES_SP_DCLx const chtype attr) { - T((T_CALLED("slk_attrset(%s)"), _traceattr(attr))); + T((T_CALLED("slk_attrset(%p,%s)"), (void *) SP_PARM, _traceattr(attr))); - if (SP != 0 && SP->_slk != 0) { - SetAttr(SP->_slk->attr, attr); + if (SP_PARM != 0 && SP_PARM->_slk != 0) { + SetAttr(SP_PARM->_slk->attr, attr); returnCode(OK); } else returnCode(ERR); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +slk_attrset(const chtype attr) +{ + return NCURSES_SP_NAME(slk_attrset) (CURRENT_SCREEN, attr); +} +#endif diff --git a/lib/libcurses/base/lib_slkattr.c b/lib/libcurses/base/lib_slkattr.c index fadcbe0afe2..44aad440d3c 100644 --- a/lib/libcurses/base/lib_slkattr.c +++ b/lib/libcurses/base/lib_slkattr.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_slkattr.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_slkattr.c,v 1.4 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -40,19 +41,27 @@ */ #include -MODULE_ID("$Id: lib_slkattr.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_slkattr.c,v 1.4 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(attr_t) -slk_attr(void) +NCURSES_SP_NAME(slk_attr) (NCURSES_SP_DCL0) { - T((T_CALLED("slk_attr()"))); + T((T_CALLED("slk_attr(%p)"), (void *) SP_PARM)); - if (SP != 0 && SP->_slk != 0) { - attr_t result = AttrOf(SP->_slk->attr) & ALL_BUT_COLOR; - int pair = GetPair(SP->_slk->attr); + if (SP_PARM != 0 && SP_PARM->_slk != 0) { + attr_t result = AttrOf(SP_PARM->_slk->attr) & ALL_BUT_COLOR; + int pair = GetPair(SP_PARM->_slk->attr); - result |= COLOR_PAIR(pair); + result |= (attr_t) ColorPair(pair); returnAttr(result); } else returnAttr(0); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(attr_t) +slk_attr(void) +{ + return NCURSES_SP_NAME(slk_attr) (CURRENT_SCREEN); +} +#endif diff --git a/lib/libcurses/base/lib_slkclear.c b/lib/libcurses/base/lib_slkclear.c index 44a542ef0c4..3da0f425796 100644 --- a/lib/libcurses/base/lib_slkclear.c +++ b/lib/libcurses/base/lib_slkclear.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_slkclear.c,v 1.4 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_slkclear.c,v 1.5 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2007,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -42,27 +43,35 @@ */ #include -MODULE_ID("$Id: lib_slkclear.c,v 1.4 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_slkclear.c,v 1.5 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) -slk_clear(void) +NCURSES_SP_NAME(slk_clear) (NCURSES_SP_DCL0) { int rc = ERR; - T((T_CALLED("slk_clear()"))); + T((T_CALLED("slk_clear(%p)"), (void *) SP_PARM)); - if (SP != NULL && SP->_slk != NULL) { - SP->_slk->hidden = TRUE; + if (SP_PARM != 0 && SP_PARM->_slk != 0) { + SP_PARM->_slk->hidden = TRUE; /* For simulated SLK's it looks much more natural to inherit those attributes from the standard screen */ - SP->_slk->win->_nc_bkgd = stdscr->_nc_bkgd; - WINDOW_ATTRS(SP->_slk->win) = WINDOW_ATTRS(stdscr); - if (SP->_slk->win == stdscr) { + SP_PARM->_slk->win->_nc_bkgd = StdScreen(SP_PARM)->_nc_bkgd; + WINDOW_ATTRS(SP_PARM->_slk->win) = WINDOW_ATTRS(StdScreen(SP_PARM)); + if (SP_PARM->_slk->win == StdScreen(SP_PARM)) { rc = OK; } else { - werase(SP->_slk->win); - rc = wrefresh(SP->_slk->win); + werase(SP_PARM->_slk->win); + rc = wrefresh(SP_PARM->_slk->win); } } returnCode(rc); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +slk_clear(void) +{ + return NCURSES_SP_NAME(slk_clear) (CURRENT_SCREEN); +} +#endif diff --git a/lib/libcurses/base/lib_slkcolor.c b/lib/libcurses/base/lib_slkcolor.c index 1fcf42647d6..a2b22a76149 100644 --- a/lib/libcurses/base/lib_slkcolor.c +++ b/lib/libcurses/base/lib_slkcolor.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_slkcolor.c,v 1.4 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_slkcolor.c,v 1.5 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2005 Free Software Foundation, Inc. * + * Copyright 2018,2020 Thomas E. Dickey * + * Copyright 1998-2014,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,8 +30,8 @@ ****************************************************************************/ /**************************************************************************** - * Author: Juergen Pfeifer, 1998 * - * and: Thomas E. Dickey 2005 * + * Author: Juergen Pfeifer, 1998,2009 * + * and: Thomas E. Dickey 2005-on * ****************************************************************************/ /* @@ -40,19 +41,53 @@ */ #include -MODULE_ID("$Id: lib_slkcolor.c,v 1.4 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_slkcolor.c,v 1.5 2023/10/17 09:52:09 nicm Exp $") +static int +_nc_slk_color(SCREEN *sp, int pair_arg) +{ + int code = ERR; + + T((T_CALLED("slk_color(%p,%d)"), (void *) sp, pair_arg)); + + if (sp != 0 + && sp->_slk != 0 + && pair_arg >= 0 + && pair_arg < sp->_pair_limit) { + TR(TRACE_ATTRS, ("... current is %s", _tracech_t(CHREF(sp->_slk->attr)))); + SetPair(sp->_slk->attr, pair_arg); + TR(TRACE_ATTRS, ("new attribute is %s", _tracech_t(CHREF(sp->_slk->attr)))); + code = OK; + } + returnCode(code); +} + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(slk_color) (NCURSES_SP_DCLx NCURSES_PAIRS_T pair_arg) +{ + return _nc_slk_color(SP_PARM, pair_arg); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +slk_color(NCURSES_PAIRS_T pair_arg) +{ + return NCURSES_SP_NAME(slk_color) (CURRENT_SCREEN, pair_arg); +} +#endif + +#if NCURSES_EXT_COLORS +NCURSES_EXPORT(int) +NCURSES_SP_NAME(extended_slk_color) (NCURSES_SP_DCLx int pair_arg) +{ + return _nc_slk_color(SP_PARM, pair_arg); +} + +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) -slk_color(short color_pair_number) +extended_slk_color(int pair_arg) { - T((T_CALLED("slk_color(%d)"), color_pair_number)); - - if (SP != 0 && SP->_slk != 0 && - color_pair_number >= 0 && color_pair_number < COLOR_PAIRS) { - TR(TRACE_ATTRS, ("... current is %s", _tracech_t(CHREF(SP->_slk->attr)))); - SetPair(SP->_slk->attr, color_pair_number); - TR(TRACE_ATTRS, ("new attribute is %s", _tracech_t(CHREF(SP->_slk->attr)))); - returnCode(OK); - } else - returnCode(ERR); + return NCURSES_SP_NAME(extended_slk_color) (CURRENT_SCREEN, pair_arg); } +#endif +#endif diff --git a/lib/libcurses/base/lib_slkinit.c b/lib/libcurses/base/lib_slkinit.c index ea1ce623c60..1473920f425 100644 --- a/lib/libcurses/base/lib_slkinit.c +++ b/lib/libcurses/base/lib_slkinit.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_slkinit.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_slkinit.c,v 1.4 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020,2022 Thomas E. Dickey * + * Copyright 1998-2009,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,6 +33,7 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -41,17 +43,49 @@ */ #include -MODULE_ID("$Id: lib_slkinit.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_slkinit.c,v 1.4 2023/10/17 09:52:09 nicm Exp $") + +#ifdef USE_SP_RIPOFF +#define SoftkeyFormat SP_PARM->slk_format +#else +#define SoftkeyFormat _nc_globals.slk_format +#endif NCURSES_EXPORT(int) -slk_init(int format) +NCURSES_SP_NAME(slk_init) (NCURSES_SP_DCLx int format) { int code = ERR; - T((T_CALLED("slk_init(%d)"), format)); - if (format >= 0 && format <= 3 && !_nc_globals.slk_format) { - _nc_globals.slk_format = 1 + format; - code = _nc_ripoffline(-SLK_LINES(_nc_globals.slk_format), _nc_slk_initialize); + START_TRACE(); + T((T_CALLED("slk_init(%p,%d)"), (void *) SP_PARM, format)); + + if (format >= 0 + && format <= 3 +#ifdef USE_SP_RIPOFF + && SP_PARM + && SP_PARM->_prescreen +#endif + && !SoftkeyFormat) { + SoftkeyFormat = 1 + format; + code = NCURSES_SP_NAME(_nc_ripoffline) (NCURSES_SP_ARGx + -SLK_LINES(SoftkeyFormat), + _nc_slk_initialize); } returnCode(code); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +slk_init(int format) +{ + int rc; + + _nc_init_pthreads(); + _nc_lock_global(prescreen); + START_TRACE(); + rc = NCURSES_SP_NAME(slk_init) (CURRENT_SCREEN_PRE, format); + _nc_unlock_global(prescreen); + + return rc; +} +#endif diff --git a/lib/libcurses/base/lib_slklab.c b/lib/libcurses/base/lib_slklab.c index 4df19d35dcf..21b01e52a83 100644 --- a/lib/libcurses/base/lib_slklab.c +++ b/lib/libcurses/base/lib_slklab.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_slklab.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_slklab.c,v 1.4 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2003 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2003,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +32,8 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * and: Juergen Pfeifer, 1998,2009 * + * and: Thomas E. Dickey 1998-on * ****************************************************************************/ /* @@ -40,14 +43,22 @@ */ #include -MODULE_ID("$Id: lib_slklab.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_slklab.c,v 1.4 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(char *) -slk_label(int n) +NCURSES_SP_NAME(slk_label) (NCURSES_SP_DCLx int n) { - T((T_CALLED("slk_label(%d)"), n)); + T((T_CALLED("slk_label(%p,%d)"), (void *) SP_PARM, n)); - if (SP == NULL || SP->_slk == NULL || n < 1 || n > SP->_slk->labcnt) + if (SP_PARM == 0 || SP_PARM->_slk == 0 || n < 1 || n > SP_PARM->_slk->labcnt) returnPtr(0); - returnPtr(SP->_slk->ent[n - 1].ent_text); + returnPtr(SP_PARM->_slk->ent[n - 1].ent_text); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(char *) +slk_label(int n) +{ + return NCURSES_SP_NAME(slk_label) (CURRENT_SCREEN, n); } +#endif diff --git a/lib/libcurses/base/lib_slkrefr.c b/lib/libcurses/base/lib_slkrefr.c index 4c58f9dbac6..4939ebc7ea6 100644 --- a/lib/libcurses/base/lib_slkrefr.c +++ b/lib/libcurses/base/lib_slkrefr.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_slkrefr.c,v 1.5 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_slkrefr.c,v 1.6 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2013,2014 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -40,9 +41,18 @@ * Write SLK window to the (virtual) screen. */ #include -#include /* num_labels, label_*, plab_norm */ -MODULE_ID("$Id: lib_slkrefr.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") +#ifndef CUR +#define CUR SP_TERMTYPE +#endif + +MODULE_ID("$Id: lib_slkrefr.c,v 1.6 2023/10/17 09:52:09 nicm Exp $") + +#ifdef USE_TERM_DRIVER +#define NumLabels InfoOf(SP_PARM).numlabels +#else +#define NumLabels num_labels +#endif /* * Paint the info line for the PC style SLK emulation. @@ -55,7 +65,7 @@ slk_paint_info(WINDOW *win) if (win && sp && (sp->slk_format == 4)) { int i; - mvwhline(win, 0, 0, 0, getmaxx(win)); + (void) mvwhline(win, 0, 0, 0, getmaxx(win)); wmove(win, 0, 0); for (i = 0; i < sp->_slk->maxlab; i++) { @@ -68,31 +78,47 @@ slk_paint_info(WINDOW *win) * Write the soft labels to the soft-key window. */ static void -slk_intern_refresh(SLK * slk) +slk_intern_refresh(SCREEN *sp) { int i; - int fmt = SP->slk_format; + int fmt; + SLK *slk; + int numlab; + + if (sp == 0) + return; + + slk = sp->_slk; + fmt = sp->slk_format; + numlab = NumLabels; + + if (slk->hidden) + return; for (i = 0; i < slk->labcnt; i++) { if (slk->dirty || slk->ent[i].dirty) { if (slk->ent[i].visible) { - if (num_labels > 0 && SLK_STDFMT(fmt)) { + if (numlab > 0 && SLK_STDFMT(fmt)) { +#ifdef USE_TERM_DRIVER + CallDriver_2(sp, td_hwlabel, i + 1, slk->ent[i].form_text); +#else if (i < num_labels) { - TPUTS_TRACE("plab_norm"); - putp(TPARM_2(plab_norm, i + 1, slk->ent[i].form_text)); + NCURSES_PUTP2("plab_norm", + TPARM_2(plab_norm, + i + 1, + slk->ent[i].form_text)); } +#endif } else { if (fmt == 4) slk_paint_info(slk->win); wmove(slk->win, SLK_LINES(fmt) - 1, slk->ent[i].ent_x); - if (SP->_slk) { - wattrset(slk->win, AttrOf(SP->_slk->attr)); - } + (void) wattrset(slk->win, (int) AttrOf(slk->attr)); waddstr(slk->win, slk->ent[i].form_text); - /* if we simulate SLK's, it's looking much more + /* if we simulate SLK's, it is looking much more natural to use the current ATTRIBUTE also for the label window */ - wattrset(slk->win, WINDOW_ATTRS(stdscr)); + (void) wattrset(slk->win, (int) WINDOW_ATTRS(StdScreen(sp))); } } slk->ent[i].dirty = FALSE; @@ -100,14 +126,16 @@ slk_intern_refresh(SLK * slk) } slk->dirty = FALSE; - if (num_labels > 0) { + if (numlab > 0) { +#ifdef USE_TERM_DRIVER + CallDriver_1(sp, td_hwlabelOnOff, slk->hidden ? FALSE : TRUE); +#else if (slk->hidden) { - TPUTS_TRACE("label_off"); - putp(label_off); + NCURSES_PUTP2("label_off", label_off); } else { - TPUTS_TRACE("label_on"); - putp(label_on); + NCURSES_PUTP2("label_on", label_on); } +#endif } } @@ -115,32 +143,48 @@ slk_intern_refresh(SLK * slk) * Refresh the soft labels. */ NCURSES_EXPORT(int) -slk_noutrefresh(void) +NCURSES_SP_NAME(slk_noutrefresh) (NCURSES_SP_DCL0) { - T((T_CALLED("slk_noutrefresh()"))); + T((T_CALLED("slk_noutrefresh(%p)"), (void *) SP_PARM)); - if (SP == NULL || SP->_slk == NULL) + if (SP_PARM == 0 || SP_PARM->_slk == 0) returnCode(ERR); - if (SP->_slk->hidden) + if (SP_PARM->_slk->hidden) returnCode(OK); - slk_intern_refresh(SP->_slk); + slk_intern_refresh(SP_PARM); + + returnCode(wnoutrefresh(SP_PARM->_slk->win)); +} - returnCode(wnoutrefresh(SP->_slk->win)); +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +slk_noutrefresh(void) +{ + return NCURSES_SP_NAME(slk_noutrefresh) (CURRENT_SCREEN); } +#endif /* * Refresh the soft labels. */ NCURSES_EXPORT(int) -slk_refresh(void) +NCURSES_SP_NAME(slk_refresh) (NCURSES_SP_DCL0) { - T((T_CALLED("slk_refresh()"))); + T((T_CALLED("slk_refresh(%p)"), (void *) SP_PARM)); - if (SP == NULL || SP->_slk == NULL) + if (SP_PARM == 0 || SP_PARM->_slk == 0) returnCode(ERR); - if (SP->_slk->hidden) + if (SP_PARM->_slk->hidden) returnCode(OK); - slk_intern_refresh(SP->_slk); + slk_intern_refresh(SP_PARM); - returnCode(wrefresh(SP->_slk->win)); + returnCode(wrefresh(SP_PARM->_slk->win)); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +slk_refresh(void) +{ + return NCURSES_SP_NAME(slk_refresh) (CURRENT_SCREEN); } +#endif diff --git a/lib/libcurses/base/lib_slkset.c b/lib/libcurses/base/lib_slkset.c index 6958f8d2a9a..4a14d669161 100644 --- a/lib/libcurses/base/lib_slkset.c +++ b/lib/libcurses/base/lib_slkset.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_slkset.c,v 1.4 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_slkset.c,v 1.5 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2007 Free Software Foundation, Inc. * + * Copyright 2019,2020 Thomas E. Dickey * + * Copyright 1998-2011,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -46,33 +47,33 @@ #endif #endif -MODULE_ID("$Id: lib_slkset.c,v 1.4 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_slkset.c,v 1.5 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) -slk_set(int i, const char *astr, int format) +NCURSES_SP_NAME(slk_set) (NCURSES_SP_DCLx int i, const char *astr, int format) { SLK *slk; - int offset; + int offset = 0; int numchrs; int numcols; int limit; const char *str = astr; const char *p; - T((T_CALLED("slk_set(%d, \"%s\", %d)"), i, str, format)); + T((T_CALLED("slk_set(%p, %d, \"%s\", %d)"), (void *) SP_PARM, i, str, format)); - if (SP == 0 - || (slk = SP->_slk) == 0 + if (SP_PARM == 0 + || (slk = SP_PARM->_slk) == 0 || i < 1 || i > slk->labcnt || format < 0 || format > 2) returnCode(ERR); - if (str == NULL) + if (str == 0) str = ""; --i; /* Adjust numbering of labels */ - limit = MAX_SKEY_LEN(SP->slk_format); + limit = MAX_SKEY_LEN(SP_PARM->slk_format); while (isspace(UChar(*str))) str++; /* skip over leading spaces */ p = str; @@ -91,17 +92,17 @@ slk_set(int i, const char *astr, int format) mbrtowc(&wc, p, need, &state); if (!iswprint((wint_t) wc)) break; - if (wcwidth(wc) + numcols > limit) + if (_nc_wacs_width(wc) + numcols > limit) break; - numcols += wcwidth(wc); + numcols += _nc_wacs_width(wc); p += need; } - numchrs = (p - str); + numchrs = (int) (p - str); #else while (isprint(UChar(*p))) p++; /* The first non-print stops */ - numcols = (p - str); + numcols = (int) (p - str); if (numcols > limit) numcols = limit; numchrs = numcols; @@ -113,13 +114,12 @@ slk_set(int i, const char *astr, int format) slk->ent[i].ent_text[numchrs] = '\0'; if ((slk->ent[i].form_text = (char *) _nc_doalloc(slk->ent[i].form_text, - (unsigned) (limit + - numchrs + 1)) + (size_t) (limit + + numchrs + 1)) ) == 0) returnCode(ERR); switch (format) { - default: case 0: /* left-justified */ offset = 0; break; @@ -133,19 +133,27 @@ slk_set(int i, const char *astr, int format) if (offset <= 0) offset = 0; else - memset(slk->ent[i].form_text, ' ', (unsigned) offset); + memset(slk->ent[i].form_text, ' ', (size_t) offset); memcpy(slk->ent[i].form_text + offset, slk->ent[i].ent_text, - (unsigned) numchrs); + (size_t) numchrs); if (offset < limit) { memset(slk->ent[i].form_text + offset + numchrs, ' ', - (unsigned) (limit - (offset + numcols))); + (size_t) (limit - (offset + numcols))); } slk->ent[i].form_text[numchrs - numcols + limit] = 0; slk->ent[i].dirty = TRUE; returnCode(OK); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +slk_set(int i, const char *astr, int format) +{ + return NCURSES_SP_NAME(slk_set) (CURRENT_SCREEN, i, astr, format); +} +#endif diff --git a/lib/libcurses/base/lib_slktouch.c b/lib/libcurses/base/lib_slktouch.c index 7137ec44b01..5477bbedfcd 100644 --- a/lib/libcurses/base/lib_slktouch.c +++ b/lib/libcurses/base/lib_slktouch.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_slktouch.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_slktouch.c,v 1.4 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2000,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,8 +30,8 @@ ****************************************************************************/ /**************************************************************************** - * Author: Zeyd M. Ben-Halim 1992,1995 * - * and: Eric S. Raymond * + * Author: Juergen Pfeifer 1997,2009 * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ /* @@ -40,16 +41,24 @@ */ #include -MODULE_ID("$Id: lib_slktouch.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_slktouch.c,v 1.4 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) -slk_touch(void) +NCURSES_SP_NAME(slk_touch) (NCURSES_SP_DCL0) { - T((T_CALLED("slk_touch()"))); + T((T_CALLED("slk_touch(%p)"), (void *) SP_PARM)); - if (SP == NULL || SP->_slk == NULL) + if (SP_PARM == 0 || SP_PARM->_slk == 0) returnCode(ERR); - SP->_slk->dirty = TRUE; + SP_PARM->_slk->dirty = TRUE; returnCode(OK); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +slk_touch(void) +{ + return NCURSES_SP_NAME(slk_touch) (CURRENT_SCREEN); +} +#endif diff --git a/lib/libcurses/base/lib_touch.c b/lib/libcurses/base/lib_touch.c index a19fb982320..845373964e9 100644 --- a/lib/libcurses/base/lib_touch.c +++ b/lib/libcurses/base/lib_touch.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_touch.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_touch.c,v 1.4 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -45,16 +46,19 @@ #include -MODULE_ID("$Id: lib_touch.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_touch.c,v 1.4 2023/10/17 09:52:09 nicm Exp $") + +#undef is_linetouched NCURSES_EXPORT(bool) is_linetouched(WINDOW *win, int line) { - T((T_CALLED("is_linetouched(%p,%d)"), win, line)); + T((T_CALLED("is_linetouched(%p,%d)"), (void *) win, line)); - /* XSI doesn't define any error */ - if (!win || (line > win->_maxy) || (line < 0)) - returnCode((bool) ERR); + /* XSI doesn't define any error, and gcc ultimately made it impossible */ + if (!win || (line > win->_maxy) || (line < 0)) { + returnCode(FALSE); + } returnCode(win->_line[line].firstchar != _NOCHANGE ? TRUE : FALSE); } @@ -62,14 +66,15 @@ is_linetouched(WINDOW *win, int line) NCURSES_EXPORT(bool) is_wintouched(WINDOW *win) { - int i; + T((T_CALLED("is_wintouched(%p)"), (void *) win)); - T((T_CALLED("is_wintouched(%p)"), win)); + if (win) { + int i; - if (win) for (i = 0; i <= win->_maxy; i++) if (win->_line[i].firstchar != _NOCHANGE) returnCode(TRUE); + } returnCode(FALSE); } @@ -78,7 +83,7 @@ wtouchln(WINDOW *win, int y, int n, int changed) { int i; - T((T_CALLED("wtouchln(%p,%d,%d,%d)"), win, y, n, changed)); + T((T_CALLED("wtouchln(%p,%d,%d,%d)"), (void *) win, y, n, changed)); if (!win || (n < 0) || (y < 0) || (y > win->_maxy)) returnCode(ERR); @@ -86,8 +91,10 @@ wtouchln(WINDOW *win, int y, int n, int changed) for (i = y; i < y + n; i++) { if (i > win->_maxy) break; - win->_line[i].firstchar = changed ? 0 : _NOCHANGE; - win->_line[i].lastchar = changed ? win->_maxx : _NOCHANGE; + win->_line[i].firstchar = (NCURSES_SIZE_T) (changed ? 0 : _NOCHANGE); + win->_line[i].lastchar = (NCURSES_SIZE_T) (changed + ? win->_maxx + : _NOCHANGE); } returnCode(OK); } diff --git a/lib/libcurses/base/lib_ungetch.c b/lib/libcurses/base/lib_ungetch.c index 122776d8ff4..eb6dada9bc5 100644 --- a/lib/libcurses/base/lib_ungetch.c +++ b/lib/libcurses/base/lib_ungetch.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_ungetch.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_ungetch.c,v 1.4 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2011,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,6 +33,7 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -43,7 +45,7 @@ #include -MODULE_ID("$Id: lib_ungetch.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_ungetch.c,v 1.4 2023/10/17 09:52:09 nicm Exp $") #include @@ -59,17 +61,20 @@ _nc_fifo_dump(SCREEN *sp) #endif /* TRACE */ NCURSES_EXPORT(int) -_nc_ungetch(SCREEN *sp, int ch) +safe_ungetch(SCREEN *sp, int ch) { int rc = ERR; - if (tail != -1) { - if (head == -1) { + T((T_CALLED("ungetch(%p,%s)"), (void *) sp, _nc_tracechar(sp, ch))); + + if (sp != 0 && tail >= 0) { + if (head < 0) { head = 0; t_inc(); peek = tail; /* no raw keys */ - } else + } else { h_dec(); + } sp->_fifo[head] = ch; T(("ungetch %s ok", _nc_tracechar(sp, ch))); @@ -81,12 +86,11 @@ _nc_ungetch(SCREEN *sp, int ch) #endif rc = OK; } - return rc; + returnCode(rc); } NCURSES_EXPORT(int) ungetch(int ch) { - T((T_CALLED("ungetch(%s)"), _nc_tracechar(SP, ch))); - returnCode(_nc_ungetch(SP, ch)); + return safe_ungetch(CURRENT_SCREEN, ch); } diff --git a/lib/libcurses/base/lib_vline.c b/lib/libcurses/base/lib_vline.c index 03fcac6b2dc..820c9c9db6d 100644 --- a/lib/libcurses/base/lib_vline.c +++ b/lib/libcurses/base/lib_vline.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_vline.c,v 1.4 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_vline.c,v 1.5 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2001,2006 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +32,8 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-on * + * and: Sven Verdoolaege 2001 * ****************************************************************************/ /* @@ -42,22 +45,21 @@ #include -MODULE_ID("$Id: lib_vline.c,v 1.4 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_vline.c,v 1.5 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) wvline(WINDOW *win, chtype ch, int n) { int code = ERR; - NCURSES_SIZE_T row, col; - NCURSES_SIZE_T end; - T((T_CALLED("wvline(%p,%s,%d)"), win, _tracechtype(ch), n)); + T((T_CALLED("wvline(%p,%s,%d)"), (void *) win, _tracechtype(ch), n)); if (win) { NCURSES_CH_T wch; - row = win->_cury; - col = win->_curx; - end = row + n - 1; + int row = win->_cury; + int col = win->_curx; + int end = row + n - 1; + if (end > win->_maxy) end = win->_maxy; @@ -69,6 +71,14 @@ wvline(WINDOW *win, chtype ch, int n) while (end >= row) { struct ldat *line = &(win->_line[end]); +#if USE_WIDEC_SUPPORT + if (col > 0 && isWidecExt(line->text[col])) { + SetChar2(line->text[col - 1], ' '); + } + if (col < win->_maxx && isWidecExt(line->text[col + 1])) { + SetChar2(line->text[col + 1], ' '); + } +#endif line->text[col] = wch; CHANGED_CELL(line, col); end--; diff --git a/lib/libcurses/base/lib_wattroff.c b/lib/libcurses/base/lib_wattroff.c index 9dfdb95a929..138a793356d 100644 --- a/lib/libcurses/base/lib_wattroff.c +++ b/lib/libcurses/base/lib_wattroff.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_wattroff.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_wattroff.c,v 1.4 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2006,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -44,12 +45,12 @@ #include #include -MODULE_ID("$Id: lib_wattroff.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_wattroff.c,v 1.4 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) wattr_off(WINDOW *win, attr_t at, void *opts GCC_UNUSED) { - T((T_CALLED("wattr_off(%p,%s)"), win, _traceattr(at))); + T((T_CALLED("wattr_off(%p,%s)"), (void *) win, _traceattr(at))); if (win) { T(("... current %s (%d)", _traceattr(WINDOW_ATTRS(win)), diff --git a/lib/libcurses/base/lib_wattron.c b/lib/libcurses/base/lib_wattron.c index cadbae69980..e18ae9daec9 100644 --- a/lib/libcurses/base/lib_wattron.c +++ b/lib/libcurses/base/lib_wattron.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_wattron.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_wattron.c,v 1.4 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * + * Copyright 2020,2022 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -44,20 +45,22 @@ #include #include -MODULE_ID("$Id: lib_wattron.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_wattron.c,v 1.4 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) wattr_on(WINDOW *win, attr_t at, void *opts GCC_UNUSED) { - T((T_CALLED("wattr_on(%p,%s)"), win, _traceattr(at))); + T((T_CALLED("wattr_on(%p,%s)"), (void *) win, _traceattr(at))); if (win != 0) { T(("... current %s (%d)", _traceattr(WINDOW_ATTRS(win)), GET_WINDOW_PAIR(win))); if_EXT_COLORS({ - if (at & A_COLOR) - win->_color = PAIR_NUMBER(at); + if (at & A_COLOR) { + win->_color = PairNumber(at); + set_extended_pair(opts, win->_color); + } }); toggle_attr_on(WINDOW_ATTRS(win), at); returnCode(OK); diff --git a/lib/libcurses/base/lib_winch.c b/lib/libcurses/base/lib_winch.c index 870ebea83a2..b58e49a7363 100644 --- a/lib/libcurses/base/lib_winch.c +++ b/lib/libcurses/base/lib_winch.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_winch.c,v 1.4 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_winch.c,v 1.5 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000,2001 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -41,16 +42,16 @@ #include -MODULE_ID("$Id: lib_winch.c,v 1.4 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_winch.c,v 1.5 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(chtype) winch(WINDOW *win) { - T((T_CALLED("winch(%p)"), win)); + T((T_CALLED("winch(%p)"), (void *) win)); if (win != 0) { - returnChar(CharOf(win->_line[win->_cury].text[win->_curx]) | - AttrOf(win->_line[win->_cury].text[win->_curx])); + returnChtype((chtype) CharOf(win->_line[win->_cury].text[win->_curx]) + | AttrOf(win->_line[win->_cury].text[win->_curx])); } else { - returnChar(0); + returnChtype(0); } } diff --git a/lib/libcurses/base/lib_window.c b/lib/libcurses/base/lib_window.c index 1143622c938..983bc39d63e 100644 --- a/lib/libcurses/base/lib_window.c +++ b/lib/libcurses/base/lib_window.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_window.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_window.c,v 1.4 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2010,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -41,7 +42,7 @@ #include -MODULE_ID("$Id: lib_window.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_window.c,v 1.4 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(void) _nc_synchook(WINDOW *win) @@ -58,33 +59,32 @@ mvderwin(WINDOW *win, int y, int x) /* move a derived window */ { WINDOW *orig; - int i; - - T((T_CALLED("mvderwin(%p,%d,%d)"), win, y, x)); - - if (win && (orig = win->_parent)) { - if (win->_parx == x && win->_pary == y) - returnCode(OK); - if (x < 0 || y < 0) - returnCode(ERR); - if ((x + getmaxx(win) > getmaxx(orig)) || - (y + getmaxy(win) > getmaxy(orig))) - returnCode(ERR); - } else - returnCode(ERR); - wsyncup(win); - win->_parx = x; - win->_pary = y; - for (i = 0; i < getmaxy(win); i++) - win->_line[i].text = &(orig->_line[y++].text[x]); - returnCode(OK); + int rc = ERR; + + T((T_CALLED("mvderwin(%p,%d,%d)"), (void *) win, y, x)); + + if (win != 0 + && (orig = win->_parent) != 0 + && (x >= 0 && y >= 0) + && (x + getmaxx(win) <= getmaxx(orig)) + && (y + getmaxy(win) <= getmaxy(orig))) { + int i; + + wsyncup(win); + win->_parx = x; + win->_pary = y; + for (i = 0; i < getmaxy(win); i++) + win->_line[i].text = &(orig->_line[y++].text[x]); + rc = OK; + } + returnCode(rc); } NCURSES_EXPORT(int) syncok(WINDOW *win, bool bf) /* enable/disable automatic wsyncup() on each change to window */ { - T((T_CALLED("syncok(%p,%d)"), win, bf)); + T((T_CALLED("syncok(%p,%d)"), (void *) win, bf)); if (win) { win->_sync = bf; @@ -100,7 +100,7 @@ wsyncup(WINDOW *win) { WINDOW *wp; - T((T_CALLED("wsyncup(%p)"), win)); + T((T_CALLED("wsyncup(%p)"), (void *) win)); if (win && win->_parent) { for (wp = win; wp->_parent; wp = wp->_parent) { int y; @@ -130,9 +130,9 @@ wsyncdown(WINDOW *win) /* mark changed every cell in win that is changed in any of its ancestors */ /* Rewritten by J. Pfeifer, 1-Apr-96 (don't even think that...) */ { - T((T_CALLED("wsyncdown(%p)"), win)); + T((T_CALLED("wsyncdown(%p)"), (void *) win)); - if (win && win->_parent) { + if (win != NULL && win->_parent != NULL) { WINDOW *pp = win->_parent; int y; @@ -169,7 +169,7 @@ wcursyncup(WINDOW *win) { WINDOW *wp; - T((T_CALLED("wcursyncup(%p)"), win)); + T((T_CALLED("wcursyncup(%p)"), (void *) win)); for (wp = win; wp && wp->_parent; wp = wp->_parent) { wmove(wp->_parent, wp->_pary + wp->_cury, wp->_parx + wp->_curx); } @@ -181,25 +181,29 @@ dupwin(WINDOW *win) /* make an exact duplicate of the given window */ { WINDOW *nwin = 0; - size_t linesize; - int i; - T((T_CALLED("dupwin(%p)"), win)); + T((T_CALLED("dupwin(%p)"), (void *) win)); if (win != 0) { - +#if NCURSES_SP_FUNCS + SCREEN *sp = _nc_screen_of(win); +#endif _nc_lock_global(curses); - if (win->_flags & _ISPAD) { - nwin = newpad(win->_maxy + 1, - win->_maxx + 1); + if (IS_PAD(win)) { + nwin = NCURSES_SP_NAME(newpad) (NCURSES_SP_ARGx + win->_maxy + 1, + win->_maxx + 1); } else { - nwin = newwin(win->_maxy + 1, - win->_maxx + 1, - win->_begy, - win->_begx); + nwin = NCURSES_SP_NAME(newwin) (NCURSES_SP_ARGx + win->_maxy + 1, + win->_maxx + 1, + win->_begy, + win->_begx); } if (nwin != 0) { + int i; + size_t linesize; nwin->_curx = win->_curx; nwin->_cury = win->_cury; @@ -236,10 +240,10 @@ dupwin(WINDOW *win) nwin->_regtop = win->_regtop; nwin->_regbottom = win->_regbottom; - if (win->_flags & _ISPAD) + if (IS_PAD(win)) nwin->_pad = win->_pad; - linesize = (win->_maxx + 1) * sizeof(NCURSES_CH_T); + linesize = (unsigned) (win->_maxx + 1) * sizeof(NCURSES_CH_T); for (i = 0; i <= nwin->_maxy; i++) { memcpy(nwin->_line[i].text, win->_line[i].text, linesize); nwin->_line[i].firstchar = win->_line[i].firstchar; diff --git a/lib/libcurses/base/nc_panel.c b/lib/libcurses/base/nc_panel.c index 452153859c9..d3e39918a8d 100644 --- a/lib/libcurses/base/nc_panel.c +++ b/lib/libcurses/base/nc_panel.c @@ -1,7 +1,8 @@ -/* $OpenBSD: nc_panel.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: nc_panel.c,v 1.4 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2000,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -34,10 +35,22 @@ #include -MODULE_ID("$Id: nc_panel.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: nc_panel.c,v 1.4 2023/10/17 09:52:09 nicm Exp $") +NCURSES_EXPORT(struct panelhook *) +NCURSES_SP_NAME(_nc_panelhook) (NCURSES_SP_DCL0) +{ + return (SP_PARM + ? &(SP_PARM->_panelHook) + : (CURRENT_SCREEN + ? &(CURRENT_SCREEN->_panelHook) + : 0)); +} + +#if NCURSES_SP_FUNCS NCURSES_EXPORT(struct panelhook *) _nc_panelhook(void) { - return (SP ? &(SP->_panelHook) : NULL); + return NCURSES_SP_NAME(_nc_panelhook) (CURRENT_SCREEN); } +#endif diff --git a/lib/libcurses/base/new_pair.c b/lib/libcurses/base/new_pair.c new file mode 100644 index 00000000000..b7dcef1da62 --- /dev/null +++ b/lib/libcurses/base/new_pair.c @@ -0,0 +1,393 @@ +/**************************************************************************** + * Copyright 2018-2020,2021 Thomas E. Dickey * + * Copyright 2017 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey * + ****************************************************************************/ + +/* new_pair.c + * + * New color-pair functions, alloc_pair and free_pair + */ + +#define NEW_PAIR_INTERNAL 1 +#include + +#ifndef CUR +#define CUR SP_TERMTYPE +#endif + +#ifdef USE_TERM_DRIVER +#define MaxColors InfoOf(SP_PARM).maxcolors +#else +#define MaxColors max_colors +#endif + +#if NCURSES_EXT_COLORS + +/* fix redefinition versys tic.h */ +#undef entry +#define entry my_entry +#undef ENTRY +#define ENTRY my_ENTRY + +#include + +#endif + +MODULE_ID("$Id: new_pair.c,v 1.1 2023/10/17 09:52:09 nicm Exp $") + +#if NCURSES_EXT_COLORS + +#ifdef NEW_PAIR_DEBUG + +static int +prev_len(SCREEN *sp, int pair) +{ + int result = 1; + int base = pair; + colorpair_t *list = sp->_color_pairs; + while (list[pair].prev != base) { + result++; + pair = list[pair].prev; + } + return result; +} + +static int +next_len(SCREEN *sp, int pair) +{ + int result = 1; + int base = pair; + colorpair_t *list = sp->_color_pairs; + while (list[pair].next != base) { + result++; + pair = list[pair].next; + } + return result; +} + +/* + * Trace the contents of LRU color-pairs. + */ +static void +dumpit(SCREEN *sp, int pair, const char *tag) +{ + colorpair_t *list = sp->_color_pairs; + char bigbuf[256 * 20]; + char *p = bigbuf; + int n; + size_t have = sizeof(bigbuf); + + _nc_STRCPY(p, tag, have); + for (n = 0; n < sp->_pair_alloc; ++n) { + if (list[n].mode != cpFREE) { + p += strlen(p); + if ((size_t) (p - bigbuf) + 50 > have) + break; + _nc_SPRINTF(p, _nc_SLIMIT(have - (p - bigbuf)) + " %d%c(%d,%d)", + n, n == pair ? '@' : ':', list[n].next, list[n].prev); + } + } + T(("(%d/%d) %ld - %s", + next_len(sp, 0), + prev_len(sp, 0), + strlen(bigbuf), bigbuf)); + + if (next_len(sp, 0) != prev_len(sp, 0)) { + endwin(); + ExitProgram(EXIT_FAILURE); + } +} +#else +#define dumpit(sp, pair, tag) /* nothing */ +#endif + +static int +compare_data(const void *a, const void *b) +{ + const colorpair_t *p = (const colorpair_t *) a; + const colorpair_t *q = (const colorpair_t *) b; + return ((p->fg == q->fg) + ? (p->bg - q->bg) + : (p->fg - q->fg)); +} + +static int +_nc_find_color_pair(SCREEN *sp, int fg, int bg) +{ + colorpair_t find; + int result = -1; + + find.fg = fg; + find.bg = bg; + if (sp != 0) { + void *pp; + if ((pp = tfind(&find, &sp->_ordered_pairs, compare_data)) != 0) { + colorpair_t *temp = *(colorpair_t **) pp; + result = (int) (temp - sp->_color_pairs); + } + } + return result; +} + +static void +delink_color_pair(SCREEN *sp, int pair) +{ + colorpair_t *list = sp->_color_pairs; + int prev = list[pair].prev; + int next = list[pair].next; + + /* delink this from its current location */ + if (list[prev].next == pair && + list[next].prev == pair) { + list[prev].next = next; + list[next].prev = prev; + dumpit(sp, pair, "delinked"); + } +} + +/* + * Discard all nodes in the fast-index. + */ +NCURSES_EXPORT(void) +_nc_free_ordered_pairs(SCREEN *sp) +{ + if (sp && sp->_ordered_pairs && sp->_pair_alloc) { + int n; + for (n = 0; n < sp->_pair_alloc; ++n) { + tdelete(&sp->_color_pairs[n], &sp->_ordered_pairs, compare_data); + } + } +} + +/* + * Use this call to update the fast-index when modifying an entry in the color + * pair table. + */ +NCURSES_EXPORT(void) +_nc_reset_color_pair(SCREEN *sp, int pair, colorpair_t * next) +{ + colorpair_t *last; + + if (ValidPair(sp, pair)) { + bool used; + + ReservePairs(sp, pair); + last = &(sp->_color_pairs[pair]); + delink_color_pair(sp, pair); + if (last->mode > cpFREE && + (last->fg != next->fg || last->bg != next->bg)) { + /* remove the old entry from fast index */ + tdelete(last, &sp->_ordered_pairs, compare_data); + used = FALSE; + } else { + used = (last->mode != cpFREE); + } + if (!used) { + /* create a new entry in fast index */ + *last = *next; + tsearch(last, &sp->_ordered_pairs, compare_data); + } + } +} + +/* + * Use this call to relink the newest pair to the front of the list, keeping + * "0" first. + */ +NCURSES_EXPORT(void) +_nc_set_color_pair(SCREEN *sp, int pair, int mode) +{ + if (ValidPair(sp, pair)) { + colorpair_t *list = sp->_color_pairs; + dumpit(sp, pair, "SET_PAIR"); + list[0].mode = cpKEEP; + if (list[pair].mode <= cpFREE) + sp->_pairs_used++; + list[pair].mode = mode; + if (list[0].next != pair) { + /* link it at the front of the list */ + list[pair].next = list[0].next; + list[list[pair].next].prev = pair; + list[pair].prev = 0; + list[0].next = pair; + } + dumpit(sp, pair, "...after"); + } +} + +/* + * If we reallocate the color-pair array, we have to adjust the fast-index. + */ +NCURSES_EXPORT(void) +_nc_copy_pairs(SCREEN *sp, colorpair_t * target, colorpair_t * source, int length) +{ + int n; + for (n = 0; n < length; ++n) { + void *find = tfind(source + n, &sp->_ordered_pairs, compare_data); + if (find != 0) { + tdelete(source + n, &sp->_ordered_pairs, compare_data); + tsearch(target + n, &sp->_ordered_pairs, compare_data); + } + } +} + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(alloc_pair) (NCURSES_SP_DCLx int fg, int bg) +{ + int pair; + + T((T_CALLED("alloc_pair(%d,%d)"), fg, bg)); + if (SP_PARM == 0) { + pair = -1; + } else if ((pair = _nc_find_color_pair(SP_PARM, fg, bg)) < 0) { + /* + * Check if all of the slots have been used. If not, find one and + * use that. + */ + if (SP_PARM->_pairs_used + 1 < SP_PARM->_pair_limit) { + bool found = FALSE; + int hint = SP_PARM->_recent_pair; + + /* + * The linear search is done to allow mixing calls to init_pair() + * and alloc_pair(). The former can make gaps... + */ + for (pair = hint + 1; pair < SP_PARM->_pair_alloc; pair++) { + if (SP_PARM->_color_pairs[pair].mode == cpFREE) { + T(("found gap %d", pair)); + found = TRUE; + break; + } + } + if (!found && (SP_PARM->_pair_alloc < SP_PARM->_pair_limit)) { + pair = SP_PARM->_pair_alloc; + ReservePairs(SP_PARM, pair); + if (SP_PARM->_color_pairs == 0) { + pair = -1; + } else { + found = TRUE; + } + } + if (!found && SP_PARM->_color_pairs != NULL) { + for (pair = 1; pair <= hint; pair++) { + if (SP_PARM->_color_pairs[pair].mode == cpFREE) { + T(("found gap %d", pair)); + found = TRUE; + break; + } + } + } + if (found) { + SP_PARM->_recent_pair = pair; + } else { + pair = ERR; + } + } else { + /* reuse the oldest one */ + pair = SP_PARM->_color_pairs[0].prev; + T(("reusing %d", pair)); + } + + if (_nc_init_pair(SP_PARM, pair, fg, bg) == ERR) + pair = ERR; + } + returnCode(pair); +} + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(find_pair) (NCURSES_SP_DCLx int fg, int bg) +{ + int pair; + + T((T_CALLED("find_pair(%d,%d)"), fg, bg)); + pair = _nc_find_color_pair(SP_PARM, fg, bg); + returnCode(pair); +} + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(free_pair) (NCURSES_SP_DCLx int pair) +{ + int result = ERR; + T((T_CALLED("free_pair(%d)"), pair)); + if (ValidPair(SP_PARM, pair) && pair < SP_PARM->_pair_alloc) { + colorpair_t *cp = &(SP_PARM->_color_pairs[pair]); + if (pair != 0) { + _nc_change_pair(SP_PARM, pair); + delink_color_pair(SP_PARM, pair); + tdelete(cp, &SP_PARM->_ordered_pairs, compare_data); + cp->mode = cpFREE; + result = OK; + SP_PARM->_pairs_used--; + } + } + returnCode(result); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +alloc_pair(int f, int b) +{ + return NCURSES_SP_NAME(alloc_pair) (CURRENT_SCREEN, f, b); +} + +NCURSES_EXPORT(int) +find_pair(int f, int b) +{ + return NCURSES_SP_NAME(find_pair) (CURRENT_SCREEN, f, b); +} + +NCURSES_EXPORT(int) +free_pair(int pair) +{ + return NCURSES_SP_NAME(free_pair) (CURRENT_SCREEN, pair); +} +#endif + +#if NO_LEAKS +NCURSES_EXPORT(void) +_nc_new_pair_leaks(SCREEN *sp) +{ + if (sp->_color_pairs) { + while (sp->_color_pairs[0].next) { + free_pair(sp->_color_pairs[0].next); + } + } +} +#endif + +#else +void _nc_new_pair(void); +void +_nc_new_pair(void) +{ +} +#endif /* NCURSES_EXT_COLORS */ diff --git a/lib/libcurses/base/resizeterm.c b/lib/libcurses/base/resizeterm.c index ac84a951b0d..f6c0c1f866b 100644 --- a/lib/libcurses/base/resizeterm.c +++ b/lib/libcurses/base/resizeterm.c @@ -1,7 +1,8 @@ -/* $OpenBSD: resizeterm.c,v 1.4 2021/03/10 20:16:08 millert Exp $ */ +/* $OpenBSD: resizeterm.c,v 1.5 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2015,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -30,6 +31,7 @@ /**************************************************************************** * Author: Thomas E. Dickey * + * and: Juergen Pfeifer * ****************************************************************************/ /* @@ -41,11 +43,12 @@ */ #include -#include -MODULE_ID("$Id: resizeterm.c,v 1.4 2021/03/10 20:16:08 millert Exp $") +#ifndef CUR +#define CUR SP_TERMTYPE +#endif -#define stolen_lines (screen_lines - SP->_lines_avail) +MODULE_ID("$Id: resizeterm.c,v 1.5 2023/10/17 09:52:09 nicm Exp $") /* * If we're trying to be reentrant, do not want any local statics. @@ -62,22 +65,33 @@ static int current_cols; #define EXTRA_DCLS /* nothing */ #endif +#if NCURSES_SP_FUNCS && !defined(USE_SP_WINDOWLIST) +#define UNUSED_SP (void) sp +#else +#define UNUSED_SP /* nothing */ +#endif + #ifdef TRACE static void show_window_sizes(const char *name) { + SCREEN *sp; WINDOWLIST *wp; _nc_lock_global(curses); - _tracef("%s resizing: %2d x %2d (%2d x %2d)", name, LINES, COLS, - screen_lines, screen_columns); - for (each_window(wp)) { - _tracef(" window %p is %2ld x %2ld at %2ld,%2ld", - &(wp->win), - (long) wp->win._maxy + 1, - (long) wp->win._maxx + 1, - (long) wp->win._begy, - (long) wp->win._begx); + for (each_screen(sp)) { + _tracef("%s resizing: %p: %2d x %2d (%2d x %2d)", name, (void *) sp, + *(ptrLines(sp)), + *(ptrCols(sp)), + screen_lines(sp), screen_columns(sp)); + for (each_window(sp, wp)) { + _tracef(" window %p is %2ld x %2ld at %2ld,%2ld", + (void *) &(wp->win), + (long) wp->win._maxy + 1, + (long) wp->win._maxx + 1, + (long) wp->win._begy, + (long) wp->win._begx); + } } _nc_unlock_global(curses); } @@ -88,15 +102,23 @@ show_window_sizes(const char *name) * structure's size. */ NCURSES_EXPORT(bool) -is_term_resized(int ToLines, int ToCols) +NCURSES_SP_NAME(is_term_resized) (NCURSES_SP_DCLx int ToLines, int ToCols) { - T((T_CALLED("is_term_resized(%d, %d)"), ToLines, ToCols)); + T((T_CALLED("is_term_resized(%p, %d, %d)"), (void *) SP_PARM, ToLines, ToCols)); returnCode(ToLines > 0 && ToCols > 0 - && (ToLines != screen_lines - || ToCols != screen_columns)); + && (ToLines != screen_lines(SP_PARM) + || ToCols != screen_columns(SP_PARM))); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(bool) +is_term_resized(int ToLines, int ToCols) +{ + return NCURSES_SP_NAME(is_term_resized) (CURRENT_SCREEN, ToLines, ToCols); +} +#endif + /* */ static ripoff_t * @@ -106,6 +128,9 @@ ripped_window(WINDOW *win) ripoff_t *rop; if (win != 0) { +#ifdef USE_SP_RIPOFF + SCREEN *sp = _nc_screen_of(win); +#endif for (each_ripoff(rop)) { if (rop->win == win && rop->line != 0) { result = rop; @@ -124,9 +149,13 @@ static int ripped_bottom(WINDOW *win) { int result = 0; - ripoff_t *rop; if (win != 0) { + ripoff_t *rop; + +#ifdef USE_SP_RIPOFF + SCREEN *sp = _nc_screen_of(win); +#endif for (each_ripoff(rop)) { if (rop->line < 0) { result -= rop->line; @@ -148,9 +177,12 @@ child_depth(WINDOW *cmp) int depth = 0; if (cmp != 0) { +#ifdef USE_SP_WINDOWLIST + SCREEN *sp = _nc_screen_of(cmp); +#endif WINDOWLIST *wp; - for (each_window(wp)) { + for (each_window(sp, wp)) { WINDOW *tst = &(wp->win); if (tst->_parent == cmp) { depth = 1 + child_depth(tst); @@ -180,19 +212,19 @@ parent_depth(WINDOW *cmp) } /* - * FIXME: must adjust position so it's within the parent! + * FIXME: must adjust position so it is within the parent! */ static int adjust_window(WINDOW *win, int ToLines, int ToCols, int stolen EXTRA_DCLS) { int result; - int bottom = CurLines + SP->_topstolen - stolen; + int bottom = CurLines + _nc_screen_of(win)->_topstolen - stolen; int myLines = win->_maxy + 1; int myCols = win->_maxx + 1; ripoff_t *rop = ripped_window(win); T((T_CALLED("adjust_window(%p,%d,%d)%s depth %d/%d currently %ldx%ld at %ld,%ld"), - win, ToLines, ToCols, + (void *) win, ToLines, ToCols, (rop != 0) ? " (rip)" : "", parent_depth(win), child_depth(win), @@ -204,13 +236,19 @@ adjust_window(WINDOW *win, int ToLines, int ToCols, int stolen EXTRA_DCLS) * If it is a ripped-off window at the bottom of the screen, simply * move it to the same relative position. */ - win->_begy = ToLines - ripped_bottom(win) - 0 - win->_yoffset; + win->_begy = (NCURSES_SIZE_T) (ToLines - ripped_bottom(win) - 0 - win->_yoffset); + if (rop->hook == _nc_slk_initialize) + _nc_format_slks( +#if NCURSES_SP_FUNCS + _nc_screen_of(win), +#endif + ToCols); } else if (win->_begy >= bottom) { /* * If it is below the bottom of the new screen, move up by the same * amount that the screen shrank. */ - win->_begy += (ToLines - CurLines); + win->_begy = (NCURSES_SIZE_T) (win->_begy + (ToLines - CurLines)); } else { if (myLines == (CurLines - stolen) && ToLines != CurLines) { @@ -241,22 +279,23 @@ adjust_window(WINDOW *win, int ToLines, int ToCols, int stolen EXTRA_DCLS) * children, decrease those to fit, then decrease the containing window, etc. */ static int -decrease_size(int ToLines, int ToCols, int stolen EXTRA_DCLS) +decrease_size(NCURSES_SP_DCLx int ToLines, int ToCols, int stolen EXTRA_DCLS) { bool found; int depth = 0; WINDOWLIST *wp; - T((T_CALLED("decrease_size(%d, %d)"), ToLines, ToCols)); + T((T_CALLED("decrease_size(%p, %d, %d)"), (void *) SP_PARM, ToLines, ToCols)); + UNUSED_SP; do { found = FALSE; TR(TRACE_UPDATE, ("decreasing size of windows to %dx%d, depth=%d", ToLines, ToCols, depth)); - for (each_window(wp)) { + for (each_window(SP_PARM, wp)) { WINDOW *win = &(wp->win); - if (!(win->_flags & _ISPAD)) { + if (!IS_PAD(win)) { if (child_depth(win) == depth) { found = TRUE; if (adjust_window(win, ToLines, ToCols, @@ -275,22 +314,23 @@ decrease_size(int ToLines, int ToCols, int stolen EXTRA_DCLS) * parent, increase those to fit, then increase the contained window, etc. */ static int -increase_size(int ToLines, int ToCols, int stolen EXTRA_DCLS) +increase_size(NCURSES_SP_DCLx int ToLines, int ToCols, int stolen EXTRA_DCLS) { bool found; int depth = 0; WINDOWLIST *wp; - T((T_CALLED("increase_size(%d, %d)"), ToLines, ToCols)); + T((T_CALLED("increase_size(%p, %d, %d)"), (void *) SP_PARM, ToLines, ToCols)); + UNUSED_SP; do { found = FALSE; TR(TRACE_UPDATE, ("increasing size of windows to %dx%d, depth=%d", ToLines, ToCols, depth)); - for (each_window(wp)) { + for (each_window(SP_PARM, wp)) { WINDOW *win = &(wp->win); - if (!(win->_flags & _ISPAD)) { + if (!IS_PAD(win)) { if (parent_depth(win) == depth) { found = TRUE; if (adjust_window(win, ToLines, ToCols, @@ -309,25 +349,26 @@ increase_size(int ToLines, int ToCols, int stolen EXTRA_DCLS) * such as ungetch(). */ NCURSES_EXPORT(int) -resize_term(int ToLines, int ToCols) +NCURSES_SP_NAME(resize_term) (NCURSES_SP_DCLx int ToLines, int ToCols) { int result = OK EXTRA_ARGS; int was_stolen; - T((T_CALLED("resize_term(%d,%d) old(%d,%d)"), - ToLines, ToCols, - screen_lines, screen_columns)); + T((T_CALLED("resize_term(%p,%d,%d) old(%d,%d)"), + (void *) SP_PARM, ToLines, ToCols, + (SP_PARM == 0) ? -1 : screen_lines(SP_PARM), + (SP_PARM == 0) ? -1 : screen_columns(SP_PARM))); - if (SP == 0) { + if (SP_PARM == 0 || ToLines <= 0 || ToCols <= 0) { returnCode(ERR); } - _nc_lock_global(curses); + _nc_nonsp_lock_global(curses); - was_stolen = (screen_lines - SP->_lines_avail); - if (is_term_resized(ToLines, ToCols)) { - int myLines = CurLines = screen_lines; - int myCols = CurCols = screen_columns; + was_stolen = (screen_lines(SP_PARM) - SP_PARM->_lines_avail); + if (NCURSES_SP_NAME(is_term_resized) (NCURSES_SP_ARGx ToLines, ToCols)) { + int myLines = CurLines = screen_lines(SP_PARM); + int myCols = CurCols = screen_columns(SP_PARM); #ifdef TRACE if (USE_TRACEF(TRACE_UPDATE)) { @@ -335,56 +376,90 @@ resize_term(int ToLines, int ToCols) _nc_unlock_global(tracef); } #endif - if (ToLines > screen_lines) { - increase_size(myLines = ToLines, myCols, was_stolen EXTRA_ARGS); + if (ToLines > screen_lines(SP_PARM)) { + result = increase_size(NCURSES_SP_ARGx + myLines = ToLines, + myCols, + was_stolen EXTRA_ARGS); CurLines = myLines; CurCols = myCols; } - if (ToCols > screen_columns) { - increase_size(myLines, myCols = ToCols, was_stolen EXTRA_ARGS); + if ((result == OK) + && (ToCols > screen_columns(SP_PARM))) { + result = increase_size(NCURSES_SP_ARGx + myLines, + myCols = ToCols, + was_stolen EXTRA_ARGS); CurLines = myLines; CurCols = myCols; } - if (ToLines < myLines || - ToCols < myCols) { - decrease_size(ToLines, ToCols, was_stolen EXTRA_ARGS); + if ((result == OK) + && (ToLines < myLines || + ToCols < myCols)) { + result = decrease_size(NCURSES_SP_ARGx + ToLines, + ToCols, + was_stolen EXTRA_ARGS); } - screen_lines = lines = ToLines; - screen_columns = columns = ToCols; + if (result == OK) { + screen_lines(SP_PARM) = (NCURSES_SIZE_T) ToLines; + screen_columns(SP_PARM) = (NCURSES_SIZE_T) ToCols; + +#ifdef USE_TERM_DRIVER + CallDriver_2(SP_PARM, td_setsize, ToLines, ToCols); +#else + lines = (NCURSES_SIZE_T) ToLines; + columns = (NCURSES_SIZE_T) ToCols; +#endif - SP->_lines_avail = lines - was_stolen; + SP_PARM->_lines_avail = (NCURSES_SIZE_T) (ToLines - was_stolen); - if (SP->oldhash) { - FreeAndNull(SP->oldhash); - } - if (SP->newhash) { - FreeAndNull(SP->newhash); - } + if (SP_PARM->oldhash) { + FreeAndNull(SP_PARM->oldhash); + } + if (SP_PARM->newhash) { + FreeAndNull(SP_PARM->newhash); + } #ifdef TRACE - if (USE_TRACEF(TRACE_UPDATE)) { - SET_LINES(ToLines - was_stolen); - SET_COLS(ToCols); - show_window_sizes("after"); - _nc_unlock_global(tracef); - } + if (USE_TRACEF(TRACE_UPDATE)) { + SET_LINES(ToLines - was_stolen); + SET_COLS(ToCols); + show_window_sizes("after"); + _nc_unlock_global(tracef); + } #endif + } } - /* - * Always update LINES, to allow for call from lib_doupdate.c which - * needs to have the count adjusted by the stolen (ripped off) lines. - */ - SET_LINES(ToLines - was_stolen); - SET_COLS(ToCols); + if (result == OK) { + /* + * Always update LINES, to allow for call from lib_doupdate.c which + * needs to have the count adjusted by the stolen (ripped off) lines. + */ + SET_LINES(ToLines - was_stolen); + SET_COLS(ToCols); + } - _nc_unlock_global(curses); + _nc_nonsp_unlock_global(curses); returnCode(result); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +resize_term(int ToLines, int ToCols) +{ + int res; + _nc_sp_lock_global(curses); + res = NCURSES_SP_NAME(resize_term) (CURRENT_SCREEN, ToLines, ToCols); + _nc_sp_unlock_global(curses); + return (res); +} +#endif + /* * This function reallocates NCURSES window structures. It is invoked in * response to a SIGWINCH interrupt. Other user-defined windows may also need @@ -394,33 +469,34 @@ resize_term(int ToLines, int ToCols) * invoked directly from the signal handler. */ NCURSES_EXPORT(int) -resizeterm(int ToLines, int ToCols) +NCURSES_SP_NAME(resizeterm) (NCURSES_SP_DCLx int ToLines, int ToCols) { int result = ERR; - T((T_CALLED("resizeterm(%d,%d) old(%d,%d)"), - ToLines, ToCols, - screen_lines, screen_columns)); + T((T_CALLED("resizeterm(%p, %d,%d) old(%d,%d)"), + (void *) SP_PARM, ToLines, ToCols, + (SP_PARM == 0) ? -1 : screen_lines(SP_PARM), + (SP_PARM == 0) ? -1 : screen_columns(SP_PARM))); - if (SP != 0) { + if (SP_PARM != 0 && ToLines > 0 && ToCols > 0) { result = OK; - SP->_sig_winch = FALSE; + SP_PARM->_sig_winch = FALSE; - if (is_term_resized(ToLines, ToCols)) { + if (NCURSES_SP_NAME(is_term_resized) (NCURSES_SP_ARGx ToLines, ToCols)) { #if USE_SIGWINCH ripoff_t *rop; - bool slk_visible = (SP != 0 - && SP->_slk != 0 - && !(SP->_slk->hidden)); + bool slk_visible = (SP_PARM != 0 + && SP_PARM->_slk != 0 + && !(SP_PARM->_slk->hidden)); if (slk_visible) { slk_clear(); } #endif - result = resize_term(ToLines, ToCols); + result = NCURSES_SP_NAME(resize_term) (NCURSES_SP_ARGx ToLines, ToCols); #if USE_SIGWINCH - clearok(curscr, TRUE); /* screen contents are unknown */ + clearok(CurScreen(SP_PARM), TRUE); /* screen contents are unknown */ /* ripped-off lines are a special case: if we did not lengthen * them, we haven't moved them either. repaint them, too. @@ -430,7 +506,7 @@ resizeterm(int ToLines, int ToCols) * not know which are really on top. */ for (each_ripoff(rop)) { - if (rop->win != stdscr + if (rop->win != StdScreen(SP_PARM) && rop->win != 0 && rop->line < 0) { @@ -443,17 +519,24 @@ resizeterm(int ToLines, int ToCols) /* soft-keys are a special case: we _know_ how to repaint them */ if (slk_visible) { - slk_restore(); - slk_touch(); - - slk_refresh(); + NCURSES_SP_NAME(slk_restore) (NCURSES_SP_ARG); + NCURSES_SP_NAME(slk_touch) (NCURSES_SP_ARG); + NCURSES_SP_NAME(slk_refresh) (NCURSES_SP_ARG); } #endif } #if USE_SIGWINCH - _nc_ungetch(SP, KEY_RESIZE); /* so application can know this */ + safe_ungetch(SP_PARM, KEY_RESIZE); /* so application can know this */ #endif } returnCode(result); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +resizeterm(int ToLines, int ToCols) +{ + return NCURSES_SP_NAME(resizeterm) (CURRENT_SCREEN, ToLines, ToCols); +} +#endif diff --git a/lib/libcurses/base/safe_sprintf.c b/lib/libcurses/base/safe_sprintf.c index 0bc79c0c088..a7b8a39fd05 100644 --- a/lib/libcurses/base/safe_sprintf.c +++ b/lib/libcurses/base/safe_sprintf.c @@ -1,7 +1,8 @@ -/* $OpenBSD: safe_sprintf.c,v 1.6 2010/10/18 18:22:35 nicm Exp $ */ +/* $OpenBSD: safe_sprintf.c,v 1.7 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2007 Free Software Foundation, Inc. * + * Copyright 2018-2020,2021 Thomas E. Dickey * + * Copyright 1998-2012,2013 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,13 +30,13 @@ ****************************************************************************/ /**************************************************************************** - * Author: Thomas E. Dickey 1997 * + * Author: Thomas E. Dickey 1997-on * ****************************************************************************/ #include #include -MODULE_ID("$Id: safe_sprintf.c,v 1.6 2010/10/18 18:22:35 nicm Exp $") +MODULE_ID("$Id: safe_sprintf.c,v 1.7 2023/10/17 09:52:09 nicm Exp $") #if USE_SAFE_SPRINTF @@ -43,7 +44,7 @@ typedef enum { Flags, Width, Prec, Type, Format } PRINTF; -#define VA_INTGR(type) ival = va_arg(ap, type) +#define VA_INTGR(type) ival = (int) va_arg(ap, type) #define VA_FLOAT(type) fval = va_arg(ap, type) #define VA_POINT(type) pval = (void *)va_arg(ap, type) @@ -57,7 +58,6 @@ _nc_printf_length(const char *fmt, va_list ap) size_t length = BUFSIZ; char *buffer; char *format; - char *tmp_format; int len = 0; size_t fmt_len; char fmt_arg[BUFSIZ]; @@ -112,15 +112,16 @@ _nc_printf_length(const char *fmt, va_list ap) } else if (state == Prec) { prec = ival; } - sprintf(fmt_arg, "%d", ival); + _nc_SPRINTF(fmt_arg, + _nc_SLIMIT(sizeof(fmt_arg)) + "%d", ival); fmt_len += strlen(fmt_arg); - if ((tmp_format = realloc(format, fmt_len)) == 0) { + if ((format = _nc_doalloc(format, fmt_len)) == 0) { free(buffer); - free(format); return -1; } - format = tmp_format; - strcpy(&format[--f], fmt_arg); + --f; + _nc_STRCPY(&format[f], fmt_arg, fmt_len - f); f = strlen(format); } else if (isalpha(UChar(*fmt))) { done = TRUE; @@ -159,9 +160,9 @@ _nc_printf_length(const char *fmt, va_list ap) case 's': VA_POINT(char *); if (prec < 0) - prec = strlen(pval); + prec = (int) strlen(pval); if (prec > (int) length) { - length = length + prec; + length = length + (size_t) prec; buffer = typeRealloc(char, length, buffer); if (buffer == 0) { free(format); @@ -191,13 +192,13 @@ _nc_printf_length(const char *fmt, va_list ap) format[f] = '\0'; switch (used) { case 'i': - sprintf(buffer, format, ival); + _nc_SPRINTF(buffer, _nc_SLIMIT(length) format, ival); break; case 'f': - sprintf(buffer, format, fval); + _nc_SPRINTF(buffer, _nc_SLIMIT(length) format, fval); break; default: - sprintf(buffer, format, pval); + _nc_SPRINTF(buffer, _nc_SLIMIT(length) format, pval); break; } len += (int) strlen(buffer); @@ -220,19 +221,26 @@ _nc_printf_length(const char *fmt, va_list ap) * Wrapper for vsprintf that allocates a buffer big enough to hold the result. */ NCURSES_EXPORT(char *) -_nc_printf_string(const char *fmt, va_list ap) +NCURSES_SP_NAME(_nc_printf_string) (NCURSES_SP_DCLx + const char *fmt, + va_list ap) { - char *result = 0; + char *result = NULL; - if (fmt != 0) { + if (SP_PARM != NULL && fmt != NULL) { #if USE_SAFE_SPRINTF - int len = _nc_printf_length(fmt, ap); + va_list ap2; + int len; + + begin_va_copy(ap2, ap); + len = _nc_printf_length(fmt, ap2); + end_va_copy(ap2); if ((int) my_length < len + 1) { - my_length = 2 * (len + 1); + my_length = (size_t) (2 * (len + 1)); my_buffer = typeRealloc(char, my_length, my_buffer); } - if (my_buffer != 0) { + if (my_buffer != NULL) { *my_buffer = '\0'; if (len >= 0) { vsprintf(my_buffer, fmt, ap); @@ -243,28 +251,45 @@ _nc_printf_string(const char *fmt, va_list ap) #define MyCols _nc_globals.safeprint_cols #define MyRows _nc_globals.safeprint_rows - if (screen_lines > MyRows || screen_columns > MyCols) { - if (screen_lines > MyRows) - MyRows = screen_lines; - if (screen_columns > MyCols) - MyCols = screen_columns; - my_length = (MyRows * (MyCols + 1)) + 1; + if (screen_lines(SP_PARM) > MyRows || screen_columns(SP_PARM) > MyCols) { + if (screen_lines(SP_PARM) > MyRows) + MyRows = screen_lines(SP_PARM); + if (screen_columns(SP_PARM) > MyCols) + MyCols = screen_columns(SP_PARM); + my_length = (size_t) (MyRows * (MyCols + 1)) + 1; + if (my_length < 80) + my_length = 80; my_buffer = typeRealloc(char, my_length, my_buffer); } - if (my_buffer != 0) { + if (my_buffer != NULL) { # if HAVE_VSNPRINTF - vsnprintf(my_buffer, my_length, fmt, ap); /* GNU extension */ + /* SUSv2, 1997 */ + int used; + while ((used = vsnprintf(my_buffer, my_length, fmt, ap)) + >= (int) my_length) { + my_length = (size_t) ((3 * used) / 2); + my_buffer = typeRealloc(char, my_length, my_buffer); + } # else - vsprintf(my_buffer, fmt, ap); /* ANSI */ + /* ISO/ANSI C, 1989 */ + vsprintf(my_buffer, fmt, ap); # endif result = my_buffer; } #endif - } else if (my_buffer != 0) { /* see _nc_freeall() */ + } else if (my_buffer != NULL) { /* see _nc_freeall() */ free(my_buffer); - my_buffer = 0; + my_buffer = NULL; my_length = 0; } return result; } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(char *) +_nc_printf_string(const char *fmt, va_list ap) +{ + return NCURSES_SP_NAME(_nc_printf_string) (CURRENT_SCREEN, fmt, ap); +} +#endif diff --git a/lib/libcurses/base/sigaction.c b/lib/libcurses/base/sigaction.c new file mode 100644 index 00000000000..148ef930f29 --- /dev/null +++ b/lib/libcurses/base/sigaction.c @@ -0,0 +1,100 @@ +/**************************************************************************** + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2002,2003 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Zeyd M. Ben-Halim 1992,1995 * + * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-2003 * + ****************************************************************************/ + +/* This file provides sigaction() emulation using sigvec() */ +/* Use only if this is non POSIX system */ + +MODULE_ID("$Id: sigaction.c,v 1.6 2023/10/17 09:52:09 nicm Exp $") + +static int +_nc_sigaction(int sig, sigaction_t * sigact, sigaction_t * osigact) +{ + return sigvec(sig, sigact, osigact); +} + +static int +_nc_sigemptyset(sigset_t * mask) +{ + *mask = 0; + return 0; +} + +static int +_nc_sigprocmask(int mode, sigset_t * mask, sigset_t * omask) +{ + sigset_t current = sigsetmask(0); + + if (omask) + *omask = current; + + if (mode == SIG_BLOCK) + current |= *mask; + else if (mode == SIG_UNBLOCK) + current &= ~*mask; + else if (mode == SIG_SETMASK) + current = *mask; + + sigsetmask(current); + return 0; +} + +static int +_nc_sigaddset(sigset_t * mask, int sig) +{ + *mask |= sigmask(sig); + return 0; +} + +/* not used in lib_tstp.c */ +#if 0 +static int +_nc_sigsuspend(sigset_t * mask) +{ + return sigpause(*mask); +} + +static int +_nc_sigdelset(sigset_t * mask, int sig) +{ + *mask &= ~sigmask(sig); + return 0; +} + +static int +_nc_sigismember(sigset_t * mask, int sig) +{ + return (*mask & sigmask(sig)) != 0; +} +#endif diff --git a/lib/libcurses/base/tries.c b/lib/libcurses/base/tries.c index 704498044b0..080c47a19a1 100644 --- a/lib/libcurses/base/tries.c +++ b/lib/libcurses/base/tries.c @@ -1,7 +1,8 @@ -/* $OpenBSD: tries.c,v 1.5 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: tries.c,v 1.6 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020,2023 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -40,8 +41,9 @@ */ #include +#include -MODULE_ID("$Id: tries.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: tries.c,v 1.6 2023/10/17 09:52:09 nicm Exp $") /* * Expand a keycode into the string that it corresponds to, returning null if @@ -74,7 +76,9 @@ _nc_expand_try(TRIES * tree, unsigned code, int *count, size_t len) *((unsigned char *) (result + len)) = 128; #ifdef TRACE if (len == 0 && USE_TRACEF(TRACE_MAXIMUM)) { - _tracef("expand_key %s %s", _nc_tracechar(SP, code), _nc_visbuf(result)); + _tracef("expand_key %s %s", + _nc_tracechar(CURRENT_SCREEN, (int) code), + _nc_visbuf(result)); _nc_unlock_global(tracef); } #endif @@ -89,7 +93,7 @@ _nc_expand_try(TRIES * tree, unsigned code, int *count, size_t len) NCURSES_EXPORT(int) _nc_remove_key(TRIES ** tree, unsigned code) { - T((T_CALLED("_nc_remove_key(%p,%d)"), tree, code)); + T((T_CALLED("_nc_remove_key(%p,%d)"), (void *) tree, code)); if (code == 0) returnCode(FALSE); @@ -121,9 +125,9 @@ _nc_remove_key(TRIES ** tree, unsigned code) NCURSES_EXPORT(int) _nc_remove_string(TRIES ** tree, const char *string) { - T((T_CALLED("_nc_remove_string(%p,%s)"), tree, _nc_visbuf(string))); + T((T_CALLED("_nc_remove_string(%p,%s)"), (void *) tree, _nc_visbuf(string))); - if (string == 0 || *string == 0) + if (!VALID_STRING(string) || *string == 0) returnCode(FALSE); while (*tree != 0) { diff --git a/lib/libcurses/base/use_window.c b/lib/libcurses/base/use_window.c index ead06ec1440..c14bdc34f30 100644 --- a/lib/libcurses/base/use_window.c +++ b/lib/libcurses/base/use_window.c @@ -1,7 +1,8 @@ -/* $OpenBSD: use_window.c,v 1.1 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: use_window.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2007,2008 Free Software Foundation, Inc. * + * Copyright 2018,2020 Thomas E. Dickey * + * Copyright 2007-2009,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -34,14 +35,19 @@ #include -MODULE_ID("$Id: use_window.c,v 1.1 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: use_window.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) use_window(WINDOW *win, NCURSES_WINDOW_CB func, void *data) { int code = OK; + TR_FUNC_BFR(1); + + T((T_CALLED("use_window(%p,%s,%p)"), + (void *) win, + TR_FUNC_ARG(0, func), + data)); - T((T_CALLED("use_window(%p,%p,%p)"), win, func, data)); _nc_lock_global(curses); code = func(win, data); _nc_unlock_global(curses); diff --git a/lib/libcurses/base/version.c b/lib/libcurses/base/version.c index 7387797accf..842461b38e4 100644 --- a/lib/libcurses/base/version.c +++ b/lib/libcurses/base/version.c @@ -1,7 +1,8 @@ -/* $OpenBSD: version.c,v 1.5 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: version.c,v 1.6 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1999-2004,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1999-2004,2005 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -34,7 +35,7 @@ #include -MODULE_ID("$Id: version.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: version.c,v 1.6 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(const char *) curses_version(void) diff --git a/lib/libcurses/base/vsscanf.c b/lib/libcurses/base/vsscanf.c index de14ffa4252..77b7aa97edf 100644 --- a/lib/libcurses/base/vsscanf.c +++ b/lib/libcurses/base/vsscanf.c @@ -1,7 +1,8 @@ -/* $OpenBSD: vsscanf.c,v 1.2 2015/09/27 05:25:00 guenther Exp $ */ +/* $OpenBSD: vsscanf.c,v 1.3 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2004,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -40,7 +41,7 @@ #if !HAVE_VSSCANF -MODULE_ID("$Id: vsscanf.c,v 1.2 2015/09/27 05:25:00 guenther Exp $") +MODULE_ID("$Id: vsscanf.c,v 1.3 2023/10/17 09:52:09 nicm Exp $") #if !(HAVE_VFSCANF || HAVE__DOSCAN) @@ -161,6 +162,7 @@ other_ch(int ch) } #endif +/*VARARGS2*/ NCURSES_EXPORT(int) vsscanf(const char *str, const char *format, va_list ap) { @@ -294,12 +296,12 @@ vsscanf(const char *str, const char *format, va_list ap) /* add %n, if the format was not that */ if (chunk != cAssigned) { - strlcat(my_fmt, "%n", len_fmt); + _nc_STRCAT(my_fmt, "%n", len_fmt); } switch (chunk) { case cAssigned: - strlcat(my_fmt, "%n", len_fmt); + _nc_STRCAT(my_fmt, "%n", len_fmt); pointer = &eaten; break; case cInt: diff --git a/lib/libcurses/base/wresize.c b/lib/libcurses/base/wresize.c index ef4a91e7150..fbfc3886f34 100644 --- a/lib/libcurses/base/wresize.c +++ b/lib/libcurses/base/wresize.c @@ -1,7 +1,8 @@ -/* $OpenBSD: wresize.c,v 1.5 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: wresize.c,v 1.6 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2019-2020,2021 Thomas E. Dickey * + * Copyright 1998-2010,2011 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,18 +30,19 @@ ****************************************************************************/ /**************************************************************************** - * Author: Thomas E. Dickey 1996-2002 * + * Author: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer * ****************************************************************************/ #include -MODULE_ID("$Id: wresize.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: wresize.c,v 1.6 2023/10/17 09:52:09 nicm Exp $") static int cleanup_lines(struct ldat *data, int length) { while (--length >= 0) - free(data[length].text); + FreeAndNull(data[length].text); free(data); return ERR; } @@ -55,23 +57,40 @@ repair_subwindows(WINDOW *cmp) WINDOWLIST *wp; struct ldat *pline = cmp->_line; int row; +#ifdef USE_SP_WINDOWLIST + SCREEN *sp = _nc_screen_of(cmp); +#endif _nc_lock_global(curses); - for (each_window(wp)) { + for (each_window(SP_PARM, wp)) { WINDOW *tst = &(wp->win); if (tst->_parent == cmp) { - if (tst->_pary > cmp->_maxy) - tst->_pary = cmp->_maxy; - if (tst->_parx > cmp->_maxx) - tst->_parx = cmp->_maxx; +#define REPAIR1(field, limit) \ + if (tst->field > cmp->limit) \ + tst->field = cmp->limit + + REPAIR1(_pary, _maxy); + REPAIR1(_parx, _maxx); + +#define REPAIR2(field, limit) \ + if (tst->limit + tst->field > cmp->limit) \ + tst->limit = (NCURSES_SIZE_T) (cmp->limit - tst->field) + + REPAIR2(_pary, _maxy); + REPAIR2(_parx, _maxx); - if (tst->_maxy + tst->_pary > cmp->_maxy) - tst->_maxy = cmp->_maxy - tst->_pary; - if (tst->_maxx + tst->_parx > cmp->_maxx) - tst->_maxx = cmp->_maxx - tst->_parx; +#define REPAIR3(field, limit) \ + if (tst->field > tst->limit) \ + tst->field = tst->limit + + REPAIR3(_cury, _maxy); + REPAIR3(_curx, _maxx); + + REPAIR3(_regtop, _maxy); + REPAIR3(_regbottom, _maxy); for (row = 0; row <= tst->_maxy; ++row) { tst->_line[row].text = &pline[tst->_pary + row].text[tst->_parx]; @@ -95,7 +114,7 @@ wresize(WINDOW *win, int ToLines, int ToCols) struct ldat *new_lines = 0; #ifdef TRACE - T((T_CALLED("wresize(%p,%d,%d)"), win, ToLines, ToCols)); + T((T_CALLED("wresize(%p,%d,%d)"), (void *) win, ToLines, ToCols)); if (win) { TR(TRACE_UPDATE, ("...beg (%ld, %ld), max(%ld,%ld), reg(%ld,%ld)", (long) win->_begy, (long) win->_begx, @@ -118,7 +137,7 @@ wresize(WINDOW *win, int ToLines, int ToCols) && ToCols == size_x) returnCode(OK); - if ((win->_flags & _SUBWIN)) { + if (IS_SUBWIN(win)) { /* * Check if the new limits will fit into the parent window's size. If * not, do not resize. We could adjust the location of the subwindow, @@ -152,13 +171,22 @@ wresize(WINDOW *win, int ToLines, int ToCols) int end = ToCols; NCURSES_CH_T *s; - if (!(win->_flags & _SUBWIN)) { + if (!IS_SUBWIN(win)) { if (row <= size_y) { if (ToCols != size_x) { - if ((s = typeMalloc(NCURSES_CH_T, ToCols + 1)) == 0) + s = typeMalloc(NCURSES_CH_T, (unsigned) ToCols + 1); + if (s == 0) returnCode(cleanup_lines(new_lines, row)); for (col = 0; col <= ToCols; ++col) { - s[col] = (col <= size_x + bool valid = (col <= size_x); + if_WIDEC({ + if (col == ToCols + && col < size_x + && isWidecBase(win->_line[row].text[col])) { + valid = FALSE; + } + }); + s[col] = (valid ? win->_line[row].text[col] : win->_nc_bkgd); } @@ -166,13 +194,16 @@ wresize(WINDOW *win, int ToLines, int ToCols) s = win->_line[row].text; } } else { - if ((s = typeMalloc(NCURSES_CH_T, ToCols + 1)) == 0) + s = typeMalloc(NCURSES_CH_T, (unsigned) ToCols + 1); + if (s == 0) returnCode(cleanup_lines(new_lines, row)); for (col = 0; col <= ToCols; ++col) s[col] = win->_nc_bkgd; } - } else { + } else if (pline != 0 && pline[win->_pary + row].text != 0) { s = &pline[win->_pary + row].text[win->_parx]; + } else { + s = 0; } if_USE_SCROLL_HINTS(new_lines[row].oldindex = row); @@ -183,11 +214,11 @@ wresize(WINDOW *win, int ToLines, int ToCols) if ((ToCols != size_x) || (row > size_y)) { if (end >= begin) { /* growing */ if (new_lines[row].firstchar < begin) - new_lines[row].firstchar = begin; + new_lines[row].firstchar = (NCURSES_SIZE_T) begin; } else { /* shrinking */ new_lines[row].firstchar = 0; } - new_lines[row].lastchar = ToCols; + new_lines[row].lastchar = (NCURSES_SIZE_T) ToCols; } new_lines[row].text = s; } @@ -198,24 +229,24 @@ wresize(WINDOW *win, int ToLines, int ToCols) if (!(win->_flags & _SUBWIN)) { if (ToCols == size_x) { for (row = ToLines + 1; row <= size_y; row++) { - free(win->_line[row].text); + FreeAndNull(win->_line[row].text); } } else { for (row = 0; row <= size_y; row++) { - free(win->_line[row].text); + FreeAndNull(win->_line[row].text); } } } - free(win->_line); + FreeAndNull(win->_line); win->_line = new_lines; /* * Finally, adjust the parameters showing screen size and cursor * position: */ - win->_maxx = ToCols; - win->_maxy = ToLines; + win->_maxx = (NCURSES_SIZE_T) ToCols; + win->_maxy = (NCURSES_SIZE_T) ToLines; if (win->_regtop > win->_maxy) win->_regtop = win->_maxy; diff --git a/lib/libcurses/build.priv.h b/lib/libcurses/build.priv.h new file mode 100644 index 00000000000..e2deba6a15a --- /dev/null +++ b/lib/libcurses/build.priv.h @@ -0,0 +1,108 @@ +/**************************************************************************** + * Copyright 2019,2020 Thomas E. Dickey * + * Copyright 2010,2012 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey 2010 * + ****************************************************************************/ + +/* + * $Id: build.priv.h,v 1.1 2023/10/17 09:52:08 nicm Exp $ + * + * build.priv.h + * + * This is a reduced version of curses.priv.h, for build-time utilities. + * Because it has fewer dependencies, this simplifies cross-compiling. + * + */ + +#ifndef CURSES_PRIV_H +#define CURSES_PRIV_H 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#if USE_RCS_IDS +#define MODULE_ID(id) static const char Ident[] = id; +#else +#define MODULE_ID(id) /*nothing */ +#endif + +#include +#include +#include + +#include +#include + +#include + +#include /* we'll use -Ipath directive to get the right one! */ + +/* usually in */ +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#endif + +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif + +#define FreeAndNull(p) do { free(p); p = 0; } while (0) +#define UChar(c) ((unsigned char)(c)) +#define SIZEOF(v) (sizeof(v) / sizeof(v[0])) + +#include +#include + +/* declare these, to avoid needing term.h */ +#if BROKEN_LINKER || USE_REENTRANT +#define NCURSES_ARRAY(name) \ + NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, name) + + NCURSES_ARRAY(boolnames); + NCURSES_ARRAY(boolfnames); + NCURSES_ARRAY(numnames); + NCURSES_ARRAY(numfnames); + NCURSES_ARRAY(strnames); + NCURSES_ARRAY(strfnames); +#endif + +#if NO_LEAKS + NCURSES_EXPORT(void) _nc_names_leaks(void); +#endif + +#ifdef __cplusplus +} +#endif +#endif /* CURSES_PRIV_H */ diff --git a/lib/libcurses/capdefaults.c b/lib/libcurses/capdefaults.c index 95c21c7d4a4..12c07ba99a7 100644 --- a/lib/libcurses/capdefaults.c +++ b/lib/libcurses/capdefaults.c @@ -1,7 +1,8 @@ -/* $OpenBSD: capdefaults.c,v 1.3 2010/01/12 23:21:58 nicm Exp $ */ +/* $OpenBSD: capdefaults.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2008 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2000,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -34,11 +35,11 @@ * and: Thomas E. Dickey 1996-on * ****************************************************************************/ -/* $Id: capdefaults.c,v 1.3 2010/01/12 23:21:58 nicm Exp $ */ +/* $Id: capdefaults.c,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /* * Compute obsolete capabilities. The reason this is an include file is - * that the two places where it's needed want the macros to generate + * that the two places where it is needed require the macros to generate * offsets to different structures. See the file Caps for explanations of * these conversions. * @@ -46,11 +47,11 @@ * postprocess_termcap(). */ { - char *sp; + char *strp; short capval; #define EXTRACT_DELAY(str) \ - (short) (sp = strchr(str, '*'), sp ? atoi(sp+1) : 0) + (short) (strp = strchr(str, '*'), strp ? atoi(strp+1) : 0) /* current (4.4BSD) capabilities marked obsolete */ if (VALID_STRING(carriage_return) diff --git a/lib/libcurses/curs_add_wch.3 b/lib/libcurses/curs_add_wch.3 index 61fee35067f..9324ebcd356 100644 --- a/lib/libcurses/curs_add_wch.3 +++ b/lib/libcurses/curs_add_wch.3 @@ -1,6 +1,8 @@ -.\" $OpenBSD: curs_add_wch.3,v 1.1 2010/09/06 17:26:17 nicm Exp $ +'\" t +.\" $OpenBSD: curs_add_wch.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ .\"*************************************************************************** -.\" Copyright (c) 2001-2002,2006 Free Software Foundation, Inc. * +.\" Copyright 2019-2021,2023 Thomas E. Dickey * +.\" Copyright 2001-2015,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -27,17 +29,24 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_add_wch.3,v 1.1 2010/09/06 17:26:17 nicm Exp $ -.TH curs_add_wch 3 "" +.\" $Id: curs_add_wch.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ +.TH curs_add_wch 3 2023-08-19 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .SH NAME \fBadd_wch\fP, \fBwadd_wch\fP, \fBmvadd_wch\fP, \fBmvwadd_wch\fP, \fBecho_wchar\fP, -\fBwecho_wchar\fP - add a complex character and rendition to a \fBcurses\fR window, then advance the cursor +\fBwecho_wchar\fP \- add a complex character and rendition to a \fBcurses\fP window, then advance the cursor .SH SYNOPSIS -.PP \fB#include \fP .sp .B "int add_wch( const cchar_t *\fIwch\fB );" @@ -47,13 +56,12 @@ .B "int mvadd_wch( int \fIy\fP, int \fIx\fP, const cchar_t *\fIwch\fB );" .br .B "int mvwadd_wch( WINDOW *\fIwin\fP, int \fIy\fP, int \fIx\fP, const cchar_t *\fIwch\fB );" -.br +.sp .B "int echo_wchar( const cchar_t *\fIwch\fB );" .br .B "int wecho_wchar( WINDOW *\fIwin\fP, const cchar_t *\fIwch\fB );" -.br .SH DESCRIPTION -.PP +.SS add_wch The \fBadd_wch\fP, \fBwadd_wch\fP, @@ -64,32 +72,36 @@ window at its current position, which is then advanced. These functions perform wrapping and special-character processing as follows: -.TP 5 -- +.bP If \fIwch\fP refers to a spacing character, then any previous character at that location is removed. A new character specified by \fIwch\fP is placed at that location with rendition specified by \fIwch\fP. -The cursor then advances to -the next spacing character on the screen. -.TP 5 -- +The cursor then advances after this spacing character, +to prepare for writing the next character on the screen. +.IP +The newly added spacing character is the base of the active complex character. +Subsequent non-spacing characters can be combined with this base +until another spacing character is written to the screen, +or the cursor is moved, e.g., using \fBwmove\fP. +.bP If \fIwch\fP refers to a non-spacing character, -all previous characters at that location are preserved. -The non-spacing characters of \fIwch\fP -are added to the spacing complex character, -and the rendition specified by \fIwch\fP is ignored. -.TP 5 -- +it is appended to the active complex character, +retaining the previous characters at that location. +The rendition specified by \fIwch\fP is ignored. +.IP +The cursor is not advanced after adding a non-spacing character. +Subsequent calls to add non-spacing characters will update the same position. +.bP If the character part of \fIwch\fP is a tab, newline, backspace or other control character, -the window is updated and the cursor moves as if \fBaddch\fR were called. -.PP +the window is updated and the cursor moves as if \fBaddch\fP were called. +.SS echo_wchar The \fBecho_wchar\fP function is functionally equivalent to a call to \fBadd_wch\fP followed by a call to -\fBrefresh\fP. +\fBrefresh\fP(3). Similarly, the \fBwecho_wchar\fP is functionally equivalent to a call to @@ -100,11 +112,134 @@ The knowledge that only a single character is being output is taken into consideration and, for non-control characters, a considerable performance gain might be seen by using the *\fBecho\fP* functions instead of their equivalents. -.SH RETURN VALUES +.SS Line Graphics +Like \fBaddch\fP(3), +\fBaddch_wch\fP accepts symbols which make it simple to draw lines and other +frequently used special characters. +These symbols correspond to the same VT100 line-drawing set as +\fBaddch\fP(3). .PP -All routines return the integer \fBERR\fR upon failure and \fBOK\fR on success. -.SH NOTES +.TS +l l l l l +l l l l l +_ _ _ _ _ +lw(1.5i) lw5 lw5 lw5 lw20. +\fBACS\fP \fBUnicode\fP \fBASCII\fP \fBacsc\fP \fBGlyph\fP +\fBName\fP \fBDefault\fP \fBDefault\fP \fBchar\fP \fBName\fP +WACS_BLOCK 0x25ae # 0 solid square block +WACS_BOARD 0x2592 # h board of squares +WACS_BTEE 0x2534 + v bottom tee +WACS_BULLET 0x00b7 o ~ bullet +WACS_CKBOARD 0x2592 : a checker board (stipple) +WACS_DARROW 0x2193 v . arrow pointing down +WACS_DEGREE 0x00b0 ' f degree symbol +WACS_DIAMOND 0x25c6 + ` diamond +WACS_GEQUAL 0x2265 > > greater-than-or-equal-to +WACS_HLINE 0x2500 \- q horizontal line +WACS_LANTERN 0x2603 # i lantern symbol +WACS_LARROW 0x2190 < , arrow pointing left +WACS_LEQUAL 0x2264 < y less-than-or-equal-to +WACS_LLCORNER 0x2514 + m lower left-hand corner +WACS_LRCORNER 0x2518 + j lower right-hand corner +WACS_LTEE 0x2524 + t left tee +WACS_NEQUAL 0x2260 ! | not-equal +WACS_PI 0x03c0 * { greek pi +WACS_PLMINUS 0x00b1 # g plus/minus +WACS_PLUS 0x253c + n plus +WACS_RARROW 0x2192 > + arrow pointing right +WACS_RTEE 0x251c + u right tee +WACS_S1 0x23ba \- o scan line 1 +WACS_S3 0x23bb \- p scan line 3 +WACS_S7 0x23bc \- r scan line 7 +WACS_S9 0x23bd \&_ s scan line 9 +WACS_STERLING 0x00a3 f } pound-sterling symbol +WACS_TTEE 0x252c + w top tee +WACS_UARROW 0x2191 ^ \- arrow pointing up +WACS_ULCORNER 0x250c + l upper left-hand corner +WACS_URCORNER 0x2510 + k upper right-hand corner +WACS_VLINE 0x2502 | x vertical line +.TE +.PP +The wide-character configuration of ncurses also defines symbols +for thick lines (\fBacsc\fP \*(``J\*('' to \*(``V\*(''): +.PP +.TS +l l l l l +l l l l l +_ _ _ _ _ +lw(1.5i) lw5 lw5 lw5 lw20. +\fBACS\fP \fBUnicode\fP \fBASCII\fP \fBacsc\fP \fBGlyph\fP +\fBName\fP \fBDefault\fP \fBDefault\fP \fBchar\fP \fBName\fP +WACS_T_BTEE 0x253b + V thick tee pointing up +WACS_T_HLINE 0x2501 - Q thick horizontal line +WACS_T_LLCORNER 0x2517 + M thick lower left corner +WACS_T_LRCORNER 0x251b + J thick lower right corner +WACS_T_LTEE 0x252b + T thick tee pointing right +WACS_T_PLUS 0x254b + N thick large plus +WACS_T_RTEE 0x2523 + U thick tee pointing left +WACS_T_TTEE 0x2533 + W thick tee pointing down +WACS_T_ULCORNER 0x250f + L thick upper left corner +WACS_T_URCORNER 0x2513 + K thick upper right corner +WACS_T_VLINE 0x2503 | X thick vertical line +.TE +.PP +and for double-lines (\fBacsc\fP \*(``A\*('' to \*(``I\*(''): .PP +.TS +l l l l l +l l l l l +_ _ _ _ _ +lw(1.5i) lw5 lw5 lw5 lw20. +\fBACS\fP \fBUnicode\fP \fBASCII\fP \fBacsc\fP \fBGlyph\fP +\fBName\fP \fBDefault\fP \fBDefault\fP \fBchar\fP \fBName\fP +WACS_D_BTEE 0x2569 + H double tee pointing up +WACS_D_HLINE 0x2550 - R double horizontal line +WACS_D_LLCORNER 0x255a + D double lower left corner +WACS_D_LRCORNER 0x255d + A double lower right corner +WACS_D_LTEE 0x2560 + F double tee pointing right +WACS_D_PLUS 0x256c + E double large plus +WACS_D_RTEE 0x2563 + G double tee pointing left +WACS_D_TTEE 0x2566 + I double tee pointing down +WACS_D_ULCORNER 0x2554 + C double upper left corner +WACS_D_URCORNER 0x2557 + B double upper right corner +WACS_D_VLINE 0x2551 | Y double vertical line +.TE +.PP +Unicode's descriptions for these characters differs slightly from ncurses, +by introducing the term \*(``light\*('' (along with less important details). +Here are its descriptions for the normal, thick, and double horizontal lines: +.bP +U+2500 BOX DRAWINGS LIGHT HORIZONTAL +.bP +U+2501 BOX DRAWINGS HEAVY HORIZONTAL +.bP +U+2550 BOX DRAWINGS DOUBLE HORIZONTAL +.SH RETURN VALUE +All routines return the integer \fBERR\fP upon failure and \fBOK\fP on success. +.PP +X/Open does not define any error conditions. +This implementation returns an error +.bP +if the window pointer is null or +.bP +if it is not possible to add a complete character in the window. +.PP +The latter may be due to different causes: +.bP +If \fBscrollok\fP(3) is not enabled, +writing a character at the lower right margin succeeds. +However, an error is returned because +it is not possible to wrap to a new line +.bP +If an error is detected when converting a multibyte character to a sequence +of bytes, +or if it is not possible to add all of the resulting bytes in the window, +an error is returned. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. +.SH NOTES Note that \fBadd_wch\fP, \fBmvadd_wch\fP, @@ -112,25 +247,111 @@ Note that \fBecho_wchar\fP may be macros. .SH PORTABILITY +All of these functions are described in the XSI Curses standard, Issue 4. +The defaults specified for line-drawing characters apply in the POSIX locale. +.SS WACS Symbols +X/Open Curses makes it clear that the WACS_ symbols should be defined as +a pointer to \fBcchar_t\fP data, e.g., in the discussion of \fBborder_set\fP. +A few implementations are problematic: +.bP +NetBSD curses defines the symbols as a \fBwchar_t\fP within a \fBcchar_t\fP. +.bP +HPUX curses equates some of the \fBACS_\fP symbols +to the analogous \fBWACS_\fP symbols as if the \fBACS_\fP symbols were +wide characters. +The misdefined symbols are the arrows +and other symbols which are not used for line-drawing. .PP -All these functions are described in the XSI Curses standard, Issue 4. -The defaults specified for forms-drawing characters apply in the POSIX locale. +X/Open Curses does not define symbols for thick- or double-lines. +SVr4 curses implementations defined their line-drawing symbols in +terms of intermediate symbols. +This implementation extends those symbols, providing new definitions +which are not in the SVr4 implementations. .PP -XSI documents constants beginning with \fBWACS_\fP which are used for -line-drawing. -Those are not currently implemented in \fBncurses\fP. -.SH SEE ALSO +Not all Unicode-capable terminals provide support for VT100-style +alternate character sets (i.e., the \fBacsc\fP capability), +with their corresponding line-drawing characters. +X/Open Curses did not address the aspect of integrating Unicode with +line-drawing characters. +Existing implementations of Unix curses (AIX, HPUX, Solaris) +use only the \fBacsc\fP character-mapping to provide this feature. +As a result, those implementations can only use single-byte line-drawing +characters. +Ncurses 5.3 (2002) provided a table of Unicode values to solve these problems. +NetBSD curses incorporated that table in 2010. +.PP +In this implementation, the Unicode values are used instead of the +terminal description's \fBacsc\fP mapping as discussed in ncurses(3) +for the environment variable \fBNCURSES_NO_UTF8_ACS\fP. +In contrast, for the same cases, the line-drawing characters +described in \fBcurs_addch\fP(3) will use only the ASCII default values. +.PP +Having Unicode available does not solve all of the problems with +line-drawing for curses: +.bP +The closest Unicode equivalents to the +VT100 graphics \fIS1\fP, \fIS3\fP, \fIS7\fP and \fIS9\fP +frequently are not displayed at +the regular intervals which the terminal used. +.bP +The \fIlantern\fP is a special case. +It originated with the AT&T 4410 terminal in the early 1980s. +There is no accessible documentation depicting the lantern symbol +on the AT&T terminal. +.IP +Lacking documentation, most readers assume that a \fIstorm lantern\fP +was intended. +But there are several possibilities, all with problems. +.IP +Unicode 6.0 (2010) does provide two lantern symbols: U+1F383 and U+1F3EE. +Those were not available in 2002, and are irrelevant since +they lie outside the BMP and as a result are not generally available +in terminals. +They are not storm lanterns, in any case. +.IP +Most \fIstorm lanterns\fP have a tapering glass chimney +(to guard against tipping); +some have a wire grid protecting the chimney. +.IP +For the tapering appearance, \[u2603] U+2603 was adequate. +In use on a terminal, no one can tell what the image represents. +Unicode calls it a snowman. +.IP +Others have suggested these alternatives: +\[sc] U+00A7 (section mark), +\[u0398] U+0398 (theta), +\[u03A6] U+03A6 (phi), +\[u03B4] U+03B4 (delta), +\[u2327] U+2327 (x in a rectangle), +\[u256C] U+256C (forms double vertical and horizontal), and +\[u2612] U+2612 (ballot box with x). +.SS Complex Characters +The complex character type \fBcchar_t\fR +can store more than one wide character (\fBwchar_t\fR). +The X/Open Curses description does not mention this possibility, +describing only the cases where \fIwch\fP is a spacing character +or a non-spacing character. .PP -\fBcurses\fR(3), -\fBcurs_addch\fR(3), -\fBcurs_attr\fR(3), -\fBcurs_clear\fR(3), -\fBcurs_outopts\fR(3), -\fBcurs_refresh\fR(3), -\fBputwc\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +This implementation assumes that \fIwch\fP is constructed using +\fBsetcchar\fP(3), and in turn that the result +.bP +contains at most one spacing character in the beginning of its list of wide +characters, +and zero or more non-spacing characters +or +.bP +may hold one non-spacing character. +.PP +In the latter case, ncurses adds the non-spacing character to the active +(base) spacing character. +.SH SEE ALSO +.na +.hy 0 +\fBcurses\fP(3), +\fBcurs_addch\fP(3), +\fBcurs_attr\fP(3), +\fBcurs_clear\fP(3), +\fBcurs_getcchar\fP(3), +\fBcurs_outopts\fP(3), +\fBcurs_refresh\fP(3), +\fBputwc\fP(3) diff --git a/lib/libcurses/curs_add_wchstr.3 b/lib/libcurses/curs_add_wchstr.3 index ab7eb5af3ec..6b4ea771401 100644 --- a/lib/libcurses/curs_add_wchstr.3 +++ b/lib/libcurses/curs_add_wchstr.3 @@ -1,6 +1,7 @@ -.\" $OpenBSD: curs_add_wchstr.3,v 1.1 2010/09/06 17:26:17 nicm Exp $ +.\" $OpenBSD: curs_add_wchstr.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ .\"*************************************************************************** -.\" Copyright (c) 2002-2004,2005 Free Software Foundation, Inc. * +.\" Copyright 2019-2021,2022 Thomas E. Dickey * +.\" Copyright 2002-2012,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -27,72 +28,97 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_add_wchstr.3,v 1.1 2010/09/06 17:26:17 nicm Exp $ -.TH curs_add_wchstr 3 "" +.\" $Id: curs_add_wchstr.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ +.TH curs_add_wchstr 3 2022-02-12 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.na +.hy 0 .SH NAME -\fBadd_wchstr\fR, -\fBadd_wchnstr\fR, -\fBwadd_wchstr\fR, -\fBwadd_wchnstr\fR, -\fBmvadd_wchstr\fR, -\fBmvadd_wchnstr\fR, -\fBmvwadd_wchstr\fR, -\fBmvwadd_wchnstr\fR \- add an array of complex characters (and attributes) to a curses window +\fBadd_wchstr\fP, +\fBadd_wchnstr\fP, +\fBwadd_wchstr\fP, +\fBwadd_wchnstr\fP, +\fBmvadd_wchstr\fP, +\fBmvadd_wchnstr\fP, +\fBmvwadd_wchstr\fP, +\fBmvwadd_wchnstr\fP \- add an array of complex characters (and attributes) to a curses window +.ad +.hy .SH SYNOPSIS -.B #include -.PP .nf -\fBint add_wchstr(const cchar_t *\fR\fIwchstr\fR\fB);\fR -.br -\fBint add_wchnstr(const cchar_t *\fR\fIwchstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fB#include \fP +.PP +\fBint add_wchstr(const cchar_t *\fIwchstr\fB);\fR .br -\fBint wadd_wchstr(WINDOW *\fR \fIwin\fR\fB, const cchar_t *\fR\fIwchstr\fR\fB);\fR +\fBint add_wchnstr(const cchar_t *\fIwchstr\fB, int \fIn\fB);\fR .br -\fBint wadd_wchnstr(WINDOW *\fR \fIwin\fR\fB, const cchar_t *\fR\fIwchstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint wadd_wchstr(WINDOW *\fR \fIwin\fB, const cchar_t *\fIwchstr\fB);\fR .br -\fBint mvadd_wchstr(int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, const cchar_t *\fR\fIwchstr\fR\fB);\fR +\fBint wadd_wchnstr(WINDOW *\fR \fIwin\fB, const cchar_t *\fIwchstr\fB, int \fIn\fB);\fR +.sp +\fBint mvadd_wchstr(int \fIy\fB, int \fIx\fB, const cchar_t *\fIwchstr\fB);\fR .br -\fBint mvadd_wchnstr(int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, const cchar_t *\fR\fIwchstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint mvadd_wchnstr(int \fIy\fB, int \fIx\fB, const cchar_t *\fIwchstr\fB, int \fIn\fB);\fR .br -\fBint mvwadd_wchstr(WINDOW *\fR\fIwin\fR\fB, int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, const cchar_t *\fR\fIwchstr\fR\fB);\fR +\fBint mvwadd_wchstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, const cchar_t *\fIwchstr\fB);\fR .br -\fBint mvwadd_wchnstr(WINDOW *\fR\fIwin\fR\fB, int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, const cchar_t *\fR\fIwchstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint mvwadd_wchnstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, const cchar_t *\fIwchstr\fB, int \fIn\fB);\fR .fi .SH DESCRIPTION -These routines copy the array of complex characters \fIwchstr\fR -into the window image structure at and after the current cursor position. -The four routines with \fIn\fR as the last -argument copy at most \fIn\fR elements, but no more than will fit on the line. -If \fBn\fR=\fB-1\fR then the whole array is copied, +These functions copy the (null-terminated) +array of complex characters \fIwchstr\fP +into the window image structure +starting at the current cursor position. +The four functions with \fIn\fP as the last +argument copy at most \fIn\fP elements, +but no more than will fit on the line. +If \fBn\fP=\fB\-1\fP then the whole array is copied, to the maximum number of characters that will fit on the line. .PP -The window cursor is \fInot\fR advanced. -These routines work faster than \fBwaddnstr\fR. -On the other hand, they do not perform checking +The window cursor is \fInot\fP advanced. +These functions work faster than \fBwaddnstr\fP. +On the other hand: +.bP +they do not perform checking (such as for the newline, backspace, or carriage return characters), +.bP they do not advance the current cursor position, -they do not expand other control characters to ^-escapes, -and they truncate the string if it crosses the right margin, +.bP +they do not expand other control characters to ^-escapes, and +.bP +they truncate the string if it crosses the right margin, rather than wrapping it around to the new line. .PP -These routines end successfully -on encountering a null \fIcchar_t\fR, or +These functions end successfully +on encountering a null \fBcchar_t\fP, or when they have filled the current line. If a complex character cannot completely fit at the end of the current line, the remaining columns are filled with the background character and rendition. +.SH RETURN VALUE +All functions return the integer \fBERR\fP upon failure and \fBOK\fP on success. +.PP +X/Open does not define any error conditions. +This implementation returns an error +if the window pointer is null. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. .SH NOTES -All functions except \fBwadd_wchnstr\fR may be macros. -.SH RETURN VALUES -All routines return the integer \fBERR\fR upon failure and \fBOK\fR on success. +All functions except \fBwadd_wchnstr\fP may be macros. .SH PORTABILITY -All these entry points are described in the XSI Curses standard, Issue 4. +These entry points are described in the XSI Curses standard, Issue 4. .SH SEE ALSO -\fBcurses\fR(3), -\fBcurs_addchstr\fR(3), -\fBcurs_addwstr\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_addwstr\fP(3). +.PP +Comparable functions in the narrow-character (ncurses) library are +described in +\fBcurs_addchstr\fP(3). diff --git a/lib/libcurses/curs_addch.3 b/lib/libcurses/curs_addch.3 index 5ef9f09ef39..c3a6998012d 100644 --- a/lib/libcurses/curs_addch.3 +++ b/lib/libcurses/curs_addch.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: curs_addch.3,v 1.4 2019/02/13 07:18:57 nicm Exp $ -.\" +.\" $OpenBSD: curs_addch.3,v 1.5 2023/10/17 09:52:08 nicm Exp $ +.\" .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2015,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,119 +30,211 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_addch.3,v 1.4 2019/02/13 07:18:57 nicm Exp $ -.TH curs_addch 3 "" +.\" $Id: curs_addch.3,v 1.5 2023/10/17 09:52:08 nicm Exp $ +.TH curs_addch 3 2023-08-19 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .SH NAME -\fBaddch\fR, \fBwaddch\fR, \fBmvaddch\fR, \fBmvwaddch\fR, -\fBechochar\fR, -\fBwechochar\fR - add a character (with attributes) to a \fBcurses\fR window, then advance the cursor +\fBaddch\fP, +\fBwaddch\fP, +\fBmvaddch\fP, +\fBmvwaddch\fP, +\fBechochar\fP, +\fBwechochar\fP \- add a character (with attributes) to a \fBcurses\fP window, then advance the cursor .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .PP -\fBint addch(const chtype ch);\fR -.br -\fBint waddch(WINDOW *win, const chtype ch);\fR +\fBint addch(const chtype \fIch\fB);\fR .br -\fBint mvaddch(int y, int x, const chtype ch);\fR +\fBint waddch(WINDOW *\fIwin\fB, const chtype \fIch\fB);\fR .br -\fBint mvwaddch(WINDOW *win, int y, int x, const chtype ch);\fR +\fBint mvaddch(int \fIy\fB, int \fIx\fB, const chtype \fIch\fB);\fR .br -\fBint echochar(const chtype ch);\fR +\fBint mvwaddch(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, const chtype \fIch\fB);\fR +.sp +\fBint echochar(const chtype \fIch\fB);\fR .br -\fBint wechochar(WINDOW *win, const chtype ch);\fR +\fBint wechochar(WINDOW *\fIwin\fB, const chtype \fIch\fB);\fR .br .SH DESCRIPTION -The \fBaddch\fR, \fBwaddch\fR, \fBmvaddch\fR and \fBmvwaddch\fR routines put -the character \fIch\fR into the given window at its current window position, -which is then advanced. They are analogous to \fBputchar\fR in \fBstdio\fR(3). -If the advance is at the right margin, the cursor automatically wraps to the -beginning of the next line. At the bottom of the current scrolling region, if -\fBscrollok\fR is enabled, the scrolling region is scrolled up one line. +.SS Adding characters +The \fBaddch\fP, \fBwaddch\fP, \fBmvaddch\fP and \fBmvwaddch\fP routines put +the character \fIch\fP into the given window at its current window position, +which is then advanced. +They are analogous to \fBputchar\fP(3) in \fBstdio\fP(3). +If the advance is at the right margin: +.bP +The cursor automatically wraps to the beginning of the next line. +.bP +At the bottom of the current scrolling region, +and if \fBscrollok\fP(3) is enabled, +the scrolling region is scrolled up one line. +.bP +If \fBscrollok\fP(3) is not enabled, +writing a character at the lower right margin succeeds. +However, an error is returned because +it is not possible to wrap to a new line .PP -If \fIch\fR is a tab, newline, or backspace, -the cursor is moved appropriately within the window. +If \fIch\fP is a tab, newline, carriage return or backspace, +the cursor is moved appropriately within the window: +.bP Backspace moves the cursor one character left; at the left edge of a window it does nothing. -Newline does a \fBclrtoeol\fR, +.bP +Carriage return moves the cursor to the window left margin on the current line. +.bP +Newline does a \fBclrtoeol\fP, then moves the cursor to the window left margin on the next line, scrolling the window if on the last line. +.bP Tabs are considered to be at every eighth column. -The tab interval may be altered by setting the \fBTABSIZE\fR variable. +The tab interval may be altered by setting the \fBTABSIZE\fP variable. +.PP +If \fIch\fP is any other nonprintable character, +it is drawn in printable form, +using the same convention as \fBunctrl\fR(3): +.bP +Control characters are displayed in the \fB^\fIX\fR notation. +.bP +Values above 128 are either meta characters +(if the screen has not been initialized, +or if \fBmeta\fP(3) has been called with a \fBTRUE\fP E parameter), +shown in the \fBM\-\fIX\fR notation, or are displayed as themselves. +In the latter case, the values may not be printable; +this follows the X/Open specification. .PP -If \fIch\fR is any control character other than tab, newline, or backspace, it -is drawn in \fB^\fR\fIX\fR notation. Calling \fBwinch\fR after adding a -control character does not return the character itself, but instead returns -the ^-representation of the control character. +Calling \fBwinch\fP after adding a +nonprintable character does not return the character itself, +but instead returns the printable representation of the character. .PP Video attributes can be combined with a character argument passed to -\fBaddch\fR or related functions by logical-ORing them into the character. +\fBaddch\fP or related functions by logical-ORing them into the character. (Thus, text, including attributes, can be copied from one place to another -using \fBinch\fR and \fBaddch\fR.) See the \fBcurs_attr\fR(3) page for +using \fBinch\fP(3) and \fBaddch\fP.) See the \fBcurs_attr\fP(3) page for values of predefined video attribute constants that can be usefully OR'ed into characters. -.PP -The \fBechochar\fR and \fBwechochar\fR routines are equivalent to a call to -\fBaddch\fR followed by a call to \fBrefresh\fR, or a call to \fBwaddch\fR -followed by a call to \fBwrefresh\fR. The knowledge that only a single +.SS Echoing characters +The \fBechochar\fP and \fBwechochar\fP routines are equivalent to a call to +\fBaddch\fP followed by a call to \fBrefresh\fP(3), or a call to \fBwaddch\fP +followed by a call to \fBwrefresh\fP. +The knowledge that only a single character is being output is used and, for non-control characters, a considerable performance gain may be seen by using these routines instead of their equivalents. .SS Line Graphics The following variables may be used to add line drawing characters to the -screen with routines of the \fBaddch\fR family. The default character listed -below is used if the \fBacsc\fR capability does not define a terminal-specific -replacement for it. +screen with routines of the \fBaddch\fP family. +The default character listed +below is used if the \fBacsc\fP capability does not define a terminal-specific +replacement for it, +or if the terminal and locale configuration requires Unicode but the +library is unable to use Unicode. +.PP The names are taken from VT100 nomenclature. .PP .TS -l l l -_ _ _ -l l l. -\fIName\fR \fIDefault\fR \fIDescription\fR -ACS_BLOCK # solid square block -ACS_BOARD # board of squares -ACS_BTEE + bottom tee -ACS_BULLET o bullet -ACS_CKBOARD : checker board (stipple) -ACS_DARROW v arrow pointing down -ACS_DEGREE ' degree symbol -ACS_DIAMOND + diamond -ACS_GEQUAL > greater-than-or-equal-to -ACS_HLINE - horizontal line -ACS_LANTERN # lantern symbol -ACS_LARROW < arrow pointing left -ACS_LEQUAL < less-than-or-equal-to -ACS_LLCORNER + lower left-hand corner -ACS_LRCORNER + lower right-hand corner -ACS_LTEE + left tee -ACS_NEQUAL ! not-equal -ACS_PI * greek pi -ACS_PLMINUS # plus/minus -ACS_PLUS + plus -ACS_RARROW > arrow pointing right -ACS_RTEE + right tee -ACS_S1 - scan line 1 -ACS_S3 - scan line 3 -ACS_S7 - scan line 7 -ACS_S9 \&_ scan line 9 -ACS_STERLING f pound-sterling symbol -ACS_TTEE + top tee -ACS_UARROW ^ arrow pointing up -ACS_ULCORNER + upper left-hand corner -ACS_URCORNER + upper right-hand corner -ACS_VLINE | vertical line +l l l l +l l l l +_ _ _ _ +l l l l. +\fBACS\fP \fBACS\fP \fBacsc\fP \fBGlyph\fP +\fBName\fP \fBDefault\fP \fBchar\fP \fBName\fP +ACS_BLOCK # 0 solid square block +ACS_BOARD # h board of squares +ACS_BTEE + v bottom tee +ACS_BULLET o ~ bullet +ACS_CKBOARD : a checker board (stipple) +ACS_DARROW v . arrow pointing down +ACS_DEGREE ' f degree symbol +ACS_DIAMOND + ` diamond +ACS_GEQUAL > > greater-than-or-equal-to +ACS_HLINE \- q horizontal line +ACS_LANTERN # i lantern symbol +ACS_LARROW < , arrow pointing left +ACS_LEQUAL < y less-than-or-equal-to +ACS_LLCORNER + m lower left-hand corner +ACS_LRCORNER + j lower right-hand corner +ACS_LTEE + t left tee +ACS_NEQUAL ! | not-equal +ACS_PI * { greek pi +ACS_PLMINUS # g plus/minus +ACS_PLUS + n plus +ACS_RARROW > + arrow pointing right +ACS_RTEE + u right tee +ACS_S1 \- o scan line 1 +ACS_S3 \- p scan line 3 +ACS_S7 \- r scan line 7 +ACS_S9 \&_ s scan line 9 +ACS_STERLING f } pound-sterling symbol +ACS_TTEE + w top tee +ACS_UARROW ^ \- arrow pointing up +ACS_ULCORNER + l upper left-hand corner +ACS_URCORNER + k upper right-hand corner +ACS_VLINE | x vertical line .TE .SH RETURN VALUE -All routines return the integer \fBERR\fR upon failure and \fBOK\fR on success -(the SVr4 manuals specify only "an integer value other than \fBERR\fR") upon -successful completion, unless otherwise noted in the preceding routine -descriptions. +All routines return the integer \fBERR\fP upon failure and \fBOK\fP on success +(the SVr4 manuals specify only +\*(``an integer value other than \fBERR\fP\*('') upon successful completion, +unless otherwise noted in the preceding routine descriptions. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. +.PP +If it is not possible to add a complete character, +an error is returned: +.bP +If \fBscrollok\fP(3) is not enabled, +writing a character at the lower right margin succeeds. +However, an error is returned because +it is not possible to wrap to a new line +.bP +If an error is detected when converting a multibyte character to a sequence +of bytes, +or if it is not possible to add all of the resulting bytes in the window, +an error is returned. .SH NOTES -Note that \fBaddch\fR, \fBmvaddch\fR, \fBmvwaddch\fR, and -\fBechochar\fR may be macros. +Note that \fBaddch\fP, \fBmvaddch\fP, \fBmvwaddch\fP, and +\fBechochar\fP may be macros. .SH PORTABILITY All these functions are described in the XSI Curses standard, Issue 4. The defaults specified for forms-drawing characters apply in the POSIX locale. +.SS ACS Symbols +X/Open Curses states that the \fBACS_\fP definitions are \fBchar\fP constants. +For the wide-character implementation (see \fBcurs_add_wch\fP), +there are analogous \fBWACS_\fP definitions which are \fBcchar_t\fP constants. +Some implementations are problematic: +.bP +Some implementations define the ACS symbols to a constant +(such as Solaris), while others define those to entries in an array. +.IP +This implementation uses an array \fBacs_map\fP, as done in SVr4 curses. +NetBSD also uses an array, actually named \fB_acs_char\fP, with a \fB#define\fP +for compatibility. +.bP +HPUX curses equates some of the \fBACS_\fP symbols +to the analogous \fBWACS_\fP symbols as if the \fBACS_\fP symbols were +wide characters. +The misdefined symbols are the arrows +and other symbols which are not used for line-drawing. +.bP +X/Open Curses (issues 2 through 7) has a typographical error +for the ACS_LANTERN symbol, equating its \*(``VT100+ Character\*('' +to \fBI\fP (capital I), while the header files for SVr4 curses +and the various implementations use \fBi\fP (lowercase). +.IP +None of the terminal descriptions on Unix platforms use uppercase-I, +except for Solaris (i.e., \fBscreen\fP's terminal description, +apparently based on the X/Open documentation around 1995). +On the other hand, the terminal description \fIgs6300\fP +(AT&T PC6300 with EMOTS Terminal Emulator) uses lowercase-i. .LP Some ACS symbols (ACS_S3, @@ -152,32 +245,79 @@ ACS_PI, ACS_NEQUAL, ACS_STERLING) were not documented in -any publicly released System V. However, many publicly available terminfos -include \fBacsc\fR strings in which their key characters (pryz{|}) are +any publicly released System V. +However, many publicly available terminfos +include \fBacsc\fP strings in which their key characters (pryz{|}) are embedded, and a second-hand list of their character descriptions has come -to light. The ACS-prefixed names for them were invented for \fBncurses\fR(3). +to light. +The ACS-prefixed names for them were invented for \fBncurses\fP(3). +.LP +The \fIdisplayed\fP values for the \fBACS_\fP and \fBWACS_\fP constants +depend on +.bP +the library configuration, i.e., \fBncurses\fP versus \fBncursesw\fP, +where the latter is capable of displaying Unicode while the former is not, and +.bP +whether the \fIlocale\fP uses UTF-8 encoding. .LP -The \fBTABSIZE\fR variable is implemented in some versions of curses, -but is not part of X/Open curses. +In certain cases, the terminal is unable to display line-drawing characters +except by using UTF-8 (see the discussion of \fBNCURSES_NO_UTF8_ACS\fP in +ncurses(3)). +.SS Character Set +X/Open Curses assumes that the parameter passed to \fBwaddch\fP contains +a single character. +As discussed in \fBcurs_attr\fP(3), that character may have been +more than eight bits in an SVr3 or SVr4 implementation, +but in the X/Open Curses model, the details are not given. +The important distinction between SVr4 curses and X/Open Curses is +that the non-character information (attributes and color) was +separated from the character information which is packed in a \fBchtype\fP +to pass to \fBwaddch\fP. +.PP +In this implementation, \fBchtype\fP holds an eight-bit character. +But ncurses allows multibyte characters to be passed in a succession +of calls to \fBwaddch\fP. +The other implementations do not do this; +a call to \fBwaddch\fP passes exactly one character +which may be rendered as one or more cells on the screen +depending on whether it is printable. +.PP +Depending on the locale settings, +ncurses will inspect the byte passed in each call to \fBwaddch\fP, +and check if the latest call will continue a multibyte sequence. +When a character is \fIcomplete\fP, +ncurses displays the character and moves to the next position in the screen. +.PP +If the calling application interrupts the succession of bytes in +a multibyte character by moving the current location (e.g., using \fBwmove\fP), +ncurses discards the partially built character, +starting over again. +.PP +For portability to other implementations, +do not rely upon this behavior: +.bP +check if a character can be represented as a single byte in the current locale +before attempting call \fBwaddch\fP, and +.bP +call \fBwadd_wch\fP for characters which cannot be handled by \fBwaddch\fP. +.SS TABSIZE +The \fBTABSIZE\fP variable is implemented in SVr4 and other versions of curses, +but is not part of X/Open curses +(see \fBcurs_variables\fP(3) for more details). .LP -If \fIch\fR is a carriage return, +If \fIch\fP is a carriage return, the cursor is moved to the beginning of the current row of the window. This is true of other implementations, but is not documented. .SH SEE ALSO -\fBcurses\fR(3), -\fBcurs_attr\fR(3), -\fBcurs_clear\fR(3), -\fBcurs_inch\fR(3), -\fBcurs_outopts\fR(3), -\fBcurs_refresh\fR(3), -\fBputc\fR(3). +\fBcurses\fP(3), +\fBcurs_attr\fP(3), +\fBcurs_clear\fP(3), +\fBcurs_inch\fP(3), +\fBcurs_outopts\fP(3), +\fBcurs_refresh\fP(3), +\fBcurs_variables\fP(3), +\fBputc\fP(3). .PP Comparable functions in the wide-character (ncursesw) library are described in -\fBcurs_add_wch\fR(3). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurs_add_wch\fP(3). diff --git a/lib/libcurses/curs_addchstr.3 b/lib/libcurses/curs_addchstr.3 index d291af1c54d..3c03e6a60a9 100644 --- a/lib/libcurses/curs_addchstr.3 +++ b/lib/libcurses/curs_addchstr.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_addchstr.3,v 1.9 2010/01/12 23:21:58 nicm Exp $ +.\" $OpenBSD: curs_addchstr.3,v 1.10 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2019-2021,2022 Thomas E. Dickey * +.\" Copyright 1998-2012,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,74 +29,91 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_addchstr.3,v 1.9 2010/01/12 23:21:58 nicm Exp $ -.TH curs_addchstr 3 "" +.\" $Id: curs_addchstr.3,v 1.10 2023/10/17 09:52:08 nicm Exp $ +.TH curs_addchstr 3 2022-02-12 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .na .hy 0 .SH NAME -\fBaddchstr\fR, -\fBaddchnstr\fR, -\fBwaddchstr\fR, -\fBwaddchnstr\fR, -\fBmvaddchstr\fR, -\fBmvaddchnstr\fR, -\fBmvwaddchstr\fR, -\fBmvwaddchnstr\fR - add a string of characters (and attributes) to a \fBcurses\fR window +\fBaddchstr\fP, +\fBaddchnstr\fP, +\fBwaddchstr\fP, +\fBwaddchnstr\fP, +\fBmvaddchstr\fP, +\fBmvaddchnstr\fP, +\fBmvwaddchstr\fP, +\fBmvwaddchnstr\fP \- add a string of characters (and attributes) to a \fBcurses\fP window .ad .hy .SH SYNOPSIS -\fB#include \fR +.nf +\fB#include \fP .PP -\fBint addchstr(const chtype *chstr);\fR +\fBint addchstr(const chtype *\fIchstr\fB);\fR .br -\fBint addchnstr(const chtype *chstr, int n);\fR +\fBint addchnstr(const chtype *\fIchstr\fB, int \fIn\fB);\fR .br -\fBint waddchstr(WINDOW *win, const chtype *chstr);\fR +\fBint waddchstr(WINDOW *\fIwin\fB, const chtype *\fIchstr\fB);\fR .br -\fBint waddchnstr(WINDOW *win, const chtype *chstr, int n);\fR +\fBint waddchnstr(WINDOW *\fIwin\fB, const chtype *\fIchstr\fB, int \fIn\fB);\fR +.sp +\fBint mvaddchstr(int \fIy\fB, int \fIx\fB, const chtype *\fIchstr\fB);\fR .br -\fBint mvaddchstr(int y, int x, const chtype *chstr);\fR +\fBint mvaddchnstr(int \fIy\fB, int \fIx\fB, const chtype *\fIchstr\fB, int \fIn\fB);\fR .br -\fBint mvaddchnstr(int y, int x, const chtype *chstr, int n);\fR +\fBint mvwaddchstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, const chtype *\fIchstr\fB);\fR .br -\fBint mvwaddchstr(WINDOW *win, int y, int x, const chtype *chstr);\fR -.br -\fBint mvwaddchnstr(WINDOW *win, int y, int x, const chtype *chstr, int n);\fR +\fBint mvwaddchnstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, const chtype *\fIchstr\fB, int \fIn\fB);\fR +.fi .SH DESCRIPTION -These routines copy \fIchstr\fR into the window image structure at and after -the current cursor position. The four routines with \fIn\fR as the last -argument copy at most \fIn\fR elements, but no more than will fit on the line. -If \fBn\fR=\fB-1\fR then the whole string is copied, to the maximum number of -characters that will fit on the line. +These functions copy the (null-terminated) +\fIchstr\fP array +into the window image structure +starting at the current cursor position. +The four functions with \fIn\fP as the last +argument copy at most \fIn\fP elements, +but no more than will fit on the line. +If \fBn\fP=\fB\-1\fP then the whole array is copied, +to the maximum number of characters that will fit on the line. .PP -The window cursor is \fInot\fR advanced, and these routines work faster than -\fBwaddnstr\fR. On the other hand, they do not perform any kind of checking -(such as for the newline, backspace, or carriage return characters), they do not -advance the current cursor position, they do not expand other control characters -to ^-escapes, and they truncate the string if it crosses the right margin, +The window cursor is \fInot\fP advanced. +These functions work faster than \fBwaddnstr\fP. +On the other hand: +.bP +they do not perform checking +(such as for the newline, backspace, or carriage return characters), +.bP +they do not advance the current cursor position, +.bP +they do not expand other control characters to ^-escapes, and +.bP +they truncate the string if it crosses the right margin, rather than wrapping it around to the new line. -.SH RETURN VALUES -All routines return the integer \fBERR\fR upon failure and \fBOK\fR on success -(the SVr4 manuals specify only "an integer value other than \fBERR\fR") upon -successful completion, unless otherwise noted in the preceding routine -descriptions. +.SH RETURN VALUE +All functions return the integer \fBERR\fP upon failure and \fBOK\fP on success. .PP X/Open does not define any error conditions. This implementation returns an error if the window pointer is null. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. .SH NOTES -Note that all routines except \fBwaddchnstr\fR may be macros. +All functions except \fBwaddchnstr\fP may be macros. .SH PORTABILITY These entry points are described in the XSI Curses standard, Issue 4. .SH SEE ALSO -\fBcurses\fR(3). +\fBcurses\fP(3), +\fBcurs_addstr\fP(3). .PP Comparable functions in the wide-character (ncursesw) library are described in -\fBcurs_add_wchstr\fR(3). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurs_add_wchstr\fP(3). diff --git a/lib/libcurses/curs_addstr.3 b/lib/libcurses/curs_addstr.3 index d1815f117c0..5afc67ae300 100644 --- a/lib/libcurses/curs_addstr.3 +++ b/lib/libcurses/curs_addstr.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_addstr.3,v 1.7 2010/01/12 23:21:58 nicm Exp $ +.\" $OpenBSD: curs_addstr.3,v 1.8 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2003,2005 Free Software Foundation, Inc. * +.\" Copyright 2019-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2012,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,72 +29,93 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_addstr.3,v 1.7 2010/01/12 23:21:58 nicm Exp $ -.TH curs_addstr 3 "" +.\" $Id: curs_addstr.3,v 1.8 2023/10/17 09:52:08 nicm Exp $ +.TH curs_addstr 3 2023-03-11 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .na .hy 0 .SH NAME -\fBaddstr\fR, -\fBaddnstr\fR, -\fBwaddstr\fR, -\fBwaddnstr\fR, -\fBmvaddstr\fR, -\fBmvaddnstr\fR, -\fBmvwaddstr\fR, -\fBmvwaddnstr\fR - add a string of characters to a \fBcurses\fR window and advance cursor +\fBaddstr\fP, +\fBaddnstr\fP, +\fBwaddstr\fP, +\fBwaddnstr\fP, +\fBmvaddstr\fP, +\fBmvaddnstr\fP, +\fBmvwaddstr\fP, +\fBmvwaddnstr\fP \- add a string of characters to a \fBcurses\fP window and advance cursor .ad .hy .SH SYNOPSIS .nf -\fB#include \fR +\fB#include \fP .PP -\fBint addstr(const char *\fR\fIstr\fR\fB);\fR +\fBint addstr(const char *\fIstr\fB);\fR .br -\fBint addnstr(const char *\fR\fIstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint addnstr(const char *\fIstr\fB, int \fIn\fB);\fR .br -\fBint waddstr(WINDOW *\fR\fIwin\fR\fB, const char *\fR\fIstr\fR\fB);\fR +\fBint waddstr(WINDOW *\fIwin\fB, const char *\fIstr\fB);\fR .br -\fBint waddnstr(WINDOW *\fR\fIwin\fR\fB, const char *\fR\fIstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint waddnstr(WINDOW *\fIwin\fB, const char *\fIstr\fB, int \fIn\fB);\fR +.sp +\fBint mvaddstr(int \fIy\fB, int \fIx\fB, const char *\fIstr\fB);\fR .br -\fBint mvaddstr(int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, const char *\fR\fIstr\fR\fB);\fR +\fBint mvaddnstr(int \fIy\fB, int \fIx\fB, const char *\fIstr\fB, int \fIn\fB);\fR .br -\fBint mvaddnstr(int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, const char *\fR\fIstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint mvwaddstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, const char *\fIstr\fB);\fR .br -\fBint mvwaddstr(WINDOW *\fR\fIwin\fR\fB, int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, const char *\fR\fIstr\fR\fB);\fR -.br -\fBint mvwaddnstr(WINDOW *\fR\fIwin\fR\fB, int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, const char *\fR\fIstr, int \fR\fIn\fR\fB);\fR +\fBint mvwaddnstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, const char *\fIstr, int \fIn\fB);\fR .fi .SH DESCRIPTION -These routines write the characters of the (null-terminated) character string -\fIstr\fR on the given window. -It is similar to calling \fBwaddch\fR once for each character in the string. -The four routines with \fIn\fR as the last argument -write at most \fIn\fR characters. -If \fIn\fR is -1, then the entire string will be added, -up to the maximum number of characters that will fit on the line, +These functions write the (null-terminated) character string +\fIstr\fP on the given window. +It is similar to calling \fBwaddch\fP once for each byte in the string. +.PP +The \fImv\fP functions perform cursor movement once, before writing any +characters. +Thereafter, the cursor is advanced as a side-effect of writing to the window. +.PP +The four functions with \fIn\fP as the last argument +write at most \fIn\fP bytes, or until a terminating null is reached. +If \fIn\fP is \-1, then the entire string will be added. .SH RETURN VALUE -All routines return the integer \fBERR\fR upon failure and \fBOK\fR on success -(the SVr4 manuals specify only "an integer value other than \fBERR\fR") upon -successful completion. +All functions return the integer \fBERR\fP upon failure and \fBOK\fP on success. .PP X/Open does not define any error conditions. This implementation returns an error +.bP if the window pointer is null or +.bP if the string pointer is null or +.bP if the corresponding calls to \fBwaddch\fP return an error. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. +If an error is returned by the \fBwmove\fP, +no characters are added to the window. +.PP +If an error is returned by \fBwaddch\fP +(e.g., +because the window is not large enough, +or an illegal byte sequence was detected) +only part of the string may be added. +Aside from that, +there is a special case in \fBwaddch\fP where an error may be +returned after successfully writing a character to the lower-right corner +of a window when \fBscrollok\fP(3) is disabled. .SH NOTES -Note that all of these routines except \fBwaddstr\fR and \fBwaddnstr\fR may be -macros. +All of these functions except \fBwaddnstr\fP may be macros. .SH PORTABILITY -All these entry points are described in the XSI Curses standard, Issue 4. The -XSI errors EILSEQ and EOVERFLOW, associated with extended-level conformance, -are not yet detected. +These functions are described in the XSI Curses standard, Issue 4. .SH SEE ALSO -\fBcurses\fR(3), \fBcurs_addch\fR(3). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_addch\fP(3). diff --git a/lib/libcurses/curs_addwstr.3 b/lib/libcurses/curs_addwstr.3 index 474fc51a24b..d5046cd838d 100644 --- a/lib/libcurses/curs_addwstr.3 +++ b/lib/libcurses/curs_addwstr.3 @@ -1,6 +1,7 @@ -.\" $OpenBSD: curs_addwstr.3,v 1.1 2010/09/06 17:26:17 nicm Exp $ +.\" $OpenBSD: curs_addwstr.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ .\"*************************************************************************** -.\" Copyright (c) 2002-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2019-2022,2023 Thomas E. Dickey * +.\" Copyright 2002-2012,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -27,69 +28,90 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_addwstr.3,v 1.1 2010/09/06 17:26:17 nicm Exp $ -.TH curs_addwstr 3 "" +.\" $Id: curs_addwstr.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ +.TH curs_addwstr 3 2023-07-15 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .na .hy 0 .SH NAME -\fBaddwstr\fR, -\fBaddnwstr\fR, -\fBwaddwstr\fR, -\fBwaddnwstr\fR, -\fBmvaddwstr\fR, -\fBmvaddnwstr\fR, -\fBmvwaddwstr\fR, -\fBmvwaddnwstr\fR \- add a string of wide characters to a \fBcurses\fR window and advance cursor +\fBaddwstr\fP, +\fBaddnwstr\fP, +\fBwaddwstr\fP, +\fBwaddnwstr\fP, +\fBmvaddwstr\fP, +\fBmvaddnwstr\fP, +\fBmvwaddwstr\fP, +\fBmvwaddnwstr\fP \- add a string of wide characters to a \fBcurses\fP window and advance cursor .ad .hy .SH SYNOPSIS .nf -\fB#include \fR +\fB#include \fP .PP -\fBint addwstr(const wchar_t *\fR\fIwstr\fR\fB);\fR +\fBint addwstr(const wchar_t *\fIwstr\fB);\fR .br -\fBint addnwstr(const wchar_t *\fR\fIwstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint addnwstr(const wchar_t *\fIwstr\fB, int \fIn\fB);\fR .br -\fBint waddwstr(WINDOW *\fR\fIwin\fR\fB, const wchar_t *\fR\fIwstr\fR\fB);\fR +\fBint waddwstr(WINDOW *\fIwin\fB, const wchar_t *\fIwstr\fB);\fR .br -\fBint waddnwstr(WINDOW *\fR\fIwin\fR\fB, const wchar_t *\fR\fIwstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint waddnwstr(WINDOW *\fIwin\fB, const wchar_t *\fIwstr\fB, int \fIn\fB);\fR +.sp +\fBint mvaddwstr(int \fIy\fB, int \fIx\fB, const wchar_t *\fIwstr\fB);\fR .br -\fBint mvaddwstr(int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, const wchar_t *\fR\fIwstr\fR\fB);\fR +\fBint mvaddnwstr(int \fIy\fB, int \fIx\fB, const wchar_t *\fIwstr\fB, int \fIn\fB);\fR .br -\fBint mvaddnwstr(int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, const wchar_t *\fR\fIwstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint mvwaddwstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, const wchar_t *\fIwstr\fB);\fR .br -\fBint mvwaddwstr(WINDOW *\fR\fIwin\fR\fB, int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, const wchar_t *\fR\fIwstr\fR\fB);\fR -.br -\fBint mvwaddnwstr(WINDOW *\fR\fIwin\fR\fB, int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, const wchar_t *\fR\fIwstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint mvwaddnwstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, const wchar_t *\fIwstr\fB, int \fIn\fB);\fR .fi .SH DESCRIPTION -These routines write the characters of the -(null-terminated) \fBwchar_t\fR character string -\fIwstr\fR on the given window. -It is similar to constructing a \fBcchar_t\fR for each wchar_t in the string, -then calling \fBwadd_wch\fR for the resulting \fBcchar_t\fR. +These functions write the characters of the +(null-terminated) \fBwchar_t\fP character string +\fIwstr\fP on the given window. +It is similar to constructing a \fBcchar_t\fP for +each \fBwchar_t\fR in the string, +then calling \fBwadd_wch\fP(3) for the resulting \fBcchar_t\fP: +.bP +spacing and non-spacing characters in the string +are processed one at a time, and +.bP +control characters are processed as in \fBwaddch\fP(3). .PP -The \fImv\fR routines perform cursor movement once, before writing any +The \fImv\fP functions perform cursor movement once, before writing any characters. Thereafter, the cursor is advanced as a side-effect of writing to the window. .PP -The four routines with \fIn\fR as the last argument -write at most \fIn\fR \fBwchar_t\fR characters. -If \fIn\fR is -1, then the entire string will be added, -up to the maximum number of characters that will fit on the line, +The four functions with \fIn\fP as the last argument +write at most \fIn\fP \fBwchar_t\fP characters, or until a terminating null is reached. -.SH RETURN VALUES -All routines return the integer \fBERR\fR upon failure and \fBOK\fR on success. +If \fIn\fP is \-1, then the entire string will be added. +.SH RETURN VALUE +All functions return the integer \fBERR\fP upon failure and \fBOK\fP on success. +.PP +X/Open does not define any error conditions. +This implementation returns an error +.bP +if the window pointer is null or +.bP +if the string pointer is null or +.bP +if the corresponding calls to \fBwadd_wch\fP return an error. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. .SH NOTES -Note that all of these routines except \fBwaddnwstr\fR may be macros. +All of these functions except \fBwaddnwstr\fP may be macros. .SH PORTABILITY -All these entry points are described in the XSI Curses standard, Issue 4. +These functions are described in the XSI Curses standard, Issue 4. .SH SEE ALSO -\fBcurses\fR(3), -\fBcurs_add_wch\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_addch\fP(3), +\fBcurs_add_wch\fP(3). diff --git a/lib/libcurses/curs_attr.3 b/lib/libcurses/curs_attr.3 index ddd033be5db..46c099b7c22 100644 --- a/lib/libcurses/curs_attr.3 +++ b/lib/libcurses/curs_attr.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: curs_attr.3,v 1.4 2019/02/13 07:18:57 nicm Exp $ +.\" $OpenBSD: curs_attr.3,v 1.5 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2016,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,244 +30,588 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_attr.3,v 1.4 2019/02/13 07:18:57 nicm Exp $ -.TH curs_attr 3 "" +.\" $Id: curs_attr.3,v 1.5 2023/10/17 09:52:08 nicm Exp $ +.TH curs_attr 3 2023-08-19 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de NS +.ie n .sp +.el .sp .5 +.ie n .in +4 +.el .in +2 +.nf +.ft CR \" Courier +.. +.de NE +.fi +.ft R +.ie n .in -4 +.el .in -2 +.. +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .na .hy 0 +.\" --------------------------------------------------------------------------- .SH NAME -\fBattroff\fR, -\fBwattroff\fR, -\fBattron\fR, -\fBwattron\fR, -\fBattrset\fR, -\fBwattrset\fR, -\fBcolor_set\fR, -\fBwcolor_set\fR, -\fBstandend\fR, -\fBwstandend\fR, -\fBstandout\fR, -\fBwstandout\fR, -\fBattr_get\fR, -\fBwattr_get\fR, -\fBattr_off\fR, -\fBwattr_off\fR, -\fBattr_on\fR, -\fBwattr_on\fR, -\fBattr_set\fR, -\fBwattr_set\fR, -\fBchgat\fR, -\fBwchgat\fR, -\fBmvchgat\fR, -\fBmvwchgat\fR, -\fBPAIR_NUMBER\fR - \fBcurses\fR character and window attribute control routines +.\" attr_get +\fBattr_get\fP, +\fBwattr_get\fP, +\fBattr_set\fP, +\fBwattr_set\fP, +.\" .br +\fBattr_off\fP, +\fBwattr_off\fP, +\fBattr_on\fP, +\fBwattr_on\fP, +.\" .br +\fBattroff\fP, +\fBwattroff\fP, +\fBattron\fP, +\fBwattron\fP, +\fBattrset\fP, +\fBwattrset\fP, +.\" .br +\fBchgat\fP, +\fBwchgat\fP, +\fBmvchgat\fP, +\fBmvwchgat\fP, +.\" .br +\fBcolor_set\fP, +\fBwcolor_set\fP, +.\" .br +\fBstandend\fP, +\fBwstandend\fP, +\fBstandout\fP, +\fBwstandout\fP \- \fBcurses\fP character and window attribute control routines .ad .hy +.\" --------------------------------------------------------------------------- .SH SYNOPSIS -\fB#include \fR +\fB#include \fP +.sp +\fBint attr_get(attr_t *\fIattrs\fB, short *\fIpair\fB, void *\fIopts\fB);\fR .br -\fBint attroff(int attrs);\fR +\fBint wattr_get(WINDOW *\fIwin\fB, attr_t *\fIattrs\fB, short *\fIpair\fB,\fR \fBvoid *\fIopts\fB);\fR .br -\fBint wattroff(WINDOW *win, int attrs);\fR +\fBint attr_set(attr_t \fIattrs\fB, short \fIpair\fB, void *\fIopts\fB);\fR .br -\fBint attron(int attrs);\fR +\fBint wattr_set(WINDOW *\fIwin\fB, attr_t \fIattrs\fB, short \fIpair\fB, void *\fIopts\fB);\fR +.sp +\fBint attr_off(attr_t \fIattrs\fB, void *\fIopts\fB);\fR .br -\fBint wattron(WINDOW *win, int attrs);\fR +\fBint wattr_off(WINDOW *\fIwin\fB, attr_t \fIattrs\fB, void *\fIopts\fB);\fR .br -\fBint attrset(int attrs);\fR +\fBint attr_on(attr_t \fIattrs\fB, void *\fIopts\fB);\fR .br -\fBint wattrset(WINDOW *win, int attrs);\fR +\fBint wattr_on(WINDOW *\fIwin\fB, attr_t \fIattrs\fB, void *\fIopts\fB);\fR +.sp +\fBint attroff(int \fIattrs);\fR .br -\fBint color_set(short color_pair_number, void* opts);\fR +\fBint wattroff(WINDOW *\fIwin\fB, int \fIattrs\fB);\fR .br -\fBint wcolor_set(WINDOW *win, short color_pair_number,\fR - \fBvoid* opts);\fR +\fBint attron(int \fIattrs\fB);\fR .br -\fBint standend(void);\fR +\fBint wattron(WINDOW *\fIwin\fB, int \fIattrs\fB);\fR .br -\fBint wstandend(WINDOW *win);\fR +\fBint attrset(int \fIattrs\fB);\fR .br -\fBint standout(void);\fR +\fBint wattrset(WINDOW *\fIwin\fB, int \fIattrs\fB);\fR +.sp +\fBint chgat(int \fIn\fB, attr_t \fIattr\fB, short \fIpair\fB,\fR \fBconst void *\fIopts\fB);\fR .br -\fBint wstandout(WINDOW *win);\fR +\fBint wchgat(WINDOW *\fIwin\fB,\fR + \fBint \fIn\fB, attr_t \fIattr\fB,\fR \fBshort \fIpair\fB, const void *\fIopts\fB);\fR .br -\fBint attr_get(attr_t *attrs, short *pair, void *opts);\fR +\fBint mvchgat(int \fIy\fB, int \fIx\fB,\fR + \fBint \fIn\fB, attr_t \fIattr\fB,\fR \fBshort \fIpair\fB, const void *\fIopts\fB);\fR .br -\fBint wattr_get(WINDOW *win, attr_t *attrs, short *pair,\fR - \fBvoid *opts);\fR +\fBint mvwchgat(WINDOW *\fIwin, int \fIy, int \fIx\fB,\fR + \fBint \fIn,\fR \fBattr_t \fIattr\fB, short \fIpair\fB, const void *\fIopts\fB);\fR +.sp +\fBint color_set(short \fIpair\fB, void* \fIopts\fB);\fR .br -\fBint attr_off(attr_t attrs, void *opts);\fR +\fBint wcolor_set(WINDOW *\fIwin\fB, short \fIpair\fB,\fR \fBvoid* \fIopts);\fR +.sp +\fBint standend(void);\fP .br -\fBint wattr_off(WINDOW *win, attr_t attrs, void *opts);\fR +\fBint wstandend(WINDOW *\fIwin\fB);\fR .br -\fBint attr_on(attr_t attrs, void *opts);\fR -.br -\fBint wattr_on(WINDOW *win, attr_t attrs, void *opts);\fR -.br -\fBint attr_set(attr_t attrs, short pair, void *opts);\fR -.br -\fBint wattr_set(WINDOW *win, attr_t attrs, short pair, void *opts);\fR -.br -\fBint chgat(int n, attr_t attr, short color,\fR - \fBconst void *opts)\fR -.br -\fBint wchgat(WINDOW *win, int n, attr_t attr,\fR - \fBshort color, const void *opts)\fR -.br -\fBint mvchgat(int y, int x, int n, attr_t attr,\fR - \fBshort color, const void *opts)\fR -.br -\fBint mvwchgat(WINDOW *win, int y, int x, int n,\fR - \fBattr_t attr, short color, const void *opts)\fR +\fBint standout(void);\fP .br +\fBint wstandout(WINDOW *\fIwin\fB);\fR +.\" --------------------------------------------------------------------------- .SH DESCRIPTION -These routines manipulate the current attributes of the named window. The -current attributes of a window apply to all characters that are written into -the window with \fBwaddch\fR, \fBwaddstr\fR and \fBwprintw\fR. Attributes are +These routines manipulate the current attributes of the named window, +which then apply to all characters that are written into +the window with \fBwaddch\fP, \fBwaddstr\fP and \fBwprintw\fP. +Attributes are a property of the character, and move with the character through any scrolling -and insert/delete line/character operations. To the extent possible, they are +and insert/delete line/character operations. +To the extent possible, they are displayed as appropriate modifications to the graphic rendition of characters put on the screen. .PP -The routine \fBattrset\fR sets the current attributes of the given window to -\fIattrs\fR. The routine \fBattroff\fR turns off the named attributes without -turning any other attributes on or off. The routine \fBattron\fR turns on the -named attributes without affecting any others. The routine \fBstandout\fR is -the same as \fBattron(A_STANDOUT)\fR. The routine \fBstandend\fR is the same -as \fBattrset(A_NORMAL)\fR or \fBattrset(0)\fR, that is, it turns off all -attributes. -.PP -The \fBattrset\fR and related routines do not affect the attributes used +These routines do not affect the attributes used when erasing portions of the window. -See \fBcurs_bkgd\fR(3) for functions which modify the attributes used for +See \fBcurs_bkgd\fP(3) for functions which modify the attributes used for erasing and clearing. .PP -The routine \fBcolor_set\fR sets the current color of the given window to the -foreground/background combination described by the color_pair_number. The -parameter opts is reserved for future use, applications must supply a null -pointer. -.PP -The routine \fBwattr_get\fR returns the current attribute and color pair for -the given window; \fBattr_get\fR returns the current attribute and color pair -for \fBstdscr\fR. -The remaining \fBattr_\fR* functions operate exactly like the corresponding -\fBattr\fR* functions, except that they take arguments of type \fBattr_t\fR -rather than \fBint\fR. -.PP -The routine \fBchgat\fR changes the attributes of a given number of characters -starting at the current cursor location of \fBstdscr\fR. It does not update -the cursor and does not perform wrapping. A character count of -1 or greater +Routines which do not have a \fBWINDOW*\fP parameter apply to \fBstdscr\fP. +For example, +\fBattr_set\fP is the \fBstdscr\fP variant of \fBwattr_set\fP. +.\" --------------------------------------------------------------------------- +.SS Window attributes +There are two sets of functions: +.bP +functions for manipulating the window attributes and color: +\fBwattr_set\fP and \fBwattr_get\fP. +.bP +functions for manipulating only the window attributes (not color): +\fBwattr_on\fP and \fBwattr_off\fP. +.PP +The \fBwattr_set\fP function sets the current attributes +of the given window to \fIattrs\fP, with color specified by \fIpair\fP. +.PP +Use \fBwattr_get\fP to retrieve attributes for the given window. +.PP +Use \fBattr_on\fP and \fBwattr_on\fP to turn on window attributes, i.e., +values OR'd together in \fIattr\fP, +without affecting other attributes. +Use \fBattr_off\fP and \fBwattr_off\fP to turn off window attributes, +again values OR'd together in \fIattr\fP, +without affecting other attributes. +.\" --------------------------------------------------------------------------- +.SS Legacy window attributes +The X/Open window attribute routines which \fIset\fP or \fIget\fP, +turn \fIon\fP or \fIoff\fP +are extensions of older routines +which assume that color pairs are OR'd into the attribute parameter. +These newer routines use similar names, because +X/Open simply added an underscore (\fB_\fP) for the newer names. +.PP +The \fBint\fP datatype used in the legacy routines is treated as if +it is the same size as \fBchtype\fP (used by \fBaddch\fP(3)). +It holds the common video attributes (such as bold, reverse), +as well as a few bits for color. +Those bits correspond to the \fBA_COLOR\fP symbol. +The \fBCOLOR_PAIR\fP macro provides a value which can be OR'd into +the attribute parameter. +For example, +as long as that value fits into the \fBA_COLOR\fP mask, +then these calls produce similar results: +.NS +attrset(A_BOLD | COLOR_PAIR(\fIpair\fP)); +attr_set(A_BOLD, \fIpair\fP, NULL); +.NE +.PP +However, if the value does not fit, then the \fBCOLOR_PAIR\fP macro +uses only the bits that fit. +For example, because in ncurses \fBA_COLOR\fP has eight (8) bits, +then \fBCOLOR_PAIR(\fI259\fB)\fR is 4 +(i.e., 259 is 4 more than the limit 255). +.PP +The \fBPAIR_NUMBER\fP macro extracts a pair number from an \fBint\fP +(or \fBchtype\fP). +For example, the \fIinput\fP and \fIoutput\fP values in these statements +would be the same: +.NS +int value = A_BOLD | COLOR_PAIR(\fIinput\fP); +int \fIoutput\fP = PAIR_NUMBER(value); +.NE +.PP +The \fBattrset\fP routine is a legacy feature predating SVr4 curses +but kept in X/Open Curses for the same reason that SVr4 curses kept it: +compatibility. +.PP +The remaining \fBattr\fP* functions operate exactly like the corresponding +\fBattr_\fP* functions, except that they take arguments of type \fBint\fP +rather than \fBattr_t\fP. +.PP +There is no corresponding \fBattrget\fP function as such in X/Open Curses, +although ncurses provides \fBgetattrs\fP (see curs_legacy(3)). +.\" --------------------------------------------------------------------------- +.SS Change character rendition +The routine \fBchgat\fP changes the attributes of a given number of characters +starting at the current cursor location of \fBstdscr\fP. +It does not update +the cursor and does not perform wrapping. +A character count of \-1 or greater than the remaining window width means to change attributes all the way to the -end of the current line. The \fBwchgat\fR function generalizes this to any -window; the \fBmvwchgat\fR function does a cursor move before acting. In these -functions, the color argument is a color-pair index (as in the first argument -of \fIinit_pair\fR, see \fBcurs_color\fR(3)). The \fBopts\fR argument is not -presently used, but is reserved for the future (leave it \fBNULL\fR). -.SS Attributes -The following video attributes, defined in \fB\fR, can be passed to -the routines \fBattron\fR, \fBattroff\fR, and \fBattrset\fR, or OR'd with the -characters passed to \fBaddch\fR. +end of the current line. +The \fBwchgat\fP function generalizes this to any window; +the \fBmvwchgat\fP function does a cursor move before acting. .PP +In these functions, +the color \fIpair\fP argument is a color-pair index +(as in the first argument of \fBinit_pair\fP, see \fBcurs_color\fP(3)). +.\" --------------------------------------------------------------------------- +.SS Change window color +The routine \fBcolor_set\fP sets the current color of the given window to the +foreground/background combination described by the color \fIpair\fP parameter. +.\" --------------------------------------------------------------------------- +.SS Standout +The routine \fBstandout\fP is +the same as \fBattron(A_STANDOUT)\fP. +The routine \fBstandend\fP is the same +as \fBattrset(A_NORMAL)\fP or \fBattrset(0)\fP, that is, it turns off all +attributes. +.PP +X/Open does not mark these \*(``restricted\*('', because +.bP +they have well established legacy use, and +.bP +there is no ambiguity about the way the attributes +might be combined with a color pair. +.\" --------------------------------------------------------------------------- +.SH VIDEO ATTRIBUTES +The following video attributes, defined in \fB\fP, can be passed to +the routines \fBattron\fP, \fBattroff\fP, and \fBattrset\fP, or OR'd with the +characters passed to \fBaddch\fP (see \fBcurs_addch\fP(3)). +.PP +.RS .TS -center ; +l l +_ _ _ l l . -\fBA_NORMAL\fR Normal display (no highlight) -\fBA_STANDOUT\fR Best highlighting mode of the terminal. -\fBA_UNDERLINE\fR Underlining -\fBA_REVERSE\fR Reverse video -\fBA_BLINK\fR Blinking -\fBA_DIM\fR Half bright -\fBA_BOLD\fR Extra bright or bold -\fBA_PROTECT\fR Protected mode -\fBA_INVIS\fR Invisible or blank mode -\fBA_ALTCHARSET\fR Alternate character set -\fBA_CHARTEXT\fR Bit-mask to extract a character -\fBCOLOR_PAIR(\fR\fIn\fR\fB)\fR Color-pair number \fIn\fR +\fBName\fP \fBDescription\fP +\fBA_NORMAL\fP Normal display (no highlight) +\fBA_STANDOUT\fP Best highlighting mode of the terminal. +\fBA_UNDERLINE\fP Underlining +\fBA_REVERSE\fP Reverse video +\fBA_BLINK\fP Blinking +\fBA_DIM\fP Half bright +\fBA_BOLD\fP Extra bright or bold +\fBA_PROTECT\fP Protected mode +\fBA_INVIS\fP Invisible or blank mode +\fBA_ALTCHARSET\fP Alternate character set +\fBA_ITALIC\fP Italics (non-X/Open extension) +\fBA_CHARTEXT\fP Bit-mask to extract a character +\fBA_COLOR\fP Bit-mask to extract a color (legacy routines) .TE +.RE .PP -The following macro is the reverse of \fBCOLOR_PAIR(\fR\fIn\fR\fB)\fR: +These video attributes are supported by \fBattr_on\fP and related functions +(which also support the attributes recognized by \fBattron\fP, etc.): .PP -.br -\fBPAIR_NUMBER(\fR\fIattrs\fR) Returns the pair number associated - with the \fBCOLOR_PAIR(\fR\fIn\fR\fB)\fR attribute. -.br +.RS +.TS +l l +_ _ _ +l l . +\fBName\fP \fBDescription\fP +\fBWA_HORIZONTAL\fP Horizontal highlight +\fBWA_LEFT\fP Left highlight +\fBWA_LOW\fP Low highlight +\fBWA_RIGHT\fP Right highlight +\fBWA_TOP\fP Top highlight +\fBWA_VERTICAL\fP Vertical highlight +.TE +.RE .PP The return values of many of these routines are not meaningful (they are implemented as macro-expanded assignments and simply return their argument). -The SVr4 manual page claims (falsely) that these routines always return \fB1\fR. +The SVr4 manual page claims (falsely) that these routines always return \fB1\fP. +.\" --------------------------------------------------------------------------- .SH NOTES -Note that \fBattroff\fR, \fBwattroff\fR, \fBattron\fR, \fBwattron\fR, -\fBattrset\fR, \fBwattrset\fR, \fBstandend\fR and \fBstandout\fR may be macros. +These functions may be macros: +.sp +.RS +\fBattroff\fP, \fBwattroff\fP, \fBattron\fP, \fBwattron\fP, +\fBattrset\fP, \fBwattrset\fP, \fBstandend\fP and \fBstandout\fP. +.RE .PP -\fBCOLOR_PAIR\fP values can only be OR'd with attributes if the pair +Color pair values can only be OR'd with attributes if the pair number is less than 256. The alternate functions such as \fBcolor_set\fP can pass a color pair value directly. -However, ncurses ABI 4 and 5 simply OR this value within the alternate functions. +However, ncurses ABI 4 and 5 simply OR this value +within the alternate functions. You must use ncurses ABI 6 to support more than 256 color pairs. +.\" --------------------------------------------------------------------------- +.SH HISTORY +X/Open Curses is largely based on SVr4 curses, +adding support for \*(``wide-characters\*('' (not specific to Unicode). +Some of the X/Open differences from SVr4 curses address the way +video attributes can be applied to wide-characters. +But aside from that, \fBattrset\fP and \fBattr_set\fP are similar. +SVr4 curses provided the basic features for manipulating video attributes. +However, earlier versions of curses provided a part of these features. +.PP +As seen in 2.8BSD, curses assumed 7-bit characters, +using the eighth bit of a byte to represent the \fIstandout\fP +feature (often implemented as bold and/or reverse video). +The BSD curses library provided functions \fBstandout\fP and \fBstandend\fP +which were carried along into X/Open Curses due to their pervasive use +in legacy applications. +.PP +Some terminals in the 1980s could support a variety of video attributes, +although the BSD curses library could do nothing with those. +System V (1983) provided an improved curses library. +It defined the \fBA_\fP symbols for use by applications to manipulate the +other attributes. +There are few useful references for the chronology. +.PP +Goodheart's book +\fIUNIX Curses Explained\fP (1991) describes SVr3 (1987), +commenting on several functions: +.bP +the \fBattron\fP, \fBattroff\fP, \fBattrset\fP functions +(and most of the functions found in SVr4 but not in BSD curses) were +introduced by System V, +.bP +the alternate character set feature with \fBA_ALTCHARSET\fP was +added in SVr2 and improved in SVr3 (by adding \fBacs_map[]\fP), +.bP +\fBstart_color\fP and related color-functions were introduced by System V.3.2, +.bP +pads, soft-keys were added in SVr3, and +.PP +Goodheart did not mention the background character or the \fBcchar_t\fP type. +Those are respectively SVr4 and X/Open features. +He did mention the \fBA_\fP constants, but did not indicate their values. +Those were not the same in different systems, +even for those marked as System V. +.PP +Different Unix systems used different sizes for the bit-fields in \fBchtype\fP +for \fIcharacters\fP and \fIcolors\fP, and took into account the different +integer sizes (32-bit versus 64-bit). +.PP +This table showing the number of bits for \fBA_COLOR\fP +and \fBA_CHARTEXT\fP +was gleaned from the curses header files for +various operating systems and architectures. +The inferred architecture and notes reflect +the format and size of the defined constants +as well as clues such as the alternate character set implementation. +A 32-bit library can be used on a 64-bit system, +but not necessarily the reverse. +.PP +.RS +.TS +l l l l l l +_ _ _ _ _ _ +l l l l l l . +\fBYear\fP \fBSystem\fP \fBArch\fP \fBColor\fP \fBChar\fP \fBNotes\fP +1992 Solaris 5.2 32 6 17 SVr4 curses +1992 HPUX 9 32 no 8 SVr2 curses +1992 AIX 3.2 32 no 23 SVr2 curses +1994 OSF/1 r3 32 no 23 SVr2 curses +1995 HP-UX 10.00 32 6 16 SVr3 \*(``curses_colr\*('' +1995 HP-UX 10.00 32 6 8 SVr4, X/Open curses +1995 Solaris 5.4 32/64 7 16 X/Open curses +1996 AIX 4.2 32 7 16 X/Open curses +1996 OSF/1 r4 32 6 16 X/Open curses +1997 HP-UX 11.00 32 6 8 X/Open curses +2000 U/Win 32/64 7/31 16 uses \fBchtype\fP +.TE +.RE +.PP +Notes: +.RS 3 +.PP +Regarding HP-UX, +.bP +HP-UX 10.20 (1996) added support for 64-bit PA-RISC processors in 1996. +.bP +HP-UX 10.30 (1997) marked \*(``curses_colr\*('' obsolete. +That version of curses was dropped with HP-UX 11.30 in 2006. +.PP +Regarding OSF/1 (and Tru64), +.bP +These used 64-bit hardware. +Like ncurses, the OSF/1 curses interface is not customized for 32-bit +and 64-bit versions. +.bP +Unlike other systems which evolved from AT&T code, +OSF/1 provided a new implementation for X/Open curses. +.PP +Regarding Solaris, +.bP +The initial release of Solaris was in 1992. +.bP +The \fIxpg4\fP (X/Open) curses was developed by MKS from 1990 to 1995. +Sun's copyright began in 1996. +.bP +Sun updated the X/Open curses interface +after 64-bit support was introduced in 1997, +but did not modify the SVr4 curses interface. +.PP +Regarding U/Win, +.bP +Development of the curses library began in 1991, stopped in 2000. +.bP +Color support was added in 1998. +.bP +The library uses only \fBchtype\fP (no \fBcchar_t\fP). +.RE +.PP +Once X/Open curses was adopted in the mid-1990s, the constraint of +a 32-bit interface with many colors and wide-characters for \fBchtype\fP +became a moot point. +The \fBcchar_t\fP structure (whose size and +members are not specified in X/Open Curses) could be extended as needed. +.PP +Other interfaces are rarely used now: +.bP +BSD curses was improved slightly in 1993/1994 using Keith Bostic's +modification to make the library 8-bit clean for \fBnvi\fP(1). +He moved \fIstandout\fP attribute to a structure member. +.IP +The resulting 4.4BSD curses was replaced by ncurses over the next ten years. +.bP +U/Win is rarely used now. +.\" --------------------------------------------------------------------------- +.SH EXTENSIONS +This implementation provides the \fBA_ITALIC\fP attribute for terminals +which have the \fBenter_italics_mode\fP (\fBsitm\fP) +and \fBexit_italics_mode\fP (\fBritm\fP) capabilities. +Italics are not mentioned in X/Open Curses. +Unlike the other video attributes, \fBA_ITALIC\fP is unrelated +to the \fBset_attributes\fP capabilities. +This implementation makes the assumption that +\fBexit_attribute_mode\fP may also reset italics. +.PP +Each of the functions added by XSI Curses has a parameter \fIopts\fP, +which X/Open Curses still (after more than twenty years) documents +as reserved for future use, saying that it should be \fBNULL\fP. +This implementation uses that parameter in ABI 6 for the functions which +have a color-pair parameter to support \fIextended color pairs\fP: +.bP +For functions which modify the color, e.g., +\fBwattr_set\fP and \fBwattr_on\fP, +if \fIopts\fP is set it is treated as a pointer to \fBint\fP, +and used to set the color pair instead of the \fBshort\fP \fIpair\fP parameter. +.bP +For functions which retrieve the color, e.g., +\fBwattr_get\fP, +if \fIopts\fP is set it is treated as a pointer to \fBint\fP, +and used to retrieve the color pair as an \fBint\fP value, +in addition to +retrieving it via the standard pointer to \fBshort\fP parameter. +.bP +For functions which turn attributes off, e.g., +\fBwattr_off\fP, +the \fIopts\fP parameter is ignored except +except to check that it is \fBNULL\fP. +.\" --------------------------------------------------------------------------- .SH PORTABILITY -These functions are supported in the XSI Curses standard, Issue 4. The -standard defined the dedicated type for highlights, \fBattr_t\fR, which is not -defined in SVr4 curses. The functions taking \fBattr_t\fR arguments are -not supported under SVr4. +These functions are supported in the XSI Curses standard, Issue 4. +The standard defined the dedicated type for highlights, +\fBattr_t\fP, which was not defined in SVr4 curses. +The functions taking \fBattr_t\fP arguments were not supported under SVr4. +.PP +Very old versions of this library did not force an update of the screen +when changing the attributes. +Use \fBtouchwin\fP to force the screen to match the updated attributes. .PP The XSI Curses standard states that whether the traditional functions -\fBattron\fR/\fBattroff\fR/\fBattrset\fR can manipulate attributes other than -\fBA_BLINK\fR, \fBA_BOLD\fR, \fBA_DIM\fR, \fBA_REVERSE\fR, \fBA_STANDOUT\fR, or -\fBA_UNDERLINE\fR is "unspecified". Under this implementation as well as +\fBattron\fP/\fBattroff\fP/\fBattrset\fP can manipulate attributes other than +\fBA_BLINK\fP, \fBA_BOLD\fP, \fBA_DIM\fP, \fBA_REVERSE\fP, \fBA_STANDOUT\fP, or +\fBA_UNDERLINE\fP is \*(``unspecified\*(''. +Under this implementation as well as SVr4 curses, these functions correctly manipulate all other highlights -(specifically, \fBA_ALTCHARSET\fR, \fBA_PROTECT\fR, and \fBA_INVIS\fR). +(specifically, \fBA_ALTCHARSET\fP, \fBA_PROTECT\fP, and \fBA_INVIS\fP). .PP -XSI Curses added the new entry points, \fBattr_get\fR, \fBattr_on\fR, -\fBattr_off\fR, \fBattr_set\fR, \fBwattr_on\fR, \fBwattr_off\fR, -\fBwattr_get\fR, \fBwattr_set\fR. These are intended to work with -a new series of highlight macros prefixed with \fBWA_\fR. +XSI Curses added these entry points: +.sp +.RS +\fBattr_get\fP, \fBattr_on\fP, +\fBattr_off\fP, \fBattr_set\fP, \fBwattr_on\fP, \fBwattr_off\fP, +\fBwattr_get\fP, \fBwattr_set\fP +.RE .PP -Older versions of this library did not force an update of the screen -when changing the attributes. -Use \fBtouchwin\fR to force the screen to match the updated attributes. +The new functions are intended to work with +a new series of highlight macros prefixed with \fBWA_\fP. +The older macros have direct counterparts in the newer set of names: .PP +.RS +.ne 9 .TS -center ; +l l +_ _ _ l l . -\fBWA_NORMAL\fR Normal display (no highlight) -\fBWA_STANDOUT\fR Best highlighting mode of the terminal. -\fBWA_UNDERLINE\fR Underlining -\fBWA_REVERSE\fR Reverse video -\fBWA_BLINK\fR Blinking -\fBWA_DIM\fR Half bright -\fBWA_BOLD\fR Extra bright or bold -\fBWA_ALTCHARSET\fR Alternate character set +\fBName\fP \fBDescription\fP +\fBWA_NORMAL\fP Normal display (no highlight) +\fBWA_STANDOUT\fP Best highlighting mode of the terminal. +\fBWA_UNDERLINE\fP Underlining +\fBWA_REVERSE\fP Reverse video +\fBWA_BLINK\fP Blinking +\fBWA_DIM\fP Half bright +\fBWA_BOLD\fP Extra bright or bold +\fBWA_ALTCHARSET\fP Alternate character set .TE +.RE .PP -The XSI curses standard specifies that each pair of corresponding \fBA_\fR -and \fBWA_\fR-using functions operates on the same current-highlight +XSI curses does not assign values to these symbols, +nor does it state whether or not they are related to the +similarly-named A_NORMAL, etc.: +.bP +The XSI curses standard specifies that each pair of corresponding \fBA_\fP +and \fBWA_\fP-using functions operates on the same current-highlight information. +.bP +However, in some implementations, those symbols have unrelated values. +.IP +For example, the Solaris \fIxpg4\fP (X/Open) curses declares +\fBattr_t\fP to be an unsigned short integer (16-bits), +while \fBchtype\fP is a unsigned integer (32-bits). +The \fBWA_\fP symbols in this case are different from the \fBA_\fP symbols +because they are used for a smaller datatype which does not +represent \fBA_CHARTEXT\fP or \fBA_COLOR\fP. +.IP +In this implementation (as in many others), the values happen to be +the same because it simplifies copying information between +\fBchtype\fP and \fBcchar_t\fP variables. +.bP +Because ncurses's \fBattr_t\fP can hold a color pair +(in the \fBA_COLOR\fP field), +a call to +\fBwattr_on\fP, +\fBwattr_off\fP, or +\fBwattr_set\fP +may alter the window's color. +If the color pair information in the attribute parameter is zero, +no change is made to the window's color. +.IP +This is consistent with SVr4 curses; +X/Open Curses does not specify this. .PP The XSI standard extended conformance level adds new highlights -\fBA_HORIZONTAL\fR, \fBA_LEFT\fR, \fBA_LOW\fR, \fBA_RIGHT\fR, \fBA_TOP\fR, -\fBA_VERTICAL\fR (and corresponding \fBWA_\fR macros for each) which this -implementation does not yet support. +\fBA_HORIZONTAL\fP, \fBA_LEFT\fP, \fBA_LOW\fP, \fBA_RIGHT\fP, \fBA_TOP\fP, +\fBA_VERTICAL\fP (and corresponding \fBWA_\fP macros for each). +As of August 2013, +no known terminal provides these highlights +(i.e., via the \fBsgr1\fP capability). +.\" --------------------------------------------------------------------------- .SH RETURN VALUE -All routines return the integer \fBOK\fR on success, or \fBERR\fP on failure. +All routines return the integer \fBOK\fP on success, or \fBERR\fP on failure. .PP X/Open does not define any error conditions. .PP -This implementation returns an error -if the window pointer is null. -The \fBwcolor_set\fP function returns an error if the color pair parameter -is outside the range 0..COLOR_PAIRS-1. -This implementation also provides -\fBgetattrs\fR -for compatibility with older versions of curses. +This implementation +.bP +returns an error if the window pointer is null. +.bP +returns an error if the color pair parameter +for \fBwcolor_set\fP is outside the range 0..COLOR_PAIRS\-1. +.bP +does not return an error if either of the parameters of \fBwattr_get\fP +used for retrieving attribute or color-pair values is \fBNULL\fP. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. +.\" --------------------------------------------------------------------------- .SH SEE ALSO -\fBcurses\fR(3), -\fBcurs_addch\fR(3), -\fBcurs_addstr\fR(3), -\fBcurs_bkgd\fR(3), -\fBcurs_printw\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +.na +\fBcurses\fP(3), +\fBcurs_addch\fP(3), +\fBcurs_addstr\fP(3), +\fBcurs_bkgd\fP(3), +\fBcurs_printw\fP(3), +\fBcurs_variables\fP(3) diff --git a/lib/libcurses/curs_beep.3 b/lib/libcurses/curs_beep.3 index 66849875d19..18d34ef1ab8 100644 --- a/lib/libcurses/curs_beep.3 +++ b/lib/libcurses/curs_beep.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_beep.3,v 1.7 2010/01/12 23:21:58 nicm Exp $ +.\" $OpenBSD: curs_beep.3,v 1.8 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2003,2005 Free Software Foundation, Inc. * +.\" Copyright 2018-2020,2021 Thomas E. Dickey * +.\" Copyright 1998-2005,2010 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,38 +29,35 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_beep.3,v 1.7 2010/01/12 23:21:58 nicm Exp $ -.TH curs_beep 3 "" +.\" $Id: curs_beep.3,v 1.8 2023/10/17 09:52:08 nicm Exp $ +.TH curs_beep 3 2021-12-25 "ncurses 6.4" "Library calls" .SH NAME -\fBbeep\fR, \fBflash\fR - \fBcurses\fR bell and screen flash routines +\fBbeep\fP, \fBflash\fP \- \fBcurses\fP bell and screen flash routines .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .PP -\fBint beep(void);\fR +\fBint beep(void);\fP .br -\fBint flash(void);\fR +\fBint flash(void);\fP .br .SH DESCRIPTION -The \fBbeep\fR and \fBflash\fR routines are used to alert the terminal user. -The routine \fBbeep\fR sounds an audible alarm on the terminal, if possible; -otherwise it flashes the screen (visible bell). The routine \fBflash\fR -flashes the screen, and if that is not possible, sounds the alert. If neither -alert is possible, nothing happens. Nearly all terminals have an audible alert +The \fBbeep\fP and \fBflash\fP routines are used to alert the terminal user. +The routine \fBbeep\fP sounds an audible alarm on the terminal, if possible; +otherwise it flashes the screen (visible bell). +The routine \fBflash\fP +flashes the screen, and if that is not possible, sounds the alert. +If neither +alert is possible, nothing happens. +Nearly all terminals have an audible alert (bell or beep), but only some can flash the screen. .SH RETURN VALUE -These routines return \fBOK\fR if they succeed in beeping or flashing, -\fBERR\fR otherwise. +These routines return \fBOK\fP if they succeed in beeping or flashing, +\fBERR\fP otherwise. .SH EXTENSIONS -SVr4's beep and flash routines always returned \fBOK\fR, so it was not +SVr4's beep and flash routines always returned \fBOK\fP, so it was not possible to tell when the beep or flash failed. .SH PORTABILITY These functions are described in the XSI Curses standard, Issue 4. -Like SVr4, it specifies that they always return \fBOK\fR. +Like SVr4, it specifies that they always return \fBOK\fP. .SH SEE ALSO -\fBcurses\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3) diff --git a/lib/libcurses/curs_bkgd.3 b/lib/libcurses/curs_bkgd.3 index 6e1fc34fbea..8fc3b607c61 100644 --- a/lib/libcurses/curs_bkgd.3 +++ b/lib/libcurses/curs_bkgd.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_bkgd.3,v 1.8 2010/01/12 23:21:58 nicm Exp $ +.\" $OpenBSD: curs_bkgd.3,v 1.9 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2002,2003 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2015,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,73 +29,136 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_bkgd.3,v 1.8 2010/01/12 23:21:58 nicm Exp $ -.TH curs_bkgd 3 "" +.\" $Id: curs_bkgd.3,v 1.9 2023/10/17 09:52:08 nicm Exp $ +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.TH curs_bkgd 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBbkgdset\fR, \fBwbkgdset\fR, -\fBbkgd\fR, \fBwbkgd\fR, -\fBgetbkgd\fR - \fBcurses\fR window background manipulation routines +\fBbkgdset\fP, \fBwbkgdset\fP, +\fBbkgd\fP, \fBwbkgd\fP, +\fBgetbkgd\fP \- \fBcurses\fP window background manipulation routines .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .PP -\fBvoid bkgdset(chtype ch);\fR +\fBvoid bkgdset(chtype \fIch\fB);\fR .br -\fBvoid wbkgdset(WINDOW *win, chtype ch);\fR +\fBvoid wbkgdset(WINDOW *\fIwin, chtype \fIch\fB);\fR +.sp +\fBint bkgd(chtype \fIch\fB);\fR .br -\fBint bkgd(chtype ch);\fR -.br -\fBint wbkgd(WINDOW *win, chtype ch);\fR -.br -\fBchtype getbkgd(WINDOW *win);\fR +\fBint wbkgd(WINDOW *\fIwin\fB, chtype \fIch\fB);\fR +.sp +\fBchtype getbkgd(WINDOW *\fIwin\fB);\fR .br .SH DESCRIPTION -The \fBbkgdset\fR and \fBwbkgdset\fR routines manipulate the -background of the named window. -The window background is a \fBchtype\fR consisting of -any combination of attributes (i.e., rendition) and a character. +.SS bkgdset +The \fBbkgdset\fP and \fBwbkgdset\fP routines +set the \fIbackground\fP for a window. +A window's background is a \fBchtype\fP consisting of +any combination of attributes (i.e., rendition) and a character: +.bP The attribute part of the background is combined (OR'ed) with all non-blank -characters that are written into the window with \fBwaddch\fR. Both -the character and attribute parts of the background are combined with -the blank characters. The background becomes a property of the +characters that are written into the window with \fBwaddch\fP. +.bP +Both the character and attribute parts of the background are combined with +blank characters that are written into the window. +.PP +The background becomes a property of each character and moves with the character through any scrolling and insert/delete line/character operations. .PP To the extent possible on a particular terminal, the attribute part of the background is displayed as the graphic rendition of the character put on the screen. -.PP -The \fBbkgd\fR and \fBwbkgd\fR functions +.SS bkgd +The \fBbkgd\fP and \fBwbkgd\fP functions set the background property of the current or specified window -and then apply this setting to every character position in that window: -.PP -.RS +and then apply this setting to every character position in that window. +According to X/Open Curses, it should do this: +.bP The rendition of every character on the screen is changed to the new background rendition. -.PP +.bP Wherever the former background character appears, it is changed to the new background character. -.RE .PP -The \fBgetbkgd\fR function returns the given window's current background +Neither X/Open Curses nor the SVr4 manual pages give details about +the way the rendition of characters on the screen is updated when +\fBbkgd\fP or \fBwbkgd\fP is used to change the background character. +.PP +This implementation, like SVr4 curses, does not store the background +and window attribute contributions to each cell separately. +It updates the rendition by comparing the character, non-color attributes and +colors contained in the background. +For each cell in the window, whether or not it is blank: +.bP +The library first compares the \fIcharacter\fP, +and if it matches the current character part of the background, +it replaces that with the new background character. +.IP +When \fBbkgdset\fP is used to set the background character, +that does not update each cell in the window. +A subsequent call to \fBbkgd\fP will only modify the \fIcharacter\fP in +cells which match the current background character. +.bP +The library then checks if the cell uses color, +i.e., its color pair value is nonzero. +If not, it simply replaces the attributes and color pair in the +cell with those from the new background character. +.bP +If the cell uses color, +and that matches the color in the current background, +the library removes attributes +which may have come from the current background +and adds attributes from the new background. +It finishes by setting the cell +to use the color from the new background. +.bP +If the cell uses color, +and that does not match the color in the current background, +the library updates only the non-color attributes, +first removing those which may have come from the current background, +and then adding attributes from the new background. +.PP +If the background's character value is zero (0), a space is assumed. +.PP +If the terminal does not support color, +or if color has not been started with \fBstart_color\fP, +the new background character's color attribute will be ignored. +.SS getbkgd +The \fBgetbkgd\fP function returns the given window's current background character/attribute pair. .SH RETURN VALUE -The routines \fBbkgd\fR and \fBwbkgd\fR return the integer \fBOK\fR. -The SVr4.0 manual says "or a non-negative integer if \fBimmedok\fR is set", -but this appears to be an error. -.SH NOTES -Note that \fBbkgdset\fR and \fBbkgd\fR may be macros. -.SH PORTABILITY These functions are described in the XSI Curses standard, Issue 4. -It specifies that \fBbkgd\fR and \fBwbkgd\fR return \fBERR\fR on failure. +It specifies that \fBbkgd\fP and \fBwbkgd\fP return \fBERR\fP on failure, but gives no failure conditions. +.PP +The routines \fBbkgd\fP and \fBwbkgd\fP return the integer \fBOK\fP, +unless the library has not been initialized. +.PP +In contrast, +the SVr4.0 manual says \fBbkgd\fP and \fBwbkgd\fP may return \fBOK\fP +"or a non-negative integer if \fBimmedok\fP is set", +which refers to the return value from \fBwrefresh\fP +(used to implement the immediate repainting). +The SVr4 curses \fBwrefresh\fP returns the number of characters +written to the screen during the refresh. +This implementation does not do that. +.SH NOTES +Note that \fBbkgdset\fP and \fBbkgd\fP may be macros. +.PP +X/Open Curses mentions that the character part of the background must +be a single-byte value. +This implementation, like SVr4, checks to ensure that, +and will reuse the old background character if the check fails. +.SH PORTABILITY +These functions are described in the XSI Curses standard, Issue 4 +(X/Open Curses). .SH SEE ALSO -\fBcurses\fR(3), -\fBcurs_addch\fR(3), -\fBcurs_attr\fR(3), -\fBcurs_outopts\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +.na +\fBcurses\fP(3), +\fBcurs_addch\fP(3), +\fBcurs_attr\fP(3), +\fBcurs_outopts\fP(3) diff --git a/lib/libcurses/curs_bkgrnd.3 b/lib/libcurses/curs_bkgrnd.3 index 89260b6ea5b..44deb443fef 100644 --- a/lib/libcurses/curs_bkgrnd.3 +++ b/lib/libcurses/curs_bkgrnd.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_bkgrnd.3,v 1.1 2010/01/12 23:21:58 nicm Exp $ +.\" $OpenBSD: curs_bkgrnd.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 2002-2004,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 2002-2015,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,40 +29,47 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_bkgrnd.3,v 1.1 2010/01/12 23:21:58 nicm Exp $ -.TH curs_bkgrnd 3 "" +.\" $Id: curs_bkgrnd.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.TH curs_bkgrnd 3 2023-08-12 "ncurses 6.4" "Library calls" .SH NAME -\fBbkgrnd\fR, -\fBwbkgrnd\fR, -\fBbkgrndset\fR, -\fBwbkgrndset\fR, -\fBgetbkgrnd\fR, -\fBwgetbkgrnd\fR \- \fBcurses\fR window complex background manipulation routines +\fBbkgrnd\fP, +\fBwbkgrnd\fP, +\fBbkgrndset\fP, +\fBwbkgrndset\fP, +\fBgetbkgrnd\fP, +\fBwgetbkgrnd\fP \- \fBcurses\fP window complex background manipulation routines .SH SYNOPSIS -.PP -.B #include +\fB#include \fR .sp -\fBint bkgrnd(\fR\fB const cchar_t *\fR\fIwch\fR\fB);\fR -.br -\fBint wbkgrnd(\fR\fB WINDOW *\fR\fIwin\fR\fB, const cchar_t *\fR\fIwch\fR\fB);\fR -.br -\fBvoid bkgrndset(const cchar_t *\fR\fIwch\fR \fB);\fR +\fBint bkgrnd(\fB const cchar_t *\fIwch\fB);\fR .br -\fBvoid wbkgrndset(WINDOW *\fR\fIwin\fR\fB, const cchar_t *\fR\fIwch\fR\fB);\fR -.br -\fBint getbkgrnd(cchar_t *\fR\fIwch\fR\fB);\fR +\fBint wbkgrnd(\fB WINDOW *\fIwin\fB, const cchar_t *\fIwch\fB);\fR +.sp +\fBvoid bkgrndset(const cchar_t *\fIwch\fR \fB);\fR .br -\fBint wgetbkgrnd(WINDOW *\fR\fIwin\fR\fB, cchar_t *\fR\fIwch\fR\fB);\fR +\fBvoid wbkgrndset(WINDOW *\fIwin\fB, const cchar_t *\fIwch\fB);\fR +.sp +\fBint getbkgrnd(cchar_t *\fIwch\fB);\fR .br +\fBint wgetbkgrnd(WINDOW *\fIwin\fB, cchar_t *\fIwch\fB);\fR .SH DESCRIPTION -The \fBbkgrndset\fR and \fBwbkgrndset\fR routines manipulate the +.SS bkgrndset +The \fBbkgrndset\fP and \fBwbkgrndset\fP routines manipulate the background of the named window. -The window background is a \fBcchar_t\fR consisting of +The window background is a \fBcchar_t\fP consisting of any combination of attributes (i.e., rendition) and a complex character. +.bP The attribute part of the background is combined (OR'ed) with all non-blank -characters that are written into the window with \fBwaddch\fR. Both +characters that are written into the window with \fBwaddch\fP. +.bP +Both the character and attribute parts of the background are combined with the blank characters. +.PP The background becomes a property of the character and moves with the character through any scrolling and insert/delete line/character operations. @@ -69,40 +77,43 @@ insert/delete line/character operations. To the extent possible on a particular terminal, the attribute part of the background is displayed as the graphic rendition of the character put on the screen. -.PP -The \fBbkgrnd\fR and \fBwbkgrnd\fR functions +.SS bkgrnd +The \fBbkgrnd\fP and \fBwbkgrnd\fP functions set the background property of the current or specified window and then apply this setting to every character position in that window: -.RS -.PP +.bP The rendition of every character on the screen is changed to the new background rendition. -.PP +.bP Wherever the former background character appears, it is changed to the new background character. -.RE -.PP -The \fBgetbkgrnd\fR function returns the given window's current background -character/attribute pair via the \fBwch\fR pointer. -. +.SS getbkgrnd +The \fBgetbkgrnd\fP function returns the given window's current background +character/attribute pair via the \fBwch\fP pointer. +If the given window pointer is null, +the character is not updated (but no error returned). .SH NOTES Note that -\fBbkgrnd\fR, -\fBbkgrndset\fR, and -\fBgetbkgrnd\fR +\fBbkgrnd\fP, +\fBbkgrndset\fP, and +\fBgetbkgrnd\fP may be macros. -.SH RETURN VALUES -The \fBbkgrndset\fR and \fBwbkgrndset\fR routines do not return a value. .PP -Upon successful completion, the other functions return \fBOK\fR. -Otherwise, they return \fBERR\fR. +X/Open Curses does not provide details on how the rendition is changed. +This implementation follows the approach used in SVr4 curses, +which is explained in the manual page for \fBwbkgd\fP. +.SH RETURN VALUE +The \fBbkgrndset\fP and \fBwbkgrndset\fP routines do not return a value. +.PP +Upon successful completion, the other functions return \fBOK\fP. +Otherwise, they return \fBERR\fP: +.bP A null window pointer is treated as an error. +.bP +A null character pointer is treated as an error. +.SH PORTABILITY +These functions are described in the XSI Curses standard, Issue 4 +(X/Open Curses). .SH SEE ALSO -\fBcurses\fR(3), -\fBcurs_bkgd\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_bkgd\fP(3) diff --git a/lib/libcurses/curs_border.3 b/lib/libcurses/curs_border.3 index 1ea0dc53044..d6dd7ad3787 100644 --- a/lib/libcurses/curs_border.3 +++ b/lib/libcurses/curs_border.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_border.3,v 1.11 2010/01/12 23:21:58 nicm Exp $ +.\" $OpenBSD: curs_border.3,v 1.12 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2007,2010 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,130 +29,136 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_border.3,v 1.11 2010/01/12 23:21:58 nicm Exp $ -.TH curs_border 3 "" +.\" $Id: curs_border.3,v 1.12 2023/10/17 09:52:08 nicm Exp $ +.TH curs_border 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .na .hy 0 .SH NAME -\fBborder\fR, -\fBwborder\fR, -\fBbox\fR, -\fBhline\fR, -\fBwhline\fR, -\fBvline\fR, -\fBwvline\fR, -\fBmvhline\fR, -\fBmvwhline\fR, -\fBmvvline\fR, -\fBmvwvline\fR - create \fBcurses\fR borders, horizontal and vertical lines +\fBborder\fP, +\fBwborder\fP, +\fBbox\fP, +\fBhline\fP, +\fBwhline\fP, +\fBvline\fP, +\fBwvline\fP, +\fBmvhline\fP, +\fBmvwhline\fP, +\fBmvvline\fP, +\fBmvwvline\fP \- create \fBcurses\fP borders, horizontal and vertical lines .ad .hy .SH SYNOPSIS -\fB#include \fR -.br -\fBint border(chtype ls, chtype rs, chtype ts, chtype bs,\fR - \fBchtype tl, chtype tr, chtype bl, chtype br);\fR -.br -\fBint wborder(WINDOW *win, chtype ls, chtype rs,\fR - \fBchtype ts, chtype bs, chtype tl, chtype tr,\fR - \fBchtype bl, chtype br);\fR -.br -\fBint box(WINDOW *win, chtype verch, chtype horch);\fR -.br -\fBint hline(chtype ch, int n);\fR -.br -\fBint whline(WINDOW *win, chtype ch, int n);\fR +\fB#include \fP +.sp +\fBint border(chtype \fIls\fB, chtype \fIrs\fB, chtype \fIts\fB, chtype \fIbs\fB,\fR + \fBchtype \fItl\fB, chtype \fItr\fB, chtype \fIbl\fB, chtype \fIbr\fB);\fR .br -\fBint vline(chtype ch, int n);\fR +\fBint wborder(WINDOW *\fIwin\fB, chtype \fIls\fB, chtype \fIrs\fB,\fR + \fBchtype \fIts\fB, chtype \fIbs\fB, chtype \fItl\fB, chtype \fItr\fB,\fR + \fBchtype \fIbl\fB, chtype \fIbr\fB);\fR +.sp +\fBint box(WINDOW *\fIwin\fB, chtype \fIverch\fB, chtype \fIhorch\fB);\fR +.sp +\fBint hline(chtype \fIch\fB, int \fIn\fB);\fR .br -\fBint wvline(WINDOW *win, chtype ch, int n);\fR +\fBint whline(WINDOW *\fIwin\fB, chtype \fIch\fB, int \fIn\fB);\fR .br -\fBint mvhline(int y, int x, chtype ch, int n);\fR +\fBint vline(chtype \fIch\fB, int \fIn\fB);\fR .br -\fBint mvwhline(WINDOW *, int y, int x, chtype ch, int n);\fR +\fBint wvline(WINDOW *\fIwin\fB, chtype \fIch\fB, int \fIn\fB);\fR +.sp +\fBint mvhline(int \fIy\fB, int \fIx\fB, chtype \fIch\fB, int \fIn\fB);\fR .br -\fBint mvvline(int y, int x, chtype ch, int n);\fR +\fBint mvwhline(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, chtype \fIch\fB, int \fIn\fB);\fR .br -\fBint mvwvline(WINDOW *, int y, int x, chtype ch, int n);\fR +\fBint mvvline(int \fIy\fB, int \fIx\fB, chtype \fIch\fB, int \fIn\fB);\fR .br +\fBint mvwvline(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, chtype \fIch\fB, int \fIn\fB);\fR .SH DESCRIPTION -The \fBborder\fR, \fBwborder\fR and \fBbox\fR routines +The \fBborder\fP, \fBwborder\fP and \fBbox\fP routines draw a box around the edges of a window. Other than the window, each argument is a character with attributes: .sp .RS -\fIls\fR - left side, +\fIls\fP \- left side, .br -\fIrs\fR - right side, +\fIrs\fP \- right side, .br -\fIts\fR - top side, +\fIts\fP \- top side, .br -\fIbs\fR - bottom side, +\fIbs\fP \- bottom side, .br -\fItl\fR - top left-hand corner, +\fItl\fP \- top left-hand corner, .br -\fItr\fR - top right-hand corner, +\fItr\fP \- top right-hand corner, .br -\fIbl\fR - bottom left-hand corner, and +\fIbl\fP \- bottom left-hand corner, and .br -\fIbr\fR - bottom right-hand corner. +\fIbr\fP \- bottom right-hand corner. .RE .PP If any of these arguments is zero, then the corresponding -default values (defined in \fBcurses.h\fR) are used instead: +default values (defined in \fBcurses.h\fP) are used instead: .sp .RS -\fBACS_VLINE\fR, +\fBACS_VLINE\fP, .br -\fBACS_VLINE\fR, +\fBACS_VLINE\fP, .br -\fBACS_HLINE\fR, +\fBACS_HLINE\fP, .br -\fBACS_HLINE\fR, +\fBACS_HLINE\fP, .br -\fBACS_ULCORNER\fR, +\fBACS_ULCORNER\fP, .br -\fBACS_URCORNER\fR, +\fBACS_URCORNER\fP, .br -\fBACS_LLCORNER\fR, +\fBACS_LLCORNER\fP, .br -\fBACS_LRCORNER\fR. +\fBACS_LRCORNER\fP. .RE .PP -\fBbox(\fR\fIwin\fR\fB, \fR\fIverch\fR\fB, \fR\fIhorch\fR\fB)\fR is a shorthand -for the following call: \fBwborder(\fR\fIwin\fR\fB,\fR \fIverch\fR\fB,\fR -\fIverch\fR\fB,\fR \fIhorch\fR\fB,\fR \fIhorch\fR\fB, 0, 0, 0, 0)\fR. +\fBbox(\fIwin\fB, \fIverch\fB, \fIhorch\fB)\fR is a shorthand +for the following call: \fBwborder(\fIwin\fB,\fR \fIverch\fB,\fR +\fIverch\fB,\fR \fIhorch\fB,\fR \fIhorch\fB, 0, 0, 0, 0)\fR. .PP -The \fBhline\fR and \fBwhline\fR functions draw a horizontal (left to right) -line using \fIch\fR starting at the current cursor position in the window. The -current cursor position is not changed. The line is at most \fIn\fR characters +The \fBhline\fP and \fBwhline\fP functions draw a horizontal (left to right) +line using \fIch\fP starting at the current cursor position in the window. +The +current cursor position is not changed. +The line is at most \fIn\fP characters long, or as many as fit into the window. .PP -The \fBvline\fR and \fBwvline\fR functions draw a vertical (top to bottom) line -using \fIch\fR starting at the current cursor position in the window. The -current cursor position is not changed. The line is at most \fIn\fR characters +The \fBvline\fP and \fBwvline\fP functions draw a vertical (top to bottom) line +using \fIch\fP starting at the current cursor position in the window. +The +current cursor position is not changed. +The line is at most \fIn\fP characters long, or as many as fit into the window. .SH RETURN VALUE -All routines return the integer \fBOK\fR. The SVr4.0 manual says "or a -non-negative integer if \fBimmedok\fR is set", but this appears to be an error. +All routines return the integer \fBOK\fP. +The SVr4.0 manual says "or a +non-negative integer if \fBimmedok\fP is set", but this appears to be an error. .PP X/Open does not define any error conditions. This implementation returns an error if the window pointer is null. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. .SH NOTES -The borders generated by these functions are \fIinside\fR borders (this +The borders generated by these functions are \fIinside\fP borders (this is also true of SVr4 curses, though the fact is not documented). .PP -Note that \fBborder\fR and \fBbox\fR may be macros. +Note that \fBborder\fP and \fBbox\fP may be macros. .SH PORTABILITY These functions are described in the XSI Curses standard, Issue 4. -The standard specifies that they return \fBERR\fR on failure, +The standard specifies that they return \fBERR\fP on failure, but specifies no error conditions. .SH SEE ALSO -\fBcurses\fR(3), \fBcurs_outopts\fR(3). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), \fBcurs_outopts\fP(3). diff --git a/lib/libcurses/curs_border_set.3 b/lib/libcurses/curs_border_set.3 index 68194312be9..e0d7b98f53d 100644 --- a/lib/libcurses/curs_border_set.3 +++ b/lib/libcurses/curs_border_set.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_border_set.3,v 1.1 2010/01/12 23:21:58 nicm Exp $ +.\" $OpenBSD: curs_border_set.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 2002-2004,2005 Free Software Foundation, Inc. * +.\" Copyright 2019-2022,2023 Thomas E. Dickey * +.\" Copyright 2002-2011,2012 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,182 +29,179 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_border_set.3,v 1.1 2010/01/12 23:21:58 nicm Exp $ -.TH curs_border_set 3 "" +.\" $Id: curs_border_set.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ +.TH curs_border_set 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .na .hy 0 .SH NAME -\fBborder_set\fR, -\fBwborder_set\fR, -\fBbox_set\fR, -\fBhline_set\fR, -\fBwhline_set\fR, -\fBmvhline_set\fR, -\fBmvwhline_set\fR, -\fBvline_set\fR, -\fBwvline_set\fR, -\fBmvvline_set\fR, -\fBmvwvline_set\fR \- create \fBcurses\fR borders or lines using complex characters and renditions +\fBborder_set\fP, +\fBwborder_set\fP, +\fBbox_set\fP, +\fBhline_set\fP, +\fBwhline_set\fP, +\fBmvhline_set\fP, +\fBmvwhline_set\fP, +\fBvline_set\fP, +\fBwvline_set\fP, +\fBmvvline_set\fP, +\fBmvwvline_set\fP \- create \fBcurses\fP borders or lines using complex characters and renditions .ad .hy .SH SYNOPSIS -.PP -\fB#include \fR +\fB#include \fP .sp -\fBint border_set(\fR - \fBconst cchar_t *\fR\fIls\fR, \fBconst cchar_t *\fR\fIrs\fR, - \fBconst cchar_t *\fR\fIts\fR, \fBconst cchar_t *\fR\fIbs\fR, - \fBconst cchar_t *\fR\fItl\fR, \fBconst cchar_t *\fR\fItr\fR, - \fBconst cchar_t *\fR\fIbl\fR, \fBconst cchar_t *\fR\fIbr\fR -\fB);\fR -.br -\fBint wborder_set(\fR - \fBWINDOW *win\fR, - \fBconst cchar_t *\fR\fIls\fR, \fBconst cchar_t *\fR\fIrs\fR, - \fBconst cchar_t *\fR\fIts\fR, \fBconst cchar_t *\fR\fIbs\fR, - \fBconst cchar_t *\fR\fItl\fR, \fBconst cchar_t *\fR\fItr\fR, - \fBconst cchar_t *\fR\fIbl\fR, \fBconst cchar_t *\fR\fIbr\fR\fB);\fR -.br -\fBint box_set(\fR - \fBWINDOW *win\fR, - \fBconst cchar_t *\fR\fIverch\fR, - \fBconst cchar_t *\fR\fIhorch\fR\fB);\fR -.br -\fBint hline_set(\fR - \fBconst cchar_t *\fR\fIwch\fR, \fBint \fR\fIn\fR\fB);\fR -.br -\fBint whline_set(\fR - \fBWINDOW *\fR\fIwin\fR, - \fBconst cchar_t *\fR\fIwch\fR, \fBint \fR\fIn\fR\fB);\fR -.br -\fBint mvhline_set(\fR - \fBint \fR\fIy\fR, \fBint \fR\fIx\fR, - \fBconst cchar_t *\fR\fIwch\fR, \fBint \fR\fIn\fR\fB);\fR -.br -\fBint mvwhline_set(\fR - \fBWINDOW *\fR\fIwin\fR, - \fBint \fR\fIy\fR, \fBint \fR\fIx\fR, - \fBconst cchar_t *\fR\fIwch\fR, \fBint \fR\fIn\fR\fB);\fR -.br -\fBint vline_set(\fR - \fBconst cchar_t *\fR\fIwch\fR, \fBint \fR\fIn\fR\fB);\fR -.br -\fBint wvline_set(\fR - \fBWINDOW *\fR\fIwin\fR, - \fBconst cchar_t *\fR\fIwch\fR, \fBint \fR\fIn\fR\fB);\fR -.br -\fBint mvvline_set(\fR - \fBint \fR\fIy\fR, \fBint \fR\fIx\fR, - \fBconst cchar_t *\fR\fIwch\fR, \fBint \fR\fIn\fR\fB);\fR -.br -\fBint mvwvline_set(\fR - \fBWINDOW *\fR\fIwin\fR, - \fBint \fR\fIy\fR, \fBint \fR\fIx\fR, - \fBconst cchar_t *\fR\fIwch\fR, \fBint \fR\fIn\fR\fB);\fR -.br +\fBint border_set(\fP + \fBconst cchar_t *\fIls\fR, \fBconst cchar_t *\fIrs\fR, + \fBconst cchar_t *\fIts\fR, \fBconst cchar_t *\fIbs\fR, + \fBconst cchar_t *\fItl\fR, \fBconst cchar_t *\fItr\fR, + \fBconst cchar_t *\fIbl\fR, \fBconst cchar_t *\fIbr\fR +\fB);\fP +.br +\fBint wborder_set(\fP + \fBWINDOW *win\fP, + \fBconst cchar_t *\fIls\fR, \fBconst cchar_t *\fIrs\fR, + \fBconst cchar_t *\fIts\fR, \fBconst cchar_t *\fIbs\fR, + \fBconst cchar_t *\fItl\fR, \fBconst cchar_t *\fItr\fR, + \fBconst cchar_t *\fIbl\fR, \fBconst cchar_t *\fIbr\fB);\fR +.br +\fBint box_set(\fP + \fBWINDOW *win\fP, + \fBconst cchar_t *\fIverch\fR, + \fBconst cchar_t *\fIhorch\fB);\fR +.br +\fBint hline_set(\fP + \fBconst cchar_t *\fIwch\fR, \fBint \fIn\fB);\fR +.br +\fBint whline_set(\fP + \fBWINDOW *\fIwin\fR, + \fBconst cchar_t *\fIwch\fR, \fBint \fIn\fB);\fR +.br +\fBint mvhline_set(\fP + \fBint \fIy\fR, \fBint \fIx\fR, + \fBconst cchar_t *\fIwch\fR, \fBint \fIn\fB);\fR +.br +\fBint mvwhline_set(\fP + \fBWINDOW *\fIwin\fR, + \fBint \fIy\fR, \fBint \fIx\fR, + \fBconst cchar_t *\fIwch\fR, \fBint \fIn\fB);\fR +.br +\fBint vline_set(\fP + \fBconst cchar_t *\fIwch\fR, \fBint \fIn\fB);\fR +.br +\fBint wvline_set(\fP + \fBWINDOW *\fIwin\fR, + \fBconst cchar_t *\fIwch\fR, \fBint \fIn\fB);\fR +.br +\fBint mvvline_set(\fP + \fBint \fIy\fR, \fBint \fIx\fR, + \fBconst cchar_t *\fIwch\fR, \fBint \fIn\fB);\fR +.br +\fBint mvwvline_set(\fP + \fBWINDOW *\fIwin\fR, + \fBint \fIy\fR, \fBint \fIx\fR, + \fBconst cchar_t *\fIwch\fR, \fBint \fIn\fB);\fR .SH DESCRIPTION -.PP The -\fBborder_set\fR +\fBborder_set\fP and -\fBwborder_set\fR +\fBwborder_set\fP functions draw a border around the edges of the current or specified window. These functions do not change the cursor position, and do not wrap. .PP Other than the window, each argument is a complex character with attributes: .RS -\fIls\fR - left side, +\fIls\fP \- left side, .br -\fIrs\fR - right side, +\fIrs\fP \- right side, .br -\fIts\fR - top side, +\fIts\fP \- top side, .br -\fIbs\fR - bottom side, +\fIbs\fP \- bottom side, .br -\fItl\fR - top left-hand corner, +\fItl\fP \- top left-hand corner, .br -\fItr\fR - top right-hand corner, +\fItr\fP \- top right-hand corner, .br -\fIbl\fR - bottom left-hand corner, and +\fIbl\fP \- bottom left-hand corner, and .br -\fIbr\fR - bottom right-hand corner. +\fIbr\fP \- bottom right-hand corner. .RE .PP If any of these arguments is zero, then the corresponding -default values (defined in \fBcurses.h\fR) are used instead: +default values (defined in \fBcurses.h\fP) are used instead: .RS -\fBWACS_VLINE\fR, +\fBWACS_VLINE\fP, .br -\fBWACS_VLINE\fR, +\fBWACS_VLINE\fP, .br -\fBWACS_HLINE\fR, +\fBWACS_HLINE\fP, .br -\fBWACS_HLINE\fR, +\fBWACS_HLINE\fP, .br -\fBWACS_ULCORNER\fR, +\fBWACS_ULCORNER\fP, .br -\fBWACS_URCORNER\fR, +\fBWACS_URCORNER\fP, .br -\fBWACS_LLCORNER\fR, and +\fBWACS_LLCORNER\fP, and .br -\fBWACS_LRCORNER\fR. +\fBWACS_LRCORNER\fP. .RE .PP -\fBbox_set(\fR\fIwin\fR, \fIverch\fR\fB, \fR\fIhorch\fR\fB);\fR +\fBbox_set(\fIwin\fR, \fIverch\fB, \fIhorch\fB);\fR is a shorthand for the following call: .PP -\fBwborder_set(\fR\fIwin\fR\fB, \fR\fIverch\fR\fB, \fR\fIverch\fR\fB,\fR - \fIhorch\fR\fB, \fR\fIhorch\fR\fB, NULL, NULL, NULL, NULL);\fR +\fBwborder_set(\fIwin\fB, \fIverch\fB, \fIverch\fB,\fR + \fIhorch\fB, \fIhorch\fB, NULL, NULL, NULL, NULL);\fR .PP The -\fB*line_set\fR +\fB*line_set\fP functions use -\fIwch\fR +\fIwch\fP to draw a line starting at the current cursor position in the window. -The line is at most \fIn\fR characters long or as many as fit into the window. +The line is at most \fIn\fP characters long or as many as fit into the window. The current cursor position is not changed. .PP The -\fBhline_set\fR, -\fBmvhline_set\fR, -\fBmvwhline_set\fR, and -\fBwhline_set\fR +\fBhline_set\fP, +\fBmvhline_set\fP, +\fBmvwhline_set\fP, and +\fBwhline_set\fP functions draw a line proceeding toward the last column of the same line. .PP The -\fBvline_set\fR, -\fBmvvline_set\fR, -\fBmvwvline_set\fR, and -\fBwvline_set\fR +\fBvline_set\fP, +\fBmvvline_set\fP, +\fBmvwvline_set\fP, and +\fBwvline_set\fP functions draw a line proceeding toward the last line of the window. .br .SH NOTES -.PP Note that -\fBborder_set\fR, -\fBhline_set\fR, -\fBmvhline_set\fR, -\fBmvvline_set\fR, -\fBmvwhline_set\fR, -\fBmvwvline_set\fR, and -\fBvline_set\fR +\fBborder_set\fP, +\fBhline_set\fP, +\fBmvhline_set\fP, +\fBmvvline_set\fP, +\fBmvwhline_set\fP, +\fBmvwvline_set\fP, and +\fBvline_set\fP may be macros. -.br -.SH RETURN VALUES -.PP +.SH RETURN VALUE Upon successful completion, these functions return -\fBOK\fR. +\fBOK\fP. Otherwise, they return -\fBERR\fR. +\fBERR\fP. .PP Functions using a window parameter return an error if it is null. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. .SH SEE ALSO -\fBncurses\fR(3), -\fBcurs_border\fR(3), -\fBcurs_outopts\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBncurses\fP(3), +\fBcurs_add_wch\fP(3), +\fBcurs_border\fP(3), +\fBcurs_outopts\fP(3) diff --git a/lib/libcurses/curs_clear.3 b/lib/libcurses/curs_clear.3 index cdf6af8dd70..461ae77e76a 100644 --- a/lib/libcurses/curs_clear.3 +++ b/lib/libcurses/curs_clear.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_clear.3,v 1.7 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_clear.3,v 1.8 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2005,2007 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2016 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,82 +29,97 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_clear.3,v 1.7 2010/01/12 23:21:59 nicm Exp $ -.TH curs_clear 3 "" +.\" $Id: curs_clear.3,v 1.8 2023/10/17 09:52:08 nicm Exp $ +.TH curs_clear 3 2023-07-01 "ncurses 6.4" "Library calls" .na .hy 0 +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .SH NAME -\fBerase\fR, -\fBwerase\fR, -\fBclear\fR, -\fBwclear\fR, -\fBclrtobot\fR, -\fBwclrtobot\fR, -\fBclrtoeol\fR, -\fBwclrtoeol\fR - clear all or part of a \fBcurses\fR window +\fBerase\fP, +\fBwerase\fP, +\fBclear\fP, +\fBwclear\fP, +\fBclrtobot\fP, +\fBwclrtobot\fP, +\fBclrtoeol\fP, +\fBwclrtoeol\fP \- clear all or part of a \fBcurses\fP window .ad .hy .SH SYNOPSIS -\fB# include \fR +\fB#include \fP .sp -\fBint erase(void);\fR +\fBint erase(void);\fP .br -\fBint werase(WINDOW *win);\fR -.br -\fBint clear(void);\fR -.br -\fBint wclear(WINDOW *win);\fR -.br -\fBint clrtobot(void);\fR -.br -\fBint wclrtobot(WINDOW *win);\fR +\fBint werase(WINDOW *\fIwin\fB);\fR +.sp +\fBint clear(void);\fP .br -\fBint clrtoeol(void);\fR +\fBint wclear(WINDOW *\fIwin\fB);\fR +.sp +\fBint clrtobot(void);\fP .br -\fBint wclrtoeol(WINDOW *win);\fR +\fBint wclrtobot(WINDOW *\fIwin\fB);\fR +.sp +\fBint clrtoeol(void);\fP .br +\fBint wclrtoeol(WINDOW *\fIwin\fB);\fR .SH DESCRIPTION -The \fBerase\fR and \fBwerase\fR routines copy blanks to every +.SS erase/werase +The \fBerase\fP and \fBwerase\fP routines copy blanks to every position in the window, clearing the screen. .PP -The \fBclear\fR and \fBwclear\fR routines are like \fBerase\fR and -\fBwerase\fR, but they also call \fBclearok\fR, so that the screen is -cleared completely on the next call to \fBwrefresh\fR for that window +Blanks created by erasure have the current background rendition (as set +by \fBwbkgdset\fP(3)) merged into them. +.SS clear/wclear +The \fBclear\fP and \fBwclear\fP routines are like \fBerase\fP and +\fBwerase\fP, but they also call \fBclearok\fP(3), so that the screen is +cleared completely on the next call to \fBwrefresh\fP for that window and repainted from scratch. -.PP -The \fBclrtobot\fR and \fBwclrtobot\fR routines erase from the cursor to the -end of screen. That is, they erase all lines below the cursor in the window. +.SS clrtobot/wclrtobot +The \fBclrtobot\fP and \fBwclrtobot\fP routines erase from the cursor to the +end of screen. +That is, they erase all lines below the cursor in the window. Also, the current line to the right of the cursor, inclusive, is erased. -.PP -The \fBclrtoeol\fR and \fBwclrtoeol\fR routines erase the current line +.SS clrtoeol/wclrtoeol +The \fBclrtoeol\fP and \fBwclrtoeol\fP routines erase the current line to the right of the cursor, inclusive, to the end of the current line. -.PP -Blanks created by erasure have the current background rendition (as set -by \fBwbkgdset\fR) merged into them. .SH RETURN VALUE -All routines return the integer \fBOK\fR on success and \fBERR\fP on failure. -The SVr4.0 manual says "or a -non-negative integer if \fBimmedok\fR is set", but this appears to be an error. +All routines return the integer \fBOK\fP on success and \fBERR\fP on failure. .PP X/Open defines no error conditions. In this implementation, -functions using a window pointer parameter return an error if it is null. +.bP +functions using a window pointer parameter return an error if it is null +.bP +\fBwclrtoeol\fP returns an error +if the cursor position is about to wrap. .SH NOTES -Note that \fBerase\fR, \fBwerase\fR, \fBclear\fR, \fBwclear\fR, -\fBclrtobot\fR, and \fBclrtoeol\fR may be macros. +Note that \fBerase\fP, \fBwerase\fP, \fBclear\fP, \fBwclear\fP, +\fBclrtobot\fP, and \fBclrtoeol\fP may be macros. .SH PORTABILITY -These functions are described in the XSI Curses standard, Issue 4. The -standard specifies that they return \fBERR\fR on failure, but specifies no +These functions are described in the XSI Curses standard, Issue 4. +The +standard specifies that they return \fBERR\fP on failure, but specifies no error conditions. .PP +The SVr4.0 manual says that these functions could +return "a non-negative integer if \fBimmedok\fP(3) is set", +referring to the return-value of \fBwrefresh\fP. +In that implementation, \fBwrefresh\fP would return a count of +the number of characters written to the terminal. +.PP Some historic curses implementations had, as an undocumented feature, the -ability to do the equivalent of \fBclearok(..., 1)\fR by saying -\fBtouchwin(stdscr)\fR or \fBclear(stdscr)\fR. This will not work under +ability to do the equivalent of \fBclearok(..., 1)\fP by saying +\fBtouchwin(stdscr)\fP or \fBclear(stdscr)\fP. +This will not work under ncurses. .PP This implementation, and others such as Solaris, sets the current position to 0,0 after erasing -via \fBwerase()\fP and \fBwclear()\fP. +via \fBwerase\fP and \fBwclear\fP. That fact is not documented in other implementations, and may not be true of implementations which were not derived from SVr4 source. @@ -114,10 +130,7 @@ even for a subwindow or derived window. If you do not want to clear the screen during the next \fBwrefresh\fP, use \fBwerase\fP instead. .SH SEE ALSO -\fBcurses\fR(3), \fBcurs_outopts\fR(3), \fBcurs_refresh\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_outopts\fP(3), +\fBcurs_refresh\fP(3), +\fBcurs_variables\fP(3) diff --git a/lib/libcurses/curs_color.3 b/lib/libcurses/curs_color.3 index 7aa05201098..5f0b8a0ab2a 100644 --- a/lib/libcurses/curs_color.3 +++ b/lib/libcurses/curs_color.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_color.3,v 1.10 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_color.3,v 1.11 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2004,2005 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2016,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,223 +29,514 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_color.3,v 1.10 2010/01/12 23:21:59 nicm Exp $ -.TH curs_color 3 "" +.\" $Id: curs_color.3,v 1.11 2023/10/17 09:52:08 nicm Exp $ +.TH curs_color 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.ds n 5 .na .hy 0 .SH NAME -\fBstart_color\fR, -\fBinit_pair\fR, -\fBinit_color\fR, -\fBhas_colors\fR, -\fBcan_change_color\fR, -\fBcolor_content\fR, -\fBpair_content\fR, -\fBCOLOR_PAIR\fR - \fBcurses\fR color manipulation routines +\fBstart_color\fP, +\fBhas_colors\fP, +\fBcan_change_color\fP, +\fBinit_pair\fP, +\fBinit_color\fP, +\fBinit_extended_pair\fP, +\fBinit_extended_color\fP, +\fBcolor_content\fP, +\fBpair_content\fP, +\fBextended_color_content\fP, +\fBextended_pair_content\fP, +\fBreset_color_pairs\fP, +\fBCOLOR_PAIR\fP, +\fBPAIR_NUMBER\fP \- \fBcurses\fP color manipulation routines .ad .hy .SH SYNOPSIS -\fB# include \fR +\fB#include \fP +.sp +\fBint start_color(void);\fP +.sp +\fBbool has_colors(void);\fP .br -\fBint start_color(void);\fR +\fBbool can_change_color(void);\fP +.sp +\fBint init_pair(short \fIpair\fB, short \fIf\fB, short \fIb\fB);\fR .br -\fBint init_pair(short pair, short f, short b);\fR +\fBint init_color(short \fIcolor\fB, short \fIr\fB, short \fIg\fB, short \fIb\fB);\fR .br -\fBint init_color(short color, short r, short g, short b);\fR +/* extensions */ .br -\fBbool has_colors(void);\fR +\fBint init_extended_pair(int \fIpair\fB, int \fIf\fB, int \fIb\fB);\fR .br -\fBbool can_change_color(void);\fR +\fBint init_extended_color(int \fIcolor\fB, int \fIr\fB, int \fIg\fB, int \fIb\fB);\fR +.sp +\fBint color_content(short \fIcolor\fB, short *\fIr\fB, short *\fIg\fB, short *\fIb\fB);\fR .br -\fBint color_content(short color, short *r, short *g, short *b);\fR +\fBint pair_content(short \fIpair\fB, short *\fIf\fB, short *\fIb\fB);\fR .br -\fBint pair_content(short pair, short *f, short *b);\fR +/* extensions */ .br +\fBint extended_color_content(int \fIcolor\fB, int *\fIr\fB, int *\fIg\fB, int *\fIb\fB);\fR +.br +\fBint extended_pair_content(int \fIpair\fB, int *\fIf\fB, int *\fIb\fB);\fR +.sp +/* extensions */ +.br +\fBvoid reset_color_pairs(void);\fP +.sp +\fBint COLOR_PAIR(int \fIn\fB);\fR +.br +\fBPAIR_NUMBER(\fIattrs\fB);\fR .SH DESCRIPTION .SS Overview -\fBcurses\fR support color attributes on terminals with that capability. To -use these routines \fBstart_color\fR must be called, usually right after -\fBinitscr\fR. Colors are always used in pairs (referred to as color-pairs). +\fBcurses\fP supports color attributes on terminals with that capability. +To use these routines \fBstart_color\fP must be called, usually right after +\fBinitscr\fP. +Colors are always used in pairs (referred to as color-pairs). A color-pair consists of a foreground color (for characters) and a background -color (for the blank field on which the characters are displayed). A -programmer initializes a color-pair with the routine \fBinit_pair\fR. After it -has been initialized, \fBCOLOR_PAIR\fR(\fIn\fR), a macro defined in -\fB\fR, can be used as a new video attribute. +color (for the blank field on which the characters are displayed). +A programmer initializes a color-pair with the routine \fBinit_pair\fP. +After it has been initialized, \fBCOLOR_PAIR\fP(\fIn\fP) +can be used to convert the pair to a video attribute. .PP If a terminal is capable of redefining colors, the programmer can use the -routine \fBinit_color\fR to change the definition of a color. The routines -\fBhas_colors\fR and \fBcan_change_color\fR return \fBTRUE\fR or \fBFALSE\fR, +routine \fBinit_color\fP to change the definition of a color. +The routines \fBhas_colors\fP and \fBcan_change_color\fP +return \fBTRUE\fP or \fBFALSE\fP, depending on whether the terminal has color capabilities and whether the -programmer can change the colors. The routine \fBcolor_content\fR allows a +programmer can change the colors. +The routine \fBcolor_content\fP allows a programmer to extract the amounts of red, green, and blue components in an -initialized color. The routine \fBpair_content\fR allows a programmer to find +initialized color. +The routine \fBpair_content\fP allows a programmer to find out how a given color-pair is currently defined. -.SS Routine Descriptions -The \fBstart_color\fR routine requires no arguments. It must be -called if the programmer wants to use colors, and before any other -color manipulation routine is called. It is good practice to call -this routine right after \fBinitscr\fR. \fBstart_color\fR initializes -eight basic colors (black, red, green, yellow, blue, magenta, cyan, -and white), and two global variables, \fBCOLORS\fR and -\fBCOLOR_PAIRS\fR (respectively defining the maximum number of colors -and color-pairs the terminal can support). It also restores the -colors on the terminal to the values they had when the terminal was -just turned on. -.PP -The \fBinit_pair\fR routine changes the definition of a color-pair. It takes -three arguments: the number of the color-pair to be changed, the foreground -color number, and the background color number. -For portable applications: -.TP 5 -- -The value of the first argument -must be between \fB1\fR and \fBCOLOR_PAIRS-1\fR. -.TP 5 -- -The value of the second and -third arguments must be between 0 and \fBCOLORS\fR. -Color pair 0 is assumed to be white on black, +.SS Color Rendering +The \fBcurses\fP library combines these inputs to produce the +actual foreground and background colors shown on the screen: +.bP +per-character video attributes (e.g., via \fBwaddch\fP), +.bP +the window attribute (e.g., by \fBwattrset\fP), and +.bP +the background character (e.g., \fBwbkgdset\fP). +.PP +Per-character and window attributes are usually set by a parameter containing +video attributes including a color pair value. +Some functions such as \fBwattr_set\fP use a separate parameter which +is the color pair number. +.PP +The background character is a special case: it includes a character value, +just as if it were passed to \fBwaddch\fP. +.PP +The \fBcurses\fP library does the actual work of combining these color +pairs in an internal function called from \fBwaddch\fP: +.bP +If the parameter passed to \fBwaddch\fP is \fIblank\fP, +and it uses the special color pair 0, +.RS +.bP +\fBcurses\fP next checks the window attribute. +.bP +If the window attribute does not use color pair 0, +\fBcurses\fP uses the color pair from the window attribute. +.bP +Otherwise, \fBcurses\fP uses the background character. +.RE +.bP +If the parameter passed to \fBwaddch\fP is \fInot blank\fP, +or it does not use the special color pair 0, +\fBcurses\fP prefers the color pair from the parameter, +if it is nonzero. +Otherwise, it tries the window attribute next, and finally the +background character. +.PP +Some \fBcurses\fP functions such as \fBwprintw\fP call \fBwaddch\fP. +Those do not combine its parameter with a color pair. +Consequently those calls use only the window attribute or +the background character. +.SH CONSTANTS +In \fB\fP the following macros are defined. +These are the standard colors (ISO-6429). +\fBcurses\fP also assumes that \fBCOLOR_BLACK\fP is the default +background color for all terminals. +.PP +.nf + \fBCOLOR_BLACK\fP + \fBCOLOR_RED\fP + \fBCOLOR_GREEN\fP + \fBCOLOR_YELLOW\fP + \fBCOLOR_BLUE\fP + \fBCOLOR_MAGENTA\fP + \fBCOLOR_CYAN\fP + \fBCOLOR_WHITE\fP +.fi +.PP +Some terminals support more than the eight (8) \*(``ANSI\*('' colors. +There are no standard names for those additional colors. +.SH VARIABLES +.SS COLORS +is initialized by \fBstart_color\fP to the maximum number of colors +the terminal can support. +.SS COLOR_PAIRS +is initialized by \fBstart_color\fP to the maximum number of color pairs +the terminal can support. +.SH FUNCTIONS +.SS start_color +The \fBstart_color\fP routine requires no arguments. +It must be called if the programmer wants to use colors, and before any other +color manipulation routine is called. +It is good practice to call this routine right after \fBinitscr\fP. +\fBstart_color\fP does this: +.bP +It initializes two global variables, \fBCOLORS\fP and +\fBCOLOR_PAIRS\fP (respectively defining the maximum number of colors +and color-pairs the terminal can support). +.bP +It initializes the special color pair \fB0\fP to the default foreground +and background colors. +No other color pairs are initialized. +.bP +It restores the colors on the terminal to the values +they had when the terminal was just turned on. +.bP +If the terminal supports the \fBinitc\fP (\fBinitialize_color\fP) capability, +\fBstart_color\fP +initializes its internal table representing the +red, green, and blue components of the color palette. +.IP +The components depend on whether the terminal uses +CGA (aka \*(``ANSI\*('') or +HLS (i.e., the \fBhls\fP (\fBhue_lightness_saturation\fP) capability is set). +The table is initialized first for eight basic colors +(black, red, green, yellow, blue, magenta, cyan, and white), +using weights that depend upon the CGA/HLS choice. +For \*(``ANSI\*('' colors the weights are \fB680\fP or \fB0\fP +depending on whether the corresponding +red, green, or blue component is used or not. +That permits using \fB1000\fP to represent bold/bright colors. +After the initial eight colors +(if the terminal supports more than eight colors) +the components are initialized using the same pattern, +but with weights of \fB1000\fP. +SVr4 uses a similar scheme, but uses \fB1000\fP +for the components of the initial eight colors. +.IP +\fBstart_color\fP does not attempt to set the terminal's color palette +to match its built-in table. +An application may use \fBinit_color\fP to alter the internal table +along with the terminal's color. +.PP +These limits apply to color values and color pairs. +Values outside these limits are not legal, and may result in a runtime error: +.bP +\fBCOLORS\fP corresponds to the terminal database's \fBmax_colors\fP capability, +(see \fBterminfo\fP(\*n)). +.bP +color values are expected to be in the range \fB0\fP to \fBCOLORS\-1\fP, +inclusive (including \fB0\fP and \fBCOLORS\-1\fP). +.bP +a special color value \fB\-1\fP is used in certain extended functions +to denote the \fIdefault color\fP (see \fBuse_default_colors\fP(3)). +.bP +\fBCOLOR_PAIRS\fP corresponds to +the terminal database's \fBmax_pairs\fP capability, +(see \fBterminfo\fP(\*n)). +.bP +legal color pair values are in the range \fB1\fP to \fBCOLOR_PAIRS\-1\fP, +inclusive. +.bP +color pair \fB0\fP is special; it denotes \*(``no color\*(''. +.IP +Color pair \fB0\fP is assumed to be white on black, but is actually whatever the terminal implements before color is initialized. It cannot be modified by the application. +.SS has_colors +The \fBhas_colors\fP routine requires no arguments. +It returns \fBTRUE\fP if +the terminal can manipulate colors; otherwise, it returns \fBFALSE\fP. +This routine facilitates writing terminal-independent programs. +For example, a programmer can use it to decide +whether to use color or some other video attribute. +.SS can_change_color +The \fBcan_change_color\fP routine requires no arguments. +It returns \fBTRUE\fP if the terminal supports colors +and can change their definitions; +other, it returns \fBFALSE\fP. +This routine facilitates writing terminal-independent programs. +.SS init_pair +The \fBinit_pair\fP routine changes the definition of a color-pair. +It takes three arguments: +the number of the color-pair to be changed, the foreground +color number, and the background color number. +For portable applications: +.bP +The first argument must be a legal color pair value. +If default colors are used (see \fBuse_default_colors\fP(3)) +the upper limit is adjusted to allow for extra pairs which use +a default color in foreground and/or background. +.bP +The second and third arguments must be legal color values. .PP -If the color-pair was previously -initialized, the screen is refreshed and all occurrences of that color-pair +If the color-pair was previously initialized, +the screen is refreshed and all occurrences of that color-pair are changed to the new definition. .PP -As an extension, ncurses allows you to set color pair 0 via -the \fBassume_default_colors\fR routine, or to specify the use of -default colors (color number \fB-1\fR) if you first invoke the -\fBuse_default_colors\fR routine. -.PP -The \fBinit_color\fR routine changes the definition of a color. It takes four -arguments: the number of the color to be changed followed by three RGB values -(for the amounts of red, green, and blue components). The value of the first -argument must be between \fB0\fR and \fBCOLORS\fR. (See the section -\fBColors\fR for the default color index.) Each of the last three arguments -must be a value between 0 and 1000. When \fBinit_color\fR is used, all +As an extension, ncurses allows you to set color pair \fB0\fP via +the \fBassume_default_colors\fP(3) routine, or to specify the use of +default colors (color number \fB\-1\fP) if you first invoke the +\fBuse_default_colors\fP(3) routine. +.SS init_extended_pair +Because \fBinit_pair\fP uses signed \fBshort\fPs for its parameters, +that limits color-pairs and color-values +to 32767 on modern hardware. +The extension \fBinit_extended_pair\fP uses \fBint\fPs +for the color-pair and color-value, +allowing a larger number of colors to be supported. +.SS init_color +The \fBinit_color\fP routine changes the definition of a color. +It takes four arguments: +the number of the color to be changed followed by three RGB values +(for the amounts of red, green, and blue components). +.bP +The first argument must be a legal color value; +default colors are not allowed here. +(See the section \fBColors\fP for the default color index.) +.bP +Each of the last three arguments +must be a value in the range \fB0\fP through \fB1000\fP. +.PP +When \fBinit_color\fP is used, all occurrences of that color on the screen immediately change to the new definition. -.PP -The \fBhas_colors\fR routine requires no arguments. It returns \fBTRUE\fR if -the terminal can manipulate colors; otherwise, it returns \fBFALSE\fR. This -routine facilitates writing terminal-independent programs. For example, a -programmer can use it to decide whether to use color or some other video -attribute. -.PP -The \fBcan_change_color\fR routine requires no arguments. It returns -\fBTRUE\fR if the terminal supports colors and can change their definitions; -other, it returns \fBFALSE\fR. This routine facilitates writing -terminal-independent programs. -.PP -The \fBcolor_content\fR routine gives programmers a way to find the intensity -of the red, green, and blue (RGB) components in a color. It requires four -arguments: the color number, and three addresses of \fBshort\fRs for storing +.SS init_extended_color +Because \fBinit_color\fP uses signed \fBshort\fPs for its parameters, +that limits color-values and their red, green, and blue components +to 32767 on modern hardware. +The extension \fBinit_extended_color\fP uses \fBint\fPs +for the color value and +for setting the red, green, and blue components, +allowing a larger number of colors to be supported. +.SS color_content +The \fBcolor_content\fP routine gives programmers a way to find the intensity +of the red, green, and blue (RGB) components in a color. +It requires four arguments: the color number, and three addresses +of \fBshort\fRs for storing the information about the amounts of red, green, and blue components in the -given color. The value of the first argument must be between 0 and -\fBCOLORS\fR. The values that are stored at the addresses pointed to by the -last three arguments are between 0 (no component) and 1000 (maximum amount of -component). -.PP -The \fBpair_content\fR routine allows programmers to find out what colors a -given color-pair consists of. It requires three arguments: the color-pair +given color. +.bP +The first argument must be a legal color value, i.e., +\fB0\fP through \fBCOLORS\-1\fP, inclusive. +.bP +The values that are stored at the addresses pointed to by the +last three arguments are in the range +\fB0\fP (no component) through \fB1000\fP +(maximum amount of component), inclusive. +.SS extended_color_content +Because \fBcolor_content\fP uses signed \fBshort\fPs for its parameters, +that limits color-values and their red, green, and blue components +to 32767 on modern hardware. +The extension \fBextended_color_content\fP uses \fBint\fPs +for the color value and +for returning the red, green, and blue components, +allowing a larger number of colors to be supported. +.SS pair_content +The \fBpair_content\fP routine allows programmers to find out what colors a +given color-pair consists of. +It requires three arguments: the color-pair number, and two addresses of \fBshort\fRs for storing the foreground and the -background color numbers. The value of the first argument must be between 1 -and \fBCOLOR_PAIRS-1\fR. The values that are stored at the addresses pointed -to by the second and third arguments are between 0 and \fBCOLORS\fR. -.SS Colors -In \fB\fR the following macros are defined. These are the default -colors. \fBcurses\fR also assumes that \fBCOLOR_BLACK\fR is the default -background color for all terminals. -.PP -.nf - \fBCOLOR_BLACK\fR - \fBCOLOR_RED\fR - \fBCOLOR_GREEN\fR - \fBCOLOR_YELLOW\fR - \fBCOLOR_BLUE\fR - \fBCOLOR_MAGENTA\fR - \fBCOLOR_CYAN\fR - \fBCOLOR_WHITE\fR -.fi +background color numbers. +.bP +The first argument must be a legal color value, +i.e., in the range \fB1\fP through \fBCOLOR_PAIRS\-1\fP, inclusive. +.bP +The values that are stored at the addresses pointed +to by the second and third arguments are in the +range \fB0\fP through \fBCOLORS\fP, inclusive. +.SS extended_pair_content +Because \fBpair_content\fP uses signed \fBshort\fPs for its parameters, +that limits color-pair and color-values to 32767 on modern hardware. +The extension \fBextended_pair_content\fP uses \fBint\fPs +for the color pair and +for returning the foreground and background colors, +allowing a larger number of colors to be supported. +.SS reset_color_pairs +The extension \fBreset_color_pairs\fP tells ncurses to discard all +of the color-pair information which was set with \fBinit_pair\fP. +It also touches the current- and standard-screens, allowing an application to +switch color palettes rapidly. +.SS PAIR_NUMBER +\fBPAIR_NUMBER(\fIattrs\fR) extracts the color +value from its \fIattrs\fP parameter and returns it as a color pair number. +.SS COLOR_PAIR +Its inverse \fBCOLOR_PAIR(\fIn\fB)\fR converts a color pair number +to an attribute. +Attributes can hold color pairs in the range 0 to 255. +If you need a color pair larger than that, you must use functions +such as \fBattr_set\fP (which pass the color pair as a separate parameter) +rather than the legacy functions such as \fBattrset\fP. .SH RETURN VALUE -The routines \fBcan_change_color()\fR and \fBhas_colors()\fR return \fBTRUE\fR -or \fBFALSE\fR. +The routines \fBcan_change_color\fP and \fBhas_colors\fP return \fBTRUE\fP +or \fBFALSE\fP. .PP -All other routines return the integer \fBERR\fR upon failure and an \fBOK\fR -(SVr4 specifies only "an integer value other than \fBERR\fR") upon successful -completion. +All other routines return the integer \fBERR\fP upon failure and an \fBOK\fP +(SVr4 specifies only \*(``an integer value +other than \fBERR\fP\*('') upon successful completion. .PP X/Open defines no error conditions. -This implementation will return \fBERR\fR on attempts to -use color values outside the range 0 to COLORS-1 +SVr4 does document some error conditions which apply in general: +.bP +This implementation will return \fBERR\fP on attempts to +use color values outside the range \fB0\fP to \fBCOLORS\fP\-1 (except for the default colors extension), -or use color pairs outside the range 0 to COLOR_PAIR-1. -Color values used in \fBinit_color\fP must be in the range 0 to 1000. +or use color pairs outside the range \fB0\fP to \fBCOLOR_PAIRS\-1\fP. +.IP +Color values used in \fBinit_color\fP must be +in the range \fB0\fP to \fB1000\fP. +.IP An error is returned from all functions if the terminal has not been initialized. +.IP An error is returned from secondary functions such as \fBinit_pair\fP if \fBstart_color\fP was not called. -.RS +.bP +SVr4 does much the same, except that +it returns \fBERR\fP from \fBpair_content\fP if the pair was not initialized +using \fBinit_pairs\fP +and +it returns \fBERR\fP from \fBcolor_content\fP +if the terminal does not support changing colors. +.IP +This implementation does not return \fBERR\fP for either case. +.PP +Specific functions make additional checks: +.RS 3 .TP 5 \fBinit_color\fP returns an error if the terminal does not support -this feature, e.g., if the \fIinitialize_color\fP capability is absent +this feature, e.g., if the \fBinitialize_color\fP capability is absent from the terminal description. .TP 5 \fBstart_color\fP -returns an error -If the color table cannot be allocated. +returns an error if the color table cannot be allocated. .RE .SH NOTES -In the \fIncurses\fR implementation, there is a separate color activation flag, -color palette, color pairs table, and associated COLORS and COLOR_PAIRS counts -for each screen; the \fBstart_color\fR function only affects the current -screen. The SVr4/XSI interface is not really designed with this in mind, and +In the \fBncurses\fP implementation, there is a separate color activation flag, +color palette, color pairs table, +and associated \fBCOLORS\fP and \fBCOLOR_PAIRS\fP counts +for each screen; the \fBstart_color\fP function only affects the current +screen. +The SVr4/XSI interface is not really designed with this in mind, and historical implementations may use a single shared color palette. .PP -Note that setting an implicit background color via a color pair affects only -character cells that a character write operation explicitly touches. To change +Setting an implicit background color via a color pair affects only +character cells that a character write operation explicitly touches. +To change the background color used when parts of a window are blanked by erasing or -scrolling operations, see \fBcurs_bkgd\fR(3). +scrolling operations, see \fBcurs_bkgd\fP(3). .PP -Several caveats apply on 386 and 486 machines with VGA-compatible graphics: -.TP 5 -- -COLOR_YELLOW is actually brown. To get yellow, use COLOR_YELLOW combined with -the \fBA_BOLD\fR attribute. -.TP 5 -- -The A_BLINK attribute should in theory cause the background to go bright. This -often fails to work, and even some cards for which it mostly works (such as the +Several caveats apply on older x86 machines +(e.g., i386, i486) with VGA-compatible graphics: +.bP +COLOR_YELLOW is actually brown. +To get yellow, use COLOR_YELLOW combined with the \fBA_BOLD\fP attribute. +.bP +The A_BLINK attribute should in theory cause the background to go bright. +This often fails to work, and even some cards for which it mostly works +(such as the Paradise and compatibles) do the wrong thing when you try to set a bright -"yellow" background (you get a blinking yellow foreground instead). -.TP 5 -- +\*(``yellow\*('' background (you get a blinking yellow foreground instead). +.bP Color RGB values are not settable. +.SH HISTORY +SVr3.2 introduced color support to curses in 1987. +.PP +SVr4 made internal changes, +e.g., moving the storage for the color state +from \fBSP\fP (the \fBSCREEN\fP structure) +to \fBcur_term\fP (the \fBTERMINAL\fP structure), +but provided the same set of library functions. +.PP +SVr4 curses limits the number of color pairs to 64, +reserving color pair zero (0) as the terminal's initial uncolored state. +This limit arises because the color pair information is a bitfield +in the \fBchtype\fP data type (denoted by \fBA_COLOR\fP). +.PP +Other implementations of curses had different limits: +.bP +PCCurses (1987-1990) provided for only eight (8) colors. +.bP +PDCurses (1992-present) inherited the 8-color limitation from PCCurses, +but changed this to 256 in version 2.5 (2001), +along with changing \fBchtype\fP from 16-bits to 32-bits. +.bP +X/Open Curses (1992-present) +added a new structure \fBcchar_t\fP to store the character, +attributes and color-pair values, allowing increased range of color-pairs. +Both color-pairs and color-values used a signed \fBshort\fP, +limiting values to 15 bits. +.bP +ncurses (1992-present) uses eight bits for \fBA_COLOR\fP in \fBchtype\fP values. +.IP +Version 5.3 provided a wide-character interface (2002), +but left color-pairs as part of the attributes-field. +.IP +Since version 6 (2015), +ncurses uses a separate \fBint\fP for color-pairs in the \fBcchar_t\fP values. +When those color-pair values fit in 8 bits, +ncurses allows color-pairs to be manipulated +via the functions using \fBchtype\fP values. +.bP +NetBSD curses used 6 bits from +2000 (when colors were first supported) until 2004. +At that point, NetBSD changed to use 10 bits. +As of 2021, that size is unchanged. +Like ncurses before version 6, +the NetBSD color-pair information is stored in +the attributes field of \fBcchar_t\fP, limiting the number of color-pairs +by the size of the bitfield. .SH PORTABILITY +.SS Extensions +The functions marked as extensions were designed for \fBncurses\fP(3), +and are not found in SVr4 curses, 4.4BSD curses, +or any other previous version of curses. +.SS Standards This implementation satisfies XSI Curses's minimum maximums -for \fBCOLORS\fR and \fBCOLOR_PAIRS\fR. +for \fBCOLORS\fP and \fBCOLOR_PAIRS\fP. .PP The \fBinit_pair\fP routine accepts negative values of foreground -and background color to support the \fBuse_default_colors\fP extension, +and background color to support the \fBuse_default_colors\fP(3) extension, but only if that routine has been first invoked. .PP -The assumption that \fBCOLOR_BLACK\fR is the default +The assumption that \fBCOLOR_BLACK\fP is the default background color for all terminals can be modified using the -\fBassume_default_colors\fP extension. +\fBassume_default_colors\fP(3) extension. .PP This implementation checks the pointers, e.g., for the values returned by \fBcolor_content\fP and \fBpair_content\fP, and will treat those as optional parameters when null. +.PP +X/Open Curses does not specify a limit for the number of colors and +color pairs which a terminal can support. +However, in its use of \fBshort\fP for the parameters, +it carries over SVr4's implementation detail for the compiled +terminfo database, which uses signed 16-bit numbers. +This implementation provides extended versions of those functions +which use \fBshort\fP parameters, +allowing applications to use larger color- and pair-numbers. +.PP +The \fBreset_color_pairs\fP function is an extension of ncurses. .SH SEE ALSO -\fBcurses\fR(3), -\fBcurs_initscr\fR(3), -\fBcurs_attr\fR(3), -\fBdefault_colors\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_initscr\fP(3), +\fBcurs_attr\fP(3), +\fBcurs_variables\fP(3), +\fBdefault_colors\fP(3) diff --git a/lib/libcurses/curs_delch.3 b/lib/libcurses/curs_delch.3 index 143fbcc0f12..8f07abce0f0 100644 --- a/lib/libcurses/curs_delch.3 +++ b/lib/libcurses/curs_delch.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_delch.3,v 1.7 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_delch.3,v 1.8 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2000,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2006,2010 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,45 +29,49 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_delch.3,v 1.7 2010/01/12 23:21:59 nicm Exp $ -.TH curs_delch 3 "" +.\" $Id: curs_delch.3,v 1.8 2023/10/17 09:52:08 nicm Exp $ +.TH curs_delch 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .SH NAME -\fBdelch\fR, -\fBwdelch\fR, -\fBmvdelch\fR, -\fBmvwdelch\fR - delete character under the cursor in a \fBcurses\fR window +\fBdelch\fP, +\fBwdelch\fP, +\fBmvdelch\fP, +\fBmvwdelch\fP \- delete character under the cursor in a \fBcurses\fP window .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint delch(void);\fR +\fBint delch(void);\fP .br -\fBint wdelch(WINDOW *win);\fR +\fBint wdelch(WINDOW *\fIwin\fB);\fR .br -\fBint mvdelch(int y, int x);\fR -.br -\fBint mvwdelch(WINDOW *win, int y, int x);\fR +\fBint mvdelch(int \fIy\fB, int \fIx\fB);\fR .br +\fBint mvwdelch(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB);\fR .SH DESCRIPTION These routines delete the character under the cursor; all characters to the right of the cursor on the same line are moved to the left one position and the -last character on the line is filled with a blank. The cursor position does -not change (after moving to \fIy\fR, \fIx\fR, if specified). (This does not +last character on the line is filled with a blank. +The cursor position does +not change (after moving to \fIy\fP, \fIx\fP, if specified). +(This does not imply use of the hardware delete character feature.) .SH RETURN VALUE -All routines return the integer \fBERR\fR upon failure and an \fBOK\fR (SVr4 -specifies only "an integer value other than \fBERR\fR") upon successful +All routines return the integer \fBERR\fP upon failure and an \fBOK\fP (SVr4 +specifies only "an integer value other than \fBERR\fP") upon successful completion. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. .SH NOTES -Note that \fBdelch\fR, \fBmvdelch\fR, and \fBmvwdelch\fR may be macros. +Note that \fBdelch\fP, \fBmvdelch\fP, and \fBmvwdelch\fP may be macros. .SH PORTABILITY -These functions are described in the XSI Curses standard, Issue 4. The -standard specifies that they return \fBERR\fR on failure, but specifies no +These functions are described in the XSI Curses standard, Issue 4. +The +standard specifies that they return \fBERR\fP on failure, but specifies no error conditions. .SH SEE ALSO -\fBcurses\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3) diff --git a/lib/libcurses/curs_deleteln.3 b/lib/libcurses/curs_deleteln.3 index cf34da5b26f..5af86330a89 100644 --- a/lib/libcurses/curs_deleteln.3 +++ b/lib/libcurses/curs_deleteln.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_deleteln.3,v 1.10 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_deleteln.3,v 1.11 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2007,2010 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,66 +29,66 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_deleteln.3,v 1.10 2010/01/12 23:21:59 nicm Exp $ -.TH curs_deleteln 3 "" +.\" $Id: curs_deleteln.3,v 1.11 2023/10/17 09:52:08 nicm Exp $ +.TH curs_deleteln 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBdeleteln\fR, -\fBwdeleteln\fR, -\fBinsdelln\fR, -\fBwinsdelln\fR, -\fBinsertln\fR, -\fBwinsertln\fR - delete and insert lines in a \fBcurses\fR window +\fBdeleteln\fP, +\fBwdeleteln\fP, +\fBinsdelln\fP, +\fBwinsdelln\fP, +\fBinsertln\fP, +\fBwinsertln\fP \- delete and insert lines in a \fBcurses\fP window .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint deleteln(void);\fR +\fBint deleteln(void);\fP .br -\fBint wdeleteln(WINDOW *win);\fR -.br -\fBint insdelln(int n);\fR -.br -\fBint winsdelln(WINDOW *win, int n);\fR -.br -\fBint insertln(void);\fR +\fBint wdeleteln(WINDOW *\fIwin\fB);\fR +.sp +\fBint insdelln(int \fIn\fB);\fR .br -\fBint winsertln(WINDOW *win);\fR +\fBint winsdelln(WINDOW *\fIwin\fB, int \fIn\fB);\fR +.sp +\fBint insertln(void);\fP .br +\fBint winsertln(WINDOW *\fIwin\fB);\fR .SH DESCRIPTION -The \fBdeleteln\fR and \fBwdeleteln\fR routines delete the line under the +The \fBdeleteln\fP and \fBwdeleteln\fP routines delete the line under the cursor in the window; all lines below the current line are moved up one line. -The bottom line of the window is cleared. The cursor position does not change. +The bottom line of the window is cleared. +The cursor position does not change. .PP -The \fBinsdelln\fR and \fBwinsdelln\fR routines, for positive \fIn\fR, insert -\fIn\fR lines into the specified window above the current line. The \fIn\fR -bottom lines are lost. For negative \fIn\fR, delete \fIn\fR lines (starting -with the one under the cursor), and move the remaining lines up. The bottom -\fIn\fR lines are cleared. The current cursor position remains the same. +The \fBinsdelln\fP and \fBwinsdelln\fP routines, for positive \fIn\fP, insert +\fIn\fP lines into the specified window above the current line. +The \fIn\fP +bottom lines are lost. +For negative \fIn\fP, delete \fIn\fP lines (starting +with the one under the cursor), and move the remaining lines up. +The bottom +\fIn\fP lines are cleared. +The current cursor position remains the same. .PP -The \fBinsertln\fR and \fBwinsertln\fR routines insert a blank line above the +The \fBinsertln\fP and \fBwinsertln\fP routines insert a blank line above the current line and the bottom line is lost. .SH RETURN VALUE -All routines return the integer \fBERR\fR upon failure and an \fBOK\fR (SVr4 -specifies only "an integer value other than \fBERR\fR") upon successful +All routines return the integer \fBERR\fP upon failure and an \fBOK\fP (SVr4 +specifies only "an integer value other than \fBERR\fP") upon successful completion. .PP X/Open defines no error conditions. In this implementation, if the window parameter is null, an error is returned. .SH PORTABILITY -These functions are described in the XSI Curses standard, Issue 4. The -standard specifies that they return \fBERR\fR on failure, but specifies no +These functions are described in the XSI Curses standard, Issue 4. +The +standard specifies that they return \fBERR\fP on failure, but specifies no error conditions. .SH NOTES -Note that all but \fBwinsdelln\fR may be macros. +Note that all but \fBwinsdelln\fP may be macros. .PP These routines do not require a hardware line delete or insert feature in the -terminal. In fact, they will not use hardware line delete/insert unless -\fBidlok(..., TRUE)\fR has been set on the current window. +terminal. +In fact, they will not use hardware line delete/insert unless +\fBidlok(..., TRUE)\fP has been set on the current window. .SH SEE ALSO -\fBcurses\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3) diff --git a/lib/libcurses/curs_extend.3 b/lib/libcurses/curs_extend.3 index f8629c72438..e3aea028cdf 100644 --- a/lib/libcurses/curs_extend.3 +++ b/lib/libcurses/curs_extend.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_extend.3,v 1.6 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_extend.3,v 1.7 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1999-2004,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1999-2010,2016 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -30,8 +31,12 @@ .\" .\" Author: Thomas E. Dickey 1999-on .\" -.\" $Id: curs_extend.3,v 1.6 2010/01/12 23:21:59 nicm Exp $ -.TH curs_extend 3 "" +.\" $Id: curs_extend.3,v 1.7 2023/10/17 09:52:08 nicm Exp $ +.TH curs_extend 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .SH NAME \fBcurses_version\fP, \fBuse_extended_names\fP \- miscellaneous curses extensions @@ -41,47 +46,51 @@ .sp \fBconst char * curses_version(void);\fP .br -\fBint use_extended_names(bool enable);\fP +\fBint use_extended_names(bool \fIenable\fB);\fR .SH DESCRIPTION These functions are extensions to the curses library which do not fit easily into other categories. -.PP -Use -.I curses_version() -to get the version number, including patch level of the library, e.g., -.B 5.0.19991023 -.PP -The -.I use_extended_names() +.SS curses_version +Use \fBcurses_version\fP +to get the version number, including patch level of the library, +prefixed by \*(``ncurses\*('', e.g., +.RS +.sp +.B ncurses 5.0.19991023 +.RE +.SS use_extended_names +The \fBuse_extended_names\fP function controls whether the calling application is able to use user-defined or nonstandard names which may be compiled into the terminfo description, i.e., via the terminfo or termcap interfaces. Normally these names are available for use, since the essential decision -is made by using the \fB-x\fP option of \fBtic\fP to compile +is made by using the \fB\-x\fP option of \fBtic\fP to compile extended terminal definitions. However you can disable this feature to ensure compatibility with other implementations of curses. +.SH RETURN VALUE +\fBcurses_version\fP returns a pointer to static memory; you should not free +this in your application. +.PP +\fBuse_extended_names\fP returns the previous state, allowing you to +save this and restore it. .SH PORTABILITY -These routines are specific to ncurses. They were not supported on -Version 7, BSD or System V implementations. It is recommended that +These routines are specific to ncurses. +They were not supported on +Version 7, BSD or System V implementations. +It is recommended that any code depending on them be conditioned using NCURSES_VERSION. .SH SEE ALSO -\fBcurs_getch\fR(3), -\fBcurs_mouse\fR(3), -\fBcurs_print\fR(3), -\fBcurs_util\fR(3), -\fBdefault_colors\fR(3), -\fBdefine_key\fR(3), -\fBkeybound\fR(3), -\fBkeyok\fR(3), -\fBresizeterm\fR(3), -\fBwresize\fR(3). +\fBcurs_getch\fP(3), +\fBcurs_mouse\fP(3), +\fBcurs_print\fP(3), +\fBcurs_util\fP(3), +\fBdefault_colors\fP(3), +\fBdefine_key\fP(3), +\fBkeybound\fP(3), +\fBkeyok\fP(3), +\fBresizeterm\fP(3), +\fBwresize\fP(3). .SH AUTHOR Thomas Dickey. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: diff --git a/lib/libcurses/curs_get_wch.3 b/lib/libcurses/curs_get_wch.3 index f3b9f0d29be..459e45ed532 100644 --- a/lib/libcurses/curs_get_wch.3 +++ b/lib/libcurses/curs_get_wch.3 @@ -1,6 +1,7 @@ -.\" $OpenBSD: curs_get_wch.3,v 1.1 2010/09/06 17:26:17 nicm Exp $ +.\" $OpenBSD: curs_get_wch.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ .\"*************************************************************************** -.\" Copyright (c) 2002-2003,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2021,2022 Thomas E. Dickey * +.\" Copyright 2002-2016,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -27,63 +28,71 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_get_wch.3,v 1.1 2010/09/06 17:26:17 nicm Exp $ -.TH curs_get_wch 3 "" +.\" $Id: curs_get_wch.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ +.TH curs_get_wch 3 2022-02-12 "ncurses 6.4" "Library calls" +.na +.hy 0 +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .SH NAME -\fBget_wch\fR, -\fBwget_wch\fR, -\fBmvget_wch\fR, -\fBmvwget_wch\fR, -\fBunget_wch\fR \- get (or push back) a wide character from curses terminal keyboard +\fBget_wch\fP, +\fBwget_wch\fP, +\fBmvget_wch\fP, +\fBmvwget_wch\fP, +\fBunget_wch\fP \- get (or push back) a wide character from curses terminal keyboard +.ad +.hy .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint get_wch(wint_t *\fR\fIwch\fR\fB);\fR +\fBint get_wch(wint_t *\fIwch\fB);\fR .br -\fBint wget_wch(WINDOW *\fR\fIwin\fR\fB, wint_t *\fR\fIwch\fR\fB);\fR +\fBint wget_wch(WINDOW *\fIwin\fB, wint_t *\fIwch\fB);\fR .br -\fBint mvget_wch(int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, wint_t *\fR\fIwch\fR\fB);\fR +\fBint mvget_wch(int \fIy\fB, int \fIx\fB, wint_t *\fIwch\fB);\fR .br -\fBint mvwget_wch(WINDOW *\fR\fIwin\fR\fB, int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, wint_t *\fR\fIwch\fR\fB);\fR -.br -\fBint unget_wch(const wchar_t \fR\fIwch\fR\fB);\fR +\fBint mvwget_wch(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, wint_t *\fIwch\fB);\fR +.sp +\fBint unget_wch(const wchar_t \fIwch\fB);\fR .SH DESCRIPTION +.SS wget_wch The -\fBget_wch\fR, -\fBwget_wch\fR, -\fBmvget_wch\fR, and -\fBmvwget_wch\fR +\fBget_wch\fP, +\fBwget_wch\fP, +\fBmvget_wch\fP, and +\fBmvwget_wch\fP functions read a character from the terminal associated with the current or specified window. In no-delay mode, -if no input is waiting, the value \fBERR\fR is returned. +if no input is waiting, the value \fBERR\fP is returned. In delay mode, the program waits until the system passes text through to the program. -Depending on the setting of \fBcbreak\fR, +Depending on the setting of \fBcbreak\fP, this is after one character (cbreak mode), or after the first newline (nocbreak mode). In half-delay mode, the program waits until the user types a character or the specified timeout interval has elapsed. .PP -Unless \fBnoecho\fR has been set, +Unless \fBnoecho\fP has been set, these routines echo the character into the designated window. .PP If the window is not a pad and has been moved or modified since the -last call to \fBwrefresh\fR, -\fBwrefresh\fR will be called before another character is read. +last call to \fBwrefresh\fP, +\fBwrefresh\fP will be called before another character is read. .PP -If \fBkeypad\fR is enabled, +If \fBkeypad\fP is enabled, these functions respond to the pressing of a function key by setting the object pointed to by -\fIwch\fR -to the corresponding -\fBKEY_\fR -value defined -in -\fB\fR -and returning -\fBKEY_CODE_YES\fR. +\fIwch\fP +to the keycode assigned to the function key, +and returning \fBKEY_CODE_YES\fP. If a character (such as escape) that could be the beginning of a function key is received, curses sets a timer. If the remainder @@ -93,70 +102,94 @@ For this reason, many terminals experience a delay between the time a user presses the escape key and the time the escape is returned to the program. .PP +The keycodes returned by these functions are the same as those +returned by \fBwgetch\fP: +.bP +The predefined function +keys are listed in \fB\fP as macros with values outside the range +of 8-bit characters. +Their names begin with \fBKEY_\fP. +.bP +Other (user-defined) function keys +which may be defined using \fBdefine_key\fP(3) have no names, +but also are expected to have values outside the range of 8-bit characters. +.SS unget_wch The -\fBunget_wch\fR +\fBunget_wch\fP function pushes the wide character -\fIwch\fR +\fIwch\fP back onto the head of the input queue, so the wide character is returned by the next call to -\fBget_wch\fR. +\fBget_wch\fP. The pushback of one character is guaranteed. If the program calls -\fBunget_wch\fR +\fBunget_wch\fP too many times without an intervening call to -\fBget_wch\fR, +\fBget_wch\fP, the operation may fail. +.PP +Unlike \fBungetch\fP and \fBwgetch\fP, +\fBunget_wch\fP cannot distinguish special characters +returned by \fBwget_wch\fP from ordinary characters. +An application can push special keys +which it may read via \fBwget_wch\fP +by checking for the \fBKEY_CODE_YES\fP result, +and using \fBungetch\fP for those special keys. .SH NOTES The header file -\fB\fR +\fB\fP automatically includes the header file -\fB\fR. +\fB\fP. .PP Applications should not define the escape key by itself as a single-character function. .PP When using -\fBget_wch\fR, -\fBwget_wch\fR, -\fBmvget_wch\fR, or -\fBmvwget_wch\fR, applications should +\fBget_wch\fP, +\fBwget_wch\fP, +\fBmvget_wch\fP, or +\fBmvwget_wch\fP, applications should not use -\fBnocbreak\fR +\fBnocbreak\fP mode and -\fBecho\fR +\fBecho\fP mode at the same time. Depending on the state of the tty driver when each character is typed, the program may produce undesirable results. .PP -All functions except \fBwget_wch\fR and \fBunget_wch\fR +All functions except \fBwget_wch\fP and \fBunget_wch\fP may be macros. -.SH RETURN VALUES +.SH RETURN VALUE When -\fBget_wch\fR, -\fBwget_wch\fR, -\fBmvget_wch\fR, and -\fBmvwget_wch\fR +\fBget_wch\fP, +\fBwget_wch\fP, +\fBmvget_wch\fP, and +\fBmvwget_wch\fP functions successfully report the pressing of a function key, they return -\fBKEY_CODE_YES\fR. +\fBKEY_CODE_YES\fP. When they successfully report a wide character, they return -\fBOK\fR. +\fBOK\fP. Otherwise, they return -\fBERR\fR. +\fBERR\fP. .PP Upon successful completion, -\fBunget_wch\fR +\fBunget_wch\fP returns -\fBOK\fR. +\fBOK\fP. Otherwise, the function returns -\fBERR\fR. +\fBERR\fP. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. .SH SEE ALSO -\fBcurses\fR(3), -\fBcurs_getch\fR(3), -\fBcurs_ins_wch\fR(3), -\fBcurs_inopts\fR(3), -\fBcurs_move\fR(3), -\fBcurs_refresh\fR(3) +\fBcurses\fP(3), +\fBcurs_getch\fP(3), +\fBcurs_ins_wch\fP(3), +\fBcurs_inopts\fP(3), +\fBcurs_move\fP(3), +\fBcurs_refresh\fP(3) diff --git a/lib/libcurses/curs_get_wstr.3 b/lib/libcurses/curs_get_wstr.3 index ce5770faf23..116a1a7edd4 100644 --- a/lib/libcurses/curs_get_wstr.3 +++ b/lib/libcurses/curs_get_wstr.3 @@ -1,6 +1,7 @@ -.\" $OpenBSD: curs_get_wstr.3,v 1.1 2010/09/06 17:26:17 nicm Exp $ +.\" $OpenBSD: curs_get_wstr.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ .\"*************************************************************************** -.\" Copyright (c) 2002-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 2002-2012,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -27,153 +28,199 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_get_wstr.3,v 1.1 2010/09/06 17:26:17 nicm Exp $ -.TH curs_get_wstr 3 "" +.\" $Id: curs_get_wstr.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ +.TH curs_get_wstr 3 2023-08-05 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .na .hy 0 .SH NAME -\fBget_wstr\fR, -\fBgetn_wstr\fR, -\fBwget_wstr\fR, -\fBwgetn_wstr\fR, -\fBmvget_wstr\fR, -\fBmvgetn_wstr\fR, -\fBmvwget_wstr\fR, -\fBmvwgetn_wstr\fR \- get an array of wide characters from a curses terminal keyboard +\fBget_wstr\fP, +\fBgetn_wstr\fP, +\fBwget_wstr\fP, +\fBwgetn_wstr\fP, +\fBmvget_wstr\fP, +\fBmvgetn_wstr\fP, +\fBmvwget_wstr\fP, +\fBmvwgetn_wstr\fP \- get an array of wide characters from a curses terminal keyboard .ad .hy .SH SYNOPSIS .nf -\fB#include \fR +\fB#include \fP .sp -\fBint get_wstr(wint_t *\fR\fIwstr\fR\fB);\fR +\fBint get_wstr(wint_t *\fIwstr\fB);\fR .br -\fBint getn_wstr(wint_t *\fR\fIwstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint getn_wstr(wint_t *\fIwstr\fB, int \fIn\fB);\fR .br -\fBint wget_wstr(WINDOW *\fR\fIwin\fR\fB, wint_t *\fR\fIwstr\fR\fB);\fR +\fBint wget_wstr(WINDOW *\fIwin\fB, wint_t *\fIwstr\fB);\fR .br -\fBint wgetn_wstr(WINDOW *\fR\fIwin\fR\fB, wint_t *\fR\fIwstr\fR\fB, int \fR\fIn\fR\fB);\fR -.br -\fBint mvget_wstr(int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, wint_t *\fR\fIwstr\fR\fB);\fR +\fBint wgetn_wstr(WINDOW *\fIwin\fB, wint_t *\fIwstr\fB, int \fIn\fB);\fR +.sp +\fBint mvget_wstr(int \fIy\fB, int \fIx\fB, wint_t *\fIwstr\fB);\fR .br -\fBint mvgetn_wstr(int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, wint_t *\fR\fIwstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint mvgetn_wstr(int \fIy\fB, int \fIx\fB, wint_t *\fIwstr\fB, int \fIn\fB);\fR .br -\fBint mvwget_wstr(WINDOW *\fR\fIwin\fR\fB, int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, wint_t *\fR\fIwstr\fR\fB);\fR +\fBint mvwget_wstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, wint_t *\fIwstr\fB);\fR .br -\fBint mvwgetn_wstr(WINDOW *\fR\fIwin\fR\fB, int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, wint_t *\fR\fIwstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint mvwgetn_wstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, wint_t *\fIwstr\fB, int \fIn\fB);\fR .fi .SH DESCRIPTION -The effect of -\fBget_wstr\fR -is as though a series of calls -to -\fBget_wch\fR -were made, until a newline, other end-of-line, or end-of-file condition is processed. -An end-of-file condition is represented by \fBWEOF\fR, as defined in \fB\fR. -The newline and end-of-line conditions are represented by the \fB\\n\fR \fBwchar_t\fR value. -In all instances, the end of the string is terminated by a null \fBwchar_t\fR. -The routine places resulting values in the area pointed to by \fIwstr\fR. -.PP -The user's erase and kill characters are interpreted. If keypad -mode is on for the window, \fBKEY_LEFT\fR and \fBKEY_BACKSPACE\fR -are both considered equivalent to the user's kill character. -.PP -Characters input are echoed only if \fBecho\fR is currently on. In that case, -backspace is echoed as deletion of the previous character (typically a left -motion). -.PP -The effect of -\fBwget_wstr\fR -is as though a series of -calls to -\fBwget_wch\fR -were made. +The function +\fBwgetn_wstr\fP +is equivalent to a series of calls to +\fBwget_wch\fP(3) +until a newline or carriage return terminates the series: +.bP +The terminating character is not included in the returned string. +.bP +An end-of-file condition is represented by \fBWEOF\fP, +as defined in \fB\fP. +.bP +In all instances, the end of the string is terminated +by a null \fBwchar_t\fP. +.bP +The function stores the result in the area pointed to +by the \fIwstr\fP parameter. +.bP +The function reads at most \fIn\fP characters, +thus preventing a possible overflow of the input buffer. +.IP +Any attempt to enter more characters +(other than the terminating newline or carriage return) +causes a beep. +.IP +Function keys also cause a beep and are ignored. .PP -The effect of -\fBmvget_wstr\fR -is as though a call to -\fBmove\fR -and then a series of calls to -\fBget_wch\fR -were -made. +The user's \fIerase\fP and \fIkill\fP characters are interpreted: +.bP +The \fIerase\fP character (e.g., \fB^H\fP) erases the character +at the end of the buffer, moving the cursor to the left. +.IP +If \fIkeypad\fP mode is on for the window, +\fBKEY_LEFT\fP and \fBKEY_BACKSPACE\fP +are both considered equivalent to the user's \fIerase\fP character. +.bP +The \fIkill\fP character (e.g., \fB^U\fP) erases the entire buffer, +leaving the cursor at the beginning of the buffer. .PP -The effect of -\fBmvwget_wstr\fR -is as though a call to -\fBwmove\fR -and then a series of calls to -\fBwget_wch\fR -were made. +Characters input are echoed only if \fBecho\fP is currently on. +In that case, +backspace is echoed as deletion of the previous character +(typically a left motion). .PP The -\fBgetn_wstr\fR, -\fBmvgetn_wstr\fR, -\fBmvwgetn_wstr\fR, and -\fBwgetn_wstr\fR +\fBgetn_wstr\fP, +\fBmvgetn_wstr\fP, +\fBmvwgetn_wstr\fP, and +\fBwgetn_wstr\fP functions are identical to the -\fBget_wstr\fR, -\fBmvget_wstr\fR, -\fBmvwget_wstr\fR, and -\fBwget_wstr\fR +\fBget_wstr\fP, +\fBmvget_wstr\fP, +\fBmvwget_wstr\fP, and +\fBwget_wstr\fP functions, respectively, except that the -\fB*n_*\fR +\fB*n_*\fP versions read at most -\fIn\fR +\fIn\fP characters, letting the application prevent overflow of the input buffer. .SH NOTES +Any of these functions other than +\fBwgetn_wstr\fP +may be macros. +.PP Using -\fBget_wstr\fR, -\fBmvget_wstr\fR, -\fBmvwget_wstr\fR, or -\fBwget_wstr\fR +\fBget_wstr\fP, +\fBmvget_wstr\fP, +\fBmvwget_wstr\fP, or +\fBwget_wstr\fP to read a line that overflows the array pointed to by -\fBwstr\fR +\fBwstr\fP causes undefined results. The use of -\fBgetn_wstr\fR, -\fBmvgetn_wstr\fR, -\fBmvwgetn_wstr\fR, or -\fBwgetn_wstr\fR, respectively, is recommended. +\fBgetn_wstr\fP, +\fBmvgetn_wstr\fP, +\fBmvwgetn_wstr\fP, or +\fBwgetn_wstr\fP, +respectively, is recommended. .PP -These functions cannot return \fBKEY_\fR values because there -is no way to distinguish a \fBKEY_\fR value from a valid \fBwchar_t\fR value. +These functions cannot return \fBKEY_\fP values because there +is no way to distinguish a \fBKEY_\fP value from a valid \fBwchar_t\fP value. +may be macros. +.SH RETURN VALUE +All of these functions return the integer \fBOK\fP upon successful completion. +If unsuccessful, they return \fBERR\fP. .PP -All of these routines except \fBwgetn_wstr\fR may be macros. -.SH RETURN VALUES -All of these functions return \fBOK\fR upon successful completion. -Otherwise, they return \fBERR\fR. +X/Open defines no error conditions. .PP -Functions using a window parameter return an error if it is null. -.RS -.TP 5 -\fBwgetn_wstr\fP -returns an error if the associated call to \fBwget_wch\fP failed. -.RE +In this implementation, +these functions return an error +.bP +if the window pointer is null, +.bP +if its timeout expires without having any data, or +.bP +if the associated call to +\fBwget_wch\fP +failed. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. .SH PORTABILITY These functions are described in The Single Unix Specification, Version 2. No error conditions are defined. -This implementation returns ERR if the window pointer is null, -or if the lower-level \fBwget_wch\fR call returns an ERR. +.PP +This implementation returns \fBERR\fP if the window pointer is null, +or if the lower-level \fBwget_wch\fP call returns an \fBERR\fP. In the latter case, -an ERR return without other data is treated as an end-of-file condition, -and the returned array contains a \fBWEOF\fR followed by a null \fBwchar_t\fR. +an \fBERR\fP return without other data is treated as an end-of-file condition, +and the returned array contains a \fBWEOF\fP followed by a null \fBwchar_t\fP. +.PP +X/Open curses documented these functions to pass an array of \fBwchar_t\fP +in 1997, but that was an error because of this part of the description: +.RS +.PP +The effect of \fBget_wstr\fP is as though a series of calls to +\fBget_wch\fP were made, until a newline character, end-of-line character, or +end-of-file character is processed. +.RE +.PP +The latter function \fIget_wch\fP can return a negative value, +while \fBwchar_t\fP is a unsigned type. +All of the vendors implement this using \fBwint_t\fP, following the standard. +.PP +X/Open Curses, Issue 7 (2009) is unclear regarding whether +the terminating \fInull \fBwchar_t\fR +value is counted in the length parameter \fIn\fP. +X/Open Curses, Issue 7 revised the corresponding description +of \fBwgetnstr\fP to address this issue. +The unrevised description of \fBwget_nwstr\fP can be interpreted either way. +This implementation counts the terminator in the length. .PP -X/Open curses documents these functions to pass an array of \fBwchar_t\fR, -but all of the vendors implement this using \fBwint_t\fR. +X/Open Curses does not specify what happens if the length \fIn\fP is negative. +.bP +For analogy with \fBwgetnstr\fP, +ncurses 6.2 uses a limit (based on \fBLINE_MAX\fP). +.bP +Some other implementations (such as Solaris xcurses) do the same, +while others (PDCurses) do not allow this. +.bP +NetBSD 7 curses imitates ncurses 6.1 in this regard, +treating a \fB\-1\fP as an indefinite number of characters. .SH SEE ALSO Functions: -\fBcurses\fR(3), -\fBcurs_get_wch\fR(3), -\fBcurs_getstr\fR(3). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_get_wch\fP(3), +\fBcurs_getstr\fP(3). diff --git a/lib/libcurses/curs_getcchar.3 b/lib/libcurses/curs_getcchar.3 new file mode 100644 index 00000000000..f2137028022 --- /dev/null +++ b/lib/libcurses/curs_getcchar.3 @@ -0,0 +1,196 @@ +.\"*************************************************************************** +.\" Copyright 2019-2021,2023 Thomas E. Dickey * +.\" Copyright 2001-2015,2017 Free Software Foundation, Inc. * +.\" * +.\" Permission is hereby granted, free of charge, to any person obtaining a * +.\" copy of this software and associated documentation files (the * +.\" "Software"), to deal in the Software without restriction, including * +.\" without limitation the rights to use, copy, modify, merge, publish, * +.\" distribute, distribute with modifications, sublicense, and/or sell * +.\" copies of the Software, and to permit persons to whom the Software is * +.\" furnished to do so, subject to the following conditions: * +.\" * +.\" The above copyright notice and this permission notice shall be included * +.\" in all copies or substantial portions of the Software. * +.\" * +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * +.\" IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * +.\" DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * +.\" OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * +.\" THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +.\" * +.\" Except as contained in this notice, the name(s) of the above copyright * +.\" holders shall not be used in advertising or otherwise to promote the * +.\" sale, use or other dealings in this Software without prior written * +.\" authorization. * +.\"*************************************************************************** +.\" +.\" $Id: curs_getcchar.3,v 1.1 2023/10/17 09:52:08 nicm Exp $ +.TH curs_getcchar 3 2023-07-01 "ncurses 6.4" "Library calls" +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.SH NAME +\fBgetcchar\fP, +\fBsetcchar\fP \- Get a wide character string and rendition from a \fBcchar_t\fP or set a \fBcchar_t\fP from a wide-character string +.SH SYNOPSIS +\fB#include \fP +.sp +\fBint getcchar(\fP +.br +.B " const cchar_t *\fIwcval\fP," +.br +.B " wchar_t *\fIwch\fP," +.br +.B " attr_t *\fIattrs\fP," +.br +.B " short *\fIcolor_pair\fP," +.br +.B " void *\fIopts\fP );" +.sp +.B "int setcchar(" +.br +.B " cchar_t *\fIwcval\fP," +.br +.B " const wchar_t *\fIwch\fP," +.br +.B " const attr_t \fIattrs\fP," +.br +.B " short \fIcolor_pair\fP," +.br +.B " const void *\fIopts\fP );" +.SH DESCRIPTION +.SS getcchar +The \fBgetcchar\fP function gets a wide-character string +and rendition from a \fBcchar_t\fP argument. +When \fIwch\fP is not a null pointer, +the \fBgetcchar\fP function does the following: +.bP +Extracts information from a \fBcchar_t\fP value \fIwcval\fP +.bP +Stores the character attributes in the location pointed to by \fIattrs\fP +.bP +Stores the color-pair in the location pointed to by \fIcolor_pair\fP +.bP +Stores the wide-character string, +characters referenced by \fIwcval\fP, into the array pointed to by \fIwch\fP. +.PP +When +\fIwch\fP +is a null pointer, the +\fBgetcchar\fP +function does the following: +.bP +Obtains the number of wide characters pointed to by \fIwcval\fP +.bP +Does not change the data referenced by +\fIattrs\fP +or +\fIcolor_pair\fP +.SS setcchar +The \fBsetcchar\fP function initializes the location pointed to by \fIwcval\fP +by using: +.bP +The character attributes in +\fIattrs\fP +.bP +The color pair in +\fIcolor_pair\fP +.bP +The wide-character string pointed to by \fIwch\fP. +The string must be L'\\0' terminated, +contain at most one spacing character, +which must be the first. +.IP +Up to \fBCCHARW_MAX\fP\-1 nonspacing characters may follow. +Additional nonspacing characters are ignored. +.IP +The string may contain a single control character instead. +In that case, no nonspacing characters are allowed. +.SH EXTENSIONS +X/Open Curses documents the \fIopts\fP argument as reserved for future use, +saying that it must be null. +This implementation +uses that parameter in ABI 6 for the functions which have a color-pair +parameter to support extended color pairs: +.bP +For functions which modify the color, e.g., \fBsetcchar\fP, +if \fIopts\fP is set it is treated as a pointer to \fBint\fP, +and used to set the color pair instead of the \fBshort\fP pair parameter. +.bP +For functions which retrieve the color, e.g., \fBgetcchar\fP, +if \fIopts\fP is set it is treated as a pointer to \fBint\fP, +and used to retrieve the color pair as an \fBint\fP value, +in addition retrieving it via the standard pointer to \fBshort\fP parameter. +.SH NOTES +The \fIwcval\fP argument may be a value generated by a call to +\fBsetcchar\fP or by a function that has a \fBcchar_t\fP output argument. +If \fIwcval\fP is constructed by any other means, the effect is unspecified. +.SH RETURN VALUE +When \fIwch\fP is a null pointer, +\fBgetcchar\fP returns the number of wide characters referenced by +\fIwcval\fP, +including one for a trailing null. +.PP +When \fIwch\fP is not a null pointer, +\fBgetcchar\fP returns \fBOK\fP upon successful completion, +and \fBERR\fP otherwise. +.PP +Upon successful completion, \fBsetcchar\fP returns \fBOK\fP. +Otherwise, it returns \fBERR\fP. +.SH PORTABILITY +The \fBCCHARW_MAX\fP symbol is specific to ncurses. +X/Open Curses does not provide details for the layout of the \fBcchar_t\fP +structure. +It tells what data are stored in it: +.bP +a spacing character (\fBwchar_t\fP, i.e., 32-bits). +.bP +non-spacing characters (again, \fBwchar_t\fP's). +.bP +attributes (at least 16 bits, inferred from the various ACS- and WACS-flags). +.bP +color pair (at least 16 bits, inferred from the \fBunsigned short\fP type). +.PP +The non-spacing characters are optional, +in the sense that zero or more may be stored in a \fBcchar_t\fP. +XOpen/Curses specifies a limit: +.RS 4 +.PP +Implementations may limit the number of non-spacing characters that can be +associated with a spacing character, provided any limit is at least 5. +.RE +.PP +The Unix implementations at the time follow that limit: +.bP +AIX\ 4 and OSF1\ 4 use the same declaration with an array of 5 non-spacing +characters \fIz\fP and a single spacing character \fIc\fP. +.bP +HP-UX\ 10 uses an opaque structure with 28 bytes, +which is large enough for the 6 \fBwchar_t\fP values. +.bP +Solaris \fIxpg4\fP curses uses a single array of 6 \fBwchar_t\fP values. +.PP +This implementation's \fBcchar_t\fP was defined in 1995 +using \fB5\fP for the total of spacing and non-spacing characters +(\fBCCHARW_MAX\fP). +That was probably due to a misreading of the AIX\ 4 header files, +because the X/Open Curses document was not generally available at that time. +Later (in 2002), this detail was overlooked when beginning to implement +the functions using the structure. +.PP +In practice, even four non-spacing characters may seem enough. +X/Open Curses documents possible uses for non-spacing characters, +including using them for ligatures between characters +(a feature apparently not supported by any curses implementation). +Unicode does not limit the (analogous) number of combining characters, +so some applications may be affected. +.SH SEE ALSO +Functions: +\fBcurs_attr\fP(3), +\fBcurs_color\fP(3), +\fBcurses\fP(3), +\fBwcwidth\fP(3). diff --git a/lib/libcurses/curs_getch.3 b/lib/libcurses/curs_getch.3 index 3d07208b35f..6ee26d07cb7 100644 --- a/lib/libcurses/curs_getch.3 +++ b/lib/libcurses/curs_getch.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: curs_getch.3,v 1.5 2021/03/10 20:16:08 millert Exp $ +.\" $OpenBSD: curs_getch.3,v 1.6 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2016,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,93 +30,135 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_getch.3,v 1.5 2021/03/10 20:16:08 millert Exp $ -.TH curs_getch 3 "" +.\" $Id: curs_getch.3,v 1.6 2023/10/17 09:52:08 nicm Exp $ +.TH curs_getch 3 2023-08-19 "ncurses 6.4" "Library calls" .na .hy 0 +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .SH NAME -\fBgetch\fR, -\fBwgetch\fR, -\fBmvgetch\fR, -\fBmvwgetch\fR, -\fBungetch\fR, -\fBhas_key\fR \- get (or push back) characters from \fBcurses\fR terminal keyboard +\fBgetch\fP, +\fBwgetch\fP, +\fBmvgetch\fP, +\fBmvwgetch\fP, +\fBungetch\fP, +\fBhas_key\fP \- get (or push back) characters from \fBcurses\fP terminal keyboard .ad .hy .SH SYNOPSIS -\fB#include \fR +.B #include .PP -\fBint getch(void);\fR +.B int getch(void); .br -\fBint wgetch(WINDOW *win);\fR -.br -\fBint mvgetch(int y, int x);\fR -.br -\fBint mvwgetch(WINDOW *win, int y, int x);\fR +.B int wgetch(WINDOW *\fIwin\fB); +.sp +.B int mvgetch(int \fIy\fB, int \fIx\fB); .br -\fBint ungetch(int ch);\fR +.B int mvwgetch(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB); +.sp +.B int ungetch(int \fIch\fB); +.sp +/* extension */ .br -\fBint has_key(int ch);\fR +.B int has_key(int \fIch\fB); .br .SH DESCRIPTION -The \fBgetch\fR, \fBwgetch\fR, \fBmvgetch\fR and \fBmvwgetch\fR, routines read +.SS Reading characters +The \fBgetch\fP, \fBwgetch\fP, \fBmvgetch\fP and \fBmvwgetch\fP, routines read a character from the window. -In no-delay mode, if no input is waiting, the value \fBERR\fR is returned. +In no-delay mode, if no input is waiting, the value \fBERR\fP is returned. In delay mode, the program waits until the system passes text through to the program. -Depending on the setting of \fBcbreak\fR, +Depending on the setting of \fBcbreak\fP, this is after one character (cbreak mode), or after the first newline (nocbreak mode). In half-delay mode, the program waits until a character is typed or the specified timeout has been reached. .PP -Unless \fBnoecho\fR has been set, +If \fBecho\fP is enabled, and the window is not a pad, then the character will also be echoed into the designated window according to the following rules: +.bP If the character is the current erase character, left arrow, or backspace, the cursor is moved one space to the left and that screen position is erased -as if \fBdelch\fR had been called. -If the character value is any other \fBKEY_\fR define, the user is alerted -with a \fBbeep\fR call. +as if \fBdelch\fP had been called. +.bP +If the character value is any other \fBKEY_\fP define, the user is alerted +with a \fBbeep\fP call. +.bP +If the character is a carriage-return, +and if \fBnl\fP is enabled, +it is translated to a line-feed after echoing. +.bP Otherwise the character is simply output to the screen. .PP If the window is not a pad, and it has been moved or modified since the last -call to \fBwrefresh\fR, \fBwrefresh\fR will be called before another character +call to \fBwrefresh\fP, \fBwrefresh\fP will be called before another character is read. +.SS Keypad mode +If \fBkeypad\fP is \fBTRUE\fP, and a function key is pressed, the token for +that function key is returned instead of the raw characters: +.bP +The predefined function +keys are listed in \fB\fP as macros with values outside the range +of 8-bit characters. +Their names begin with \fBKEY_\fP. +.bP +Other (user-defined) function keys which may be defined +using \fBdefine_key\fP(3) +have no names, but also are expected to have values outside the range of +8-bit characters. .PP -If \fBkeypad\fR is \fBTRUE\fR, and a function key is pressed, the token for -that function key is returned instead of the raw characters. -Possible function -keys are defined in \fB\fR as macros with values outside the range -of 8-bit characters whose names begin with \fBKEY_\fR. Thus, a variable +Thus, a variable intended to hold the return value of a function key must be of short size or larger. .PP When a character that could be the beginning of a function key is received (which, on modern terminals, means an escape character), -\fBcurses\fR sets a timer. +\fBcurses\fP sets a timer. If the remainder of the sequence does not come in within the designated time, the character is passed through; otherwise, the function key value is returned. For this reason, many terminals experience a delay between the time a user presses the escape key and the escape is returned to the program. .PP -The \fBungetch\fR routine places \fIch\fR back onto the input queue to be -returned by the next call to \fBwgetch\fR. +In \fBncurses\fP, the timer normally expires after +the value in \fBESCDELAY\fP (see \fBcurs_variables\fP(3)). +If \fBnotimeout\fP is \fBTRUE\fP, the timer does not expire; +it is an infinite (or very large) value. +Because function keys usually begin with an escape character, +the terminal may appear to hang in notimeout mode after pressing the escape key +until another key is pressed. +.SS Ungetting characters +The \fBungetch\fP routine places \fIch\fP back onto the input queue to be +returned by the next call to \fBwgetch\fP. There is just one input queue for all windows. +.SS Predefined key-codes +The following special keys are defined in \fB\fP. +.bP +Except for the special case \fBKEY_RESIZE\fP, +it is necessary to enable \fBkeypad\fP for \fBgetch\fP to return these codes. +.bP +Not all of these are necessarily supported on any particular terminal. +.bP +The naming convention may seem obscure, with some apparent +misspellings (such as \*(``RSUME\*('' for \*(``resume\*(''). +The names correspond to the long terminfo capability names for the keys, +and were defined long ago, in the 1980s. .PP -.SS Function Keys -The following function keys, defined in \fB\fR, might be returned by -\fBgetch\fR if \fBkeypad\fR has been enabled. -Note that not all of these are -necessarily supported on any particular terminal. -.sp +.RS .TS -center tab(/) ; -l l +tab(/) ; l l . -\fIName\fR/\fIKey\fR \fIname\fR +\fBName\fP/\fBKey\fP \fBname\fP +_ KEY_BREAK/Break key KEY_DOWN/The four arrow keys ... KEY_UP @@ -126,8 +169,8 @@ KEY_BACKSPACE/Backspace KEY_F0/T{ Function keys; space for 64 keys is reserved. T} -KEY_F(\fIn\fR)/T{ -For 0 \(<= \fIn\fR \(<= 63 +KEY_F(\fIn\fP)/T{ +For 0 \(<= \fIn\fP \(<= 63 T} KEY_DL/Delete line KEY_IL/Insert line @@ -167,7 +210,7 @@ KEY_FIND/Find key KEY_HELP/Help key KEY_MARK/Mark key KEY_MESSAGE/Message key -KEY_MOUSE/Mouse event read +KEY_MOUSE/Mouse event occurred KEY_MOVE/Move key KEY_NEXT/Next object key KEY_OPEN/Open key @@ -195,7 +238,7 @@ KEY_SEXIT/Shifted exit key KEY_SFIND/Shifted find key KEY_SHELP/Shifted help key KEY_SHOME/Shifted home key -KEY_SIC/Shifted input key +KEY_SIC/Shifted insert key KEY_SLEFT/Shifted left arrow key KEY_SMESSAGE/Shifted message key KEY_SMOVE/Shifted move key @@ -205,7 +248,7 @@ KEY_SPREVIOUS/Shifted prev key KEY_SPRINT/Shifted print key KEY_SREDO/Shifted redo key KEY_SREPLACE/Shifted replace key -KEY_SRIGHT/Shifted right arrow +KEY_SRIGHT/Shifted right arrow key KEY_SRSUME/Shifted resume key KEY_SSAVE/Shifted save key KEY_SSUSPEND/Shifted suspend key @@ -213,118 +256,164 @@ KEY_SUNDO/Shifted undo key KEY_SUSPEND/Suspend key KEY_UNDO/Undo key .TE +.RE .PP Keypad is arranged like this: -.sp +.PP +.RS .TS -center allbox tab(/) ; +allbox tab(/) ; c c c . -\fBA1\fR/\fBup\fR/\fBA3\fR -\fBleft\fR/\fBB2\fR/\fBright\fR -\fBC1\fR/\fBdown\fR/\fBC3\fR +\fBA1\fP/\fBup\fP/\fBA3\fP +\fBleft\fP/\fBB2\fP/\fBright\fP +\fBC1\fP/\fBdown\fP/\fBC3\fP .TE +.RE .sp -The \fBhas_key\fR routine takes a key value from the above list, and -returns TRUE or FALSE according to whether +A few of these predefined values do \fInot\fP correspond to a real key: +.bP +.B KEY_RESIZE +is returned when the \fBSIGWINCH\fP signal has been detected +(see \fBinitscr\fP(3) and \fBresizeterm\fP(3)). +This code is returned whether or not \fBkeypad\fP has been enabled. +.bP +.B KEY_MOUSE +is returned for mouse-events (see \fBcurs_mouse\fP(3)). +This code relies upon whether or not \fBkeypad\fP(3) has been enabled, +because (e.g., with \fBxterm\fP(1) mouse prototocol) ncurses must +read escape sequences, +just like a function key. +.SS Testing key-codes +The \fBhas_key\fP routine takes a key-code value from the above list, and +returns \fBTRUE\fP or \fBFALSE\fP according to whether the current terminal type recognizes a key with that value. -Note that a few values do not correspond to a real key, -e.g., \fBKEY_RESIZE\fP and \fBKEY_MOUSE\fP. -See \fBresizeterm\fR(3) for more details about \fBKEY_RESIZE\fP, and -\fBcurs_mouse\fR(3) for a discussion of \fBKEY_MOUSE\fP. .PP +The library also supports these extensions: +.RS 3 +.TP 5 +.B define_key +defines a key-code for a given string (see \fBdefine_key\fP(3)). +.TP 5 +.B key_defined +checks if there is a key-code defined for a given +string (see \fBkey_defined\fP(3)). +.RE .SH RETURN VALUE -All routines return the integer \fBERR\fR upon failure and an integer value -other than \fBERR\fR (\fBOK\fR in the case of ungetch()) upon successful +All routines return the integer \fBERR\fP upon failure and an integer value +other than \fBERR\fP (\fBOK\fP in the case of \fBungetch\fP) upon successful completion. .RS 3 .TP 5 \fBungetch\fP -returns ERR +returns \fBERR\fP if there is no more room in the FIFO. .TP \fBwgetch\fP -returns ERR +returns \fBERR\fP if the window pointer is null, or -if its timeout expires without having any data. +if its timeout expires without having any data, or +if the execution was interrupted by a signal (\fBerrno\fP will be set to +\fBEINTR\fP). .RE +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. .SH NOTES Use of the escape key by a programmer for a single character function is discouraged, as it will cause a delay of up to one second while the keypad code looks for a following function-key sequence. .PP -Note that some keys may be the same as commonly used control -keys, e.g., \fBKEY_ENTER\fP versus control/M, \fBKEY_BACKSPACE\fP versus control/H. +Some keys may be the same as commonly used control +keys, e.g., +\fBKEY_ENTER\fP versus control/M, +\fBKEY_BACKSPACE\fP versus control/H. Some curses implementations may differ according to whether they treat these control keys specially (and ignore the terminfo), or use the terminfo definitions. -\fBNcurses\fR uses the terminfo definition. +\fBNcurses\fP uses the terminfo definition. If it says that \fBKEY_ENTER\fP is control/M, -\fBgetch\fR will return \fBKEY_ENTER\fP +\fBgetch\fP will return \fBKEY_ENTER\fP when you press control/M. .PP -When using \fBgetch\fR, \fBwgetch\fR, \fBmvgetch\fR, or -\fBmvwgetch\fR, nocbreak mode (\fBnocbreak\fR) and echo mode -(\fBecho\fR) should not be used at the same time. +Generally, \fBKEY_ENTER\fP denotes the character(s) sent by the \fIEnter\fP +key on the numeric keypad: +.bP +the terminal description lists the most useful keys, +.bP +the \fIEnter\fP key on the regular keyboard is already handled by +the standard ASCII characters for carriage-return and line-feed, +.bP +depending on whether \fBnl\fP or \fBnonl\fP was called, +pressing \*(``Enter\*('' on the regular keyboard +may return either a carriage-return or line-feed, and finally +.bP +\*(``Enter or send\*('' is the standard description for this key. +.PP +When using \fBgetch\fP, \fBwgetch\fP, \fBmvgetch\fP, or +\fBmvwgetch\fP, nocbreak mode (\fBnocbreak\fP) and echo mode +(\fBecho\fP) should not be used at the same time. Depending on the state of the tty driver when each character is typed, the program may produce undesirable results. .PP -Note that \fBgetch\fR, \fBmvgetch\fR, and \fBmvwgetch\fR may be macros. +Note that \fBgetch\fP, \fBmvgetch\fP, and \fBmvwgetch\fP may be macros. .PP Historically, the set of keypad macros was largely defined by the extremely function-key-rich keyboard of the AT&T 7300, aka 3B1, aka Safari 4. Modern personal computers usually have only a small subset of these. IBM PC-style -consoles typically support little more than \fBKEY_UP\fR, \fBKEY_DOWN\fR, -\fBKEY_LEFT\fR, \fBKEY_RIGHT\fR, \fBKEY_HOME\fR, \fBKEY_END\fR, -\fBKEY_NPAGE\fR, \fBKEY_PPAGE\fR, and function keys 1 through 12. +consoles typically support little more than \fBKEY_UP\fP, \fBKEY_DOWN\fP, +\fBKEY_LEFT\fP, \fBKEY_RIGHT\fP, \fBKEY_HOME\fP, \fBKEY_END\fP, +\fBKEY_NPAGE\fP, \fBKEY_PPAGE\fP, and function keys 1 through 12. The Ins key -is usually mapped to \fBKEY_IC\fR. +is usually mapped to \fBKEY_IC\fP. .SH PORTABILITY The *get* functions are described in the XSI Curses standard, Issue 4. They read single-byte characters only. The standard specifies that they return -\fBERR\fR on failure, but specifies no error conditions. +\fBERR\fP on failure, but specifies no error conditions. .PP -The echo behavior of these functions on input of \fBKEY_\fR or backspace +The echo behavior of these functions on input of \fBKEY_\fP or backspace characters was not specified in the SVr4 documentation. This description is adopted from the XSI Curses standard. .PP -The behavior of \fBgetch\fR and friends in the presence of handled signals is +The behavior of \fBgetch\fP and friends in the presence of handled signals is unspecified in the SVr4 and XSI Curses documentation. Under historical curses implementations, it varied depending on whether the operating system's -implementation of handled signal receipt interrupts a \fBread\fR(2) call in +implementation of handled signal receipt interrupts a \fBread\fP(2) call in progress or not, and also (in some implementations) depending on whether an input timeout or non-blocking mode has been set. .PP +\fBKEY_MOUSE\fP is mentioned in XSI Curses, along with a few related +terminfo capabilities, but no higher-level functions use the feature. +The implementation in ncurses is an extension. +.PP +\fBKEY_RESIZE\fP is an extension first implemented for ncurses. +NetBSD curses later added this extension. +.PP Programmers concerned about portability should be prepared for either of two -cases: (a) signal receipt does not interrupt \fBgetch\fR; (b) signal receipt -interrupts \fBgetch\fR and causes it to return ERR with \fBerrno\fR set to -\fBEINTR\fR. -Under the \fBncurses\fR implementation, handled signals never -interrupt \fBgetch\fR. +cases: (a) signal receipt does not interrupt \fBgetch\fP; (b) signal receipt +interrupts \fBgetch\fP and causes it to return \fBERR\fP with \fBerrno\fP set to +\fBEINTR\fP. .PP -The \fBhas_key\fR function is unique to \fBncurses\fR. +The \fBhas_key\fP function is unique to \fBncurses\fP. We recommend that -any code using it be conditionalized on the \fBNCURSES_VERSION\fR feature macro. +any code using it be conditionalized on the \fBNCURSES_VERSION\fP feature macro. .SH SEE ALSO -\fBcurses\fR(3), -\fBcurs_inopts\fR(3), -\fBcurs_mouse\fR(3), -\fBcurs_move\fR(3), -\fBcurs_refresh\fR(3), -\fBresizeterm\fR(3). +\fBcurses\fP(3), +\fBcurs_inopts\fP(3), +\fBcurs_mouse\fP(3), +\fBcurs_move\fP(3), +\fBcurs_outopts\fP(3), +\fBcurs_refresh\fP(3), +\fBcurs_variables\fP(3), +\fBresizeterm\fP(3). .PP Comparable functions in the wide-character (ncursesw) library are described in -\fBcurs_get_wch\fR(3). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurs_get_wch\fP(3). diff --git a/lib/libcurses/curs_getstr.3 b/lib/libcurses/curs_getstr.3 index 7edf7fc2c65..0b33bffe342 100644 --- a/lib/libcurses/curs_getstr.3 +++ b/lib/libcurses/curs_getstr.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_getstr.3,v 1.9 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_getstr.3,v 1.10 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2003,2005 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,97 +29,264 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_getstr.3,v 1.9 2010/01/12 23:21:59 nicm Exp $ -.TH curs_getstr 3 "" +.\" $Id: curs_getstr.3,v 1.10 2023/10/17 09:52:08 nicm Exp $ +.TH curs_getstr 3 2023-08-05 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .na .hy 0 .SH NAME -\fBgetstr\fR, -\fBgetnstr\fR, -\fBwgetstr\fR, -\fBwgetnstr\fR, -\fBmvgetstr\fR, -\fBmvgetnstr\fR, -\fBmvwgetstr\fR, -\fBmvwgetnstr\fR - accept character strings from \fBcurses\fR terminal keyboard +\fBgetstr\fP, +\fBgetnstr\fP, +\fBwgetstr\fP, +\fBwgetnstr\fP, +\fBmvgetstr\fP, +\fBmvgetnstr\fP, +\fBmvwgetstr\fP, +\fBmvwgetnstr\fP \- accept character strings from \fBcurses\fP terminal keyboard .ad .hy .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint getstr(char *str);\fR +\fBint getstr(char *\fIstr\fB);\fR .br -\fBint getnstr(char *str, int n);\fR +\fBint getnstr(char *\fIstr\fB, int \fIn\fB);\fR .br -\fBint wgetstr(WINDOW *win, char *str);\fR +\fBint wgetstr(WINDOW *\fIwin\fB, char *\fIstr\fB);\fR .br -\fBint wgetnstr(WINDOW *win, char *str, int n);\fR -.br -\fBint mvgetstr(int y, int x, char *str);\fR -.br -\fBint mvwgetstr(WINDOW *win, int y, int x, char *str);\fR +\fBint wgetnstr(WINDOW *\fIwin\fB, char *\fIstr\fB, int \fIn\fB);\fR +.sp +\fBint mvgetstr(int \fIy\fB, int \fIx\fB, char *\fIstr\fB);\fR .br -\fBint mvgetnstr(int y, int x, char *str, int n);\fR +\fBint mvwgetstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, char *\fIstr\fB);\fR .br -\fBint mvwgetnstr(WINDOW *, int y, int x, char *str, int n);\fR +\fBint mvgetnstr(int \fIy\fB, int \fIx\fB, char *\fIstr\fB, int \fIn\fB);\fR .br +\fBint mvwgetnstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, char *\fIstr\fB, int \fIn\fB);\fR .SH DESCRIPTION -The function \fBgetstr\fR is equivalent to a series of calls to \fBgetch\fR, -until a newline or carriage return is received (the terminating character is -not included in the returned string). The resulting value is placed in the -area pointed to by the character pointer \fIstr\fR. +The function +\fBwgetnstr\fP +is equivalent to a series of calls to +\fBwgetch\fP(3), +until a newline or carriage return terminates the series: +.bP +The terminating character is not included in the returned string. +.bP +In all instances, the end of the string is terminated +by a NUL. +.bP +The function stores the result in the area pointed to +by the \fIstr\fP parameter. +.bP +The function reads at most \fIn\fP characters, +thus preventing a possible overflow of the input buffer. +.IP +Any attempt to enter more characters +(other than the terminating newline or carriage return) +causes a beep. +.IP +Function keys also cause a beep and are ignored. .PP -\fBwgetnstr\fR reads at most \fIn\fR characters, thus preventing a possible -overflow of the input buffer. Any attempt to enter more characters (other -than the terminating newline or carriage return) causes a beep. Function -keys also cause a beep and are ignored. The \fBgetnstr\fR function reads -from the \fIstdscr\fR default window. +The user's \fIerase\fP and \fIkill\fP characters are interpreted: +.bP +The \fIerase\fP character (e.g., \fB^H\fP) erases the character +at the end of the buffer, moving the cursor to the left. +.IP +If \fIkeypad\fP mode is on for the window, +\fBKEY_LEFT\fP and \fBKEY_BACKSPACE\fP +are both considered equivalent to the user's \fIerase\fP character. +.bP +The \fIkill\fP character (e.g., \fB^U\fP) erases the entire buffer, +leaving the cursor at the beginning of the buffer. .PP -The user's erase and kill characters are interpreted. If keypad -mode is on for the window, \fBKEY_LEFT\fR and \fBKEY_BACKSPACE\fR -are both considered equivalent to the user's kill character. +Characters input are echoed only if \fBecho\fP is currently on. +In that case, +backspace is echoed as deletion of the previous character +(typically a left motion). .PP -Characters input are echoed only if \fBecho\fR is currently on. In that case, -backspace is echoed as deletion of the previous character (typically a left -motion). +The +\fBgetnstr\fP, +\fBmvgetnstr\fP, +\fBmvwgetnstr\fP, and +\fBwgetnstr\fP +functions are identical +to the +\fBgetstr\fP, +\fBmvgetstr\fP, +\fBmvwgetstr\fP, and +\fBwgetstr\fP +functions, respectively, +except that the +\fB*n*\fP +versions read at most +\fIn\fP +characters, letting the application prevent overflow of the +input buffer. +.SH NOTES +Any of these functions other than +\fBwgetnstr\fP +may be macros. +.PP +Using +\fBgetstr\fP, +\fBmvgetstr\fP, +\fBmvwgetstr\fP, or +\fBwgetstr\fP +to read a line that +overflows the array pointed to by +\fBstr\fP +causes undefined +results. +The use of +\fBgetnstr\fP, +\fBmvgetnstr\fP, +\fBmvwgetnstr\fP, or +\fBwgetnstr\fP, +respectively, is recommended. .SH RETURN VALUE -All routines return the integer \fBERR\fR upon failure and an \fBOK\fR (SVr4 -specifies only "an integer value other than \fBERR\fR") upon successful -completion. +All of these functions return the integer \fBOK\fP upon successful completion. +(SVr4 specifies only \*(``an integer value other than \fBERR\fP\*('') +If unsuccessful, they return \fBERR\fP. .PP X/Open defines no error conditions. .PP In this implementation, these functions return an error -if the window pointer is null, or -if its timeout expires without having any data. +.bP +if the window pointer is null, +.bP +if its timeout expires without having any data, or +.bP +if the associated call to +\fBwgetch\fP +failed. .PP This implementation provides an extension as well. -If a SIGWINCH interrupts the function, it will return \fBKEY_RESIZE\fP +If a \fBSIGWINCH\fP interrupts the function, it will return \fBKEY_RESIZE\fP rather than \fBOK\fP or \fBERR\fP. -.SH NOTES -Note that \fBgetstr\fR, \fBmvgetstr\fR, and \fBmvwgetstr\fR may be macros. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. .SH PORTABILITY -These functions are described in the XSI Curses standard, Issue 4. -They read single-byte characters only. -The standard does not define any error conditions. -This implementation returns ERR if the window pointer is null, -or if the lower-level \fBwgetch\fR call returns an ERR. +These functions are described in The Single Unix Specification, Version 2. +No error conditions are defined. +.PP +This implementation returns \fBERR\fP if the window pointer is null, +or if the lower-level \fBwgetch\fP(3) call returns an \fBERR\fP. .PP SVr3 and early SVr4 curses implementations did not reject function keys; -the SVr4.0 documentation claimed that "special keys" (such as function -keys, "home" key, "clear" key, \fIetc\fR.) are "interpreted", without -giving details. It lied. In fact, the `character' value appended to the +the SVr4.0 documentation claimed that \*(``special keys\*('' +(such as function keys, +\*(``home\*('' key, +\*(``clear\*('' key, +\fIetc\fP.) are \*(``interpreted\*('', +without giving details. +It lied. +In fact, the \*(``character\*('' value appended to the string by those implementations was predictable but not useful (being, in fact, the low-order eight bits of the key's KEY_ value). .PP -The functions \fBgetnstr\fR, \fBmvgetnstr\fR, and \fBmvwgetnstr\fR were +The functions \fBgetnstr\fP, \fBmvgetnstr\fP, and \fBmvwgetnstr\fP were present but not documented in SVr4. +.PP +X/Open Curses, Issue 5 (2007) stated that these functions +\*(``read at most \fIn\fP bytes\*('' +but did not state whether the terminating NUL is counted in that limit. +X/Open Curses, Issue 7 (2009) changed that to say they +\*(``read at most \fIn\fP\-1 bytes\*('' +to allow for the terminating NUL. +As of 2018, some implementations count it, some do not: +.bP +ncurses 6.1 and PDCurses do not count the NUL in the given limit, while +.bP +Solaris SVr4 and NetBSD curses count the NUL as part of the limit. +.bP +Solaris xcurses provides both: +its wide-character \fBwget_nstr\fP reserves a NUL, +but its \fBwgetnstr\fP does not count the NUL consistently. +.PP +In SVr4 curses, +a negative value of \fIn\fP tells \fBwgetnstr\fP to assume that the +caller's buffer is large enough to hold the result, +i.e., to act like \fBwgetstr\fP. +X/Open Curses does not mention this +(or anything related to negative or zero values of \fIn\fP), +however most implementations +use the feature, with different limits: +.bP +Solaris SVr4 curses and PDCurses limit the result to 255 bytes. +Other Unix systems than Solaris are likely to use the same limit. +.bP +Solaris xcurses limits the result to \fBLINE_MAX\fP bytes. +.bP +NetBSD 7 assumes no particular limit for the result from \fBwgetstr\fP. +However, it limits the \fBwgetnstr\fP parameter \fIn\fP to ensure +that it is greater than zero. +.IP +A comment in NetBSD's source code states that this is specified in SUSv2. +.bP +ncurses (before 6.2) assumes no particular limit for the result +from \fBwgetstr\fP, and treats the \fIn\fP parameter of \fBwgetnstr\fP +like SVr4 curses. +.bP +ncurses 6.2 uses \fBLINE_MAX\fP, +or a larger (system-dependent) value +which the \fBsysconf\fP function may provide. +If neither \fBLINE_MAX\fP or \fBsysconf\fP is available, +ncurses uses the POSIX value for \fBLINE_MAX\fP (a 2048 byte limit). +In either case, it reserves a byte for the terminating NUL. +.PP +Although \fBgetnstr\fP is equivalent to a series of calls to \fBgetch\fP, +it also makes changes to the curses modes to allow simple editing of +the input buffer: +.bP +\fBgetnstr\fP saves the current value of the \fBnl\fP, \fBecho\fP, +\fBraw\fP and \fBcbreak\fP modes, and sets +\fBnl\fP, +\fBnoecho\fP, +\fBnoraw\fP, and +\fBcbreak\fP. +.IP +\fBgetnstr\fP handles the echoing of characters, +rather than relying on the caller to set an appropriate mode. +.bP +It also obtains the \fIerase\fP and \fIkill\fP characters +from \fBerasechar\fP and \fBkillchar\fP, respectively. +.bP +On return, \fBgetnstr\fP restores the modes to their previous values. +.PP +Other implementations differ in their treatment of special characters: +.bP +While they may set the \fIecho\fP mode, +other implementations do not modify the \fIraw\fP mode, +They may take the \fIcbreak\fP +mode set by the caller into account when deciding whether to handle +echoing within \fBgetnstr\fP or as a side-effect of the \fBgetch\fP calls. +.bP +The original ncurses (as \fIpcurses\fP in 1986) set \fBnoraw\fP and \fBcbreak\fP +when accepting input for \fBgetnstr\fP. +That may have been done to make function- and cursor-keys work; +it is not necessary with ncurses. +.IP +Since 1995, ncurses has provided signal handlers for INTR and QUIT +(e.g., \fB^C\fP or \fB^\\\fP). +With the \fBnoraw\fP and \fBcbreak\fP settings, +those may catch a signal and stop the program, +where other implementations allow one to enter those characters in the buffer. +.bP +Starting in 2021 (ncurses 6.3), \fBgetnstr\fP sets \fBraw\fP, +rather than \fBnoraw\fP and \fBcbreak\fP for better compatibility with +SVr4-curses, e.g., allowing one to enter a \fB^C\fP into the buffer. .SH SEE ALSO -\fBcurses\fR(3), \fBcurs_getch\fR(3). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_getch\fP(3), +\fBcurs_termattrs\fP(3), +\fBcurs_variables\fP(3). diff --git a/lib/libcurses/curs_getyx.3 b/lib/libcurses/curs_getyx.3 index ee882cc497f..6c6b6f199e3 100644 --- a/lib/libcurses/curs_getyx.3 +++ b/lib/libcurses/curs_getyx.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_getyx.3,v 1.7 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_getyx.3,v 1.8 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * +.\" Copyright 2020-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2007,2010 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,58 +29,57 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_getyx.3,v 1.7 2010/01/12 23:21:59 nicm Exp $ -.TH curs_getyx 3 "" +.\" $Id: curs_getyx.3,v 1.8 2023/10/17 09:52:08 nicm Exp $ +.TH curs_getyx 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBgetyx\fR, -\fBgetparyx\fR, -\fBgetbegyx\fR, -\fBgetmaxyx\fR - get \fBcurses\fR cursor and window coordinates +\fBgetyx\fP, +\fBgetparyx\fP, +\fBgetbegyx\fP, +\fBgetmaxyx\fP \- get \fBcurses\fP cursor and window coordinates .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBvoid getyx(WINDOW *win, int y, int x);\fR +\fBvoid getyx(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB);\fR .br -\fBvoid getparyx(WINDOW *win, int y, int x);\fR +\fBvoid getparyx(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB);\fR .br -\fBvoid getbegyx(WINDOW *win, int y, int x);\fR -.br -\fBvoid getmaxyx(WINDOW *win, int y, int x);\fR +\fBvoid getbegyx(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB);\fR .br +\fBvoid getmaxyx(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB);\fR .SH DESCRIPTION -The \fBgetyx\fR macro places the current cursor position of the given window in -the two integer variables \fIy\fR and \fIx\fR. +The \fBgetyx\fP macro places the current cursor position of the given window in +the two integer variables \fIy\fP and \fIx\fP. .PP -If \fIwin\fR is a subwindow, the \fBgetparyx\fR macro places the beginning +If \fIwin\fP is a subwindow, the \fBgetparyx\fP macro places the beginning coordinates of the subwindow relative to the parent window into two integer -variables \fIy\fR and \fIx\fR. -Otherwise, \fB-1\fR is placed into \fIy\fR and \fIx\fR. +variables \fIy\fP and \fIx\fP. +Otherwise, \fB\-1\fP is placed into \fIy\fP and \fIx\fP. .PP -Like \fBgetyx\fR, the \fBgetbegyx\fR and \fBgetmaxyx\fR macros store +Like \fBgetyx\fP, the \fBgetbegyx\fP and \fBgetmaxyx\fP macros store the current beginning coordinates and size of the specified window. .SH RETURN VALUE The return values of these macros are undefined (i.e., they should not be used as the right-hand side of assignment statements). .SH NOTES All of these interfaces are macros. -A "\fB&\fR" is not necessary before the variables \fIy\fR and \fIx\fR. +A "\fB&\fP" is not necessary before the variables \fIy\fP and \fIx\fP. .SH PORTABILITY The -\fBgetyx\fR, -\fBgetparyx\fR, -\fBgetbegyx\fR and -\fBgetmaxyx\fR +\fBgetyx\fP, +\fBgetparyx\fP, +\fBgetbegyx\fP and +\fBgetmaxyx\fP macros are described in the XSI Curses standard, Issue 4. .PP This implementation also provides functions -\fBgetbegx\fR, -\fBgetbegy\fR, -\fBgetcurx\fR, -\fBgetcury\fR, -\fBgetmaxx\fR, -\fBgetmaxy\fR, -\fBgetparx\fR and -\fBgetpary\fR +\fBgetbegx\fP, +\fBgetbegy\fP, +\fBgetcurx\fP, +\fBgetcury\fP, +\fBgetmaxx\fP, +\fBgetmaxy\fP, +\fBgetparx\fP and +\fBgetpary\fP for compatibility with older versions of curses. .PP Although X/Open Curses does not address this, @@ -97,12 +97,6 @@ have (at least since release 1.8.1) differed by one from some other implementations. The difference is hidden by means of the macro \fBgetmaxyx\fP. .SH SEE ALSO -\fBcurses\fR(3), -\fBcurs_legacy\fR(3), -\fBcurs_opaque\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_legacy\fP(3), +\fBcurs_opaque\fP(3) diff --git a/lib/libcurses/curs_in_wch.3 b/lib/libcurses/curs_in_wch.3 index 97eea48692f..5b5efaccab7 100644 --- a/lib/libcurses/curs_in_wch.3 +++ b/lib/libcurses/curs_in_wch.3 @@ -1,6 +1,7 @@ -.\" $OpenBSD: curs_in_wch.3,v 1.1 2010/09/06 17:26:17 nicm Exp $ +.\" $OpenBSD: curs_in_wch.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ .\"*************************************************************************** -.\" Copyright (c) 2002,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2021,2022 Thomas E. Dickey * +.\" Copyright 2002-2010,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -27,43 +28,45 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_in_wch.3,v 1.1 2010/09/06 17:26:17 nicm Exp $ -.TH curs_in_wch 3 "" +.\" $Id: curs_in_wch.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ +.TH curs_in_wch 3 2022-02-12 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .SH NAME -\fBin_wch\fR, -\fBmvin_wch\fR, -\fBmvwin_wch\fR, -\fBwin_wch\fR - extract a complex character and rendition from a window +\fBin_wch\fP, +\fBmvin_wch\fP, +\fBmvwin_wch\fP, +\fBwin_wch\fP \- extract a complex character and rendition from a window .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint in_wch(cchar_t *\fR\fIwcval\fR\fB);\fR +\fBint in_wch(cchar_t *\fIwcval\fB);\fR .br -\fBint mvin_wch(int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, cchar_t *\fR\fIwcval\fR\fB);\fR -.br -\fBint mvwin_wch(WINDOW *\fR\fIwin\fR\fB, int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, cchar_t *\fR\fIwcval\fR\fB);\fR +\fBint win_wch(WINDOW *\fIwin\fB, cchar_t *\fIwcval\fB);\fR +.sp +\fBint mvin_wch(int \fIy\fB, int \fIx\fB, cchar_t *\fIwcval\fB);\fR .br -\fBint win_wch(WINDOW *\fR\fIwin\fR\fB, cchar_t *\fR\fIwcval\fR\fB);\fR +\fBint mvwin_wch(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, cchar_t *\fIwcval\fB);\fR .SH DESCRIPTION These functions extract the complex character and rendition from -the current position in the named window into the \fBcchar_t\fR object +the current position in the named window into the \fBcchar_t\fP object referenced by wcval. .SH RETURN VALUE No errors are defined in the XSI Curses standard. -This implementation checks for null pointers, returns ERR in that case. -Also, the \fImv\fR routines check for error moving the cursor, returning ERR -in that case. -Otherwise they return OK +This implementation checks for null pointers, returns \fBERR\fP in that case. +Also, the \fImv\fP routines check for error moving the cursor, +returning \fBERR\fP in that case. +Otherwise they return \fBOK\fP. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. .SH NOTES Note that all of these routines may be macros. .SH PORTABILITY These functions are described in the XSI Curses standard, Issue 4. .SH SEE ALSO -\fBcurses\fR(3), -\fBcurs_inch\fR(3). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_inch\fP(3). diff --git a/lib/libcurses/curs_in_wchstr.3 b/lib/libcurses/curs_in_wchstr.3 index 5ba964b6f78..96899c6a9e0 100644 --- a/lib/libcurses/curs_in_wchstr.3 +++ b/lib/libcurses/curs_in_wchstr.3 @@ -1,6 +1,7 @@ -.\" $OpenBSD: curs_in_wchstr.3,v 1.1 2010/09/06 17:26:17 nicm Exp $ +.\" $OpenBSD: curs_in_wchstr.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ .\"*************************************************************************** -.\" Copyright (c) 2002-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2021,2022 Thomas E. Dickey * +.\" Copyright 2002-2012,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -27,97 +28,100 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_in_wchstr.3,v 1.1 2010/09/06 17:26:17 nicm Exp $ -.TH curs_in_wchstr 3 "" +.\" $Id: curs_in_wchstr.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ +.TH curs_in_wchstr 3 2022-02-12 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .na .hy 0 .SH NAME -\fBin_wchstr\fR, -\fBin_wchnstr\fR, -\fBwin_wchstr\fR, -\fBwin_wchnstr\fR, -\fBmvin_wchstr\fR, -\fBmvin_wchnstr\fR, -\fBmvwin_wchstr\fR, -\fBmvwin_wchnstr\fR \- get an array of complex characters and renditions from a curses window +\fBin_wchstr\fP, +\fBin_wchnstr\fP, +\fBwin_wchstr\fP, +\fBwin_wchnstr\fP, +\fBmvin_wchstr\fP, +\fBmvin_wchnstr\fP, +\fBmvwin_wchstr\fP, +\fBmvwin_wchnstr\fP \- get an array of complex characters and renditions from a curses window .ad .hy .SH SYNOPSIS .nf -\fB#include \fR +\fB#include \fP .sp -\fBint in_wchstr(cchar_t *\fR\fIwchstr\fR\fB);\fR +\fBint in_wchstr(cchar_t *\fIwchstr\fB);\fR .br -\fBint in_wchnstr(cchar_t *\fR\fIwchstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint in_wchnstr(cchar_t *\fIwchstr\fB, int \fIn\fB);\fR .br -\fBint win_wchstr(WINDOW *\fR\fIwin\fR\fB, cchar_t *\fR\fIwchstr\fR\fB);\fR +\fBint win_wchstr(WINDOW *\fIwin\fB, cchar_t *\fIwchstr\fB);\fR .br -\fBint win_wchnstr(WINDOW *\fR\fIwin\fR\fB, cchar_t *\fR\fIwchstr\fR\fB, int \fR\fIn\fR\fB);\fR -.br -\fBint mvin_wchstr(int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, cchar_t *\fR\fIwchstr\fR\fB);\fR +\fBint win_wchnstr(WINDOW *\fIwin\fB, cchar_t *\fIwchstr\fB, int \fIn\fB);\fR +.sp +\fBint mvin_wchstr(int \fIy\fB, int \fIx\fB, cchar_t *\fIwchstr\fB);\fR .br -\fBint mvin_wchnstr(int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, cchar_t *\fR\fIwchstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint mvin_wchnstr(int \fIy\fB, int \fIx\fB, cchar_t *\fIwchstr\fB, int \fIn\fB);\fR .br -\fBint mvwin_wchstr(WINDOW *\fR\fIwin\fR\fB, int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, cchar_t *\fR\fIwchstr\fR\fB);\fR +\fBint mvwin_wchstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, cchar_t *\fIwchstr\fB);\fR .br -\fBint mvwin_wchnstr(WINDOW *\fR\fIwin\fR\fB, int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, cchar_t *\fR\fIwchstr\fR, int \fIn\fR\fB);\fR +\fBint mvwin_wchnstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, cchar_t *\fIwchstr\fR, int \fIn\fB);\fR .fi .SH DESCRIPTION -These functions return an array of complex characters in \fIwchstr\fR, +These functions return an array of complex characters in \fIwchstr\fP, starting at the current cursor position in the named window. Attributes (rendition) are stored with the characters. .PP The -\fBin_wchnstr\fR, -\fBmvin_wchnstr\fR, -\fBmvwin_wchnstr\fR +\fBin_wchnstr\fP, +\fBmvin_wchnstr\fP, +\fBmvwin_wchnstr\fP and -\fBwin_wchnstr\fR +\fBwin_wchnstr\fP fill the array with at most -\fIn\fR -\fBcchar_t\fR +\fIn\fP +\fBcchar_t\fP elements. .br .SH NOTES Note that all routines except -\fBwin_wchnstr\fR +\fBwin_wchnstr\fP may be macros. .PP Reading a line that overflows the array pointed to by -\fIwchstr\fR +\fIwchstr\fP with -\fBin_wchstr\fR, -\fBmvin_wchstr\fR, -\fBmvwin_wchstr\fR +\fBin_wchstr\fP, +\fBmvin_wchstr\fP, +\fBmvwin_wchstr\fP or -\fBwin_wchstr\fR -causes undefined results. Therefore, the use of -\fBin_wchnstr\fR, -\fBmvin_wchnstr\fR, -\fBmvwin_wchnstr\fR, or -\fBwin_wchnstr\fR +\fBwin_wchstr\fP +causes undefined results. +Therefore, the use of +\fBin_wchnstr\fP, +\fBmvin_wchnstr\fP, +\fBmvwin_wchnstr\fP, or +\fBwin_wchnstr\fP is recommended. -.SH RETURN VALUES +.SH RETURN VALUE Upon successful completion, these functions return -\fBOK\fR. +\fBOK\fP. Otherwise, they return -\fBERR\fR. +\fBERR\fP. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. .SH PORTABILITY The XSI Curses defines no error conditions. This implementation checks for null pointers, -returning ERR in that case. +returning \fBERR\fP in that case. .SH SEE ALSO Functions: -\fBcurses\fR(3), -\fBcurs_in_wch\fR(3), -\fBcurs_instr\fR(3), -\fBcurs_inwstr\fR(3) -\fBcurs_inchstr\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_in_wch\fP(3), +\fBcurs_instr\fP(3), +\fBcurs_inwstr\fP(3) +\fBcurs_inchstr\fP(3) diff --git a/lib/libcurses/curs_inch.3 b/lib/libcurses/curs_inch.3 index 7c338a0471c..255cc07dc20 100644 --- a/lib/libcurses/curs_inch.3 +++ b/lib/libcurses/curs_inch.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: curs_inch.3,v 1.4 2019/02/13 07:18:57 nicm Exp $ +.\" $OpenBSD: curs_inch.3,v 1.5 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,51 +30,91 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_inch.3,v 1.4 2019/02/13 07:18:57 nicm Exp $ -.TH curs_inch 3 "" +.\" $Id: curs_inch.3,v 1.5 2023/10/17 09:52:08 nicm Exp $ +.TH curs_inch 3 2023-08-19 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .SH NAME -\fBinch\fR, \fBwinch\fR, \fBmvinch\fR, \fBmvwinch\fR -- get a character and attributes from a \fBcurses\fR window +\fBinch\fP, +\fBwinch\fP, +\fBmvinch\fP, +\fBmvwinch\fP \- get a character and attributes from a \fBcurses\fP window .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBchtype inch(void);\fR +\fBchtype inch(void);\fP .br -\fBchtype winch(WINDOW *win);\fR -.br -\fBchtype mvinch(int y, int x);\fR -.br -\fBchtype mvwinch(WINDOW *win, int y, int x);\fR +\fBchtype winch(WINDOW *\fIwin\fB);\fR +.sp +\fBchtype mvinch(int \fIy\fB, int \fIx\fB);\fR .br +\fBchtype mvwinch(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB);\fR .SH DESCRIPTION -These routines return the character, of type \fBchtype\fR, at the current -position in the named window. If any attributes are set for that position, -their values are OR'ed into the value returned. Constants defined in -\fB\fR can be used with the \fB&\fR (logical AND) operator to +These routines return the character, of type \fBchtype\fP, at the current +position in the named window. +If any attributes are set for that position, +their values are OR'ed into the value returned. +Constants defined in +\fB\fP can be used with the \fB&\fP (logical AND) operator to extract the character or attributes alone. . .SS Attributes -The following bit-masks may be AND-ed with characters returned by \fBwinch\fR. -. +The following bit-masks may be AND-ed with characters returned by \fBwinch\fP. +.PP .TS l l . -\fBA_CHARTEXT\fR Bit-mask to extract character -\fBA_ATTRIBUTES\fR Bit-mask to extract attributes -\fBA_COLOR\fR Bit-mask to extract color-pair field information +\fBA_CHARTEXT\fP Bit-mask to extract character +\fBA_ATTRIBUTES\fP Bit-mask to extract attributes +\fBA_COLOR\fP Bit-mask to extract color-pair field information .TE +.SH RETURN VALUE +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. +.PP +The \fBwinch\fP function does not return an error if the window contains +characters larger than 8-bits (255). +Only the low-order 8 bits of the character are used by \fBwinch\fP. .SH NOTES Note that all of these routines may be macros. .SH PORTABILITY These functions are described in the XSI Curses standard, Issue 4. -.SH SEE ALSO -\fBcurses\fR(3). .PP -Comparable functions in the wide-character (ncursesw) library are -described in -\fBcurs_in_wch\fR(3). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Very old systems (before standardization) provide a different function +with the same name: +.bP +The \fBwinch\fP function was part of the original BSD curses library, +which stored a 7-bit character combined with the \fIstandout\fP attribute. +.IP +In BSD curses, \fBwinch\fP returned only the character (as an integer) +with the \fIstandout\fP attribute removed. +.bP +System V curses added support for several video attributes which +could be combined with characters in the window. +.IP +Reflecting this improvement, the function was altered to return the +character combined with all video attributes in a \fBchtype\fP value. +.PP +X/Open Curses does not specify +the size and layout of attributes, color and character values in +\fBchtype\fP; it is implementation-dependent. +This implementation uses 8 bits for character values. +An application using more bits, e.g., a Unicode value, +should use the wide-character equivalents to these functions. +.SH SEE ALSO +.TP 5 +\fBcurses\fP(3) +gives an overview of the WINDOW and \fBchtype\fP data types. +.TP 5 +\fBcurs_attr\fP(3) +goes into more detail, pointing out portability problems and +constraints on the use of \fBchtype\fP for returning window information. +.TP 5 +\fBcurs_in_wch\fP(3) +describes comparable functions for the wide-character (ncursesw) library. diff --git a/lib/libcurses/curs_inchstr.3 b/lib/libcurses/curs_inchstr.3 index f9f2907fc42..dc8475a6cdb 100644 --- a/lib/libcurses/curs_inchstr.3 +++ b/lib/libcurses/curs_inchstr.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_inchstr.3,v 1.8 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_inchstr.3,v 1.9 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,76 +29,87 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_inchstr.3,v 1.8 2010/01/12 23:21:59 nicm Exp $ -.TH curs_inchstr 3 "" +.\" $Id: curs_inchstr.3,v 1.9 2023/10/17 09:52:08 nicm Exp $ +.TH curs_inchstr 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .na .hy 0 .SH NAME -\fBinchstr\fR, -\fBinchnstr\fR, -\fBwinchstr\fR, -\fBwinchnstr\fR, -\fBmvinchstr\fR, -\fBmvinchnstr\fR, -\fBmvwinchstr\fR, -\fBmvwinchnstr\fR - get a string of characters (and attributes) from a \fBcurses\fR window +\fBinchstr\fP, +\fBinchnstr\fP, +\fBwinchstr\fP, +\fBwinchnstr\fP, +\fBmvinchstr\fP, +\fBmvinchnstr\fP, +\fBmvwinchstr\fP, +\fBmvwinchnstr\fP \- get a string of characters (and attributes) from a \fBcurses\fP window .ad .hy .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint inchstr(chtype *chstr);\fR +\fBint inchstr(chtype *\fIchstr\fB);\fR .br -\fBint inchnstr(chtype *chstr, int n);\fR +\fBint inchnstr(chtype *\fIchstr\fB, int \fIn\fB);\fR .br -\fBint winchstr(WINDOW *win, chtype *chstr);\fR +\fBint winchstr(WINDOW *\fIwin\fB, chtype *\fIchstr\fB);\fR .br -\fBint winchnstr(WINDOW *win, chtype *chstr, int n);\fR -.br -\fBint mvinchstr(int y, int x, chtype *chstr);\fR -.br -\fBint mvinchnstr(int y, int x, chtype *chstr, int n);\fR +\fBint winchnstr(WINDOW *\fIwin\fB, chtype *\fIchstr\fB, int \fIn\fB);\fR +.sp +\fBint mvinchstr(int \fIy\fB, int \fIx\fB, chtype *\fIchstr\fB);\fR .br -\fBint mvwinchstr(WINDOW *win, int y, int x, chtype *chstr);\fR +\fBint mvinchnstr(int \fIy\fB, int \fIx\fB, chtype *\fIchstr\fB, int \fIn\fB);\fR .br -\fBint mvwinchnstr(WINDOW *win, int y, int x, chtype *chstr, int n);\fR +\fBint mvwinchstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, chtype *\fIchstr\fB);\fR .br +\fBint mvwinchnstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, chtype *\fIchstr\fB, int \fIn\fB);\fR .SH DESCRIPTION -These routines return a NULL-terminated array of \fBchtype\fR quantities, +These routines return a NULL-terminated array of \fBchtype\fP quantities, starting at the current cursor position in the named window and ending at the -right margin of the window. The four functions with \fIn\fR as -the last argument, return a leading substring at most \fIn\fR characters long +right margin of the window. +The four functions with \fIn\fP as +the last argument, return a leading substring at most \fIn\fP characters long (exclusive of the trailing (chtype)0). -Constants defined in \fB\fR can be used with the \fB&\fR (logical +Constants defined in \fB\fP can be used with the \fB&\fP (logical AND) operator to extract the character or the attribute alone from any position -in the \fIchstr\fR [see \fBcurs_inch\fR(3)]. +in the \fIchstr\fP [see \fBcurs_inch\fP(3)]. .SH RETURN VALUE -All routines return the integer \fBERR\fR upon failure and an integer value -other than \fBERR\fR upon successful completion (the number of characters +All routines return the integer \fBERR\fP upon failure and an integer value +other than \fBERR\fP upon successful completion (the number of characters retrieved, exclusive of the trailing 0). .PP -No error conditions are defined. -If the \fIchstr\fP parameter is null, -no data is returned, -and the return value is zero. +X/Open Curses defines no error conditions. +In this implementation: +.bP +If the \fIwin\fP parameter is null, an error is returned, +.bP +If the \fIchstr\fP parameter is null, an error is returned, +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. .SH NOTES -Note that all routines except \fBwinchnstr\fR may be macros. SVr4 does not -document whether the result string is 0-terminated; it does not document +Note that all routines except \fBwinchnstr\fP may be macros. +SVr4 does not +document whether the result string is zero-terminated; it does not document whether a length limit argument includes any trailing 0; and it does not document the meaning of the return value. .SH PORTABILITY -These functions are described in the XSI Curses standard, Issue 4. It is no -more specific than the SVr4 documentation on the trailing 0. It does specify -that the successful return of the functions is \fBOK\fR. +These functions are described in the XSI Curses standard, Issue 4. +It is no +more specific than the SVr4 documentation on the trailing 0. +It does specify +that the successful return of the functions is \fBOK\fP. .SH SEE ALSO -\fBcurses\fR(3), \fBcurs_inch\fR(3). +\fBcurses\fP(3), \fBcurs_inch\fP(3). .PP Comparable functions in the wide-character (ncursesw) library are described in -\fBcurs_in_wchstr\fR(3). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurs_in_wchstr\fP(3). diff --git a/lib/libcurses/curs_initscr.3 b/lib/libcurses/curs_initscr.3 index 61de6f22c00..23fca562f5c 100644 --- a/lib/libcurses/curs_initscr.3 +++ b/lib/libcurses/curs_initscr.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_initscr.3,v 1.9 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_initscr.3,v 1.10 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2003,2005 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2016,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,107 +29,282 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_initscr.3,v 1.9 2010/01/12 23:21:59 nicm Exp $ -.TH curs_initscr 3 "" +.\" $Id: curs_initscr.3,v 1.10 2023/10/17 09:52:08 nicm Exp $ +.TH curs_initscr 3 2023-08-19 "ncurses 6.4" "Library calls" +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .na .hy 0 .SH NAME -\fBinitscr\fR, -\fBnewterm\fR, -\fBendwin\fR, -\fBisendwin\fR, -\fBset_term\fR, -\fBdelscreen\fR - \fBcurses\fR screen initialization and manipulation routines +\fBinitscr\fP, +\fBnewterm\fP, +\fBendwin\fP, +\fBisendwin\fP, +\fBset_term\fP, +\fBdelscreen\fP \- \fBcurses\fP screen initialization and manipulation routines .ad .hy .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBWINDOW *initscr(void);\fR +\fBWINDOW *initscr(void);\fP .br -\fBint endwin(void);\fR -.br -\fBbool isendwin(void);\fR -.br -\fBSCREEN *newterm(char *type, FILE *outfd, FILE *infd);\fR -.br -\fBSCREEN *set_term(SCREEN *new);\fR +\fBint endwin(void);\fP +.sp +\fBbool isendwin(void);\fP +.sp +\fBSCREEN *newterm(const char *\fItype\fB, FILE *\fIoutf\fB, FILE *\fIinf\fB);\fR .br -\fBvoid delscreen(SCREEN* sp);\fR +\fBSCREEN *set_term(SCREEN *\fInew\fB);\fR .br +\fBvoid delscreen(SCREEN* \fIsp\fB);\fR .SH DESCRIPTION -\fBinitscr\fR is normally the first \fBcurses\fR routine to call when -initializing a program. A few special routines sometimes need to be -called before it; these are \fBslk_init\fR, \fBfilter\fR, \fBripoffline\fR, -\fBuse_env\fR. For multiple-terminal applications, \fBnewterm\fR may be -called before \fBinitscr\fR. +.SS initscr +\fBinitscr\fP is normally the first \fBcurses\fP routine to call when +initializing a program. +A few special routines sometimes need to be called before it; +these are \fBslk_init\fP(3), \fBfilter\fP, \fBripoffline\fP, +\fBuse_env\fP. +For multiple-terminal applications, +\fBnewterm\fP may be called before \fBinitscr\fP. .PP -The initscr code determines the terminal type and initializes all \fBcurses\fR -data structures. \fBinitscr\fR also causes the first call to \fBrefresh\fR to -clear the screen. If errors occur, \fBinitscr\fR writes an appropriate error -message to standard error and exits; otherwise, a pointer is returned to -\fBstdscr\fR. -.PP -A program that outputs to more than one terminal should use the \fBnewterm\fR -routine for each terminal instead of \fBinitscr\fR. A program that needs to -inspect capabilities, so it can continue to run in a line-oriented mode if the +The initscr code determines the terminal type and initializes all \fBcurses\fP +data structures. +\fBinitscr\fP also causes the first call to \fBrefresh\fP(3) +to clear the screen. +If errors occur, \fBinitscr\fP writes an appropriate error +message to standard error and exits; +otherwise, a pointer is returned to \fBstdscr\fP. +.SS newterm +A program that outputs to more than one terminal should use the \fBnewterm\fP +routine for each terminal instead of \fBinitscr\fP. +A program that needs to inspect capabilities, +so it can continue to run in a line-oriented mode if the terminal cannot support a screen-oriented program, would also use -\fBnewterm\fR. The routine \fBnewterm\fR should be called once for each -terminal. It returns a variable of type \fBSCREEN *\fR which should be saved -as a reference to that terminal. The arguments are the \fItype\fR of the -terminal to be used in place of \fB$TERM\fR, a file pointer for output to the -terminal, and another file pointer for input from the terminal (if \fItype\fR -is \fBNULL\fR, \fB$TERM\fR will be used). The program must also call -\fBendwin\fR for each terminal being used before exiting from \fBcurses\fR. -If \fBnewterm\fR is called more than once for the same terminal, the first -terminal referred to must be the last one for which \fBendwin\fR is called. +\fBnewterm\fP. .PP -A program should always call \fBendwin\fR before exiting or escaping from -\fBcurses\fR mode temporarily. This routine restores tty modes, moves the -cursor to the lower left-hand corner of the screen and resets the terminal into -the proper non-visual mode. Calling \fBrefresh\fR or \fBdoupdate\fR after a -temporary escape causes the program to resume visual mode. +The routine \fBnewterm\fP should be called once for each terminal. +It returns a variable of type \fBSCREEN *\fP which should be saved +as a reference to that terminal. +\fBnewterm\fP's arguments are +.bP +the \fItype\fP of the terminal to be used in place of \fB$TERM\fP, +.bP +an output stream connected to the terminal, and +.bP +an input stream connected to the terminal .PP -The \fBisendwin\fR routine returns \fBTRUE\fR if \fBendwin\fR has been -called without any subsequent calls to \fBwrefresh\fR, and \fBFALSE\fR -otherwise. +If the \fItype\fP parameter is \fBNULL\fP, \fB$TERM\fP will be used. .PP -The \fBset_term\fR routine is used to switch between different -terminals. The screen reference \fBnew\fR becomes the new current -terminal. The previous terminal is returned by the routine. This is -the only routine which manipulates \fBSCREEN\fR pointers; all other -routines affect only the current terminal. +The file descriptor of the output stream is passed to \fBsetupterm\fP(3), +which returns a pointer to a \fBTERMINAL\fP structure. +\fBnewterm\fP's return value holds a pointer to the \fBTERMINAL\fP structure. +.SS endwin +The program must also call +\fBendwin\fP for each terminal being used before exiting from \fBcurses\fP. +If \fBnewterm\fP is called more than once for the same terminal, the first +terminal referred to must be the last one for which \fBendwin\fP is called. .PP -The \fBdelscreen\fR routine frees storage associated with the -\fBSCREEN\fR data structure. The \fBendwin\fR routine does not do -this, so \fBdelscreen\fR should be called after \fBendwin\fR if a -particular \fBSCREEN\fR is no longer needed. +A program should always call \fBendwin\fP before exiting or escaping from +\fBcurses\fP mode temporarily. +This routine +.bP +resets colors to correspond with the default color pair 0, +.bP +moves the cursor to the lower left-hand corner of the screen, +.bP +clears the remainder of the line so that it uses the default colors, +.bP +sets the cursor to normal visibility (see \fBcurs_set\fP(3)), +.bP +stops cursor-addressing mode using the \fIexit_ca_mode\fP terminal capability, +.bP +restores tty modes (see \fBreset_shell_mode\fP(3)). +.PP +Calling \fBrefresh\fP(3) or \fBdoupdate\fP(3) after a +temporary escape causes the program to resume visual mode. +.SS isendwin +The \fBisendwin\fP routine returns \fBTRUE\fP if \fBendwin\fP has been +called without any subsequent calls to \fBwrefresh\fP, +and \fBFALSE\fP otherwise. +.SS set_term +The \fBset_term\fP routine is used to switch between different terminals. +The screen reference \fInew\fP becomes the new current terminal. +The previous terminal is returned by the routine. +This is the only routine which manipulates \fBSCREEN\fP pointers; +all other routines affect only the current terminal. +.SS delscreen +The \fBdelscreen\fP routine frees storage associated with the +\fBSCREEN\fP data structure. +The \fBendwin\fP routine does not do +this, so \fBdelscreen\fP should be called after \fBendwin\fP if a +particular \fBSCREEN\fP is no longer needed. .SH RETURN VALUE -\fBendwin\fR returns the integer \fBERR\fR upon failure and \fBOK\fR +\fBendwin\fP returns the integer \fBERR\fP upon failure and \fBOK\fP upon successful completion. .PP -Routines that return pointers always return \fBNULL\fR on error. +Routines that return pointers always return \fBNULL\fP on error. .PP X/Open defines no error conditions. In this implementation +.bP \fBendwin\fP returns an error if the terminal was not initialized. -.SH NOTES -Note that \fBinitscr\fR and \fBnewterm\fR may be macros. +.bP +\fBnewterm\fP +returns an error if it cannot allocate the data structures for the screen, +or for the top-level windows within the screen, +i.e., +\fBcurscr\fP, \fBnewscr\fP, or \fBstdscr\fP. +.bP +\fBset_term\fP +returns no error. .SH PORTABILITY -These functions are described in the XSI Curses standard, Issue 4. It -specifies that portable applications must not call \fBinitscr\fR more than -once. +These functions were described in the XSI Curses standard, Issue 4. +As of 2015, the current document is X/Open Curses, Issue 7. +.SS Differences +X/Open specifies that portable applications must not +call \fBinitscr\fP more than once: +.bP +The portable way to use \fBinitscr\fP is once only, +using \fBrefresh\fP (see curs_refresh(3)) +to restore the screen after \fBendwin\fP. +.bP +This implementation allows using \fBinitscr\fP after \fBendwin\fP. .PP -Old versions of curses, e.g., BSD 4.4, may have returned a null pointer -from \fBinitscr\fR when an error is detected, rather than exiting. -It is safe but redundant to check the return value of \fBinitscr\fR +Old versions of curses, e.g., BSD 4.4, would return a null pointer +from \fBinitscr\fP when an error is detected, rather than exiting. +It is safe but redundant to check the return value of \fBinitscr\fP in XSI Curses. +.PP +Calling \fBendwin\fP does not dispose of the memory allocated in \fBinitscr\fP +or \fBnewterm\fP. +Deleting a \fBSCREEN\fP provides a way to do this: +.bP +X/Open Curses does not say what happens to \fBWINDOW\fPs when \fBdelscreen\fP +\*(``frees storage associated with the \fBSCREEN\fP\*('' +nor does the SVr4 documentation help, +adding that it should be called after \fBendwin\fP if a \fBSCREEN\fP +is no longer needed. +.bP +However, \fBWINDOW\fPs are implicitly associated with a \fBSCREEN\fP. +so that it is reasonable to expect \fBdelscreen\fP to deal with these. +.bP +SVr4 curses deletes the standard \fBWINDOW\fP structures +\fBstdscr\fP and \fBcurscr\fP as well as a work area \fBnewscr\fP. +SVr4 curses ignores other windows. +.bP +Since version 4.0 (1996), ncurses has maintained a list of all windows +for each screen, +using that information to delete those windows when \fBdelscreen\fP is called. +.bP +NetBSD copied this feature of ncurses in 2001. +PDCurses follows the SVr4 model, +deleting only the standard \fBWINDOW\fP structures. +.SS High-level versus low-level +Different implementations may disagree regarding the level of some functions. +For example, \fBSCREEN\fP (returned by \fBnewterm\fP) and +\fBTERMINAL\fP (returned by \fBsetupterm\fP(3)) hold file descriptors for +the output stream. +If an application switches screens using \fBset_term\fR, +or switches terminals using \fBset_curterm\fP(3), +applications which use the output file descriptor can have different +behavior depending on which structure holds the corresponding descriptor. +.PP +For example +.bP +NetBSD's \fBbaudrate\fP(3) function uses the descriptor in \fBTERMINAL\fP. +\fBncurses\fP and SVr4 use the descriptor in \fBSCREEN\fP. +.bP +NetBSD and \fBncurses\fP use the descriptor +in \fBTERMINAL\fP +for terminal I/O modes, +e.g., +\fBdef_shell_mode\fP(3), +\fBdef_prog_mode\fP(3). +SVr4 curses uses the descriptor in \fBSCREEN\fP. +.SS Unset TERM Variable +If the TERM variable is missing or empty, \fBinitscr\fP uses the +value \*(``unknown\*('', +which normally corresponds to a terminal entry with the \fIgeneric\fP +(\fIgn\fP) capability. +Generic entries are detected by \fBsetupterm\fP(3) +and cannot be used for full-screen operation. +Other implementations may handle a missing/empty TERM variable differently. +.SS Signal Handlers +Quoting from X/Open Curses, section 3.1.1: +.RS 5 +.hy 0 +.PP +.I Curses implementations may provide for special handling of the +.I \fBSIGINT\fP, +.I \fBSIGQUIT\fP and +.I \fBSIGTSTP\fP signals +.I if their disposition is \fBSIG_DFL\fP at the time +\fBinitscr\fI is called \fR... +.PP +.I Any special handling for these signals may remain in effect for the +.I life of the process or until the process changes the disposition of +.I the signal. +.PP +.I None of the Curses functions are required to be safe +.I with respect to signals \fP... +.RE +.hy +.PP +This implementation establishes signal handlers during initialization, +e.g., \fBinitscr\fP or \fBnewterm\fP. +Applications which must handle these signals should set up the corresponding +handlers \fIafter\fP initializing the library: +.TP 5 +.B SIGINT +The handler \fIattempts\fP to cleanup the screen on exit. +Although it \fIusually\fP works as expected, there are limitations: +.RS 5 +.bP +Walking the \fBSCREEN\fP list is unsafe, since all list management +is done without any signal blocking. +.bP +On systems which have \fBREENTRANT\fP turned on, \fBset_term\fP uses +functions which could deadlock or misbehave in other ways. +.bP +\fBendwin\fP calls other functions, many of which use stdio or +other library functions which are clearly unsafe. +.RE +.TP 5 +.B SIGTERM +This uses the same handler as \fBSIGINT\fP, with the same limitations. +It is not mentioned in X/Open Curses, but is more suitable for this +purpose than \fBSIGQUIT\fP (which is used in debugging). +.TP 5 +.B SIGTSTP +This handles the \fIstop\fP signal, used in job control. +When resuming the process, this implementation discards pending +input with \fBflushinput\fP (see curs_util(3)), and repaints the screen +assuming that it has been completely altered. +It also updates the saved terminal modes with \fBdef_shell_mode\fP +(see \fBcurs_kernel\fP(3)). +.TP 5 +.B SIGWINCH +This handles the window-size changes which were ignored in +the standardization efforts. +The handler sets a (signal-safe) variable +which is later tested in \fBwgetch\fP (see curs_getch(3)). +If \fBkeypad\fP has been enabled for the corresponding window, +\fBwgetch\fP returns the key symbol \fBKEY_RESIZE\fP. +At the same time, \fBwgetch\fP calls \fBresizeterm\fP to adjust the +standard screen \fBstdscr\fP, +and update other data such as \fBLINES\fP and \fBCOLS\fP. .SH SEE ALSO -\fBcurses\fR(3), \fBcurs_kernel\fR(3), \fBcurs_refresh\fR(3), -\fBcurs_slk\fR(3), \fBcurs_util\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_kernel\fP(3), +\fBcurs_refresh\fP(3), +\fBcurs_slk\fP(3), +\fBterminfo\fP(3), +\fBcurs_util\fP(3), +\fBcurs_variables\fP(3). diff --git a/lib/libcurses/curs_inopts.3 b/lib/libcurses/curs_inopts.3 index 4172ca9fbae..8f42fda375c 100644 --- a/lib/libcurses/curs_inopts.3 +++ b/lib/libcurses/curs_inopts.3 @@ -1,7 +1,9 @@ -.\" $OpenBSD: curs_inopts.3,v 1.8 2010/01/12 23:21:59 nicm Exp $ +'\" t +.\" $OpenBSD: curs_inopts.3,v 1.9 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2003,2005 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2016,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,217 +30,386 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_inopts.3,v 1.8 2010/01/12 23:21:59 nicm Exp $ -.TH curs_inopts 3 "" +.\" $Id: curs_inopts.3,v 1.9 2023/10/17 09:52:08 nicm Exp $ +.TH curs_inopts 3 2023-08-19 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .na .hy 0 .SH NAME -\fBcbreak\fR, -\fBnocbreak\fR, -\fBecho\fR, -\fBnoecho\fR, -\fBhalfdelay\fR, -\fBintrflush\fR, -\fBkeypad\fR, -\fBmeta\fR, -\fBnodelay\fR, -\fBnotimeout\fR, -\fBraw\fR, -\fBnoraw\fR, -\fBnoqiflush\fR, -\fBqiflush\fR, -\fBtimeout\fR, -\fBwtimeout\fR, -\fBtypeahead\fR - \fBcurses\fR input options +\fBcbreak\fP, +\fBecho\fP, +\fBhalfdelay\fP, +\fBintrflush\fP, +\fBis_cbreak\fP, +\fBis_echo\fP, +\fBis_nl\fP, +\fBis_raw\fP, +\fBkeypad\fP, +\fBmeta\fP, +\fBnl\fP, +\fBnocbreak\fP, +\fBnodelay\fP, +\fBnoecho\fP, +\fBnonl\fP, +\fBnoqiflush\fP, +\fBnoraw\fP, +\fBnotimeout\fP, +\fBqiflush\fP, +\fBraw\fP, +\fBtimeout\fP, +\fBwtimeout\fP, +\fBtypeahead\fP \- \fBcurses\fP input options .ad .hy .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .PP -\fBint cbreak(void);\fR +\fBint cbreak(void);\fP .br -\fBint nocbreak(void);\fR +\fBint nocbreak(void);\fP +.sp +\fBint echo(void);\fP .br -\fBint echo(void);\fR +\fBint noecho(void);\fP +.sp +\fBint intrflush(WINDOW *\fIwin\fB, bool \fIbf\fB);\fR .br -\fBint noecho(void);\fR +\fBint keypad(WINDOW *\fIwin\fB, bool \fIbf\fB);\fR .br -\fBint halfdelay(int tenths);\fR +\fBint meta(WINDOW *\fIwin\fB, bool \fIbf\fB);\fR .br -\fBint intrflush(WINDOW *win, bool bf);\fR +\fBint nodelay(WINDOW *\fIwin\fB, bool \fIbf\fB);\fR .br -\fBint keypad(WINDOW *win, bool bf);\fR +\fBint notimeout(WINDOW *\fIwin\fB, bool \fIbf\fB);\fR +.sp +\fBint nl(void);\fP .br -\fBint meta(WINDOW *win, bool bf);\fR +\fBint nonl(void);\fP +.sp +\fBint raw(void);\fP .br -\fBint nodelay(WINDOW *win, bool bf);\fR +\fBint noraw(void);\fP +.sp +\fBvoid qiflush(void);\fP .br -\fBint raw(void);\fR +\fBvoid noqiflush(void);\fP +.sp +\fBint halfdelay(int \fItenths\fB);\fR .br -\fBint noraw(void);\fR +\fBvoid timeout(int \fIdelay\fB);\fR .br -\fBvoid noqiflush(void);\fR +\fBvoid wtimeout(WINDOW *\fIwin\fB, int \fIdelay\fB);\fR +.sp +\fBint typeahead(int \fIfd\fB);\fR +.sp +/* extensions */ .br -\fBvoid qiflush(void);\fR +\fBint is_cbreak(void);\fP .br -\fBint notimeout(WINDOW *win, bool bf);\fR +\fBint is_echo(void);\fP .br -\fBvoid timeout(int delay);\fR +\fBint is_nl(void);\fP .br -\fBvoid wtimeout(WINDOW *win, int delay);\fR -.br -\fBint typeahead(int fd);\fR +\fBint is_raw(void);\fP .br .SH DESCRIPTION +The \fBncurses\fP library provides several functions which let an application +change the way input from the terminal is handled. +Some are global, applying to all windows. +Others apply only to a specific window. +Window-specific settings are not automatically applied to new or derived +windows. +An application must apply these to each window, if the same behavior +is needed. +.\" +.SS cbreak/nocbreak Normally, the tty driver buffers typed characters until a newline or carriage -return is typed. The \fBcbreak\fR routine disables line buffering and +return is typed. +The \fBcbreak\fP routine disables line buffering and erase/kill character-processing (interrupt and flow control characters are unaffected), making characters typed by the user immediately available to the -program. The \fBnocbreak\fR routine returns the terminal to normal (cooked) +program. +The \fBnocbreak\fP routine returns the terminal to normal (cooked) mode. .PP -Initially the terminal may or may not be in \fBcbreak\fR mode, as the mode is -inherited; therefore, a program should call \fBcbreak\fR or \fBnocbreak\fR -explicitly. Most interactive programs using \fBcurses\fR set the \fBcbreak\fR -mode. Note that \fBcbreak\fR overrides \fBraw\fR. -[See \fBcurs_getch\fR(3) for a -discussion of how these routines interact with \fBecho\fR and \fBnoecho\fR.] -.PP -The \fBecho\fR and \fBnoecho\fR routines control whether characters typed by -the user are echoed by \fBgetch\fR as they are typed. Echoing by the tty -driver is always disabled, but initially \fBgetch\fR is in echo mode, so -characters typed are echoed. Authors of most interactive programs prefer to do +Initially the terminal may or may not be in \fBcbreak\fP mode, as the mode is +inherited; therefore, a program should call \fBcbreak\fP or \fBnocbreak\fP +explicitly. +Most interactive programs using \fBcurses\fP set the \fBcbreak\fP +mode. +Note that \fBcbreak\fP overrides \fBraw\fP. +[See \fBcurs_getch\fP(3) for a +discussion of how these routines interact with \fBecho\fP and \fBnoecho\fP.] +.\" +.SS echo/noecho +The \fBecho\fP and \fBnoecho\fP routines control whether characters typed by +the user are echoed by \fBgetch\fP(3) as they are typed. +Echoing by the tty +driver is always disabled, but initially \fBgetch\fP is in echo mode, so +characters typed are echoed. +Authors of most interactive programs prefer to do their own echoing in a controlled area of the screen, or not to echo at all, so -they disable echoing by calling \fBnoecho\fR. -[See \fBcurs_getch\fR(3) for a -discussion of how these routines interact with \fBcbreak\fR and -\fBnocbreak\fR.] -.PP -The \fBhalfdelay\fR routine is used for half-delay mode, which is similar to -\fBcbreak\fR mode in that characters typed by the user are immediately -available to the program. However, after blocking for \fItenths\fR tenths of -seconds, ERR is returned if nothing has been typed. The value of \fBtenths\fR -must be a number between 1 and 255. Use \fBnocbreak\fR to leave half-delay +they disable echoing by calling \fBnoecho\fP. +[See \fBcurs_getch\fP(3) for a +discussion of how these routines interact with \fBcbreak\fP and +\fBnocbreak\fP.] +.\" +.SS halfdelay +The \fBhalfdelay\fP routine is used for half-delay mode, which is similar to +\fBcbreak\fP mode in that characters typed by the user are immediately +available to the program. +However, after blocking for \fItenths\fP tenths of +seconds, \fBERR\fP is returned if nothing has been typed. +The value of \fItenths\fP +must be a number between 1 and 255. +Use \fBnocbreak\fP to leave half-delay mode. -.PP -If the \fBintrflush\fR option is enabled, (\fIbf\fR is \fBTRUE\fR), when an -interrupt key is pressed on the keyboard (interrupt, break, quit) all output in +.\" +.SS intrflush +If the \fBintrflush\fP option is enabled (\fIbf\fP is \fBTRUE\fP), and an +interrupt key is pressed on the keyboard (interrupt, break, quit), all output in the tty driver queue will be flushed, giving the effect of faster response to -the interrupt, but causing \fBcurses\fR to have the wrong idea of what is on -the screen. Disabling (\fIbf\fR is \fBFALSE\fR), the option prevents the -flush. The default for the option is inherited from the tty driver settings. +the interrupt, but causing \fBcurses\fP to have the wrong idea of what is on +the screen. +Disabling the option (\fIbf\fP is \fBFALSE\fP) prevents the +flush. +The default for the option is inherited from the tty driver settings. The window argument is ignored. -.PP -The \fBkeypad\fR option enables the keypad of the user's terminal. If -enabled (\fIbf\fR is \fBTRUE\fR), the user can press a function key -(such as an arrow key) and \fBwgetch\fR returns a single value -representing the function key, as in \fBKEY_LEFT\fR. If disabled -(\fIbf\fR is \fBFALSE\fR), \fBcurses\fR does not treat function keys +.\" +.SS keypad +The \fBkeypad\fP option enables the keypad of the user's terminal. +If +enabled (\fIbf\fP is \fBTRUE\fP), the user can press a function key +(such as an arrow key) and \fBwgetch\fP(3) returns a single value +representing the function key, as in \fBKEY_LEFT\fP. +If disabled +(\fIbf\fP is \fBFALSE\fP), \fBcurses\fP does not treat function keys specially and the program has to interpret the escape sequences -itself. If the keypad in the terminal can be turned on (made to +itself. +If the keypad in the terminal can be turned on (made to transmit) and off (made to work locally), turning on this option -causes the terminal keypad to be turned on when \fBwgetch\fR is -called. The default value for keypad is false. -.PP +causes the terminal keypad to be turned on when \fBwgetch\fP(3) is +called. +The default value for keypad is \fBFALSE\fP. +.\" +.SS meta Initially, whether the terminal returns 7 or 8 significant bits on -input depends on the control mode of the tty driver [see termio(7)]. -To force 8 bits to be returned, invoke \fBmeta\fR(\fIwin\fR, -\fBTRUE\fR); this is equivalent, under POSIX, to setting the CS8 flag -on the terminal. To force 7 bits to be returned, invoke -\fBmeta\fR(\fIwin\fR, \fBFALSE\fR); this is equivalent, under POSIX, -to setting the CS7 flag on the terminal. The window argument, -\fIwin\fR, is always ignored. If the terminfo capabilities \fBsmm\fR -(meta_on) and \fBrmm\fR (meta_off) are defined for the terminal, -\fBsmm\fR is sent to the terminal when \fBmeta\fR(\fIwin\fR, -\fBTRUE\fR) is called and \fBrmm\fR is sent when \fBmeta\fR(\fIwin\fR, -\fBFALSE\fR) is called. -.PP -The \fBnodelay\fR option causes \fBgetch\fR to be a non-blocking call. -If no input is ready, \fBgetch\fR returns \fBERR\fR. If disabled -(\fIbf\fR is \fBFALSE\fR), \fBgetch\fR waits until a key is pressed. -.PP -While interpreting an input escape sequence, \fBwgetch\fR sets a timer -while waiting for the next character. If \fBnotimeout(\fR\fIwin\fR, -\fBTRUE\fR) is called, then \fBwgetch\fR does not set a timer. The +input depends on the control mode of the tty driver [see \fBtermios\fP(3)]. +To force 8 bits to be returned, invoke \fBmeta\fP(\fIwin\fP, +\fBTRUE\fP); this is equivalent, under POSIX, to setting the CS8 flag +on the terminal. +To force 7 bits to be returned, invoke +\fBmeta\fP(\fIwin\fP, \fBFALSE\fP); this is equivalent, under POSIX, +to setting the CS7 flag on the terminal. +The window argument, +\fIwin\fP, is always ignored. +If the terminfo capabilities \fBsmm\fP +(meta_on) and \fBrmm\fP (meta_off) are defined for the terminal, +\fBsmm\fP is sent to the terminal when \fBmeta\fP(\fIwin\fP, +\fBTRUE\fP) is called and \fBrmm\fP is sent when \fBmeta\fP(\fIwin\fP, +\fBFALSE\fP) is called. +.\" +.SS nl/nonl +The \fBnl\fP and \fBnonl\fP routines control whether the underlying display +device translates the return key into newline on input. +.\" +.SS nodelay +The \fBnodelay\fP option causes \fBgetch\fP to be a non-blocking call. +If no input is ready, \fBgetch\fP returns \fBERR\fP. +If disabled +(\fIbf\fP is \fBFALSE\fP), \fBgetch\fP waits until a key is pressed. +.SS notimeout +When interpreting an escape sequence, \fBwgetch\fP(3) sets a timer +while waiting for the next character. +If \fBnotimeout(\fIwin\fR, +\fBTRUE\fP) is called, then \fBwgetch\fP does not set a timer. +The purpose of the timeout is to differentiate between sequences received from a function key and those typed by a user. -.PP -The \fBraw\fR and \fBnoraw\fR routines place the terminal into or out of raw -mode. Raw mode is similar to \fBcbreak\fR mode, in that characters typed are -immediately passed through to the user program. The differences are that in +.\" +.SS raw/noraw +The \fBraw\fP and \fBnoraw\fP routines place the terminal into or out of raw +mode. +Raw mode is similar to \fBcbreak\fP mode, in that characters typed are +immediately passed through to the user program. +The differences are that in raw mode, the interrupt, quit, suspend, and flow control characters are all -passed through uninterpreted, instead of generating a signal. The behavior of +passed through uninterpreted, instead of generating a signal. +The behavior of the BREAK key depends on other bits in the tty driver that are not set by -\fBcurses\fR. -.PP -When the \fBnoqiflush\fR routine is used, normal flush of input and -output queues associated with the \fBINTR\fR, \fBQUIT\fR and -\fBSUSP\fR characters will not be done [see termio(7)]. When -\fBqiflush\fR is called, the queues will be flushed when these control -characters are read. You may want to call \fBnoqiflush()\fR in a signal +\fBcurses\fP. +.\" +.SS qiflush/noqiflush +When the \fBnoqiflush\fP routine is used, normal flush of input and +output queues associated with the \fBINTR\fP, \fBQUIT\fP and +\fBSUSP\fP characters will not be done [see \fBtermios\fP(3)]. +When +\fBqiflush\fP is called, the queues will be flushed when these control +characters are read. +You may want to call \fBnoqiflush\fP in a signal handler if you want output to continue as though the interrupt had not occurred, after the handler exits. -.PP -The \fBtimeout\fR and \fBwtimeout\fR routines set blocking or -non-blocking read for a given window. If \fIdelay\fR is negative, +.\" +.SS timeout/wtimeout +The \fBtimeout\fP and \fBwtimeout\fP routines set blocking or +non-blocking read for a given window. +If \fIdelay\fP is negative, blocking read is used (i.e., waits indefinitely for -input). If \fIdelay\fR is zero, then non-blocking read is used -(i.e., read returns \fBERR\fR if no input is waiting). If -\fIdelay\fR is positive, then read blocks for \fIdelay\fR -milliseconds, and returns \fBERR\fR if there is still no input. -Hence, these routines provide the same functionality as \fBnodelay\fR, +input). +If \fIdelay\fP is zero, then non-blocking read is used +(i.e., read returns \fBERR\fP if no input is waiting). +If +\fIdelay\fP is positive, then read blocks for \fIdelay\fP +milliseconds, and returns \fBERR\fP if there is still no input. +Hence, these routines provide the same functionality as \fBnodelay\fP, plus the additional capability of being able to block for only -\fIdelay\fR milliseconds (where \fIdelay\fR is positive). -.PP -The \fBcurses\fR library does ``line-breakout optimization'' by looking for -typeahead periodically while updating the screen. If input is found, -and it is coming from a tty, the current update is postponed until -\fBrefresh\fR or \fBdoupdate\fR is called again. This allows faster -response to commands typed in advance. Normally, the input FILE -pointer passed to \fBnewterm\fR, or \fBstdin\fR in the case that -\fBinitscr\fR was used, will be used to do this typeahead checking. -The \fBtypeahead\fR routine specifies that the file descriptor -\fIfd\fR is to be used to check for typeahead instead. If \fIfd\fR is --1, then no typeahead checking is done. +\fIdelay\fP milliseconds (where \fIdelay\fP is positive). +.\" +.SS typeahead +The \fBcurses\fP library does \*(``line-breakout optimization\*('' +by looking for typeahead periodically while updating the screen. +If input is found, and it is coming from a tty, +the current update is postponed until +\fBrefresh\fP(3) or \fBdoupdate\fP is called again. +This allows faster response to commands typed in advance. +Normally, the input FILE +pointer passed to \fBnewterm\fP, or \fBstdin\fP in the case that +\fBinitscr\fP was used, will be used to do this typeahead checking. +The \fBtypeahead\fP routine specifies that the file descriptor +\fIfd\fP is to be used to check for typeahead instead. +If \fIfd\fP is +\-1, then no typeahead checking is done. +.\" .SH RETURN VALUE -All routines that return an integer return \fBERR\fR upon failure and OK (SVr4 -specifies only "an integer value other than \fBERR\fR") upon successful -completion, unless otherwise noted in the preceding routine descriptions. +All routines that return an integer return \fBERR\fP upon failure and \fBOK\fP +(SVr4 specifies only \*(``an integer value other than \fBERR\fP\*('') +upon successful completion, +unless otherwise noted in the preceding routine descriptions. .PP X/Open does not define any error conditions. In this implementation, functions with a window parameter will return an error if it is null. Any function will also return an error if the terminal was not initialized. Also, -.RS +.RS 3 .TP 5 \fBhalfdelay\fP returns an error if its parameter is outside the range 1..255. .RE +.SH EXTENSIONS +This implementation provides four functions which may be used to detect +if the corresponding flags were set or reset: +.PP +.TS +l l l. +\fBQuery\fP \fBSet\fP \fBReset\fP +_ +is_cbreak cbreak nocbreak +is_echo echo noecho +is_nl nl nonl +is_raw raw noraw +.TE +.PP +In each case, the function returns +.TP 5 +1 +if the flag is set, +.TP 5 +0 +if the flag is reset, or +.TP 5 +-1 +if the curses library was not initialized. +.PP +These routines are specific to ncurses. +They were not supported on Version 7, BSD or System V implementations. +It is recommended that any code depending on ncurses extensions +be conditioned using NCURSES_VERSION. .SH PORTABILITY -These functions are described in the XSI Curses standard, Issue 4. +Except as noted in the section on extensions, +these functions are described in the XSI Curses standard, Issue 4. .PP The ncurses library obeys the XPG4 standard and the historical practice of the AT&T curses implementations, in that the echo bit is cleared when curses -initializes the terminal state. BSD curses differed from this slightly; it -left the echo bit on at initialization, but the BSD \fBraw\fR call turned it -off as a side-effect. For best portability, set echo or noecho explicitly +initializes the terminal state. +BSD curses differed from this slightly; it +left the echo bit on at initialization, but the BSD \fBraw\fP call turned it +off as a side-effect. +For best portability, set \fBecho \fPor \fBnoecho\fP explicitly just after initialization, even if your program remains in cooked mode. +.PP +The XSI Curses standard is ambiguous on the question of whether \fBraw\fP +should disable the CRLF translations controlled by \fBnl\fP and \fBnonl\fP. +BSD curses did turn off these translations; AT&T curses (at least as late as +SVr1) did not. +We chose to do so, on the theory that a programmer requesting +raw input wants a clean (ideally 8-bit clean) connection that the operating +system will not alter. +.PP +When \fBkeypad\fP is first enabled, +ncurses loads the key-definitions for the current terminal description. +If the terminal description includes extended string capabilities, +e.g., from using the \fB\-x\fP option of \fBtic\fP, +then ncurses also defines keys for the capabilities whose names +begin with \*(``k\*(''. +The corresponding keycodes are generated and (depending on previous +loads of terminal descriptions) may differ from one execution of a +program to the next. +The generated keycodes are recognized by the \fBkeyname\fP function +(which will then return a name beginning with \*(``k\*('' denoting the +terminfo capability name rather than \*(``K\*('', used for curses key-names). +On the other hand, an application can use \fBdefine_key\fP to establish +a specific keycode for a given string. +This makes it possible for an application to check for an extended +capability's presence with \fBtigetstr\fP, +and reassign the keycode to match its own needs. +.PP +Low-level applications can use \fBtigetstr\fP to obtain the definition +of any particular string capability. +Higher-level applications which use the curses \fBwgetch\fP +and similar functions to return keycodes rely upon the order in which +the strings are loaded. +If more than one key definition has the same string value, +then \fBwgetch\fP can return only one keycode. +Most curses implementations (including ncurses) +load key definitions in the order +defined by the array of string capability names. +The last key to be loaded determines the keycode which will be returned. +In ncurses, you may also have extended capabilities interpreted as +key definitions. +These are loaded after the predefined keys, +and if a capability's value is the same as a previously-loaded +key definition, +the later definition is the one used. .SH NOTES -Note that \fBecho\fR, \fBnoecho\fR, \fBhalfdelay\fR, \fBintrflush\fR, -\fBmeta\fR, \fBnodelay\fR, \fBnotimeout\fR, \fBnoqiflush\fR, -\fBqiflush\fR, \fBtimeout\fR, and \fBwtimeout\fR may be macros. +Note that +\fBecho\fP, +\fBnoecho\fP, +\fBhalfdelay\fP, +\fBintrflush\fP, +\fBmeta\fP, +\fBnl\fP, +\fBnonl\fP, +\fBnodelay\fP, +\fBnotimeout\fP, +\fBnoqiflush\fP, +\fBqiflush\fP, +\fBtimeout\fP, and +\fBwtimeout\fP may be macros. .PP -The \fBnoraw\fR and \fBnocbreak\fR calls follow historical practice in that -they attempt to restore to normal (`cooked') mode from raw and cbreak modes -respectively. Mixing raw/noraw and cbreak/nocbreak calls leads to tty driver +The \fBnoraw\fP and \fBnocbreak\fP calls follow historical practice in that +they attempt to restore to normal (\*(``cooked\*('') mode +from raw and cbreak modes respectively. +Mixing raw/noraw and cbreak/nocbreak calls leads to tty driver control states that are hard to predict or understand; it is not recommended. .SH SEE ALSO -\fBcurses\fR(3), \fBcurs_getch\fR(3), \fBcurs_initscr\fR(3), \fBtermio\fR(7) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_getch\fP(3), +\fBcurs_initscr\fP(3), +\fBcurs_util\fP(3), +\fBdefine_key\fP(3), +\fBtermios\fP(3) diff --git a/lib/libcurses/curs_ins_wch.3 b/lib/libcurses/curs_ins_wch.3 index 5e8e3eec5b6..e01c60a0b60 100644 --- a/lib/libcurses/curs_ins_wch.3 +++ b/lib/libcurses/curs_ins_wch.3 @@ -1,6 +1,7 @@ -.\" $OpenBSD: curs_ins_wch.3,v 1.1 2010/09/06 17:26:17 nicm Exp $ +.\" $OpenBSD: curs_ins_wch.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ .\"*************************************************************************** -.\" Copyright (c) 2002,2006 Free Software Foundation, Inc. * +.\" Copyright 2019-2021,2022 Thomas E. Dickey * +.\" Copyright 2002-2010,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -27,40 +28,42 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_ins_wch.3,v 1.1 2010/09/06 17:26:17 nicm Exp $ -.TH curs_ins_wch 3 "" +.\" $Id: curs_ins_wch.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ +.TH curs_ins_wch 3 2022-02-12 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .SH NAME -\fBins_wch\fR, -\fBmvins_wch\fR, -\fBmvwins_wch\fR, -\fBwins_wch\fR \- insert a complex character and rendition into a window +\fBins_wch\fP, +\fBmvins_wch\fP, +\fBmvwins_wch\fP, +\fBwins_wch\fP \- insert a complex character and rendition into a window .SH SYNOPSIS #include .sp -\fBint ins_wch(const cchar_t *\fR\fIwch\fR\fB);\fR +\fBint ins_wch(const cchar_t *\fIwch\fB);\fR .br -\fBint wins_wch(WINDOW *\fR\fIwin, const cchar_t *\fR\fIwch\fR\fB);\fR -.br -\fBint mvins_wch(int \fR\fIy, int \fR\fIx, const cchar_t *\fR\fIwch\fR\fB);\fR +\fBint wins_wch(WINDOW *\fIwin\fB, const cchar_t *\fIwch\fB);\fR +.sp +\fBint mvins_wch(int \fIy\fB, int \fIx\fB, const cchar_t *\fIwch\fB);\fR .br -\fBint mvwins_wch(WINDOW *\fR\fIwin, int \fR\fIy, int \fR\fIx, const cchar_t *\fR\fIwch\fR\fB);\fR +\fBint mvwins_wch(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, const cchar_t *\fIwch\fB);\fR .SH DESCRIPTION -These routines, insert the complex character \fIwch\fR with rendition +These routines, insert the complex character \fIwch\fP with rendition before the character under the cursor. All characters to the right of the cursor are moved one space to the right, with the possibility of the rightmost character on the line being lost. The insertion operation does not change the cursor position. .SH RETURN VALUE -If successful, these functions return OK. -If not, they return ERR. +If successful, these functions return \fBOK\fP. +If not, they return \fBERR\fP. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. .SH ERRORS No errors are defined. .SH SEE ALSO -\fBcurses\fR(3), -\fBcurs_insch\fR(3). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_insch\fP(3). diff --git a/lib/libcurses/curs_ins_wstr.3 b/lib/libcurses/curs_ins_wstr.3 index d488fc6b8be..b5e819a891e 100644 --- a/lib/libcurses/curs_ins_wstr.3 +++ b/lib/libcurses/curs_ins_wstr.3 @@ -1,6 +1,7 @@ -.\" $OpenBSD: curs_ins_wstr.3,v 1.1 2010/09/06 17:26:17 nicm Exp $ +.\" $OpenBSD: curs_ins_wstr.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ .\"*************************************************************************** -.\" Copyright (c) 2002,2005 Free Software Foundation, Inc. * +.\" Copyright 2019-2021,2022 Thomas E. Dickey * +.\" Copyright 2002-2012,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -27,61 +28,65 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_ins_wstr.3,v 1.1 2010/09/06 17:26:17 nicm Exp $ -.TH curs_ins_wstr 3 "" +.\" $Id: curs_ins_wstr.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ +.TH curs_ins_wstr 3 2022-02-12 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .na .hy 0 .SH NAME -\fBins_wstr\fR, -\fBins_nwstr\fR, -\fBwins_wstr\fR, -\fBwins_nwstr\fR, -\fBmvins_wstr\fR, -\fBmvins_nwstr\fR, -\fBmvwins_wstr\fR, -\fBmvwins_nwstr\fR \- insert a wide-character string into a curses window +\fBins_wstr\fP, +\fBins_nwstr\fP, +\fBwins_wstr\fP, +\fBwins_nwstr\fP, +\fBmvins_wstr\fP, +\fBmvins_nwstr\fP, +\fBmvwins_wstr\fP, +\fBmvwins_nwstr\fP \- insert a wide-character string into a curses window .ad .hy .SH SYNOPSIS .nf -\fB#include \fR +\fB#include \fP .sp -\fBint ins_wstr(const wchar_t *\fR\fIwstr);\fR +\fBint ins_wstr(const wchar_t *\fIwstr);\fR .br -\fBint ins_nwstr(const wchar_t *\fR\fIwstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint ins_nwstr(const wchar_t *\fIwstr\fB, int \fIn\fB);\fR .br -\fBint wins_wstr(WINDOW *\fR\fIwin\fR\fB, const wchar_t *\fR\fIwstr\fR\fB);\fR +\fBint wins_wstr(WINDOW *\fIwin\fB, const wchar_t *\fIwstr\fB);\fR .br -\fBint wins_nwstr(WINDOW *\fR\fIwin\fR\fB, const wchar_t *\fR\fIwstr\fR\fB, int \fR\fIn\fR\fB);\fR -.br -\fBint mvins_wstr(int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, const wchar_t *\fR\fIwstr\fR\fB);\fR +\fBint wins_nwstr(WINDOW *\fIwin\fB, const wchar_t *\fIwstr\fB, int \fIn\fB);\fR +.sp +\fBint mvins_wstr(int \fIy\fB, int \fIx\fB, const wchar_t *\fIwstr\fB);\fR .br -\fBint mvins_nwstr(int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, const wchar_t *\fR\fIwstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint mvins_nwstr(int \fIy\fB, int \fIx\fB, const wchar_t *\fIwstr\fB, int \fIn\fB);\fR .br -\fBint mvwins_wstr(WINDOW *\fR\fIwin\fR\fB, int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, const wchar_t *\fR\fIwstr\fR\fB);\fR +\fBint mvwins_wstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, const wchar_t *\fIwstr\fB);\fR .br -\fBint mvwins_nwstr(WINDOW *\fR\fIwin\fR\fB, int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, const wchar_t *\fR\fIwstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint mvwins_nwstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, const wchar_t *\fIwstr\fB, int \fIn\fB);\fR .fi .SH DESCRIPTION -These routines insert a \fBwchar_t\fR character string +These routines insert a \fBwchar_t\fP character string (as many characters as will fit on the line) before the character under the cursor. All characters to the right of the cursor are shifted right, with the possibility of the rightmost characters on the line being lost. No wrapping is performed. The cursor position does not change -(after moving to \fIy\fR, \fIx\fR, if specified). -The four routines with \fIn\fR as the last argument -insert a leading substring of at most \fIn\fR \fBwchar_t\fR characters. -If \fIn\fR is less than 1, the entire string is inserted. +(after moving to \fIy\fP, \fIx\fP, if specified). +The four routines with \fIn\fP as the last argument +insert a leading substring of at most \fIn\fP \fBwchar_t\fP characters. +If \fIn\fP is less than 1, the entire string is inserted. .PP -If a character in \fIwstr\fR is a tab, newline, carriage return or +If a character in \fIwstr\fP is a tab, newline, carriage return or backspace, the cursor is moved appropriately within the window. -A newline also does a \fBclrtoeol\fR before moving. +A newline also does a \fBclrtoeol\fP before moving. Tabs are considered to be at every eighth column. -If a character in \fIwstr\fR is another control character, -it is drawn in the \fB^\fR\fIX\fR notation. -Calling \fBwin_wch\fR after adding a control character +If a character in \fIwstr\fP is another control character, +it is drawn in the \fB^\fIX\fR notation. +Calling \fBwin_wch\fP after adding a control character (and moving to it, if necessary) does not return the control character, but instead returns a character in the ^-representation @@ -93,17 +98,15 @@ If the first character in the string is a nonspacing character, these functions will fail. XSI does not define what will happen if a nonspacing character follows a control character. -.SH RETURN VALUES -Upon successful completion, these functions return OK. -Otherwise, they return ERR. +.SH RETURN VALUE +Upon successful completion, these functions return \fBOK\fP. +Otherwise, they return \fBERR\fP. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. .SH SEE ALSO -\fBcurses\fR(3), -\fBcurs_insstr\fR(3), -\fBcurs_in_wch\fR(3), -\fBcurs_ins_wch\fR(3). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_insstr\fP(3), +\fBcurs_in_wch\fP(3), +\fBcurs_ins_wch\fP(3). diff --git a/lib/libcurses/curs_insch.3 b/lib/libcurses/curs_insch.3 index 4895ebce40d..f87bf98388d 100644 --- a/lib/libcurses/curs_insch.3 +++ b/lib/libcurses/curs_insch.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_insch.3,v 1.8 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_insch.3,v 1.9 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2003,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,49 +29,52 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_insch.3,v 1.8 2010/01/12 23:21:59 nicm Exp $ -.TH curs_insch 3 "" +.\" $Id: curs_insch.3,v 1.9 2023/10/17 09:52:08 nicm Exp $ +.TH curs_insch 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .SH NAME -\fBinsch\fR, -\fBwinsch\fR, -\fBmvinsch\fR, -\fBmvwinsch\fR - insert a character before cursor in a \fBcurses\fR window +\fBinsch\fP, +\fBwinsch\fP, +\fBmvinsch\fP, +\fBmvwinsch\fP \- insert a character before cursor in a \fBcurses\fP window .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint insch(chtype ch);\fR +\fBint insch(chtype \fIch\fB);\fR .br -\fBint winsch(WINDOW *win, chtype ch);\fR -.br -\fBint mvinsch(int y, int x, chtype ch);\fR -.br -\fBint mvwinsch(WINDOW *win, int y, int x, chtype ch);\fR +\fBint winsch(WINDOW *\fIwin\fB, chtype \fIch\fB);\fR +.sp +\fBint mvinsch(int \fIy\fB, int \fIx\fB, chtype \fIch\fB);\fR .br +\fBint mvwinsch(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, chtype \fIch\fB);\fR .SH DESCRIPTION -These routines insert the character \fIch\fR before the character under the -cursor. All characters to the right of the cursor are moved one space to the +These routines insert the character \fIch\fP before the character under the +cursor. +All characters to the right of the cursor are moved one space to the right, with the possibility of the rightmost character on the line being lost. The insertion operation does not change the cursor position. .SH RETURN VALUE -All routines that return an integer return \fBERR\fR upon failure and OK (SVr4 -specifies only "an integer value other than \fBERR\fR") upon successful -completion, unless otherwise noted in the preceding routine descriptions. +All routines that return an integer return \fBERR\fP upon failure and \fBOK\fP +(SVr4 specifies only "an integer value other than \fBERR\fP") +upon successful completion, +unless otherwise noted in the preceding routine descriptions. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. .SH NOTES These routines do not necessarily imply use of a hardware insert character feature. .PP -Note that \fBinsch\fR, \fBmvinsch\fR, and \fBmvwinsch\fR may be macros. +Note that \fBinsch\fP, \fBmvinsch\fP, and \fBmvwinsch\fP may be macros. .SH PORTABILITY These functions are described in the XSI Curses standard, Issue 4. .SH SEE ALSO -\fBcurses\fR(3). +\fBcurses\fP(3). .PP Comparable functions in the wide-character (ncursesw) library are described in -\fBcurs_ins_wch\fR(3). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurs_ins_wch\fP(3). diff --git a/lib/libcurses/curs_insstr.3 b/lib/libcurses/curs_insstr.3 index e5d824f99fd..7edc43b8b11 100644 --- a/lib/libcurses/curs_insstr.3 +++ b/lib/libcurses/curs_insstr.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_insstr.3,v 1.10 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_insstr.3,v 1.11 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2019-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,36 +29,39 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_insstr.3,v 1.10 2010/01/12 23:21:59 nicm Exp $ -.TH curs_insstr 3 "" +.\" $Id: curs_insstr.3,v 1.11 2023/10/17 09:52:08 nicm Exp $ +.TH curs_insstr 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .SH NAME -\fBinsstr\fR, -\fBinsnstr\fR, -\fBwinsstr\fR, -\fBwinsnstr\fR, -\fBmvinsstr\fR, -\fBmvinsnstr\fR, -\fBmvwinsstr\fR, -\fBmvwinsnstr\fR - insert string before cursor in a \fBcurses\fR window +\fBinsstr\fP, +\fBinsnstr\fP, +\fBwinsstr\fP, +\fBwinsnstr\fP, +\fBmvinsstr\fP, +\fBmvinsnstr\fP, +\fBmvwinsstr\fP, +\fBmvwinsnstr\fP \- insert string before cursor in a \fBcurses\fP window .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .br -\fBint insstr(const char *str);\fR +\fBint insstr(const char *\fIstr\fB);\fR .br -\fBint insnstr(const char *str, int n);\fR +\fBint insnstr(const char *\fIstr\fB, int \fIn\fB);\fR .br -\fBint winsstr(WINDOW *win, const char *str);\fR +\fBint winsstr(WINDOW *\fIwin\fB, const char *\fIstr\fB);\fR .br -\fBint winsnstr(WINDOW *win, const char *str, int n);\fR +\fBint winsnstr(WINDOW *\fIwin\fB, const char *\fIstr\fB, int \fIn\fB);\fR +.sp +\fBint mvinsstr(int \fIy\fB, int \fIx\fB, const char *\fIstr\fB);\fR .br -\fBint mvinsstr(int y, int x, const char *str);\fR +\fBint mvinsnstr(int \fIy\fB, int \fIx\fB, const char *\fIstr\fB, int \fIn\fB);\fR .br -\fBint mvinsnstr(int y, int x, const char *str, int n);\fR -.br -\fBint mvwinsstr(WINDOW *win, int y, int x, const char *str);\fR -.br -\fBint mvwinsnstr(WINDOW *win, int y, int x, const char *str, int n);\fR +\fBint mvwinsstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, const char *\fIstr\fB);\fR .br +\fBint mvwinsnstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, const char *\fIstr\fB, int \fIn\fB);\fR .SH DESCRIPTION These routines insert a character string (as many characters as will fit on the line) @@ -65,39 +69,38 @@ before the character under the cursor. All characters to the right of the cursor are shifted right with the possibility of the rightmost characters on the line being lost. The cursor position does not change -(after moving to \fIy\fR, \fIx\fR, if specified). -The functions with \fIn\fR as the last argument -insert a leading substring of at most \fIn\fR characters. -If \fIn\fR<=0, then the entire string is inserted. +(after moving to \fIy\fP, \fIx\fP, if specified). +The functions with \fIn\fP as the last argument +insert a leading substring of at most \fIn\fP characters. +If \fIn\fP<=0, then the entire string is inserted. .PP Special characters are handled as in \fBaddch\fP. .SH RETURN VALUE -All routines that return an integer return \fBERR\fR upon failure and OK (SVr4 -specifies only "an integer value other than \fBERR\fR") upon successful -completion, unless otherwise noted in the preceding routine descriptions. +All routines that return an integer return \fBERR\fP upon failure and \fBOK\fP +(SVr4 specifies only "an integer value other than \fBERR\fP") +upon successful completion, +unless otherwise noted in the preceding routine descriptions. .PP X/Open defines no error conditions. In this implementation, if the window parameter is null or the str parameter is null, an error is returned. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. .SH NOTES -Note that all but \fBwinsnstr\fR may be macros. +Note that all but \fBwinsnstr\fP may be macros. .SH PORTABILITY These functions are described in the XSI Curses standard, Issue 4, which adds const qualifiers to the arguments. .LP -The Single Unix Specification, Version 2 states that +The Single Unix Specification, Version 2 states that \fBinsnstr\fP and \fBwinsnstr\fP perform wrapping. This is probably an error, since it makes this group of functions inconsistent. Also, no implementation of curses documents this inconsistency. .SH SEE ALSO -\fBcurses\fR(3), -\fBcurs_util\fR(3), -\fBcurs_clear\fR(3), -\fBcurs_inch\fR(3). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_util\fP(3), +\fBcurs_clear\fP(3), +\fBcurs_inch\fP(3). diff --git a/lib/libcurses/curs_instr.3 b/lib/libcurses/curs_instr.3 index 140ffcde798..03caed844c4 100644 --- a/lib/libcurses/curs_instr.3 +++ b/lib/libcurses/curs_instr.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_instr.3,v 1.8 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_instr.3,v 1.9 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,64 +29,72 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_instr.3,v 1.8 2010/01/12 23:21:59 nicm Exp $ -.TH curs_instr 3 "" +.\" $Id: curs_instr.3,v 1.9 2023/10/17 09:52:08 nicm Exp $ +.TH curs_instr 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .SH NAME -\fBinstr\fR, -\fBinnstr\fR, -\fBwinstr\fR, -\fBwinnstr\fR, -\fBmvinstr\fR, -\fBmvinnstr\fR, -\fBmvwinstr\fR, -\fBmvwinnstr\fR - get a string of characters from a \fBcurses\fR window +\fBinstr\fP, +\fBinnstr\fP, +\fBwinstr\fP, +\fBwinnstr\fP, +\fBmvinstr\fP, +\fBmvinnstr\fP, +\fBmvwinstr\fP, +\fBmvwinnstr\fP \- get a string of characters from a \fBcurses\fP window .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint instr(char *str);\fR +\fBint instr(char *\fIstr\fB);\fR .br -\fBint innstr(char *str, int n);\fR +\fBint innstr(char *\fIstr\fB, int \fIn\fB);\fR .br -\fBint winstr(WINDOW *win, char *str);\fR +\fBint winstr(WINDOW *\fIwin\fB, char *\fIstr\fB);\fR .br -\fBint winnstr(WINDOW *win, char *str, int n);\fR -.br -\fBint mvinstr(int y, int x, char *str);\fR -.br -\fBint mvinnstr(int y, int x, char *str, int n);\fR +\fBint winnstr(WINDOW *\fIwin\fB, char *\fIstr\fB, int \fIn\fB);\fR +.sp +\fBint mvinstr(int \fIy\fB, int \fIx\fB, char *\fIstr\fB);\fR .br -\fBint mvwinstr(WINDOW *win, int y, int x, char *str);\fR +\fBint mvinnstr(int \fIy\fB, int \fIx\fB, char *\fIstr\fB, int \fIn\fB);\fR .br -\fBint mvwinnstr(WINDOW *win, int y, int x, char *str, int n);\fR +\fBint mvwinstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, char *\fIstr\fB);\fR .br +\fBint mvwinnstr(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, char *\fIstr\fB, int \fIn\fB);\fR .SH DESCRIPTION -These routines return a string of characters in \fIstr\fR, extracted starting +These routines return a string of characters in \fIstr\fP, extracted starting at the current cursor position in the named window. -Attributes are stripped from the characters. The four -functions with \fIn\fR as the last argument return a leading substring at most -\fIn\fR characters long (exclusive of the trailing NUL). +Attributes are stripped from the characters. +The four +functions with \fIn\fP as the last argument return a leading substring at most +\fIn\fP characters long (exclusive of the trailing NUL). .SH RETURN VALUE -All of the functions return \fBERR\fR upon failure, +All of the functions return \fBERR\fP upon failure, or the number of characters actually read into the string. .PP -X/Open defines no error conditions. -In this implementation, -if the window parameter is null or the str parameter is null, -a zero is returned. +X/Open Curses defines no error conditions. +In this implementation: +.bP +If the \fIwin\fP parameter is null, an error is returned, +.bP +If the \fIchstr\fP parameter is null, an error is returned, +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. .SH NOTES -Note that all routines except \fBwinnstr\fR may be macros. +Note that all routines except \fBwinnstr\fP may be macros. .SH PORTABILITY SVr4 does not document whether a length limit includes or excludes the trailing NUL. .PP The ncurses library extends the XSI description by allowing a negative -value for \fIn\fR. +value for \fIn\fP. In this case, the functions return the string ending at the right margin. .SH SEE ALSO -\fBcurses\fR(3). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3). diff --git a/lib/libcurses/curs_inwstr.3 b/lib/libcurses/curs_inwstr.3 index 8cd418c7dfd..966b239b0f3 100644 --- a/lib/libcurses/curs_inwstr.3 +++ b/lib/libcurses/curs_inwstr.3 @@ -1,6 +1,7 @@ -.\" $OpenBSD: curs_inwstr.3,v 1.1 2010/09/06 17:26:17 nicm Exp $ +.\" $OpenBSD: curs_inwstr.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ .\"*************************************************************************** -.\" Copyright (c) 2002-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 2002-2012,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -27,68 +28,78 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_inwstr.3,v 1.1 2010/09/06 17:26:17 nicm Exp $ -.TH curs_inwstr 3 "" +.\" $Id: curs_inwstr.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ +.TH curs_inwstr 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .SH NAME -\fBinwstr\fR, -\fBinnwstr\fR, -\fBwinwstr\fR, -\fBwinnwstr\fR, -\fBmvinwstr\fR, -\fBmvinnwstr\fR, -\fBmvwinwstr\fR, -\fBmvwinnwstr\fR \- get a string of \fBwchar_t\fR characters from a curses window +\fBinwstr\fP, +\fBinnwstr\fP, +\fBwinwstr\fP, +\fBwinnwstr\fP, +\fBmvinwstr\fP, +\fBmvinnwstr\fP, +\fBmvwinwstr\fP, +\fBmvwinnwstr\fP \- get a string of \fBwchar_t\fP characters from a curses window .SH SYNOPSIS .nf -\fB#include \fR +\fB#include \fP .sp -\fBint inwstr(\fR\fBwchar_t *\fR\fIstr\fR\fB);\fR +\fBint inwstr(\fBwchar_t *\fIwstr\fB);\fR .br -\fBint innwstr(\fR\fBwchar_t *\fR\fIstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint innwstr(\fBwchar_t *\fIwstr\fB, int \fIn\fB);\fR .br -\fBint winwstr(\fR\fBWINDOW *\fR\fIwin\fR\fB, wchar_t *\fR\fIstr\fR\fB);\fR +\fBint winwstr(\fBWINDOW *\fIwin\fB, wchar_t *\fIwstr\fB);\fR .br -\fBint winnwstr(\fR\fBWINDOW *\fR\fIwin\fR\fB, wchar_t *\fR\fIstr\fR\fB, int \fR\fIn\fR\fB);\fR -.br -\fBint mvinwstr(\fR\fBint \fR\fIy\fR\fB, int \fR\fIx\fR\fB, wchar_t *\fR\fIstr\fR\fB);\fR +\fBint winnwstr(\fBWINDOW *\fIwin\fB, wchar_t *\fIwstr\fB, int \fIn\fB);\fR +.sp +\fBint mvinwstr(\fBint \fIy\fB, int \fIx\fB, wchar_t *\fIwstr\fB);\fR .br -\fBint mvinnwstr(\fR\fBint \fR\fIy\fR\fB, int \fR\fIx\fR\fB, wchar_t *\fR\fIstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint mvinnwstr(\fBint \fIy\fB, int \fIx\fB, wchar_t *\fIwstr\fB, int \fIn\fB);\fR .br -\fBint mvwinwstr(\fR\fBWINDOW *\fR\fIwin\fR\fB, int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, wchar_t *\fR\fIstr\fR\fB);\fR +\fBint mvwinwstr(\fBWINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, wchar_t *\fIwstr\fB);\fR .br -\fBint mvwinnwstr(\fR\fBWINDOW *\fR\fIwin\fR\fB, int \fR\fIy\fR\fB, int \fR\fIx\fR\fB, wchar_t *\fR\fIstr\fR\fB, int \fR\fIn\fR\fB);\fR +\fBint mvwinnwstr(\fBWINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, wchar_t *\fIwstr\fB, int \fIn\fB);\fR .fi .SH DESCRIPTION -These routines return a string of \fBwchar_t\fR characters in \fIwstr\fR, +These routines return a string of \fBwchar_t\fP wide characters in \fIwstr\fP, extracted starting at the current cursor position in the named window. -Attributes are stripped from the characters. -The four functions with \fIn\fR as the last argument return a leading substring at most -\fIn\fR bytes long (exclusive of the trailing NUL). -Transfer stops at the end of the current line, or when \fIn\fR bytes have -been stored at the location referenced by \fIwstr\fR. .PP -If the size \fIn\fR is not large enough to store a complete character, +The four functions with \fIn\fP as the last argument return +a leading substring at most \fIn\fP characters long +(exclusive of the trailing NUL). +Transfer stops at the end of the current line, or when \fIn\fP characters have +been stored at the location referenced by \fIwstr\fP. +.PP +If the size \fIn\fP is not large enough to store a complete complex character, an error is generated. .SH NOTES -Note that all routines except -\fBwinnwstr\fR +All routines except +\fBwinnwstr\fP may be macros. -.SH RETURN VALUES +.PP +Each cell in the window holds a complex character (i.e., base- +and combining-characters) together with attributes and color. +These functions store only the wide characters, +ignoring attributes and color. +Use \fBin_wchstr\fP to return the complex characters from a window. +.SH RETURN VALUE All routines return -\fBERR\fR -upon failure. Upon -successful completion, the *\fBinwstr\fR +\fBERR\fP +upon failure. +Upon +successful completion, the *\fBinwstr\fP routines return -\fBOK\fR, and the *\fBinnwstr\fR +\fBOK\fP, and the *\fBinnwstr\fP routines return the number of characters read into the string. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. .SH SEE ALSO -\fBcurses\fR(3), -\fBcurs_instr\fR(3), -\fBcurs_in_wchstr\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_instr\fP(3), +\fBcurs_in_wchstr\fP(3) diff --git a/lib/libcurses/curs_kernel.3 b/lib/libcurses/curs_kernel.3 index 4a69f9aab1f..07b470d222f 100644 --- a/lib/libcurses/curs_kernel.3 +++ b/lib/libcurses/curs_kernel.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_kernel.3,v 1.9 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_kernel.3,v 1.10 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2001,2005 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2016,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,126 +29,161 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_kernel.3,v 1.9 2010/01/12 23:21:59 nicm Exp $ -.TH curs_kernel 3 "" +.\" $Id: curs_kernel.3,v 1.10 2023/10/17 09:52:08 nicm Exp $ +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.TH curs_kernel 3 2023-08-19 "ncurses 6.4" "Library calls" .na .hy 0 .SH NAME -\fBdef_prog_mode\fR, -\fBdef_shell_mode\fR, -\fBreset_prog_mode\fR, -\fBreset_shell_mode\fR, -\fBresetty\fR, -\fBsavetty\fR, -\fBgetsyx\fR, -\fBsetsyx\fR, -\fBripoffline\fR, -\fBcurs_set\fR, -\fBnapms\fR - low-level \fBcurses\fR routines +\fBdef_prog_mode\fP, +\fBdef_shell_mode\fP, +\fBreset_prog_mode\fP, +\fBreset_shell_mode\fP, +\fBresetty\fP, +\fBsavetty\fP, +\fBgetsyx\fP, +\fBsetsyx\fP, +\fBripoffline\fP, +\fBcurs_set\fP, +\fBnapms\fP \- low-level \fBcurses\fP routines .ad .hy .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint def_prog_mode(void);\fR +\fBint def_prog_mode(void);\fP .br -\fBint def_shell_mode(void);\fR -.br -\fBint reset_prog_mode(void);\fR -.br -\fBint reset_shell_mode(void);\fR -.br -\fBint resetty(void);\fR -.br -\fBint savetty(void);\fR -.br -\fBvoid getsyx(int y, int x);\fR +\fBint def_shell_mode(void);\fP +.sp +\fBint reset_prog_mode(void);\fP .br -\fBvoid setsyx(int y, int x);\fR +\fBint reset_shell_mode(void);\fP +.sp +\fBint resetty(void);\fP .br -\fBint ripoffline(int line, int (*init)(WINDOW *, int));\fR +\fBint savetty(void);\fP +.sp +\fBvoid getsyx(int \fIy\fB, int \fIx\fB);\fR .br -\fBint curs_set(int visibility);\fR +\fBvoid setsyx(int \fIy\fB, int \fIx\fB);\fR +.sp +\fBint ripoffline(int \fIline\fB, int (*\fIinit\fB)(WINDOW *, int));\fR .br -\fBint napms(int ms);\fR +\fBint curs_set(int \fIvisibility\fB);\fR .br +\fBint napms(int \fIms\fB);\fR .SH DESCRIPTION -The following routines give low-level access to various \fBcurses\fR -capabilities. Theses routines typically are used inside library -routines. +The following routines give low-level access +to various \fBcurses\fP capabilities. +These routines typically are used inside library routines. +.SS def_prog_mode, def_shell_mode +The \fBdef_prog_mode\fP and \fBdef_shell_mode\fP routines save the +current terminal modes as the \*(``program\*('' +(in \fBcurses\fP) or \*(``shell\*('' +(not in \fBcurses\fP) state for use by the \fBreset_prog_mode\fP and +\fBreset_shell_mode\fP routines. +This is done automatically by \fBinitscr\fP. +There is one such save area for each screen context +allocated by \fBnewterm\fP. +.SS reset_prog_mode, reset_shell_mode +The \fBreset_prog_mode\fP and \fBreset_shell_mode\fP routines restore +the terminal to \*(``program\*('' (in \fBcurses\fP) or \*(``shell\*('' (out of +\fBcurses\fP) state. +These are done automatically by \fBendwin\fP(3) and, +after an \fBendwin\fP, by \fBdoupdate\fP, +so they normally are not called. +.SS resetty, savetty +The \fBresetty\fP and \fBsavetty\fP routines save and restore the +state of the terminal modes. +\fBsavetty\fP saves the current state in +a buffer and \fBresetty\fP restores the state to what it was at the +last call to \fBsavetty\fP. +.SS getsyx +The \fBgetsyx\fP routine returns the current coordinates +of the \fIvirtual screen\fP cursor in \fIy\fP and \fIx\fP. +If \fBleaveok\fP is currently \fBTRUE\fP, then +\fB\-1\fP,\fB\-1\fP is returned. +If lines have been removed from the top of the +screen, using \fBripoffline\fP, \fIy\fP and \fIx\fP include these lines; +therefore, \fIy\fP and \fIx\fP should be used only as arguments for +\fBsetsyx\fP. .PP -The \fBdef_prog_mode\fR and \fBdef_shell_mode\fR routines save the -current terminal modes as the "program" (in \fBcurses\fR) or "shell" -(not in \fBcurses\fR) state for use by the \fBreset_prog_mode\fR and -\fBreset_shell_mode\fR routines. This is done automatically by -\fBinitscr\fR. There is one such save area for each screen context -allocated by \fBnewterm()\fR. -.PP -The \fBreset_prog_mode\fR and \fBreset_shell_mode\fR routines restore -the terminal to "program" (in \fBcurses\fR) or "shell" (out of -\fBcurses\fR) state. These are done automatically by \fBendwin\fR -and, after an \fBendwin\fR, by \fBdoupdate\fR, so they normally are -not called. -.PP -The \fBresetty\fR and \fBsavetty\fR routines save and restore the -state of the terminal modes. \fBsavetty\fR saves the current state in -a buffer and \fBresetty\fR restores the state to what it was at the -last call to \fBsavetty\fR. -.PP -The \fBgetsyx\fR routine returns the current coordinates of the virtual screen -cursor in \fIy\fR and \fIx\fR. If \fBleaveok\fR is currently \fBTRUE\fR, then -\fB-1\fR,\fB-1\fR is returned. If lines have been removed from the top of the -screen, using \fBripoffline\fR, \fIy\fR and \fIx\fR include these lines; -therefore, \fIy\fR and \fIx\fR should be used only as arguments for -\fBsetsyx\fR. -.PP -The \fBsetsyx\fR routine sets the virtual screen cursor to -\fIy\fR, \fIx\fR. If \fIy\fR and \fIx\fR are both \fB-1\fR, then -\fBleaveok\fR is set. The two routines \fBgetsyx\fR and \fBsetsyx\fR +Few applications will use this feature, +most use \fBgetyx\fP instead. +.SS setsyx +The \fBsetsyx\fP routine sets +the \fIvirtual screen\fP cursor to \fIy\fP, \fIx\fP. +If \fIy\fP and \fIx\fP are both \fB\-1\fP, then +\fBleaveok\fP is set. +The two routines \fBgetsyx\fP and \fBsetsyx\fP are designed to be used by a library routine, which manipulates -\fBcurses\fR windows but does not want to change the current position -of the program's cursor. The library routine would call \fBgetsyx\fR +\fBcurses\fP windows but does not want to change the current position +of the program's cursor. +The library routine would call \fBgetsyx\fP at the beginning, do its manipulation of its own windows, do a -\fBwnoutrefresh\fR on its windows, call \fBsetsyx\fR, and then call -\fBdoupdate\fR. +\fBwnoutrefresh\fP on its windows, call \fBsetsyx\fP, and then call +\fBdoupdate\fP. .PP -The \fBripoffline\fR routine provides access to the same facility that -\fBslk_init\fR [see \fBcurs_slk\fR(3)] uses to reduce the size of the -screen. \fBripoffline\fR must be called before \fBinitscr\fR or -\fBnewterm\fR is called. If \fIline\fR is positive, a line is removed -from the top of \fBstdscr\fR; if \fIline\fR is negative, a line is -removed from the bottom. When this is done inside \fBinitscr\fR, the -routine \fBinit\fR (supplied by the user) is called with two -arguments: a window pointer to the one-line window that has been -allocated and an integer with the number of columns in the window. -Inside this initialization routine, the integer variables \fBLINES\fR -and \fBCOLS\fR (defined in \fB\fR) are not guaranteed to be -accurate and \fBwrefresh\fR or \fBdoupdate\fR must not be called. It -is allowable to call \fBwnoutrefresh\fR during the initialization -routine. +Few applications will use this feature, +most use \fBwmove\fP instead. +.SS ripoffline +The \fBripoffline\fP routine provides access to the same facility that +\fBslk_init\fP [see \fBcurs_slk\fP(3)] uses to reduce the size of the +screen. +\fBripoffline\fP must be called before \fBinitscr\fP or +\fBnewterm\fP is called, to prepare these initial actions: +.bP +If \fIline\fP is positive, a line is removed from the top of \fBstdscr\fP. +.bP +if \fIline\fP is negative, a line is removed from the bottom. .PP -\fBripoffline\fR can be called up to five times before calling \fBinitscr\fR or -\fBnewterm\fR. +When the resulting initialization is done inside \fBinitscr\fP, the +routine \fBinit\fP (supplied by the user) is called with two +arguments: +.bP +a window pointer to the one-line window that has been +allocated and +.bP +an integer with the number of columns in the window. .PP -The \fBcurs_set\fR routine sets the cursor state is set to invisible, -normal, or very visible for \fBvisibility\fR equal to \fB0\fR, -\fB1\fR, or \fB2\fR respectively. If the terminal supports the -\fIvisibility\fR requested, the previous \fIcursor\fR state is -returned; otherwise, \fBERR\fR is returned. +Inside this initialization routine, the integer variables \fBLINES\fP +and \fBCOLS\fP (defined in \fB\fP) are not guaranteed to be +accurate and \fBwrefresh\fP or \fBdoupdate\fP must not be called. +It is allowable to call \fBwnoutrefresh\fP during the initialization routine. .PP -The \fBnapms\fR routine is used to sleep for \fIms\fR milliseconds. +\fBripoffline\fP can be called up to five times before calling \fBinitscr\fP or +\fBnewterm\fP. +.SS curs_set +The \fBcurs_set\fP routine sets the cursor state to invisible, +normal, or very visible for \fBvisibility\fP equal to \fB0\fP, +\fB1\fP, or \fB2\fP respectively. +If the terminal supports the \fIvisibility\fP requested, +the previous \fIcursor\fP state is returned; +otherwise, \fBERR\fP is returned. +.SS napms +The \fBnapms\fP routine is used to sleep for \fIms\fP milliseconds. .SH RETURN VALUE -Except for \fBcurs_set\fR, these routines always return \fBOK\fR. +Except for \fBcurs_set\fP, these routines always return \fBOK\fP. .PP -\fBcurs_set\fR -returns the previous cursor state, or \fBERR\fR if the -requested \fIvisibility\fR is not supported. +\fBcurs_set\fP +returns the previous cursor state, or \fBERR\fP if the +requested \fIvisibility\fP is not supported. .PP X/Open defines no error conditions. In this implementation -.RS .TP 5 -\fBdef_prog_mode\fR, \fBdef_shell_mode\fR, \fBreset_prog_mode\fR, \fBreset_shell_mode\fR +.na +.hy 0 +\fBdef_prog_mode\fP, \fBdef_shell_mode\fP, \fBreset_prog_mode\fP, \fBreset_shell_mode\fP +.hy +.ad return an error if the terminal was not initialized, or if the I/O call to obtain the terminal settings fails. @@ -155,34 +191,35 @@ if the I/O call to obtain the terminal settings fails. \fBripoffline\fP returns an error if the maximum number of ripped-off lines exceeds the maximum (NRIPS = 5). -.RE .SH NOTES -Note that \fBgetsyx\fR is a macro, so \fB&\fR is not necessary before -the variables \fIy\fR and \fIx\fR. +Note that \fBgetsyx\fP is a macro, so \fB&\fP is not necessary before +the variables \fIy\fP and \fIx\fP. .PP -Older SVr4 man pages warn that the return value of \fBcurs_set\fR "is currently -incorrect". This implementation gets it right, but it may be unwise to count +Older SVr4 man pages warn that the return value +of \fBcurs_set\fP \*(``is currently incorrect\*(''. +This implementation gets it right, but it may be unwise to count on the correctness of the return value anywhere else. .PP -Both ncurses and SVr4 will call \fBcurs_set\fR in \fBendwin\fR -if \fBcurs_set\fR +Both ncurses and SVr4 will call \fBcurs_set\fP in \fBendwin\fP +if \fBcurs_set\fP has been called to make the cursor other than normal, i.e., either invisible or very visible. There is no way for ncurses to determine the initial cursor state to restore that. .SH PORTABILITY -The functions \fBsetsyx\fR and \fBgetsyx\fR are not described in the XSI -Curses standard, Issue 4. All other functions are as described in XSI Curses. +The \fIvirtual screen\fP functions \fBsetsyx\fP and \fBgetsyx\fP +are not described in the XSI Curses standard, Issue 4. +All other functions are as described in XSI Curses. .PP -The SVr4 documentation describes \fBsetsyx\fR and \fBgetsyx\fR as having return -type int. This is misleading, as they are macros with no documented semantics +The SVr4 documentation describes \fBsetsyx\fP and \fBgetsyx\fP +as having return type int. +This is misleading, as they are macros with no documented semantics for the return value. .SH SEE ALSO -\fBcurses\fR(3), \fBcurs_initscr\fR(3), \fBcurs_outopts\fR(3), \fBcurs_refresh\fR(3), -\fBcurs_scr_dump\fR(3), \fBcurs_slk\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_initscr\fP(3), +\fBcurs_outopts\fP(3), +\fBcurs_refresh\fP(3), +\fBcurs_scr_dump\fP(3), +\fBcurs_slk\fP(3), +\fBcurs_variables\fP(3). diff --git a/lib/libcurses/curs_legacy.3 b/lib/libcurses/curs_legacy.3 index 21ac9e5db77..e00cdf6ff7e 100644 --- a/lib/libcurses/curs_legacy.3 +++ b/lib/libcurses/curs_legacy.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_legacy.3,v 1.1 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_legacy.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 2007 Free Software Foundation, Inc. * +.\" Copyright 2019-2022,2023 Thomas E. Dickey * +.\" Copyright 2007-2015,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,68 +29,81 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_legacy.3,v 1.1 2010/01/12 23:21:59 nicm Exp $ -.TH curs_legacy 3 "" +.\" $Id: curs_legacy.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.TH curs_legacy 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBgetbegx\fR, -\fBgetbegy\fR, -\fBgetcurx\fR, -\fBgetcury\fR, -\fBgetmaxx\fR, -\fBgetmaxy\fR, -\fBgetparx\fR, -\fBgetpary\fR - get \fBcurses\fR cursor and window coordinates +curs_legacy \- get \fBcurses\fP cursor and window coordinates, attributes .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint getbegx(WINDOW *win);\fR -.br -\fBint getbegy(WINDOW *win);\fR -.br -\fBint getcurx(WINDOW *win);\fR -.br -\fBint getcury(WINDOW *win);\fR -.br -\fBint getmaxx(WINDOW *win);\fR +\fBint getattrs(const WINDOW *\fIwin\fB);\fR +.sp +\fBint getbegx(const WINDOW *\fIwin\fB);\fR .br -\fBint getmaxy(WINDOW *win);\fR +\fBint getbegy(const WINDOW *\fIwin\fB);\fR +.sp +\fBint getcurx(const WINDOW *\fIwin\fB);\fR .br -\fBint getparx(WINDOW *win);\fR +\fBint getcury(const WINDOW *\fIwin\fB);\fR +.sp +\fBint getmaxx(const WINDOW *\fIwin\fB);\fR .br -\fBint getpary(WINDOW *win);\fR +\fBint getmaxy(const WINDOW *\fIwin\fB);\fR +.sp +\fBint getparx(const WINDOW *\fIwin\fB);\fR .br +\fBint getpary(const WINDOW *\fIwin\fB);\fR .SH DESCRIPTION -The \fBgetbegy\fR and \fBgetbegx\fR functions return the same -data as \fBgetbegyx\fR. -.PP -The \fBgetcury\fR and \fBgetcurx\fR functions return the same -data as \fBgetyx\fR. -.PP -The \fBgetmaxy\fR and \fBgetmaxx\fR functions return the same -data as \fBgetmaxyx\fR. -.PP -The \fBgetpary\fR and \fBgetparx\fR functions return the same -data as \fBgetparyx\fR. +These legacy functions are simpler to use than the X/Open Curses functions: +.bP +The \fBgetattrs\fP function returns the same attribute data as \fBwattr_get\fP. +.IP +However, \fBgetattrs\fP returns an integer (actually a \fBchtype\fP), +while \fBwattr_get\fP returns the current color pair in a separate parameter. +In the wide-character library configuration, +color pairs may not fit into a \fBchtype\fP, +so \fBwattr_get\fP is the only way to obtain the color information. +.IP +Because \fBgetattrs\fP returns the attributes in a single parameter, +it would not be possible for an application to distinguish that from +\fBERR\fP (a \fI-1\fP). +If the window parameter is null, \fBgetattrs\fP returns \fBA_NORMAL\fP (zero). +.bP +The \fBgetbegy\fP and \fBgetbegx\fP functions return the same +data as \fBgetbegyx\fP. +.bP +The \fBgetcury\fP and \fBgetcurx\fP functions return the same +data as \fBgetyx\fP. +.bP +The \fBgetmaxy\fP and \fBgetmaxx\fP functions return the same +data as \fBgetmaxyx\fP. +.bP +The \fBgetpary\fP and \fBgetparx\fP functions return the same +data as \fBgetparyx\fP. .SH RETURN VALUE -These functions return an integer, -or ERR if the window parameter is null. +Except as noted, +these functions return an integer, +or \fBERR\fP if the window parameter is null. .SH NOTES All of these interfaces are provided as macros and functions. The macros are suppressed (and only the functions provided) -when \fBNCURSES_OPAQUE\fR is defined. +when \fBNCURSES_OPAQUE\fP is defined. The standard forms such as \fBgetyx\fP must be implemented as macros, and (in this implementation) are defined in terms of the functions described here, to avoid reliance on internal details of the WINDOW structure. .SH PORTABILITY These functions were supported on Version 7, BSD or System V implementations. +None of those implementations checked the window parameter. +.PP +The \fBgetattrs\fP function and macro are defined to return a (signed) integer +for compatibility with those implementations +although an unsigned type would have been more appropriate. .SH SEE ALSO -\fBcurses\fR(3), -\fBcurs_getyx\fR(3), -\fBcurs_opaque\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_getyx\fP(3), +\fBcurs_opaque\fP(3) diff --git a/lib/libcurses/curs_memleaks.3 b/lib/libcurses/curs_memleaks.3 new file mode 100644 index 00000000000..697d69ce9c4 --- /dev/null +++ b/lib/libcurses/curs_memleaks.3 @@ -0,0 +1,127 @@ +.\"*************************************************************************** +.\" Copyright 2019-2021,2022 Thomas E. Dickey * +.\" Copyright 2008-2010,2017 Free Software Foundation, Inc. * +.\" * +.\" Permission is hereby granted, free of charge, to any person obtaining a * +.\" copy of this software and associated documentation files (the * +.\" "Software"), to deal in the Software without restriction, including * +.\" without limitation the rights to use, copy, modify, merge, publish, * +.\" distribute, distribute with modifications, sublicense, and/or sell * +.\" copies of the Software, and to permit persons to whom the Software is * +.\" furnished to do so, subject to the following conditions: * +.\" * +.\" The above copyright notice and this permission notice shall be included * +.\" in all copies or substantial portions of the Software. * +.\" * +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * +.\" IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * +.\" DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * +.\" OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * +.\" THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +.\" * +.\" Except as contained in this notice, the name(s) of the above copyright * +.\" holders shall not be used in advertising or otherwise to promote the * +.\" sale, use or other dealings in this Software without prior written * +.\" authorization. * +.\"*************************************************************************** +.\" +.\" $Id: curs_memleaks.3,v 1.1 2023/10/17 09:52:08 nicm Exp $ +.TH curs_memleaks 3 2022-06-04 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.na +.hy 0 +.SH NAME +\fBexit_curses\fP, +\fBexit_terminfo\fP \- \fBcurses\fP memory-leak checking +.ad +.hy +.SH SYNOPSIS +\fB#include \fP +.br +\fBvoid exit_curses(int \fIcode\fB);\fR +.sp +\fB#include \fP +.br +\fBvoid exit_terminfo(int \fIcode\fB);\fR +.sp +/* deprecated (intentionally not declared in curses.h or term.h) */ +.br +\fBvoid _nc_freeall(void);\fP +.br +\fBvoid _nc_free_and_exit(int \fIcode\fB);\fR +.br +\fBvoid _nc_free_tinfo(int \fIcode\fB);\fR +.SH DESCRIPTION +These functions are used to simplify analysis of memory leaks in the ncurses +library. +.PP +Any implementation of curses must not free the memory associated with +a screen, since (even after calling \fBendwin\fP(3)), it must be available +for use in the next call to \fBrefresh\fP(3). +There are also chunks of memory held for performance reasons. +That makes it hard to analyze curses applications for memory leaks. +When using the specially configured debugging version of the ncurses library, +applications can call functions which free those chunks of memory, +simplifying the process of memory-leak checking. +.PP +Some of the functions are named with a \*(``_nc_\*('' prefix +because they are not intended for use in the non-debugging library: +.TP 5 +\fB_nc_freeall\fP +This frees (almost) all of the memory allocated by ncurses. +.TP 5 +\fB_nc_free_and_exit\fP +This frees the memory allocated by ncurses (like \fB_nc_freeall\fP), +and exits the program. +It is preferred over \fB_nc_freeall\fP since some of that memory +may be required to keep the application running. +Simply exiting (with the given exit-code) is safer. +.TP 5 +\fB_nc_free_tinfo\fP +Use this function if only the low-level terminfo functions (and +corresponding library) are used. +Like \fB_nc_free_and_exit\fP, it exits the program after freeing memory. +.PP +The functions prefixed \*(``_nc\*('' are normally not available; +they must be configured into the library +at build time using the \fB\-\-disable-leaks\fP option. +That compiles-in code that frees memory that normally would not be freed. +.PP +The \fBexit_curses\fP and \fBexit_terminfo\fP functions +call \fB_nc_free_and_exit\fP and \fB_nc_free_tinfo\fP if +the library is configured to support memory-leak checking. +If the library is not configured to support memory-leak checking, +they simply call \fBexit\fP. +.SH RETURN VALUE +These functions do not return a value. +.SH PORTABILITY +These functions are not part of X/Open Curses; +nor do other implementations of curses provide a similar feature. +.PP +In any implementation of X/Open Curses, an application can free part +of the memory allocated by curses: +.bP +The portable part of \fBexit_curses\fP can be freed using \fBdelscreen\fP, +passing the \fBSCREEN*\fP pointer returned by \fBnewterm\fP. +.IP +In some implementations, there is a global variable \fBsp\fP +which could be used, e.g., if the screen were only initialized +using \fBinitscr\fP. +.bP +The portable part of \fBexit_terminfo\fP can be freed using \fBdel_curterm\fP. +.IP +In this case, there is a global variable \fBcur_term\fP which can be +used as parameter. +.SH SEE ALSO +\fBcurs_initscr\fP(3), +\fBterminfo\fP(3). +\fBcurses\fP(3). diff --git a/lib/libcurses/curs_mouse.3 b/lib/libcurses/curs_mouse.3 index d97a82ea860..3aca5e92f7a 100644 --- a/lib/libcurses/curs_mouse.3 +++ b/lib/libcurses/curs_mouse.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: curs_mouse.3,v 1.4 2019/02/13 07:18:57 nicm Exp $ +.\" $OpenBSD: curs_mouse.3,v 1.5 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2015,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,75 +30,102 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_mouse.3,v 1.4 2019/02/13 07:18:57 nicm Exp $ -.TH curs_mouse 3 "" +.\" $Id: curs_mouse.3,v 1.5 2023/10/17 09:52:08 nicm Exp $ +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de NS +.ie n .sp +.el .sp .5 +.ie n .in +4 +.el .in +2 +.nf +.ft CR \" Courier +.. +.de NE +.fi +.ft R +.ie n .in -4 +.el .in -2 +.. +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.TH curs_mouse 3 2023-07-01 "ncurses 6.4" "Library calls" .na .hy 0 .SH NAME -\fBgetmouse\fR, \fBungetmouse\fR, -\fBmousemask\fR, \fBwenclose\fR, -\fBmouse_trafo\fR, \fBwmouse_trafo\fR, -\fBmouseinterval\fR - mouse interface through curses +\fBhas_mouse\fP, +\fBgetmouse\fP, \fBungetmouse\fP, +\fBmousemask\fP, \fBwenclose\fP, +\fBmouse_trafo\fP, \fBwmouse_trafo\fP, +\fBmouseinterval\fP \- mouse interface through curses .ad .hy .SH SYNOPSIS -.nf -\fB#include +\fB#include \fP .PP -\fBtypedef unsigned long mmask_t; +\fBtypedef unsigned long mmask_t;\fP .PP -typedef struct -{ - short id; \fI/* ID to distinguish multiple devices */\fB - int x, y, z; \fI/* event coordinates */\fB - mmask_t bstate; \fI/* button state bits */\fB -} -MEVENT;\fR +.nf +\fBtypedef struct {\fP +\fB short id; \fI/* ID to distinguish multiple devices */\fR +\fB int x, y, z; \fI/* event coordinates */\fR +\fB mmask_t bstate; \fI/* button state bits */\fR +\fB} MEVENT;\fP .fi +.PP +\fBbool has_mouse(void);\fP +.sp +\fBint getmouse(MEVENT *\fIevent\fB);\fR .br -\fBint getmouse(MEVENT *event);\fR -.br -\fBint ungetmouse(MEVENT *event);\fR -.br -\fBmmask_t mousemask(mmask_t newmask, mmask_t *oldmask);\fR -.br -\fBbool wenclose(const WINDOW *win, int y, int x);\fR -.br -\fBbool mouse_trafo(int* pY, int* pX, bool to_screen);\fR -.br -\fBbool wmouse_trafo(const WINDOW* win, int* pY, int* pX,\fR -.br - \fBbool to_screen);\fR +\fBint ungetmouse(MEVENT *\fIevent\fB);\fR +.sp +\fBmmask_t mousemask(mmask_t \fInewmask\fB, mmask_t *\fIoldmask\fB);\fR +.sp +\fBbool wenclose(const WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB);\fR +.sp +\fBbool mouse_trafo(int* \fIpY\fB, int* \fIpX\fB, bool \fIto_screen\fB);\fR .br -\fBint mouseinterval(int erval);\fR +\fBbool wmouse_trafo(const WINDOW* \fIwin\fB,\fR + \fBint* \fIpY\fB, int* \fIpX\fB, bool \fIto_screen\fB);\fR +.sp +\fBint mouseinterval(int \fIerval\fB);\fR .br .SH DESCRIPTION These functions provide an interface to mouse events from -\fBncurses\fR(3). -Mouse events are represented by \fBKEY_MOUSE\fR -pseudo-key values in the \fBwgetch\fR input stream. -.PP -To make mouse events visible, use the \fBmousemask\fR function. -This will set -the mouse events to be reported. +\fBncurses\fP(3). +Mouse events are represented by \fBKEY_MOUSE\fP +pseudo-key values in the \fBwgetch\fP(3) input stream. +.SS mousemask +To make mouse events visible, use the \fBmousemask\fP function. +This sets the mouse events to be reported. By default, no mouse events are reported. -The function will return a mask to indicate which of the specified mouse events -can be reported; on complete failure it returns 0. -If oldmask is non-NULL, -this function fills the indicated location with the previous value of the given -window's mouse event mask. +.bP +The function returns an updated copy of \fInewmask\fP +to indicate which of the specified mouse events can be reported. +.IP +If the screen has not been initialized, +or if the terminal does not support mouse-events, +this function returns 0. +.bP +If \fIoldmask\fP is non-NULL, +this function fills the indicated location with the previous value of the +current screen's mouse event mask. .PP As a side effect, setting a zero mousemask may turn off the mouse pointer; setting a nonzero mask may turn it on. Whether this happens is device-dependent. -.PP +.SS Mouse events Here are the mouse event type masks which may be defined: .PP .TS l l _ _ l l. -\fIName\fR \fIDescription\fR +\fBName\fP \fBDescription\fP BUTTON1_PRESSED mouse button 1 down BUTTON1_RELEASED mouse button 1 up BUTTON1_CLICKED mouse button 1 clicked @@ -135,111 +163,173 @@ ALL_MOUSE_EVENTS report all button state changes REPORT_MOUSE_POSITION report mouse movement _ .TE -.PP -Once a class of mouse events have been made visible in a window, -calling the \fBwgetch\fR function on that window may return -\fBKEY_MOUSE\fR as an indicator that a mouse event has been queued. +.SS getmouse +Once a class of mouse events has been made visible in a window, +calling the \fBwgetch\fP function on that window may return +\fBKEY_MOUSE\fP as an indicator that a mouse event has been queued. To read the event data and pop the event off the queue, call -\fBgetmouse\fR. -This function will return \fBOK\fR if a mouse event -is actually visible in the given window, \fBERR\fR otherwise. -When \fBgetmouse\fR returns \fBOK\fR, the data deposited as y and +\fBgetmouse\fP. +This function will return \fBOK\fP if a mouse event +is actually visible in the given window, \fBERR\fP otherwise. +When \fBgetmouse\fP returns \fBOK\fP, the data deposited as y and x in the event structure coordinates will be screen-relative character-cell coordinates. The returned state mask will have exactly one bit set to indicate the event type. -.PP -The \fBungetmouse\fR function behaves analogously to \fBungetch\fR. +The corresponding data in the queue is marked invalid. +A subsequent call to \fBgetmouse\fP will retrieve the next older +item from the queue. +.SS ungetmouse +The \fBungetmouse\fP function behaves analogously to \fBungetch\fP. It pushes -a \fBKEY_MOUSE\fR event onto the input queue, and associates with that event +a \fBKEY_MOUSE\fP event onto the input queue, and associates with that event the given state data and screen-relative character-cell coordinates. -.PP -The \fBwenclose\fR function tests whether a given pair of screen-relative -character-cell coordinates is enclosed by a given window, returning TRUE -if it is and FALSE otherwise. +.SS wenclose +The \fBwenclose\fP function tests whether a given pair of screen-relative +character-cell coordinates is enclosed by a given window, returning \fBTRUE\fP +if it is and \fBFALSE\fP otherwise. It is useful for determining what subset of the screen windows enclose the location of a mouse event. -.PP -The \fBwmouse_trafo\fR function transforms a given pair of coordinates +.SS wmouse_trafo +The \fBwmouse_trafo\fP function transforms a given pair of coordinates from stdscr-relative coordinates to coordinates relative to the given window or vice versa. -Please remember, that stdscr-relative coordinates are not always identical +The resulting stdscr-relative coordinates are not always identical to window-relative coordinates due to the mechanism to reserve lines on top or bottom of the screen for other purposes -(see the \fBripoffline()\fP and \fBslk_init\fR calls, for example). -If the parameter \fBto_screen\fR is \fBTRUE\fR, the pointers -\fBpY, pX\fR must reference the coordinates of a location -inside the window \fBwin\fR. +(see the \fBripoffline\fP and \fBslk_init\fP(3) calls, for example). +.bP +If the parameter \fIto_screen\fP is \fBTRUE\fP, the pointers +\fIpY, pX\fP must reference the coordinates of a location +inside the window \fIwin\fP. They are converted to window-relative coordinates and returned through the pointers. -If the conversion was successful, the function returns \fBTRUE\fR. +If the conversion was successful, the function returns \fBTRUE\fP. +.bP If one of the parameters was NULL or the location is -not inside the window, \fBFALSE\fR is returned. -If \fBto_screen\fR is -\fBFALSE\fR, the pointers \fBpY, pX\fR must reference window-relative +not inside the window, \fBFALSE\fP is returned. +.bP +If \fIto_screen\fP is +\fBFALSE\fP, the pointers \fIpY, pX\fP must reference window-relative coordinates. They are converted to stdscr-relative coordinates if the -window \fBwin\fR encloses this point. -In this case the function returns \fBTRUE\fR. +window \fIwin\fP encloses this point. +In this case the function returns \fBTRUE\fP. +.bP If one of the parameters is NULL or the point is not inside the -window, \fBFALSE\fR is returned. -Please notice, that the referenced coordinates +window, \fBFALSE\fP is returned. +The referenced coordinates are only replaced by the converted coordinates if the transformation was successful. -.PP -The \fBmouse_trafo\fR function performs the same translation -as \fBwmouse_trafo\fR, -using stdscr for \fBwin\fR. -.PP -The \fBmouseinterval\fR function sets the maximum time (in thousands of a +.SS mouse_trafo +The \fBmouse_trafo\fP function performs the same translation +as \fBwmouse_trafo\fP, +using stdscr for \fIwin\fP. +.SS mouseinterval +The \fBmouseinterval\fP function sets the maximum time (in thousands of a second) that can elapse between press and release events for them to be recognized as a click. -Use \fBmouseinterval(0)\fR to disable click resolution. +Use \fBmouseinterval(0)\fP to disable click resolution. This function returns the previous interval value. -Use \fBmouseinterval(-1)\fR to obtain the interval without altering it. +Use \fBmouseinterval(\-1)\fP to obtain the interval without altering it. The default is one sixth of a second. +.SS has_mouse +The \fBhas_mouse\fP function returns \fBTRUE\fP if the mouse driver has been +successfully initialized. .PP Note that mouse events will be ignored when input is in cooked mode, and will cause an error beep when cooked mode is being simulated in a window by a -function such as \fBgetstr\fR that expects a linefeed for input-loop +function such as \fBgetstr\fP that expects a linefeed for input-loop termination. .SH RETURN VALUE -\fBgetmouse\fR and \fBungetmouse\fR -return the integer \fBERR\fR upon failure or \fBOK\fR -upon successful completion. -.RS +\fBgetmouse\fP and \fBungetmouse\fP +return the integer \fBERR\fP upon failure or \fBOK\fP +upon successful completion: +.RS 3 .TP 5 \fBgetmouse\fP returns an error. +.bP If no mouse driver was initialized, or if the mask parameter is zero, +.bP +It returns an error if a mouse event was detected which did not match the +current \fImousemask\fP. +.bP +It also returns an error if no more events remain in the queue. .TP 5 \fBungetmouse\fP returns an error if the FIFO is full. .RE .PP -\fBmousemask\fR +\fBmousemask\fP returns the mask of reportable events. .PP -\fBmouseinterval\fR +\fBmouseinterval\fP returns the previous interval value, unless the terminal was not initialized. In that case, it returns the maximum interval value (166). .PP -\fBwenclose\fR and \fBwmouse_trafo\fR -are boolean functions returning \fBTRUE\fR or \fBFALSE\fR depending +\fBwenclose\fP and \fBwmouse_trafo\fP +are boolean functions returning \fBTRUE\fP or \fBFALSE\fP depending on their test result. .SH PORTABILITY -These calls were designed for \fBncurses\fR(3), and are not found in SVr4 +These calls were designed for \fBncurses\fP(3), and are not found in SVr4 curses, 4.4BSD curses, or any other previous version of curses. .PP -The feature macro \fBNCURSES_MOUSE_VERSION\fR is provided so the preprocessor +SVr4 curses had support for the mouse in a variant of \fBxterm\fP(1). +It is mentioned in a few places, but with no supporting documentation: +.bP +the \*(``libcurses\*('' manual page lists functions for this feature +which are prototyped in \fBcurses.h\fP: +.NS +extern int mouse_set(long int); +extern int mouse_on(long int); +extern int mouse_off(long int); +extern int request_mouse_pos(void); +extern int map_button(unsigned long); +extern void wmouse_position(WINDOW *, int *, int *); +extern unsigned long getmouse(void), getbmap(void); +.NE +.bP +the \*(``terminfo\*('' manual page lists capabilities for the feature +.NS +buttons btns BT Number of buttons on the mouse +get_mouse getm Gm Curses should get button events +key_mouse kmous Km 0631, Mouse event has occurred +mouse_info minfo Mi Mouse status information +req_mouse_pos reqmp RQ Request mouse position report +.NE +.bP +the interface made assumptions (as does ncurses) about the escape sequences +sent to and received from the terminal. +.IP +For instance +the SVr4 curses library used the \fBget_mouse\fP capability to tell the +terminal which mouse button events it should send, +passing the mouse-button bit-mask to the terminal. +Also, it could ask the terminal +where the mouse was using the \fBreq_mouse_pos\fP capability. +.IP +Those features required a terminal which had been modified to work with curses. +They were not part of the X Consortium's xterm. +.PP +When developing the xterm mouse support for ncurses in September 1995, +Eric Raymond was uninterested in using the same interface due to its +lack of documentation. +Later, in 1998, Mark Hesseling provided support in +PDCurses 2.3 using the SVr4 interface. +PDCurses, however, does not use video terminals, +making it unnecessary to be concerned about compatibility with the +escape sequences. +.PP +The feature macro \fBNCURSES_MOUSE_VERSION\fP is provided so the preprocessor can be used to test whether these features are present. -If the interface is changed, the value of \fBNCURSES_MOUSE_VERSION\fR will be +If the interface is changed, the value of \fBNCURSES_MOUSE_VERSION\fP will be incremented. -These values for \fBNCURSES_MOUSE_VERSION\fR may be +These values for \fBNCURSES_MOUSE_VERSION\fP may be specified when configuring ncurses: -.RS +.RS 3 .TP 3 1 has definitions for reserved events. @@ -251,62 +341,78 @@ removes the definitions for reserved events. The mask uses 29 bits. .RE .PP -The order of the \fBMEVENT\fR structure members is not guaranteed. +The order of the \fBMEVENT\fP structure members is not guaranteed. Additional fields may be added to the structure in the future. .PP -Under \fBncurses\fR(3), these calls are implemented using either +Under \fBncurses\fP(3), these calls are implemented using either xterm's built-in mouse-tracking API or platform-specific drivers including -.RS -Alessandro Rubini's gpm server. -.br +.RS 3 +.bP +Alessandro Rubini's gpm server +.bP FreeBSD sysmouse -.br +.bP OS/2 EMX .RE +.PP If you are using an unsupported configuration, mouse events will not be visible to -\fBncurses\fR(3) (and the \fBmousemask\fR function will always -return \fB0\fR). +\fBncurses\fP(3) (and the \fBmousemask\fP function will always +return \fB0\fP). .PP -If the terminfo entry contains a \fBXM\fR string, +If the terminfo entry contains a \fBXM\fP string, this is used in the xterm mouse driver to control the way the terminal is initialized for mouse operation. -The default, if \fBXM\fR is not found, +The default, if \fBXM\fP is not found, corresponds to private mode 1000 of xterm: -.RS +.PP +.RS 3 \\E[?1000%?%p1%{1}%=%th%el%; .RE -The z member in the event structure is not presently used. +.PP +The mouse driver also recognizes a newer xterm private mode 1006, e.g., +.PP +.RS 3 +\\E[?1006;1000%?%p1%{1}%=%th%el%; +.RE +.PP +The \fIz\fP member in the event structure is not presently used. It is intended for use with touch screens (which may be pressure-sensitive) or with 3D-mice/trackballs/power gloves. +.PP +The \fBALL_MOUSE_EVENTS\fP class does not include \fBREPORT_MOUSE_POSITION\fP. +They are distinct. +For example, in xterm, +wheel/scrolling mice send position reports as a sequence of +presses of buttons 4 or 5 without matching button-releases. .SH BUGS Mouse events under xterm will not in fact be ignored during cooked mode, -if they have been enabled by \fBmousemask\fR. +if they have been enabled by \fBmousemask\fP. Instead, the xterm mouse report sequence will appear in the string read. .PP Mouse events under xterm will not be detected correctly in a window with its keypad bit off, since they are interpreted as a variety of function key. -Your terminfo description should have \fBkmous\fR set to "\\E[M" +Your terminfo description should have \fBkmous\fP set to \*(``\\E[M\*('' (the beginning of the response from xterm for mouse clicks). -Other values for \fBkmous\fR are permitted, +Other values for \fBkmous\fP are permitted, but under the same assumption, i.e., it is the beginning of the response. .PP Because there are no standard terminal responses that would serve to identify -terminals which support the xterm mouse protocol, \fBncurses\fR assumes that -if your $TERM environment variable contains "xterm", -or \fBkmous\fR is defined in -the terminal description, then the terminal may send mouse events. +terminals which support the xterm mouse protocol, \fBncurses\fP assumes that +if \fBkmous\fP is defined in the terminal description, +or if the terminal description's primary name or aliases +contain the string \*(``xterm\*('', +then the terminal may send mouse events. +The \fBkmous\fP capability is checked first, +allowing the use of newer xterm mouse protocols +such as xterm's private mode 1006. .SH SEE ALSO -\fBcurses\fR(3), -\fBcurs_kernel\fR(3), -\fBcurs_slk\fR(3). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_inopts\fP(3), +\fBcurs_kernel\fP(3), +\fBcurs_slk\fP(3), +\fBcurs_variables\fP(3). diff --git a/lib/libcurses/curs_move.3 b/lib/libcurses/curs_move.3 index 9244f61405f..2db6287d14b 100644 --- a/lib/libcurses/curs_move.3 +++ b/lib/libcurses/curs_move.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_move.3,v 1.6 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_move.3,v 1.7 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,44 +29,39 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_move.3,v 1.6 2010/01/12 23:21:59 nicm Exp $ -.TH curs_move 3 "" +.\" $Id: curs_move.3,v 1.7 2023/10/17 09:52:08 nicm Exp $ +.TH curs_move 3 2023-07-01 "ncurses 6.4" "Library calls" .na .hy 0 .SH NAME -\fBmove\fR, -\fBwmove\fR - move \fBcurses\fR window cursor +\fBmove\fP, +\fBwmove\fP \- move \fBcurses\fP window cursor .ad .hy .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint move(int y, int x);\fR -.br -\fBint wmove(WINDOW *win, int y, int x);\fR +\fBint move(int \fIy\fB, int \fIx\fB);\fR .br +\fBint wmove(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB);\fR .SH DESCRIPTION -These routines move the cursor associated with the window to line \fIy\fR and -column \fIx\fR. This routine does not move the physical cursor of the terminal -until \fBrefresh\fR is called. The position specified is relative to the upper +These routines move the cursor associated with the window to line \fIy\fP and +column \fIx\fP. +This routine does not move the physical cursor of the terminal +until \fBrefresh\fP(3) is called. +The position specified is relative to the upper left-hand corner of the window, which is (0,0). .SH RETURN VALUE -These routines return \fBERR\fR upon failure and OK (SVr4 -specifies only "an integer value other than \fBERR\fR") upon successful +These routines return \fBERR\fP upon failure and \fBOK\fP (SVr4 +specifies only "an integer value other than \fBERR\fP") upon successful completion. .PP Specifically, they return an error if the window pointer is null, or if the position is outside the window. .SH NOTES -Note that \fBmove\fR may be a macro. +Note that \fBmove\fP may be a macro. .SH PORTABILITY These functions are described in the XSI Curses standard, Issue 4. .SH SEE ALSO -\fBcurses\fR(3), \fBcurs_refresh\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), \fBcurs_refresh\fP(3) diff --git a/lib/libcurses/curs_opaque.3 b/lib/libcurses/curs_opaque.3 index 33992ce8fc8..f6a6629fa0f 100644 --- a/lib/libcurses/curs_opaque.3 +++ b/lib/libcurses/curs_opaque.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_opaque.3,v 1.2 2015/11/12 12:43:21 jmc Exp $ +.\" $OpenBSD: curs_opaque.3,v 1.3 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 2007 Free Software Foundation, Inc. * +.\" Copyright 2020-2022,2023 Thomas E. Dickey * +.\" Copyright 2007-2014,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,95 +29,119 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_opaque.3,v 1.2 2015/11/12 12:43:21 jmc Exp $ -.TH curs_opaque 3 "" +.\" $Id: curs_opaque.3,v 1.3 2023/10/17 09:52:08 nicm Exp $ +.TH curs_opaque 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .na .hy 0 .SH NAME -\fBis_cleared\fR, -\fBis_idlok\fR, -\fBis_idcok\fR, -\fBis_immedok\fR, -\fBis_keypad\fR, -\fBis_leaveok\fR, -\fBis_nodelay\fR, -\fBis_notimeout\fR, -\fBis_scrollok\fR, -\fBis_syncok\fR, -\fBwgetparent\fR, -\fBwgetscrreg\fR - \fBcurses\fR window properties +\fBis_cleared\fP, +\fBis_idlok\fP, +\fBis_idcok\fP, +\fBis_immedok\fP, +\fBis_keypad\fP, +\fBis_leaveok\fP, +\fBis_nodelay\fP, +\fBis_notimeout\fP, +\fBis_pad\fP, +\fBis_scrollok\fP, +\fBis_subwin\fP, +\fBis_syncok\fP, +\fBwgetdelay\fP, +\fBwgetparent\fP, +\fBwgetscrreg\fP \- \fBcurses\fP window properties .ad .hy .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBbool is_cleared(const WINDOW *win);\fR +\fBbool is_cleared(const WINDOW *\fIwin\fB);\fR .br -\fBbool is_idcok(const WINDOW *win);\fR +\fBbool is_idcok(const WINDOW *\fIwin\fB);\fR .br -\fBbool is_idlok(const WINDOW *win);\fR +\fBbool is_idlok(const WINDOW *\fIwin\fB);\fR .br -\fBbool is_immedok(const WINDOW *win);\fR +\fBbool is_immedok(const WINDOW *\fIwin\fB);\fR .br -\fBbool is_keypad(const WINDOW *win);\fR +\fBbool is_keypad(const WINDOW *\fIwin\fB);\fR .br -\fBbool is_leaveok(const WINDOW *win);\fR +\fBbool is_leaveok(const WINDOW *\fIwin\fB);\fR .br -\fBbool is_nodelay(const WINDOW *win);\fR +\fBbool is_nodelay(const WINDOW *\fIwin\fB);\fR .br -\fBbool is_notimeout(const WINDOW *win);\fR +\fBbool is_notimeout(const WINDOW *\fIwin\fB);\fR .br -\fBbool is_scrollok(const WINDOW *win);\fR +\fBbool is_pad(const WINDOW *\fIwin\fB);\fR .br -\fBbool is_syncok(const WINDOW *win);\fR +\fBbool is_scrollok(const WINDOW *\fIwin\fB);\fR .br -\fBWINDOW * wgetparent(const WINDOW *win);\fR +\fBbool is_subwin(const WINDOW *\fIwin\fB);\fR .br -\fBint wgetscrreg(const WINDOW *win, int *top, int *bottom);\fR +\fBbool is_syncok(const WINDOW *\fIwin\fB);\fR .br +\fBWINDOW * wgetparent(const WINDOW *\fIwin\fB);\fR +.br +\fBint wgetdelay(const WINDOW *\fIwin\fB);\fR +.br +\fBint wgetscrreg(const WINDOW *\fIwin\fB, int *\fItop\fB, int *\fIbottom\fB);\fR .SH DESCRIPTION This implementation provides functions which return properties -set in the WINDOW structure, allowing it to be ``opaque'' if -the symbol \fBNCURSES_OPAQUE\fR is defined: +set in the WINDOW structure, allowing it to be \*(``opaque\*('' if +the symbol \fBNCURSES_OPAQUE\fP is defined: +.TP 5 +\fBis_cleared\fP +returns the value set in \fBclearok\fP(3) +.TP 5 +\fBis_idcok\fP +returns the value set in \fBidcok\fP(3) +.TP 5 +\fBis_idlok\fP +returns the value set in \fBidlok\fP(3) .TP 5 -\fBis_cleared\fR -returns the value set in \fBclearok\fR +\fBis_immedok\fP +returns the value set in \fBimmedok\fP(3) .TP 5 -\fBis_idcok\fR -returns the value set in \fBidcok\fR +\fBis_keypad\fP +returns the value set in \fBkeypad\fP(3) .TP 5 -\fBis_idlok\fR -returns the value set in \fBidlok\fR +\fBis_leaveok\fP +returns the value set in \fBleaveok\fP(3) .TP 5 -\fBis_immedok\fR -returns the value set in \fBimmedok\fR +\fBis_nodelay\fP +returns the value set in \fBnodelay\fP(3) .TP 5 -\fBis_keypad\fR -returns the value set in \fBkeypad\fR +\fBis_notimeout\fP +returns the value set in \fBnotimeout\fP(3) .TP 5 -\fBis_leaveok\fR -returns the value set in \fBleaveok\fR +\fBis_pad\fP +returns \fBTRUE\fP if the window is a pad +i.e., created by \fBnewpad\fP(3) .TP 5 -\fBis_nodelay\fR -returns the value set in \fBnodelay\fR +\fBis_scrollok\fP +returns the value set in \fBscrollok\fP(3) .TP 5 -\fBis_notimeout\fR -returns the value set in \fBnotimeout\fR +\fBis_subwin\fP +returns \fBTRUE\fP if the window is a subwindow, +i.e., created by \fBsubwin\fP(3) or \fBderwin\fP(3) .TP 5 -\fBis_scrollok\fR -returns the value set in \fBscrollok\fR +\fBis_syncok\fP +returns the value set in \fBsyncok\fP(3) .TP 5 -\fBis_syncok\fR -returns the value set in \fBsyncok\fR +\fBwgetdelay\fP +returns the delay timeout as set in \fBwtimeout\fP(3). .TP 5 -\fBwgetparent\fR +\fBwgetparent\fP returns the parent WINDOW pointer for subwindows, or NULL for windows having no parent. .TP 5 -\fBwgetscrreg\fR -returns the top and bottom rows for the scrolling margin as set in \fBwsetscrreg\fP. +\fBwgetscrreg\fP +returns the top and bottom rows for the scrolling margin +as set in \fBwsetscrreg\fP. .SH RETURN VALUE -These functions all return TRUE or FALSE, except as noted. +These functions all return \fBTRUE\fP or \fBFALSE\fP, except as noted. .SH NOTES Both a macro and a function are provided for each name. .SH PORTABILITY @@ -125,13 +150,7 @@ They were not supported on Version 7, BSD or System V implementations. It is recommended that any code depending on ncurses extensions be conditioned using NCURSES_VERSION. .SH SEE ALSO -\fBcurses\fR(3), -\fBcurs_inopts\fR(3), -\fBcurs_outopts\fR(3), -\fBcurs_window\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_inopts\fP(3), +\fBcurs_outopts\fP(3), +\fBcurs_window\fP(3) diff --git a/lib/libcurses/curs_outopts.3 b/lib/libcurses/curs_outopts.3 index 302b40891a2..b4a056bc3c1 100644 --- a/lib/libcurses/curs_outopts.3 +++ b/lib/libcurses/curs_outopts.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_outopts.3,v 1.12 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_outopts.3,v 1.13 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2005,2007 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2016,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,66 +29,63 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_outopts.3,v 1.12 2010/01/12 23:21:59 nicm Exp $ -.TH curs_outopts 3 "" +.\" $Id: curs_outopts.3,v 1.13 2023/10/17 09:52:08 nicm Exp $ +.TH curs_outopts 3 2023-07-01 "ncurses 6.4" "Library calls" .na .hy 0 +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .SH NAME -\fBclearok\fR, -\fBidlok\fR, -\fBidcok\fR, -\fBimmedok\fR, -\fBleaveok\fR, -\fBsetscrreg\fR, -\fBwsetscrreg\fR, -\fBscrollok\fR, -\fBnl\fR, -\fBnonl\fR - \fBcurses\fR output options +\fBclearok\fP, +\fBidlok\fP, +\fBidcok\fP, +\fBimmedok\fP, +\fBleaveok\fP, +\fBsetscrreg\fP, +\fBwsetscrreg\fP, +\fBscrollok\fP \- \fBcurses\fP output options .ad .hy .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint clearok(WINDOW *win, bool bf);\fR +\fBint clearok(WINDOW *\fIwin\fB, bool \fIbf\fB);\fR .br -\fBint idlok(WINDOW *win, bool bf);\fR +\fBint idlok(WINDOW *\fIwin\fB, bool \fIbf\fB);\fR .br -\fBvoid idcok(WINDOW *win, bool bf);\fR +\fBvoid idcok(WINDOW *\fIwin\fB, bool \fIbf\fB);\fR .br -\fBvoid immedok(WINDOW *win, bool bf);\fR +\fBvoid immedok(WINDOW *\fIwin\fB, bool \fIbf\fB);\fR .br -\fBint leaveok(WINDOW *win, bool bf);\fR +\fBint leaveok(WINDOW *\fIwin\fB, bool \fIbf\fB);\fR .br -\fBint setscrreg(int top, int bot);\fR -.br -\fBint wsetscrreg(WINDOW *win, int top, int bot);\fR -.br -\fBint scrollok(WINDOW *win, bool bf);\fR -.br -\fBint nl(void);\fR -.br -\fBint nonl(void);\fR +\fBint scrollok(WINDOW *\fIwin\fB, bool \fIbf\fB);\fR +.sp +\fBint setscrreg(int \fItop\fB, int \fIbot\fB);\fR .br +\fBint wsetscrreg(WINDOW *\fIwin\fB, int \fItop\fB, int \fIbot\fB);\fR .SH DESCRIPTION These routines set options that change the style of output within -\fBcurses\fR. -All options are initially \fBFALSE\fR, unless otherwise stated. -It is not necessary to turn these options off before calling \fBendwin\fR. -.PP -If \fBclearok\fR is called with \fBTRUE\fR as argument, the next -call to \fBwrefresh\fR with this window will clear the screen completely and +\fBcurses\fP. +All options are initially \fBFALSE\fP, unless otherwise stated. +It is not necessary to turn these options off before calling \fBendwin\fP(3). +.SS clearok +If \fBclearok\fP is called with \fBTRUE\fP as argument, the next +call to \fBwrefresh\fP with this window will clear the screen completely and redraw the entire screen from scratch. This is useful when the contents of the screen are uncertain, or in some cases for a more pleasing visual effect. If -the \fIwin\fR argument to \fBclearok\fR is the global variable \fBcurscr\fR, -the next call to \fBwrefresh\fR with any window causes the screen to be cleared +the \fIwin\fP argument to \fBclearok\fP is the global variable \fBcurscr\fP, +the next call to \fBwrefresh\fP with any window causes the screen to be cleared and repainted from scratch. -.PP -If \fBidlok\fR is called with \fBTRUE\fR as second argument, \fBcurses\fR +.SS idlok +If \fBidlok\fP is called with \fBTRUE\fP as second argument, \fBcurses\fP considers using the hardware insert/delete line feature of terminals so equipped. -Calling \fBidlok\fR with \fBFALSE\fR as second argument disables use +Calling \fBidlok\fP with \fBFALSE\fP as second argument disables use of line insertion and deletion. This option should be enabled only if the application needs insert/delete line, for example, for a screen editor. @@ -95,86 +93,71 @@ It is disabled by default because insert/delete line tends to be visually annoying when used in applications where it is not really needed. If insert/delete line -cannot be used, \fBcurses\fR redraws the changed portions of all lines. -.PP -If \fBidcok\fR is called with \fBFALSE\fR as second argument, \fBcurses\fR +cannot be used, \fBcurses\fP redraws the changed portions of all lines. +.SS idcok +If \fBidcok\fP is called with \fBFALSE\fP as second argument, \fBcurses\fP no longer considers using the hardware insert/delete character feature of terminals so equipped. Use of character insert/delete is enabled by default. -Calling \fBidcok\fR with \fBTRUE\fR as second argument re-enables use +Calling \fBidcok\fP with \fBTRUE\fP as second argument re-enables use of character insertion and deletion. -.PP -If \fBimmedok\fR is called with \fBTRUE as argument\fR, any change -in the window image, such as the ones caused by \fBwaddch, wclrtobot, wscrl\fR, -etc., automatically cause a call to \fBwrefresh\fR. +.SS immedok +If \fBimmedok\fP is called with \fBTRUE as argument\fP, any change +in the window image, such as the ones caused by \fBwaddch, wclrtobot, wscrl\fP, +etc., automatically cause a call to \fBwrefresh\fP. However, it may -degrade performance considerably, due to repeated calls to \fBwrefresh\fR. +degrade performance considerably, due to repeated calls to \fBwrefresh\fP. It is disabled by default. -.PP +.SS leaveok Normally, the hardware cursor is left at the location of the window cursor being refreshed. -The \fBleaveok\fR option allows the cursor to be left +The \fBleaveok\fP option allows the cursor to be left wherever the update happens to leave it. It is useful for applications where the cursor is not used, since it reduces the need for cursor motions. -.PP -The \fBsetscrreg\fR and \fBwsetscrreg\fR routines allow the application +.SS scrollok +The \fBscrollok\fP option controls what happens when the cursor of a window is +moved off the edge of the window or scrolling region, either as a result of a +newline action on the bottom line, or typing the last character of the last +line. +If disabled, (\fIbf\fP is \fBFALSE\fP), the cursor is left on the bottom +line. +If enabled, (\fIbf\fP is \fBTRUE\fP), the window is scrolled up one line +(Note that to get the physical scrolling effect on the terminal, it is +also necessary to call \fBidlok\fP). +.SS setscrreg/wsetscrreg +The \fBsetscrreg\fP and \fBwsetscrreg\fP routines allow the application programmer to set a software scrolling region in a window. -\fItop\fR and -\fIbot\fR are the line numbers of the top and bottom margin of the scrolling +The \fItop\fP and +\fIbot\fP parameters +are the line numbers of the top and bottom margin of the scrolling region. (Line 0 is the top line of the window.) If this option and -\fBscrollok\fR are enabled, an attempt to move off the bottom margin line +\fBscrollok\fP are enabled, an attempt to move off the bottom margin line causes all lines in the scrolling region to scroll one line in the direction of the first line. Only the text of the window is scrolled. (Note that this has nothing to do with the use of a physical scrolling region capability in the terminal, like that in the VT100. -If \fBidlok\fR is enabled and the terminal +If \fBidlok\fP is enabled and the terminal has either a scrolling region or insert/delete line capability, they will probably be used by the output routines.) -.PP -The \fBscrollok\fR option controls what happens when the cursor of a window is -moved off the edge of the window or scrolling region, either as a result of a -newline action on the bottom line, or typing the last character of the last -line. -If disabled, (\fIbf\fR is \fBFALSE\fR), the cursor is left on the bottom -line. -If enabled, (\fIbf\fR is \fBTRUE\fR), the window is scrolled up one line -(Note that to get the physical scrolling effect on the terminal, it is -also necessary to call \fBidlok\fR). -.PP -The \fBnl\fR and \fBnonl\fR routines control whether the underlying display -device translates the return key into newline on input, and whether it -translates newline into return and line-feed on output (in either case, the -call \fBaddch('\\n')\fR does the equivalent of return and line feed on the -virtual screen). -Initially, these translations do occur. -If you disable them -using \fBnonl\fR, \fBcurses\fR will be able to make better use of the line-feed -capability, resulting in faster cursor motion. -Also, \fBcurses\fR will then be -able to detect the return key. .SH RETURN VALUE -The functions \fBsetscrreg\fR and \fBwsetscrreg\fR return \fBOK\fR upon success -and \fBERR\fR upon failure. +The functions \fBsetscrreg\fP and \fBwsetscrreg\fP return \fBOK\fP upon success +and \fBERR\fP upon failure. All other routines that return an integer always -return \fBOK\fR. +return \fBOK\fP. .PP -X/Open does not define any error conditions. +X/Open Curses does not define any error conditions. .PP -In this implementation, those functions that have a window pointer -will return an error if the window pointer is null. -.RS -.TP 5 -.B wclrtoeol -returns an error -if the cursor position is about to wrap. -.TP 5 -.B wsetscrreg +In this implementation, +.bP +those functions that have a window pointer +will return an error if the window pointer is null +.bP +\fBwsetscrreg\fP returns an error if the scrolling region limits extend outside the window. -.RE .PP X/Open does not define any error conditions. This implementation returns an error @@ -182,43 +165,51 @@ if the window pointer is null. .SH PORTABILITY These functions are described in the XSI Curses standard, Issue 4. .PP -The XSI Curses standard is ambiguous on the question of whether \fBraw\fR() -should disable the CRLF translations controlled by \fBnl\fR() and \fBnonl\fR(). -BSD curses did turn off these translations; AT&T curses (at least as late as -SVr1) did not. -We choose to do so, on the theory that a programmer requesting -raw input wants a clean (ideally 8-bit clean) connection that the operating -system will not alter. +From the outset, ncurses used \fBnl\fP/\fBnonl\fP to control the conversion +of newlines to carriage return/line-feed on output as well as input. +XSI Curses documents only the use of these functions for input. +This difference arose from converting the \fIpcurses\fP source +(which used \fBioctl\fP calls with the \fBsgttyb\fP structure) +to termios (i.e., the POSIX terminal interface). +In the former, both input and output were controlled via a single +option \fBCRMOD\fP, +while the latter separates these features. +Because that conversion interferes with output optimization, +\fBnl\fP/\fBnonl\fP were amended after ncurses 6.2 +to eliminate their effect on output. .PP Some historic curses implementations had, as an undocumented feature, the -ability to do the equivalent of \fBclearok(..., 1)\fR by saying -\fBtouchwin(stdscr)\fR or \fBclear(stdscr)\fR. -This will not work under -ncurses. +ability to do the equivalent of \fBclearok(..., 1)\fP by saying +\fBtouchwin(stdscr)\fP or \fBclear(stdscr)\fP. +This will not work under ncurses. .PP -Earlier System V curses implementations specified that with \fBscrollok\fR +Earlier System V curses implementations specified that with \fBscrollok\fP enabled, any window modification triggering a scroll also forced a physical refresh. -XSI Curses does not require this, and \fBncurses\fR avoids doing -it to perform better vertical-motion optimization at \fBwrefresh\fR +XSI Curses does not require this, and \fBncurses\fP avoids doing +it to perform better vertical-motion optimization at \fBwrefresh\fP time. .PP The XSI Curses standard does not mention that the cursor should be -made invisible as a side-effect of \fBleaveok\fR. +made invisible as a side-effect of \fBleaveok\fP. SVr4 curses documentation does this, but the code does not. -Use \fBcurs_set\fR to make the cursor invisible. +Use \fBcurs_set\fP to make the cursor invisible. .SH NOTES -Note that \fBclearok\fR, \fBleaveok\fR, \fBscrollok\fR, \fBidcok\fR, \fBnl\fR, -\fBnonl\fR and \fBsetscrreg\fR may be macros. -.PP -The \fBimmedok\fR routine is useful for windows that are used as terminal +Note that +\fBclearok\fP, +\fBleaveok\fP, +\fBscrollok\fP, +\fBidcok\fP, and +\fBsetscrreg\fP may be macros. +.PP +The \fBimmedok\fP routine is useful for windows that are used as terminal emulators. .SH SEE ALSO -\fBcurses\fR(3), \fBcurs_addch\fR(3), \fBcurs_clear\fR(3), -\fBcurs_initscr\fR(3), \fBcurs_scroll\fR(3), \fBcurs_refresh\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +.na +\fBcurses\fP(3), +\fBcurs_addch\fP(3), +\fBcurs_clear\fP(3), +\fBcurs_initscr\fP(3), +\fBcurs_scroll\fP(3), +\fBcurs_refresh\fP(3), +\fBcurs_variables\fP(3). diff --git a/lib/libcurses/curs_overlay.3 b/lib/libcurses/curs_overlay.3 index 1c82f91bc93..62de0d4eb52 100644 --- a/lib/libcurses/curs_overlay.3 +++ b/lib/libcurses/curs_overlay.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_overlay.3,v 1.8 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_overlay.3,v 1.9 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2020-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2013,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,43 +29,47 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_overlay.3,v 1.8 2010/01/12 23:21:59 nicm Exp $ -.TH curs_overlay 3 "" +.\" $Id: curs_overlay.3,v 1.9 2023/10/17 09:52:08 nicm Exp $ +.TH curs_overlay 3 2023-07-01 "ncurses 6.4" "Library calls" .na .hy 0 .SH NAME -\fBoverlay\fR, -\fBoverwrite\fR, -\fBcopywin\fR - overlay and manipulate overlapped \fBcurses\fR windows +\fBoverlay\fP, +\fBoverwrite\fP, +\fBcopywin\fP \- overlay and manipulate overlapped \fBcurses\fP windows .ad .hy .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint overlay(const WINDOW *srcwin, WINDOW *dstwin);\fR +\fBint overlay(const WINDOW *\fIsrcwin\fB, WINDOW *\fIdstwin\fB);\fR .br -\fBint overwrite(const WINDOW *srcwin, WINDOW *dstwin);\fR +\fBint overwrite(const WINDOW *\fIsrcwin\fB, WINDOW *\fIdstwin\fB);\fR .br -\fBint copywin(const WINDOW *srcwin, WINDOW *dstwin, int sminrow,\fR - \fBint smincol, int dminrow, int dmincol, int dmaxrow,\fR - \fBint dmaxcol, int overlay);\fR +\fBint copywin(const WINDOW *\fIsrcwin\fB, WINDOW *\fIdstwin\fB, int \fIsminrow\fB,\fR + \fBint \fIsmincol\fB, int \fIdminrow\fB, int \fIdmincol\fB, int \fIdmaxrow\fB,\fR + \fBint \fIdmaxcol\fB, int \fIoverlay\fB);\fR .SH DESCRIPTION -The \fBoverlay\fR and \fBoverwrite\fR routines overlay \fIsrcwin\fR on -top of \fIdstwin\fR. \fIscrwin\fR and \fIdstwin\fR are not required -to be the same size; only text where the two windows overlap is -copied. The difference is that \fBoverlay\fR is non-destructive -(blanks are not copied) whereas \fBoverwrite\fR is destructive. -.PP -The \fBcopywin\fR routine provides a finer granularity of control over the -\fBoverlay\fR and \fBoverwrite\fR routines. Like in the \fBprefresh\fR -routine, a rectangle is specified in the destination window, (\fIdminrow\fR, -\fIdmincol\fR) and (\fIdmaxrow\fR, \fIdmaxcol\fR), and the upper-left-corner -coordinates of the source window, (\fIsminrow\fR, \fIsmincol\fR). If the -argument \fIoverlay\fR is \fBtrue\fR, then copying is non-destructive, as in -\fBoverlay\fR. +.SS overlay, overwrite +The \fBoverlay\fP and \fBoverwrite\fP routines overlay \fIsrcwin\fP on +top of \fIdstwin\fP. +\fIscrwin\fP and \fIdstwin\fP are not required +to be the same size; only text where the two windows overlap is copied. +The difference is that \fBoverlay\fP is non-destructive +(blanks are not copied) whereas \fBoverwrite\fP is destructive. +.SS copywin +The \fBcopywin\fP routine provides a finer granularity of control over the +\fBoverlay\fP and \fBoverwrite\fP routines. +As in the \fBprefresh\fP routine, +a rectangle is specified in the destination window, (\fIdminrow\fP, +\fIdmincol\fP) and (\fIdmaxrow\fP, \fIdmaxcol\fP), and the upper-left-corner +coordinates of the source window, (\fIsminrow\fP, \fIsmincol\fP). +If the argument \fIoverlay\fP is \fBtrue\fP, +then copying is non-destructive, +as in \fBoverlay\fP. .SH RETURN VALUE -Routines that return an integer return \fBERR\fR upon failure, and \fBOK\fR -(SVr4 only specifies "an integer value other than \fBERR\fR") upon successful +Routines that return an integer return \fBERR\fP upon failure, and \fBOK\fP +(SVr4 only specifies "an integer value other than \fBERR\fP") upon successful completion. .PP X/Open defines no error conditions. @@ -74,16 +79,11 @@ In this implementation, if either of the window pointers are null, or if some part of the window would be placed off-screen. .SH NOTES -Note that \fBoverlay\fR and \fBoverwrite\fR may be macros. +Note that \fBoverlay\fP and \fBoverwrite\fP may be macros. .SH PORTABILITY The XSI Curses standard, Issue 4 describes these functions (adding the const -qualifiers). It further specifies their behavior in the presence of characters +qualifiers). +It further specifies their behavior in the presence of characters with multibyte renditions (not yet supported in this implementation). .SH SEE ALSO -\fBcurses\fR(3), \fBcurs_pad\fR(3), \fBcurs_refresh\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), \fBcurs_pad\fP(3), \fBcurs_refresh\fP(3) diff --git a/lib/libcurses/curs_pad.3 b/lib/libcurses/curs_pad.3 index 8562f93d035..57937d737af 100644 --- a/lib/libcurses/curs_pad.3 +++ b/lib/libcurses/curs_pad.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_pad.3,v 1.9 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_pad.3,v 1.10 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2004,2005 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2015,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,40 +29,45 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_pad.3,v 1.9 2010/01/12 23:21:59 nicm Exp $ -.TH curs_pad 3 "" +.\" $Id: curs_pad.3,v 1.10 2023/10/17 09:52:08 nicm Exp $ +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.TH curs_pad 3 2023-07-01 "ncurses 6.4" "Library calls" .na .hy 0 .SH NAME -\fBnewpad\fR, -\fBsubpad\fR, -\fBprefresh\fR, -\fBpnoutrefresh\fR, -\fBpechochar\fR, -\fBpecho_wchar\fR - create and display \fBcurses\fR pads +\fBnewpad\fP, +\fBsubpad\fP, +\fBprefresh\fP, +\fBpnoutrefresh\fP, +\fBpechochar\fP, +\fBpecho_wchar\fP \- create and display \fBcurses\fP pads .ad .hy .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBWINDOW *newpad(int nlines, int ncols);\fR +\fBWINDOW *newpad(int \fInlines\fB, int \fIncols\fB);\fR .br -\fBWINDOW *subpad(WINDOW *orig, int nlines, int ncols,\fR - \fBint begin_y, int begin_x);\fR +\fBWINDOW *subpad(WINDOW *\fIorig\fB, int \fInlines\fB, int \fIncols\fB,\fR + \fBint \fIbegin_y\fB, int \fIbegin_x\fB);\fR .br -\fBint prefresh(WINDOW *pad, int pminrow, int pmincol,\fR - \fBint sminrow, int smincol, int smaxrow, int smaxcol);\fR +\fBint prefresh(WINDOW *\fIpad\fB, int \fIpminrow\fB, int \fIpmincol\fB,\fR + \fBint \fIsminrow\fB, int \fIsmincol\fB, int \fIsmaxrow\fB, int \fIsmaxcol\fB);\fR .br -\fBint pnoutrefresh(WINDOW *pad, int pminrow, int pmincol,\fR - \fBint sminrow, int smincol, int smaxrow, int smaxcol);\fR +\fBint pnoutrefresh(WINDOW *\fIpad\fB, int \fIpminrow\fB, int \fIpmincol\fB,\fR + \fBint \fIsminrow\fB, int \fIsmincol\fB, int \fIsmaxrow\fB, int \fIsmaxcol\fB);\fR .br -\fBint pechochar(WINDOW *pad, chtype ch);\fR +\fBint pechochar(WINDOW *\fIpad\fB, chtype \fIch\fB);\fR .br -\fBint pecho_wchar(WINDOW *pad, const cchar_t *wch);\fR +\fBint pecho_wchar(WINDOW *\fIpad\fB, const cchar_t *\fIwch\fB);\fR .SH DESCRIPTION -The \fBnewpad\fR routine creates and returns a pointer to a new pad data -structure with the given number of lines, \fInlines\fR, and columns, -\fIncols\fR. +.SS newpad +The \fBnewpad\fP routine creates and returns a pointer to a new pad data +structure with the given number of lines, \fInlines\fP, and columns, +\fIncols\fP. A pad is like a window, except that it is not restricted by the screen size, and is not necessarily associated with a particular part of the screen. @@ -69,69 +75,75 @@ Pads can be used when a large window is needed, and only a part of the window will be on the screen at one time. Automatic refreshes of pads (e.g., from scrolling or echoing of input) do not occur. +.PP It is not -legal to call \fBwrefresh\fR with a \fIpad\fR as an argument; the routines -\fBprefresh\fR or \fBpnoutrefresh\fR should be called instead. +legal to call \fBwrefresh\fP with a \fIpad\fP as an argument; the routines +\fBprefresh\fP or \fBpnoutrefresh\fP should be called instead. Note that these routines require additional parameters to specify the part of the pad to be displayed and the location on the screen to be used for the display. -.PP -The \fBsubpad\fR routine creates and returns a pointer to a subwindow within a -pad with the given number of lines, \fInlines\fR, and columns, \fIncols\fR. -Unlike \fBsubwin\fR, which uses screen coordinates, the window is at position -(\fIbegin\fR_\fIx\fR\fB,\fR \fIbegin\fR_\fIy\fR) on the pad. +.SS subpad +The \fBsubpad\fP routine creates and returns a pointer to a subwindow within a +pad with the given number of lines, \fInlines\fP, and columns, \fIncols\fP. +Unlike \fBsubwin\fP, which uses screen coordinates, the window is at position +(\fIbegin\fR_\fIx\fB,\fR \fIbegin\fR_\fIy\fR) on the pad. The window is -made in the middle of the window \fIorig\fR, so that changes made to one window +made in the middle of the window \fIorig\fP, so that changes made to one window affect both windows. During the use of this routine, it will often be -necessary to call \fBtouchwin\fR or \fBtouchline\fR on \fIorig\fR before -calling \fBprefresh\fR. -.PP -The \fBprefresh\fR and \fBpnoutrefresh\fR routines are analogous to -\fBwrefresh\fR and \fBwnoutrefresh\fR except that they relate to pads instead +necessary to call \fBtouchwin\fP or \fBtouchline\fP on \fIorig\fP before +calling \fBprefresh\fP. +.SS prefresh, pnoutrefresh +The \fBprefresh\fP and \fBpnoutrefresh\fP routines are analogous to +\fBwrefresh\fP and \fBwnoutrefresh\fP except that they relate to pads instead of windows. The additional parameters are needed to indicate what part of the pad and screen are involved. -\fIpminrow\fR and \fIpmincol\fR specify the upper +.bP +The \fIpminrow\fP and \fIpmincol\fP parameters specify the upper left-hand corner of the rectangle to be displayed in the pad. -\fIsminrow\fR, -\fIsmincol\fR, \fIsmaxrow\fR, and \fIsmaxcol\fR specify the edges of the +.bP +The \fIsminrow\fP, +\fIsmincol\fP, \fIsmaxrow\fP, and \fIsmaxcol\fP +parameters specify the edges of the rectangle to be displayed on the screen. +.PP The lower right-hand corner of the rectangle to be displayed in the pad is calculated from the screen coordinates, since the rectangles must be the same size. Both rectangles must be entirely contained within their respective structures. Negative values of -\fIpminrow\fR, \fIpmincol\fR, \fIsminrow\fR, or \fIsmincol\fR are treated as if +\fIpminrow\fP, \fIpmincol\fP, \fIsminrow\fP, or \fIsmincol\fP are treated as if they were zero. -.PP -The \fBpechochar\fR routine is functionally equivalent to a call to \fBaddch\fR -followed by a call to \fBrefresh\fR, a call to \fBwaddch\fR followed by a call -to \fBwrefresh\fR, or a call to \fBwaddch\fR followed by a call to -\fBprefresh\fR. +.SS pechochar +The \fBpechochar\fP routine is functionally equivalent to a call to \fBaddch\fP +followed by a call to \fBrefresh\fP(3), +a call to \fBwaddch\fP followed by a call +to \fBwrefresh\fP, or a call to \fBwaddch\fP followed by a call to +\fBprefresh\fP. The knowledge that only a single character is being output is taken into consideration and, for non-control characters, a considerable performance gain might be seen by using these routines instead of their equivalents. -In the case of \fBpechochar\fR, the last location of the pad on -the screen is reused for the arguments to \fBprefresh\fR. -.PP -The \fBpecho_wchar\fR function is the analogous wide-character -form of \fBpechochar\fR. +In the case of \fBpechochar\fP, the last location of the pad on +the screen is reused for the arguments to \fBprefresh\fP. +.SS pecho_wchar +The \fBpecho_wchar\fP function is the analogous wide-character +form of \fBpechochar\fP. It outputs one character to a pad and immediately refreshes the pad. -It does this by a call to \fBwadd_wch\fR followed by a call to \fBprefresh\fR. +It does this by a call to \fBwadd_wch\fP followed by a call to \fBprefresh\fP. .SH RETURN VALUE -Routines that return an integer return \fBERR\fR upon failure and \fBOK\fR -(SVr4 only specifies "an integer value other than \fBERR\fR") upon successful +Routines that return an integer return \fBERR\fP upon failure and \fBOK\fP +(SVr4 only specifies "an integer value other than \fBERR\fP") upon successful completion. .PP -Routines that return pointers return \fBNULL\fR on error, and set \fBerrno\fR -to \fBENOMEM\fR. +Routines that return pointers return \fBNULL\fP on error, and set \fBerrno\fP +to \fBENOMEM\fP. .PP X/Open does not define any error conditions. In this implementation -.RS +.RS 3 .TP 5 \fBprefresh\fP and \fBpnoutrefresh\fP return an error @@ -151,14 +163,78 @@ if the window is not really a pad, and the associated call to \fBwecho_wchar\fP returns an error. .RE .SH NOTES -Note that \fBpechochar\fR may be a macro. +Note that \fBpechochar\fP may be a macro. .SH PORTABILITY -The XSI Curses standard, Issue 4 describes these functions. +BSD curses has no \fIpad\fP feature. +.PP +SVr2 curses (1986) provided the \fBnewpad\fP and related functions, +documenting them in a single line each. +SVr3 (1987) provided more extensive documentation. +.PP +The documentation does not explain the term \fIpad\fP. +However, the Apollo \fIAegis\fP workstation operating system +supported a graphical \fIpad\fP feature: +.bP +These graphical pads could be much larger than the computer's display. +.bP +The read-only output from a command could be scrolled back to inspect, +and select text from the pad. +.PP +The two uses may be related. +.PP +The XSI Curses standard, Issue 4 describes these functions, +without significant change from the SVr3 documentation. +It describes no error conditions. +The behavior of \fBsubpad\fP if the parent window is not +a pad is undocumented, +and is not checked by the vendor Unix implementations: +.bP +SVr4 curses sets a flag in the \fBWINDOW\fP structure in \fBnewpad\fP +which tells if the window is a \fIpad\fP. +.IP +However, it uses this information only in +\fBwaddch\fP (to decide if it should call \fBwrefresh\fP) and +\fBwscrl\fP (to avoid scrolling a pad), +and does not check in \fBwrefresh\fP to ensure that the pad +is refreshed properly. +.bP +Solaris X/Open Curses checks if a window is a pad in \fBwnoutrefresh\fP, +returning \fBERR\fP in that case. +.IP +However, it only sets the flag for subwindows if the parent window is a pad. +Its \fBnewpad\fP function does not set this information. +Consequently, the check will never fail. +.IP +It makes no comparable check in \fBpnoutrefresh\fP, +though interestingly enough, a comment in the source code +states that the lack of a check was an MKS extension. +.bP +NetBSD 7 curses +sets a flag in the \fBWINDOW\fP structure for \fBnewpad\fP and \fBsubpad\fP, +using this to help with the distinction between \fBwnoutrefresh\fP +and \fBpnoutrefresh\fP. +.IP +It does not check for the case where a subwindow is created in +a pad using \fBsubwin\fP or \fBderwin\fP. +.IP +The \fBdupwin\fP function returns a regular window when duplicating a pad. +Likewise, \fBgetwin\fP always returns a window, even if the saved +data was from a pad. +.PP +This implementation +.bP +sets a flag in the \fBWINDOW\fP structure for \fBnewpad\fP and \fBsubpad\fP, +.bP +allows a \fBsubwin\fP or \fBderwin\fP call to succeed having a pad parent by +forcing the subwindow to be a pad, +.bP +checks in both \fBwnoutrefresh\fP and \fBpnoutrefresh\fP to ensure +that pads and windows are handled distinctly, and +.bP +ensures that \fBdupwin\fP and \fBgetwin\fP treat +pads versus windows consistently. .SH SEE ALSO -\fBcurses\fR(3), \fBcurs_refresh\fR(3), \fBcurs_touch\fR(3), \fBcurs_addch\fR(3). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_refresh\fP(3), +\fBcurs_touch\fP(3), +\fBcurs_addch\fP(3). diff --git a/lib/libcurses/curs_print.3 b/lib/libcurses/curs_print.3 index ad2c33f5fbc..9e14d140984 100644 --- a/lib/libcurses/curs_print.3 +++ b/lib/libcurses/curs_print.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_print.3,v 1.9 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_print.3,v 1.10 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2021,2022 Thomas E. Dickey * +.\" Copyright 1998-2010,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,29 +29,32 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_print.3,v 1.9 2010/01/12 23:21:59 nicm Exp $ -.TH curs_print 3 "" +.\" $Id: curs_print.3,v 1.10 2023/10/17 09:52:08 nicm Exp $ +.TH curs_print 3 2022-02-12 "ncurses 6.4" "Library calls" .SH NAME -\fBmcprint\fR - ship binary data to printer +\fBmcprint\fP \- ship binary data to printer .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint mcprint(char *data, int len);\fR +\fBint mcprint(char *\fIdata\fB, int \fIlen\fB);\fR .SH DESCRIPTION -This function uses the \fBmc5p\fR or \fBmc4\fR and \fBmc5\fR capabilities, +This function uses the \fBmc5p\fP or \fBmc4\fP and \fBmc5\fP capabilities, if they are present, to ship given data to a printer attached to the terminal. .PP -Note that the \fBmcprint\fR code has no way to do flow control with the printer -or to know how much buffering it has. Your application is responsible for +Note that the \fBmcprint\fP code has no way to do flow control with the printer +or to know how much buffering it has. +Your application is responsible for keeping the rate of writes to the printer below its continuous throughput rate -(typically about half of its nominal cps rating). Dot-matrix printers and +(typically about half of its nominal cps rating). +Dot-matrix printers and 6-page-per-minute lasers can typically handle 80cps, so a good conservative rule of thumb is to sleep for a second after shipping each 80-character line. . .SH RETURN VALUE -The \fBmcprint\fR function returns \fBERR\fR if the write operation aborted -for some reason. In this case, errno will contain either an error associated -with \fBwrite(2)\fR or one of the following: +The \fBmcprint\fP function returns \fBERR\fP if the write operation aborted +for some reason. +In this case, \fBerrno\fP will contain either an error associated +with \fBwrite\fP(2) or one of the following: .TP 5 ENODEV Capabilities for printer redirection do not exist. @@ -58,19 +62,13 @@ Capabilities for printer redirection do not exist. ENOMEM Couldn't allocate sufficient memory to buffer the printer write. .PP -When \fBmcprint\fR succeeds, it returns the number of characters actually +When \fBmcprint\fP succeeds, it returns the number of characters actually sent to the printer. .SH PORTABILITY -The \fBmcprint\fR call was designed for \fBncurses\fR(3), and is not found +The \fBmcprint\fP call was designed for \fBncurses\fP(3), and is not found in SVr4 curses, 4.4BSD curses, or any other previous version of curses. .SH BUGS -Padding in the \fBmc5p\fR, \fBmc4\fR and \fBmc5\fR capabilities will not be +Padding in the \fBmc5p\fP, \fBmc4\fP and \fBmc5\fP capabilities will not be interpreted. .SH SEE ALSO -\fBcurses\fR(3)\fR -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3) diff --git a/lib/libcurses/curs_printw.3 b/lib/libcurses/curs_printw.3 index 02333f945aa..68ea5b8b129 100644 --- a/lib/libcurses/curs_printw.3 +++ b/lib/libcurses/curs_printw.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_printw.3,v 1.11 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_printw.3,v 1.12 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2021,2022 Thomas E. Dickey * +.\" Copyright 1998-2010,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,47 +29,57 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_printw.3,v 1.11 2010/01/12 23:21:59 nicm Exp $ -.TH curs_printw 3 "" +.\" $Id: curs_printw.3,v 1.12 2023/10/17 09:52:08 nicm Exp $ +.TH curs_printw 3 2022-02-12 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .na .hy 0 .SH NAME -\fBprintw\fR, -\fBwprintw\fR, -\fBmvprintw\fR, -\fBmvwprintw\fR, -\fBvwprintw\fR, \fBvw_printw\fR - print formatted output in \fBcurses\fR windows +\fBprintw\fP, +\fBwprintw\fP, +\fBmvprintw\fP, +\fBmvwprintw\fP, +\fBvwprintw\fP, \fBvw_printw\fP \- print formatted output in \fBcurses\fP windows .ad .hy .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint printw(const char *fmt, ...);\fR +\fBint printw(const char *\fIfmt\fB, ...);\fR .br -\fBint wprintw(WINDOW *win, const char *fmt, ...);\fR +\fBint wprintw(WINDOW *\fIwin\fB, const char *\fIfmt\fB, ...);\fR .br -\fBint mvprintw(int y, int x, const char *fmt, ...);\fR +\fBint mvprintw(int \fIy\fB, int \fIx\fB, const char *\fIfmt\fB, ...);\fR .br -\fBint mvwprintw(WINDOW *win, int y, int x, const char *fmt, ...);\fR +\fBint mvwprintw(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, const char *\fIfmt\fB, ...);\fR .br -\fBint vwprintw(WINDOW *win, const char *fmt, va_list varglist);\fR -.br -\fBint vw_printw(WINDOW *win, const char *fmt, va_list varglist);\fR +\fBint vw_printw(WINDOW *\fIwin\fB, const char *\fIfmt\fB, va_list \fIvarglist\fB);\fR +.sp +/* obsolete */ .br +\fBint vwprintw(WINDOW *\fIwin\fB, const char *\fIfmt\fB, va_list \fIvarglist\fB);\fR .SH DESCRIPTION -The \fBprintw\fR, \fBwprintw\fR, \fBmvprintw\fR and \fBmvwprintw\fR -routines are analogous to \fBprintf\fR [see \fBprintf\fR(3)]. In -effect, the string that would be output by \fBprintf\fR is output -instead as though \fBwaddstr\fR were used on the given window. +The \fBprintw\fP, \fBwprintw\fP, \fBmvprintw\fP and \fBmvwprintw\fP +routines are analogous to \fBprintf\fP [see \fBprintf\fP(3)]. +In +effect, the string that would be output by \fBprintf\fP is output +instead as though \fBwaddstr\fP were used on the given window. .PP -The \fBvwprintw\fR and \fBwv_printw\fR routines are analogous -to \fBvprintf\fR [see \fBprintf\fR(3)] -and perform a \fBwprintw\fR using a variable argument list. -The third argument is a \fBva_list\fR, a pointer to a -list of arguments, as defined in \fB\fR. +The \fBvwprintw\fP and \fBvw_printw\fP routines are analogous +to \fBvprintf\fP [see \fBprintf\fP(3)] +and perform a \fBwprintw\fP using a variable argument list. +The third argument is a \fBva_list\fP, a pointer to a +list of arguments, as defined in \fB\fP. .SH RETURN VALUE -Routines that return an integer return \fBERR\fR upon failure and \fBOK\fR -(SVr4 only specifies "an integer value other than \fBERR\fR") upon successful +Routines that return an integer return \fBERR\fP upon failure and \fBOK\fP +(SVr4 only specifies "an integer value other than \fBERR\fP") upon successful completion. .PP X/Open defines no error conditions. @@ -76,21 +87,70 @@ In this implementation, an error may be returned if it cannot allocate enough memory for the buffer used to format the results. It will return an error if the window pointer is null. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. +.SH HISTORY +While \fBprintw\fP was implemented in 4BSD, +it was unused until 4.2BSD (which used it in games). +That early version of curses was before the ANSI C standard. +It did not use , though that was available. +In 1991 (a couple of years after SVr4 was generally available, +and after the C standard was published), +other developers updated the library, +using internally in 4.4BSD curses. +Even with this improvement, +BSD curses did not use function prototypes (or even declare +functions) in the header until 1992. +.PP +SVr2 documented +\fBprintw\fP, +\fBwprintw\fP +tersely as \*(``printf on \fIstdscr\fP\*('' and +tersely as \*(``printf on \fIwin\fP\*('', respectively. +.PP +SVr3 added +\fBmvprintw\fP, and +\fBmvwprintw\fP, with a three-line summary saying that they were analogous +to \fBprintf\fP(3), +explaining that the string which would be output from \fBprintf\fP(3) would +instead be output using \fBwaddstr\fP on the given window. +SVr3 also added \fBvwprintw\fP, saying that the third parameter +is a \fBva_list\fP, defined in , +and referring the reader to the manual pages for \fIvarargs\fP and +\fBvprintf\fP for detailed descriptions. +.PP +SVr4 added no new variations of \fBprintw\fP, +but provided for using or to define the \fBva_list\fP +type. +.PP +X/Open Curses added \fBvw_printw\fP to replace \fBvwprintw\fP, +stating that its \fBva_list\fP definition requires . .SH PORTABILITY -The XSI Curses standard, Issue 4 describes these functions. The function -\fBvwprintw\fR is marked TO BE WITHDRAWN, and is to be replaced by a function -\fBvw_printw\fR using the \fB\fR interface. +In this implementation, \fBvw_printw\fP and \fBvwprintw\fP are equivalent, +to support legacy applications. +However, the latter (\fBvwprintw\fP) is obsolete: +.bP +The XSI Curses standard, Issue 4 described these functions. +The function +\fBvwprintw\fP is marked TO BE WITHDRAWN, and is to be replaced by a function +\fBvw_printw\fP using the \fB\fP interface. +.bP The Single Unix Specification, Version 2 states that -\fBvw_printw\fR is preferred to \fBvwprintw\fR since the latter requires -including \fB\fR, which -cannot be used in the same file as \fB\fR. -This implementation uses \fB\fR for both, because that header -is included in \fB. +\fBvw_printw\fP is preferred to \fBvwprintw\fP since the latter requires +including \fB\fP, which +cannot be used in the same file as \fB\fP. +This implementation uses \fB\fP for both, +because that header is included in \fB. +.bP +X/Open Curses, Issue 5 (December 2007) marked \fBvwprintw\fP (along with +\fBvwscanw\fP and the termcap interface) as withdrawn. .SH SEE ALSO -\fBcurses\fR(3), \fBprintf\fR(3), \fBvprintf(3)\fR -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +.na +\fBcurses\fP(3), +\fBcurs_addstr\fP(3), +\fBcurs_scanw\fP(3), +\fBtermcap\fP(3), +\fBprintf\fP(3), +\fBvprintf\fP(3). diff --git a/lib/libcurses/curs_refresh.3 b/lib/libcurses/curs_refresh.3 index b9c53bd85a4..705fe32cb9c 100644 --- a/lib/libcurses/curs_refresh.3 +++ b/lib/libcurses/curs_refresh.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_refresh.3,v 1.7 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_refresh.3,v 1.8 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2001,2005 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2016 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,91 +29,112 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_refresh.3,v 1.7 2010/01/12 23:21:59 nicm Exp $ -.TH curs_refresh 3 "" +.\" $Id: curs_refresh.3,v 1.8 2023/10/17 09:52:08 nicm Exp $ +.TH curs_refresh 3 2023-08-19 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .na .hy 0 .SH NAME -\fBdoupdate\fR, -\fBredrawwin\fR, -\fBrefresh\fR, -\fBwnoutrefresh\fR, -\fBwredrawln\fR, -\fBwrefresh\fR - refresh \fBcurses\fR windows and lines +\fBdoupdate\fP, +\fBredrawwin\fP, +\fBrefresh\fP, +\fBwnoutrefresh\fP, +\fBwredrawln\fP, +\fBwrefresh\fP \- refresh \fBcurses\fP windows and lines .ad .hy .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint refresh(void);\fR +\fBint refresh(void);\fP .br -\fBint wrefresh(WINDOW *win);\fR +\fBint wrefresh(WINDOW *\fIwin\fB);\fR .br -\fBint wnoutrefresh(WINDOW *win);\fR +\fBint wnoutrefresh(WINDOW *\fIwin\fB);\fR .br -\fBint doupdate(void);\fR -.br -\fBint redrawwin(WINDOW *win);\fR -.br -\fBint wredrawln(WINDOW *win, int beg_line, int num_lines);\fR +\fBint doupdate(void);\fP +.sp +\fBint redrawwin(WINDOW *\fIwin\fB);\fR .br +\fBint wredrawln(WINDOW *\fIwin\fB, int \fIbeg_line\fB, int \fInum_lines\fB);\fR .SH DESCRIPTION -The \fBrefresh\fR and \fBwrefresh\fR routines (or \fBwnoutrefresh\fR and -\fBdoupdate\fR) must be called to get actual output to the terminal, as other -routines merely manipulate data structures. -The routine \fBwrefresh\fR copies -the named window to the physical terminal screen, taking into account what is -already there to do optimizations. -The \fBrefresh\fR routine is the -same, using \fBstdscr\fR as the default window. -Unless \fBleaveok\fR has been +.SS refresh/wrefresh +The \fBrefresh\fP and \fBwrefresh\fP routines (or \fBwnoutrefresh\fP and +\fBdoupdate\fP) must be called to get actual output to the terminal, +as other routines merely manipulate data structures. +The routine \fBwrefresh\fP copies +the named window to the \fIphysical screen\fP, +taking into account what is already there to do optimizations. +The \fBrefresh\fP routine is the +same, using \fBstdscr\fP as the default window. +Unless \fBleaveok\fP(3) has been enabled, the physical cursor of the terminal is left at the location of the cursor for that window. -.PP -The \fBwnoutrefresh\fR and \fBdoupdate\fR routines allow multiple updates with -more efficiency than \fBwrefresh\fR alone. +.SS wnoutrefresh/doupdate +The \fBwnoutrefresh\fP and \fBdoupdate\fP routines allow multiple updates with +more efficiency than \fBwrefresh\fP alone. In addition to all the window -structures, \fBcurses\fR keeps two data structures representing the terminal -screen: a physical screen, describing what is actually on the screen, and a -virtual screen, describing what the programmer wants to have on the screen. +structures, \fBcurses\fP keeps two data structures representing the terminal +screen: +.bP +a \fIphysical screen\fP, +describing what is actually on the screen, and +.bP +a \fIvirtual screen\fP, +describing what the programmer wants to have on the screen. +.PP +The routine \fBwrefresh\fP works by +.bP +first calling \fBwnoutrefresh\fP, +which copies the named window to the \fIvirtual screen\fP, and +.bP +then calling \fBdoupdate\fP, which compares +the \fIvirtual screen\fP to the \fIphysical screen\fP +and does the actual update. .PP -The routine \fBwrefresh\fR works by first calling \fBwnoutrefresh\fR, which -copies the named window to the virtual screen, and then calling \fBdoupdate\fR, -which compares the virtual screen to the physical screen and does the actual -update. If the programmer wishes to output several windows at once, a series -of calls to \fBwrefresh\fR results in alternating calls to \fBwnoutrefresh\fR -and \fBdoupdate\fR, causing several bursts of output to the screen. +of calls to \fBwrefresh\fP results in alternating calls to \fBwnoutrefresh\fP +and \fBdoupdate\fP, causing several bursts of output to the screen. By first -calling \fBwnoutrefresh\fR for each window, it is then possible to call -\fBdoupdate\fR once, resulting in only one burst of output, with fewer total +calling \fBwnoutrefresh\fP for each window, it is then possible to call +\fBdoupdate\fP once, resulting in only one burst of output, with fewer total characters transmitted and less CPU time used. -If the \fIwin\fR argument to -\fBwrefresh\fR is the global variable \fBcurscr\fR, the screen is immediately -cleared and repainted from scratch. .PP -The phrase "copies the named window to the virtual screen" above is ambiguous. -What actually happens is that all \fItouched\fR (changed) lines in the window +If the \fIwin\fP argument to +\fBwrefresh\fP is the \fIphysical screen\fP +(i.e., the global variable \fBcurscr\fP), +the screen is immediately cleared and repainted from scratch. +.PP +The phrase \*(``copies the named window +to the virtual screen\*('' above is ambiguous. +What actually happens is that all \fItouched\fP (changed) lines in the window are copied to the virtual screen. This affects programs that use overlapping windows; it means that if two windows overlap, you can refresh them in either order and the overlap region will be modified only when it is explicitly changed. -(But see the section on \fBPORTABILITY\fR below for a warning about +(But see the section on \fBPORTABILITY\fP below for a warning about exploiting this behavior.) -.PP -The \fBwredrawln\fR routine indicates to \fBcurses\fR that some screen lines +.SS wredrawln/redrawwin +The \fBwredrawln\fP routine indicates to \fBcurses\fP that some screen lines are corrupted and should be thrown away before anything is written over them. It touches the indicated lines (marking them changed). -The routine \fBredrawwin\fR() touches the entire window. +The routine \fBredrawwin\fP touches the entire window. .SH RETURN VALUE -Routines that return an integer return \fBERR\fR upon failure, and \fBOK\fR -(SVr4 only specifies "an integer value other than \fBERR\fR") upon successful +Routines that return an integer return \fBERR\fP upon failure, and \fBOK\fP +(SVr4 only specifies "an integer value other than \fBERR\fP") upon successful completion. .PP X/Open does not define any error conditions. In this implementation -.RS +.RS 3 .TP 5 \fBwnoutrefresh\fP returns an error @@ -124,23 +146,19 @@ returns an error if the associated call to \fBtouchln\fP returns an error. .RE .SH NOTES -Note that \fBrefresh\fR and \fBredrawwin\fR may be macros. +Note that \fBrefresh\fP and \fBredrawwin\fP may be macros. .SH PORTABILITY The XSI Curses standard, Issue 4 describes these functions. .PP -Whether \fBwnoutrefresh()\fR copies to the virtual screen the entire contents +Whether \fBwnoutrefresh\fP copies to the virtual screen the entire contents of a window or just its changed portions has never been well-documented in historic curses versions (including SVr4). It might be unwise to rely on either behavior in programs that might have to be linked with other curses implementations. -Instead, you can do an explicit \fBtouchwin()\fR before the -\fBwnoutrefresh()\fR call to guarantee an entire-contents copy anywhere. +Instead, you can do an explicit \fBtouchwin\fP before the +\fBwnoutrefresh\fP call to guarantee an entire-contents copy anywhere. .SH SEE ALSO -\fBcurses\fR(3), \fBcurs_outopts\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_outopts\fP(3) +\fBcurs_variables\fP(3). diff --git a/lib/libcurses/curs_scanw.3 b/lib/libcurses/curs_scanw.3 index 4e287ec0aea..1cb238bbec2 100644 --- a/lib/libcurses/curs_scanw.3 +++ b/lib/libcurses/curs_scanw.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_scanw.3,v 1.11 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_scanw.3,v 1.12 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2000,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2021,2022 Thomas E. Dickey * +.\" Copyright 1998-2010,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,72 +29,143 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_scanw.3,v 1.11 2010/01/12 23:21:59 nicm Exp $ -.TH curs_scanw 3 "" +.\" $Id: curs_scanw.3,v 1.12 2023/10/17 09:52:08 nicm Exp $ +.TH curs_scanw 3 2022-02-12 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .SH NAME -\fBscanw\fR, -\fBwscanw\fR, -\fBmvscanw\fR, -\fBmvwscanw\fR, -\fBvwscanw\fR, \fBvw_scanw\fR - convert formatted input from a \fBcurses\fR window +\fBscanw\fP, +\fBwscanw\fP, +\fBmvscanw\fP, +\fBmvwscanw\fP, +\fBvwscanw\fP, \fBvw_scanw\fP \- convert formatted input from a \fBcurses\fP window .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint scanw(char *fmt, ...);\fR +\fBint scanw(const char *\fIfmt\fB, ...);\fR .br -\fBint wscanw(WINDOW *win, char *fmt, ...);\fR +\fBint wscanw(WINDOW *\fIwin\fB, const char *\fIfmt\fB, ...);\fR .br -\fBint mvscanw(int y, int x, char *fmt, ...);\fR +\fBint mvscanw(int \fIy\fB, int \fIx\fB, const char *\fIfmt\fB, ...);\fR .br -\fBint mvwscanw(WINDOW *win, int y, int x, char *fmt, ...);\fR -.br -\fBint vw_scanw(WINDOW *win, char *fmt, va_list varglist);\fR +\fBint mvwscanw(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB, const char *\fIfmt\fB, ...);\fR +.sp +\fBint vw_scanw(WINDOW *\fIwin\fB, const char *\fIfmt\fB, va_list \fIvarglist\fB);\fR +.sp +/* obsolete */ .br -\fBint vwscanw(WINDOW *win, char *fmt, va_list varglist);\fR +\fBint vwscanw(WINDOW *\fIwin\fB, const char *\fIfmt\fB, va_list \fIvarglist\fB);\fR .SH DESCRIPTION -The \fBscanw\fR, \fBwscanw\fR and \fBmvscanw\fR routines are analogous to -\fBscanf\fR [see \fBscanf\fR(3)]. The effect of these routines is as though -\fBwgetstr\fR were called on the window, and the resulting line used as input -for \fBsscanf\fR(3). Fields which do not map to a variable in the \fIfmt\fR +The \fBscanw\fP, \fBwscanw\fP and \fBmvscanw\fP routines are analogous to +\fBscanf\fP [see \fBscanf\fP(3)]. +The effect of these routines is as though +\fBwgetstr\fP were called on the window, and the resulting line used as input +for \fBsscanf\fP(3). +Fields which do not map to a variable in the \fIfmt\fP field are lost. .PP -The \fBvwscanw\fR and \fBvw_scanw\fR routines are analogous to \fBvscanf\fR. -They perform a \fBwscanw\fR using a variable argument list. -The third argument is a \fIva_list\fR, -a pointer to a list of arguments, as defined in \fB\fR. +The \fBvwscanw\fP and \fBvw_scanw\fP routines are analogous to \fBvscanf\fP(3). +They perform a \fBwscanw\fP using a variable argument list. +The third argument is a \fBva_list\fP, +a pointer to a list of arguments, as defined in \fB\fP. .SH RETURN VALUE -\fBvwscanw\fR returns \fBERR\fR on failure and an integer equal to the +\fBvwscanw\fP returns \fBERR\fP on failure and an integer equal to the number of fields scanned on success. .PP -Applications may use the return value from the \fBscanw\fR, \fBwscanw\fR, -\fBmvscanw\fR and \fBmvwscanw\fR routines to determine the number of fields +Applications may use the return value from the \fBscanw\fP, \fBwscanw\fP, +\fBmvscanw\fP and \fBmvwscanw\fP routines to determine the number of fields which were mapped in the call. +.PP +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. +.SH HISTORY +While \fBscanw\fP was implemented in 4BSD, +none of the BSD releases used it until 4.4BSD (in a game). +That early version of curses was before the ANSI C standard. +It did not use , though that was available. +In 1991 (a couple of years after SVr4 was generally available, +and after the C standard was published), +other developers updated the library, +using internally in 4.4BSD curses. +Even with this improvement, +BSD curses did not use function prototypes (or even declare +functions) in the header until 1992. +.PP +SVr2 documented +\fBscanw\fP, +\fBwscanw\fP +tersely as \*(``scanf through \fIstdscr\fP\*('' and +tersely as \*(``scanf through \fIwin\fP\*('', respectively. +.PP +SVr3 added +\fBmvscanw\fP, and +\fBmvwscanw\fP, with a three-line summary saying that they were analogous +to \fBscanf\fP(3), +explaining that the string which would be output from \fBscanf\fP(3) would +instead be output using \fBwaddstr\fP on the given window. +SVr3 also added \fBvwscanw\fP, saying that the third parameter +is a \fBva_list\fP, defined in , +and referring the reader to the manual pages for \fIvarargs\fP and +\fBvprintf\fP for detailed descriptions. +(Because the SVr3 documentation does not mention \fBvscanf\fP, +that reference to \fBvprintf\fP may not be an error). +.PP +SVr4 added no new variations of \fBscanw\fP, +but provided for using or to define the \fBva_list\fP +type. +.PP +X/Open Curses added \fBvw_scanw\fP to replace \fBvwscanw\fP, +stating that its \fBva_list\fP definition requires . .SH PORTABILITY -The XSI Curses standard, Issue 4 describes these functions. The function -\fBvwscanw\fR is marked TO BE WITHDRAWN, and is to be replaced by a function -\fBvw_scanw\fR using the \fB\fR interface. +In this implementation, \fBvw_scanw\fP and \fBvwscanw\fP are equivalent, +to support legacy applications. +However, the latter (\fBvwscanw\fP) is obsolete: +.bP +The XSI Curses standard, Issue 4 described these functions, +noting that the function +\fBvwscanw\fP is marked TO BE WITHDRAWN, and is to be replaced by a function +\fBvw_scanw\fP using the \fB\fP interface. +.bP The Single Unix Specification, Version 2 states that -\fBvw_scanw\fR is preferred to \fBvwscanw\fR since the latter requires -including \fB\fR, which -cannot be used in the same file as \fB\fR. -This implementation uses \fB\fR for both, because that header -is included in \fB. +\fBvw_scanw\fP is preferred to \fBvwscanw\fP since the latter requires +including \fB\fP, which +cannot be used in the same file as \fB\fP. +This implementation uses \fB\fP for both, because that header +is included in \fB. +.bP +X/Open Curses, Issue 5 (December 2007) marked \fBvwscanw\fP (along with +\fBvwprintw\fP and the termcap interface) as withdrawn. .LP Both XSI and The Single Unix Specification, Version 2 state that these -functions return ERR or OK. -Since the underlying \fBscanf\fR can return the number of items scanned, +functions return \fBERR\fP or \fBOK\fP. +.bP +Since the underlying \fBscanf\fP(3) can return the number of items scanned, and the SVr4 code was documented to use this feature, this is probably an editing error which was introduced in XSI, rather than being done intentionally. -Portable applications should only test if the return value is ERR, -since the OK value (zero) is likely to be misleading. +.bP +This implementation returns the number of items scanned, +for compatibility with SVr4 curses. +As of 2018, NetBSD curses also returns the number of items scanned. +Both ncurses and NetBSD curses call \fBvsscanf\fP to scan the string, +which returns \fBEOF\fP on error. +.bP +Portable applications should only test if the return value is \fBERR\fP, +since the \fBOK\fP value (zero) is likely to be misleading. +.IP One possible way to get useful results would be to use a "%n" conversion at the end of the format string to ensure that something was processed. .SH SEE ALSO -\fBcurses\fR(3), \fBcurs_getstr\fR(3), \fBcurs_printw\fR(3), \fBscanf\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +.na +\fBcurses\fP(3), +\fBcurs_getstr\fP(3), +\fBcurs_printw\fP(3), +\fBtermcap\fP(3), +\fBscanf\fP(3). diff --git a/lib/libcurses/curs_scr_dump.3 b/lib/libcurses/curs_scr_dump.3 index 168ae84f75b..e91fda2521d 100644 --- a/lib/libcurses/curs_scr_dump.3 +++ b/lib/libcurses/curs_scr_dump.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_scr_dump.3,v 1.3 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_scr_dump.3,v 1.4 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,77 +29,89 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_scr_dump.3,v 1.3 2010/01/12 23:21:59 nicm Exp $ -.TH curs_scr_dump 3 "" +.\" $Id: curs_scr_dump.3,v 1.4 2023/10/17 09:52:08 nicm Exp $ +.TH curs_scr_dump 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .na .hy 0 .SH NAME -\fBscr_dump\fR, -\fBscr_restore\fR, -\fBscr_init\fR, -\fBscr_set\fR - read (write) a \fBcurses\fR screen from (to) a file +\fBscr_dump\fP, +\fBscr_restore\fP, +\fBscr_init\fP, +\fBscr_set\fP \- read (write) a \fBcurses\fP screen from (to) a file .ad .hy .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint scr_dump(const char *filename);\fR +\fBint scr_dump(const char *\fIfilename\fB);\fR .br -\fBint scr_restore(const char *filename);\fR +\fBint scr_restore(const char *\fIfilename\fB);\fR .br -\fBint scr_init(const char *filename);\fR -.br -\fBint scr_set(const char *filename);\fR +\fBint scr_init(const char *\fIfilename\fB);\fR .br +\fBint scr_set(const char *\fIfilename\fB);\fR .SH DESCRIPTION -The \fBscr_dump\fR routine dumps the current contents of the virtual screen -to the file \fIfilename\fR. -.PP -The \fBscr_restore\fR routine sets the virtual screen to the contents -of \fIfilename\fR, which must have been written using \fBscr_dump\fR. The next -call to \fBdoupdate\fR restores the screen to the way it looked in the dump -file. -.PP -The \fBscr_init\fR routine reads in the contents of \fIfilename\fR and uses -them to initialize the \fBcurses\fR data structures about what the terminal -currently has on its screen. If the data is determined to be valid, -\fBcurses\fR bases its next update of the screen on this information rather -than clearing the screen and starting from scratch. \fBscr_init\fR is used -after \fBinitscr\fR or a \fBsystem\fR call to share -the screen with another process which has done a \fBscr_dump\fR after its -\fBendwin\fR call. The data is declared invalid if the terminfo capabilities -\fBrmcup\fR and \fBnrrmc\fR exist; also if the terminal has been written to -since the preceding \fBscr_dump\fR call. -.PP -The \fBscr_set\fR routine is a combination of \fBscr_restore\fR and -\fBscr_init\fR. It tells the program that the information in \fIfilename\fR is +.SS scr_dump +The \fBscr_dump\fP routine dumps the current contents +of the \fIvirtual screen\fP +to the file \fIfilename\fP. +.SS scr_restore +The \fBscr_restore\fP routine sets the \fIvirtual screen\fP to the contents +of \fIfilename\fP, which must have been written using \fBscr_dump\fP. +The next call to \fBdoupdate\fP restores +the \fIphysical screen\fP to the way it looked in the dump file. +.SS scr_init +The \fBscr_init\fP routine reads in the contents of \fIfilename\fP and uses +them to initialize the \fBcurses\fP data structures about what the terminal +currently has on its screen. +If the data is determined to be valid, +\fBcurses\fP bases its next update of the screen on this information rather +than clearing the screen and starting from scratch. +\fBscr_init\fP is used +after \fBinitscr\fP(3) or a \fBsystem\fP(3) call to share +the screen with another process which has done a \fBscr_dump\fP after its +\fBendwin\fP(3) call. +The data is declared invalid +.bP +if the terminfo capabilities \fBrmcup\fP and \fBnrrmc\fP exist, also +.bP +if the terminal has been written to since the preceding \fBscr_dump\fP call. +.SS scr_set +The \fBscr_set\fP routine is a combination of \fBscr_restore\fP and +\fBscr_init\fP. It tells the program that the information in \fIfilename\fP is what is currently on the screen, and also what the program wants on the screen. This can be thought of as a screen inheritance function. .PP -To read (write) a window from (to) a file, use the \fBgetwin\fR and -\fBputwin\fR routines [see \fBcurs_util\fR(3)]. +To read (write) a window from (to) a file, use the \fBgetwin\fP and +\fBputwin\fP routines [see \fBcurs_util\fP(3)]. .SH RETURN VALUE -All routines return the integer \fBERR\fR upon failure and \fBOK\fR +All routines return the integer \fBERR\fP upon failure and \fBOK\fP upon success. .PP X/Open defines no error conditions. In this implementation, each will return an error if the file cannot be opened. .SH NOTES -Note that \fBscr_init\fR, \fBscr_set\fR, and \fBscr_restore\fR may be macros. +Note that \fBscr_init\fP, \fBscr_set\fP, and \fBscr_restore\fP may be macros. .SH PORTABILITY The XSI Curses standard, Issue 4, describes these functions (adding the const qualifiers). .PP -The SVr4 docs merely say under \fBscr_init\fR that the dump data is also +The SVr4 docs merely say under \fBscr_init\fP that the dump data is also considered invalid "if the time-stamp of the tty is old" but do not define -"old". +\*(``old\*(''. .SH SEE ALSO -\fBcurses\fR(3), \fBcurs_initscr\fR(3), \fBcurs_refresh\fR(3), -\fBcurs_util\fR(3), \fBsystem\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_initscr\fP(3), +\fBcurs_refresh\fP(3), +\fBcurs_util\fP(3), +\fBscr_dump\fP(5), +\fBsystem\fP(3) diff --git a/lib/libcurses/curs_scroll.3 b/lib/libcurses/curs_scroll.3 index b88c95ed1ea..84a818ecb7d 100644 --- a/lib/libcurses/curs_scroll.3 +++ b/lib/libcurses/curs_scroll.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_scroll.3,v 1.9 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_scroll.3,v 1.10 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2006,2010 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,56 +29,59 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_scroll.3,v 1.9 2010/01/12 23:21:59 nicm Exp $ -.TH curs_scroll 3 "" +.\" $Id: curs_scroll.3,v 1.10 2023/10/17 09:52:08 nicm Exp $ +.TH curs_scroll 3 2023-08-19 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .na .hy 0 .SH NAME -\fBscroll\fR, -\fBscrl\fR, -\fBwscrl\fR - scroll a \fBcurses\fR window +\fBscroll\fP, +\fBscrl\fP, +\fBwscrl\fP \- scroll a \fBcurses\fP window .ad .hy .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint scroll(WINDOW *win);\fR -.br -\fBint scrl(int n);\fR -.br -\fBint wscrl(WINDOW *win, int n);\fR +\fBint scroll(WINDOW *\fIwin\fB);\fR +.sp +\fBint scrl(int \fIn\fB);\fR .br +\fBint wscrl(WINDOW *\fIwin\fB, int \fIn\fB);\fR .SH DESCRIPTION -The \fBscroll\fR routine scrolls the window up one line. +The \fBscroll\fP routine scrolls the window up one line. This involves moving the lines in the window data structure. As an optimization, if the scrolling -region of the window is the entire screen, the physical screen may be scrolled -at the same time. +region of the window is the entire screen, +the \fIphysical screen\fP may be scrolled at the same time. .PP -For positive \fIn\fR, the \fBscrl\fR and \fBwscrl\fR routines scroll the -window up \fIn\fR lines (line \fIi\fR+\fIn\fR becomes \fIi\fR); otherwise -scroll the window down \fIn\fR lines. +For positive \fIn\fP, the \fBscrl\fP and \fBwscrl\fP routines scroll the +window up \fIn\fP lines (line \fIi\fP+\fIn\fP becomes \fIi\fP); otherwise +scroll the window down \fIn\fP lines. This involves moving the lines in the window character image structure. The current cursor position is not changed. .PP -For these functions to work, scrolling must be enabled via \fBscrollok\fR. +For these functions to work, scrolling must be enabled via \fBscrollok\fP(3). .SH RETURN VALUE -These routines return \fBERR\fR upon failure, and \fBOK\fR (SVr4 only specifies -"an integer value other than \fBERR\fR") upon successful completion. +These routines return \fBERR\fP upon failure, and \fBOK\fP (SVr4 only specifies +"an integer value other than \fBERR\fP") upon successful completion. .PP X/Open defines no error conditions. .PP This implementation returns an error if the window pointer is null, or -if scrolling is not enabled in the window, e.g., with \fBscrollok\fP. +if scrolling is not enabled in the window, e.g., with \fBscrollok\fP(3). .SH NOTES -Note that \fBscrl\fR and \fBscroll\fR may be macros. +Note that \fBscrl\fP and \fBscroll\fP may be macros. .PP The SVr4 documentation says that the optimization of physically scrolling -immediately if the scroll region is the entire screen "is" performed, not -"may be" performed. +immediately if the scroll region is the entire screen \*(``is\*('' performed, +not \*(``may be\*('' performed. This implementation deliberately does not guarantee that this will occur, to leave open the possibility of smarter optimization of multiple scroll actions on the next update. @@ -89,10 +93,4 @@ Under this implementation it is. .SH PORTABILITY The XSI Curses standard, Issue 4 describes these functions. .SH SEE ALSO -\fBcurses\fR(3), \fBcurs_outopts\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), \fBcurs_outopts\fP(3) diff --git a/lib/libcurses/curs_slk.3 b/lib/libcurses/curs_slk.3 index ff4dc2cc90c..a5017383505 100644 --- a/lib/libcurses/curs_slk.3 +++ b/lib/libcurses/curs_slk.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_slk.3,v 1.10 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_slk.3,v 1.11 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2016,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,127 +29,185 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_slk.3,v 1.10 2010/01/12 23:21:59 nicm Exp $ -.TH curs_slk 3 "" +.\" $Id: curs_slk.3,v 1.11 2023/10/17 09:52:08 nicm Exp $ +.TH curs_slk 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .na .hy 0 .SH NAME -\fBslk_init\fR, -\fBslk_set\fR, -\fBslk_refresh\fR, -\fBslk_noutrefresh\fR, -\fBslk_label\fR, -\fBslk_clear\fR, -\fBslk_restore\fR, -\fBslk_touch\fR, -\fBslk_attron\fR, -\fBslk_attrset\fR, -\fBslk_attroff\fR, -\fBslk_attr_on\fR, -\fBslk_attr_set\fR, -\fBslk_attr_off\fR, -\fBslk_attr\fR, -\fBslk_color\fR - \fBcurses\fR soft label routines +\fBslk_init\fP, +\fBslk_set\fP, +\fBslk_wset\fP, +\fBslk_refresh\fP, +\fBslk_noutrefresh\fP, +\fBslk_label\fP, +\fBslk_clear\fP, +\fBslk_restore\fP, +\fBslk_touch\fP, +\fBslk_attron\fP, +\fBslk_attrset\fP, +\fBslk_attroff\fP, +\fBslk_attr_on\fP, +\fBslk_attr_set\fP, +\fBslk_attr_off\fP, +\fBslk_attr\fP, +\fBslk_color\fP, +\fBextended_slk_color\fP \- \fBcurses\fP soft label routines .ad .hy .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint slk_init(int fmt);\fR -.br -\fBint slk_set(int labnum, const char *label, int fmt);\fR -.br -\fBint slk_refresh(void);\fR -.br -\fBint slk_noutrefresh(void);\fR +\fBint slk_init(int \fIfmt\fB);\fR +.sp +\fBint slk_set(int \fIlabnum\fB, const char *\fIlabel\fB, int \fIfmt\fB);\fR .br -\fBchar *slk_label(int labnum);\fR +\fBint slk_wset(int \fIlabnum\fB, const wchar_t *\fIlabel\fB, int \fIfmt\fB);\fR +.sp +\fBchar *slk_label(int \fIlabnum\fB);\fR +.sp +\fBint slk_refresh(void);\fP .br -\fBint slk_clear(void);\fR +\fBint slk_noutrefresh(void);\fP .br -\fBint slk_restore(void);\fR +\fBint slk_clear(void);\fP .br -\fBint slk_touch(void);\fR +\fBint slk_restore(void);\fP .br -\fBint slk_attron(const chtype attrs);\fR +\fBint slk_touch(void);\fP +.sp +\fBint slk_attron(const chtype \fIattrs\fB);\fR .br -\fBint slk_attroff(const chtype attrs);\fR +\fBint slk_attroff(const chtype \fIattrs\fB);\fR .br -\fBint slk_attrset(const chtype attrs);\fR +\fBint slk_attrset(const chtype \fIattrs\fB);\fR .br -\fBint slk_attr_on(attr_t attrs, void* opts);\fR +\fBint slk_attr_on(attr_t \fIattrs\fB, void* \fIopts\fB);\fR .br -\fBint slk_attr_off(const attr_t attrs, void * opts);\fR +\fBint slk_attr_off(const attr_t \fIattrs\fB, void * \fIopts\fB);\fR .br -\fBint slk_attr_set(const attr_t attrs,\fR +\fBint slk_attr_set(const attr_t \fIattrs\fB, short \fIpair\fB, void* \fIopts\fB);\fR .br - \fBshort color_pair_number, void* opts);\fR +/* extension */ .br -\fBattr_t slk_attr(void);\fR +\fBattr_t slk_attr(void);\fP +.sp +\fBint slk_color(short \fIpair\fB);\fR .br -\fBint slk_color(short color_pair_number);\fR +/* extension */ .br +\fBint extended_slk_color(int \fIpair\fB);\fR .SH DESCRIPTION The slk* functions manipulate the set of soft function-key labels that exist on -many terminals. For those terminals that do not have soft labels, -\fBcurses\fR takes over the bottom line of \fBstdscr\fR, reducing the size of -\fBstdscr\fR and the variable \fBLINES\fR. \fBcurses\fR standardizes on eight -labels of up to eight characters each. In addition to this, the ncurses +many terminals. +For those terminals that do not have soft labels, +\fBcurses\fP takes over the bottom line of \fBstdscr\fP, reducing the size of +\fBstdscr\fP and the variable \fBLINES\fP. +\fBcurses\fP standardizes on eight +labels of up to eight characters each. +In addition to this, the ncurses implementation supports a mode where it simulates 12 labels of up to five -characters each. This is most common for todays PC like enduser devices. -Please note that ncurses simulates this mode by taking over up to two lines at -the bottom of the screen, it does not try to use any hardware support for this +characters each. +This is useful for PC-like enduser devices. +ncurses simulates this mode by taking over up to two lines at +the bottom of the screen; +it does not try to use any hardware support for this mode. -.PP -The \fBslk_init\fR routine must be called before \fBinitscr\fR or \fBnewterm\fR -is called. If \fBinitscr\fR eventually uses a line from \fBstdscr\fR to -emulate the soft labels, then \fIfmt\fR determines how the labels are arranged -on the screen. Setting \fIfmt\fR to \fB0\fR indicates a 3-2-3 arrangement of -the labels, \fB1\fR indicates a 4-4 arrangement and \fB2\fR indicates the -PC like 4-4-4 mode. If \fBfmt\fR is set to \fB3\fR, it is again the PC like -4-4-4 mode, but in addition an index line is generated, helping the user to +.SS Initialization +The \fBslk_init\fP routine must be called before \fBinitscr\fP or \fBnewterm\fP +is called. +If \fBinitscr\fP eventually uses a line from \fBstdscr\fP to +emulate the soft labels, +then \fIfmt\fP determines how the labels are arranged on the screen: +.RS 3 +.TP 3 +.B 0 +indicates a 3\-2\-3 arrangement of +the labels. +.TP 3 +.B 1 +indicates a 4\-4 arrangement +.TP 3 +.B 2 +indicates the PC-like 4\-4\-4 mode. +.TP 3 +.B 3 +is again the PC-like 4\-4\-4 mode, +but in addition an index line is generated, helping the user to identify the key numbers easily. -.PP -The \fBslk_set\fR routine requires \fIlabnum\fR to be a label number, -from \fB1\fR to \fB8\fR (resp. \fB12\fR); \fIlabel\fR must be the string -to be put on the label, up to eight (resp. five) characters in length. -A null string or a null pointer sets up a blank label. \fIfmt\fR is either -\fB0\fR, \fB1\fR, or \fB2\fR, indicating whether the label is to be +.RE +.SS Labels +The \fBslk_set\fP routine +(and the \fBslk_wset\fP routine for the wide-character library) +has three parameters: +.RS 3 +.TP 5 +.I labnum +is the label number, from \fB1\fP to \fB8\fP +(12 if \fIfmt\fP in \fBslk_init\fP is \fB2\fP or \fB3\fP); +.TP +.I label +is be the string to put on the label, +up to eight +(five if \fIfmt\fP in \fBslk_init\fP is \fB2\fP or \fB3\fP) +characters in length. +A null string or a null pointer sets up a blank label. +.TP +.I fmt +is either +\fB0\fP, \fB1\fP, or \fB2\fP, indicating whether the label is to be left-justified, centered, or right-justified, respectively, within the label. +.RE .PP -The \fBslk_refresh\fR and \fBslk_noutrefresh\fR routines correspond to -the \fBwrefresh\fR and \fBwnoutrefresh\fR routines. -.PP -The \fBslk_label\fR routine returns the current label for label number -\fIlabnum\fR, with leading and trailing blanks stripped. -.PP -The \fBslk_clear\fR routine clears the soft labels from the screen. +The \fBslk_label\fP routine returns the current label for label number +\fIlabnum\fP, with leading and trailing blanks stripped. +.SS Screen updates +The \fBslk_refresh\fP and \fBslk_noutrefresh\fP routines correspond to +the \fBwrefresh\fP and \fBwnoutrefresh\fP routines. .PP -The \fBslk_restore\fR routine restores the soft labels to the screen -after a \fBslk_clear\fR has been performed. +The \fBslk_clear\fP routine clears the soft labels from the screen. .PP -The \fBslk_touch\fR routine forces all the soft labels to be output -the next time a \fBslk_noutrefresh\fR is performed. +The \fBslk_restore\fP routine restores the soft labels to the screen +after a \fBslk_clear\fP has been performed. .PP -The \fBslk_attron\fR, \fBslk_attrset\fR, \fBslk_attroff\fR and \fBslk_attr\fR -routines correspond to \fBattron\fR, \fBattrset\fR, \fBattroff\fR and \fBattr_get\fR. +The \fBslk_touch\fP routine forces all the soft labels to be output +the next time a \fBslk_noutrefresh\fP is performed. +.SS Video attributes +The +\fBslk_attron\fP, \fBslk_attrset\fP, \fBslk_attroff\fP and \fBslk_attr\fP +routines correspond to +\fBattron\fP, \fBattrset\fP, \fBattroff\fP and \fBattr_get\fP, respectively. They have an effect only if soft labels are simulated on the bottom line of -the screen. The default highlight for soft keys is A_STANDOUT (as in +the screen. +The default highlight for soft keys is A_STANDOUT (as in System V curses, which does not document this fact). -.PP -The \fBslk_color\fR routine corresponds to \fBcolor_set\fR. It has an effect only +.SS Colors +The \fBslk_color\fP routine corresponds to \fBcolor_set\fP. +It has an effect only if soft labels are simulated on the bottom line of the screen. +.PP +Because \fBslk_color\fP accepts only \fBshort\fP (signed 16-bit integer) values, +this implementation provides +\fBextended_slk_color\fP which accepts an integer value, e.g., 32-bits. . .SH RETURN VALUE -These routines return \fBERR\fR upon failure and OK (SVr4 specifies only "an -integer value other than \fBERR\fR") upon successful completion. +These routines return \fBERR\fP upon failure +and \fBOK\fP (SVr4 specifies only "an integer value other than \fBERR\fP") +upon successful completion. .PP X/Open defines no error conditions. In this implementation -.RS +.RS 3 .TP 5 -\fBslk_attr\fR +\fBslk_attr\fP returns the attribute used for the soft keys. .TP 5 .na @@ -166,20 +225,19 @@ if the terminal or the softkeys were not initialized. \fBslk_attr_set\fP returns an error if the terminal or the softkeys were not initialized, or -the color pair is outside the range 0..COLOR_PAIRS-1, -or opts is not null. +the color pair is outside the range 0..COLOR_PAIRS\-1. .TP 5 \fBslk_color\fP returns an error if the terminal or the softkeys were not initialized, or -the color pair is outside the range 0..COLOR_PAIRS-1. +the color pair is outside the range 0..COLOR_PAIRS\-1. .TP 5 -\fBslk_init\fR +\fBslk_init\fP returns an error if the format parameter is outside the range 0..3. .TP 5 -\fBslk_label\fR -returns \fBNULL\fR on error. +\fBslk_label\fP +returns \fBNULL\fP on error. .TP 5 \fBslk_set\fP returns an error @@ -188,20 +246,109 @@ the \fIlabnum\fP parameter is outside the range of label counts, or if the format parameter is outside the range 0..2, or if memory for the labels cannot be allocated. .RE +.SH HISTORY +SVr3 introduced these functions: + slk_clear + slk_init + slk_label + slk_noutrefresh + slk_refresh + slk_restore + slk_set + slk_touch +.PP +SVr4 added these functions: + slk_attroff + slk_attron + slk_attrset + slk_start +.PP +X/Open Curses added these: + slk_attr_off + slk_attr_on + slk_attr_set + slk_color + slk_wset +.SH EXTENSIONS +X/Open Curses documents the \fIopts\fP argument as reserved for future use, +saying that it must be null. +This implementation +uses that parameter in ABI 6 for the functions which have a color-pair +parameter to support extended color pairs. +.PP +For functions which modify the color, e.g., \fBslk_attr_set\fP, +if \fIopts\fP is set it is treated as a pointer to \fBint\fP, +and used to set the color pair instead of the \fBshort\fP pair parameter. .SH NOTES -Most applications would use \fBslk_noutrefresh\fR because a -\fBwrefresh\fR is likely to follow soon. +Most applications would use \fBslk_noutrefresh\fP because a +\fBwrefresh\fP is likely to follow soon. .SH PORTABILITY -The XSI Curses standard, Issue 4, describes these functions. It changes the -argument type of the attribute-manipulation functions \fBslk_attron\fR, -\fBslk_attroff\fR, \fBslk_attrset\fR to be \fBattr_t\fR, and adds \fBconst\fR -qualifiers. The format codes \fB2\fR and \fB3\fR for \fBslk_init()\fR and the -function \fBslk_attr\fR are specific to ncurses. +The XSI Curses standard, Issue 4, described the soft-key functions, +with some differences from SVr4 curses: +.bP +It added functions like the SVr4 +attribute-manipulation functions \fBslk_attron\fP, +\fBslk_attroff\fP, \fBslk_attrset\fP, +but which use \fBattr_t\fP parameters (rather than \fBchtype\fP), +along with a reserved \fIopts\fP parameter. +.IP +Two of these new functions (unlike the SVr4 functions) have no provision +for color: \fBslk_attr_on\fP and \fBslk_attr_off\fP. +.IP +The third function (\fBslk_attr_set\fP) has a color-pair parameter. +.bP +It added \fBconst\fP qualifiers to parameters (unnecessarily), and +.bP +It added \fBslk_color\fP. +.PP +Although \fBslk_start\fP is declared in the curses header file, +it was not documented by SVr4 other than its presence in a list +of libtermlib.so.1 symbols. +Reading the source code (i.e., Illumos): +.bP +\fBslk_start\fP has two parameters: +.RS +.bP +\fIng\fP (number of groups) and +.bP +\fIgp\fP (group pointer). +.RE +.bP +Soft-key groups are an array of \fIng\fP integers. +.bP +In SVr4, \fBslk_init\fP calls \fBslk_start\fP passing a null for \fIgp\fP. +For this case, \fBslk_start\fP uses the number of groups \fIng\fP +(3 for the 3-2-3 layout, 2 for the 4-4 layout) which \fBslk_init\fP provided. +.IP +If \fIng\fP is neither 2 or 3, +\fBslk_start\fP checks the terminfo \fIfln\fP (label_format) capability, +interpreting that as a comma-separated list of numbers, +e.g., \*(``3,2,3\*('' for the 3-2-3 layout. +.IP +Finally, if there is no \fIfln\fP capability, \fBslk_start\fP returns ERR. +.bP +If \fBslk_start\fP is given a non-null \fIgp\fP, +it copies the \fIng\fP elements of the group of soft-keys, up to 16. +.IP +If there are more than 16 elements, \fBslk_start\fP returns an error. +.bP +The format codes \fB2\fP and \fB3\fP for \fBslk_init\fP +were added by ncurses in 1996. +PDCurses 2.4 added this feature in 2001. +.PP +The function \fBslk_attr\fP was added by ncurses in 1996. +.PP +X/Open Curses does not specify a limit for the number of colors and +color pairs which a terminal can support. +However, in its use of \fBshort\fP for the parameters, +it carries over SVr4's implementation detail for the compiled +terminfo database, which uses signed 16-bit numbers. +This implementation provides extended versions of those functions +which use \fBint\fP parameters, +allowing applications to use larger color- and pair-numbers. .SH SEE ALSO -\fBcurses\fR(3), \fBcurs_attr\fR(3), \fBcurs_initscr\fR(3), \fBcurs_refresh\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_attr\fP(3), +\fBcurs_initscr\fP(3), +\fBcurs_refresh\fP(3), +\fBcurs_variables\fP(3). diff --git a/lib/libcurses/curs_sp_funcs.3 b/lib/libcurses/curs_sp_funcs.3 new file mode 100644 index 00000000000..1e0b6223a76 --- /dev/null +++ b/lib/libcurses/curs_sp_funcs.3 @@ -0,0 +1,286 @@ +.\"*************************************************************************** +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 2010-2015,2017 Free Software Foundation, Inc. * +.\" * +.\" Permission is hereby granted, free of charge, to any person obtaining a * +.\" copy of this software and associated documentation files (the * +.\" "Software"), to deal in the Software without restriction, including * +.\" without limitation the rights to use, copy, modify, merge, publish, * +.\" distribute, distribute with modifications, sublicense, and/or sell * +.\" copies of the Software, and to permit persons to whom the Software is * +.\" furnished to do so, subject to the following conditions: * +.\" * +.\" The above copyright notice and this permission notice shall be included * +.\" in all copies or substantial portions of the Software. * +.\" * +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * +.\" IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * +.\" DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * +.\" OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * +.\" THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +.\" * +.\" Except as contained in this notice, the name(s) of the above copyright * +.\" holders shall not be used in advertising or otherwise to promote the * +.\" sale, use or other dealings in this Software without prior written * +.\" authorization. * +.\"*************************************************************************** +.\" +.\" $Id: curs_sp_funcs.3,v 1.1 2023/10/17 09:52:08 nicm Exp $ +.TH curs_sp_funcs 3 2023-08-19 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.na +.hy 0 +.SH NAME +curs_sp_funcs \- \fBcurses\fP screen-pointer extension +.ad +.hy +.SH SYNOPSIS +\fB#include \fP +.nf +.na +.sp +\fBint alloc_pair_sp(SCREEN* \fIsp\fB, int \fIfg\fB, int \fIbg\fB);\fR +\fBint assume_default_colors_sp(SCREEN* \fIsp\fB, int \fIfg\fB, int \fIbg\fB);\fR +\fBint baudrate_sp(SCREEN* \fIsp\fB);\fR +\fBint beep_sp(SCREEN* \fIsp\fB);\fR +\fBbool can_change_color_sp(SCREEN* \fIsp\fB);\fR +\fBint cbreak_sp(SCREEN* \fIsp\fB);\fR +\fBint color_content_sp(SCREEN* \fIsp\fB, short \fIcolor\fB, short* \fIr\fB, short* \fIg\fB, short* \fIb\fB);\fR +\fBint curs_set_sp(SCREEN* \fIsp\fB, int \fIvisibility\fR);\fR +\fBint def_prog_mode_sp(SCREEN* \fIsp\fB);\fR +\fBint def_shell_mode_sp(SCREEN* \fIsp\fB);\fR +.sp +\fBint define_key_sp(SCREEN* \fIsp\fB, const char * \fIdefinition\fB, int \fIkeycode\fB);\fR +\fBint delay_output_sp(SCREEN* \fIsp\fB, int \fIms\fB);\fR +\fBint doupdate_sp(SCREEN* \fIsp\fB);\fR +\fBint echo_sp(SCREEN* \fIsp\fB);\fR +\fBint endwin_sp(SCREEN* \fIsp\fB);\fR +\fBchar erasechar_sp(SCREEN* \fIsp\fB);\fR +\fBint erasewchar_sp(SCREEN* \fIsp\fB, wchar_t *\fIch\fB);\fR +\fBint extended_color_content_sp(SCREEN * \fIsp\fB, int \fIcolor\fB, int * \fIr\fB, int * \fIg\fB, int * \fIb\fB);\fR +\fBint extended_pair_content_sp(SCREEN* \fIsp\fB, int \fIpair\fB, int * \fIfg\fB, int * \fIbg\fB);\fR +\fBint extended_slk_color_sp(SCREEN* \fIsp\fB, int \fIpair\fB);\fR +.sp +\fBvoid filter_sp(SCREEN* \fIsp\fB);\fR +\fBint find_pair_sp(SCREEN* \fIsp\fB, int \fIfg\fB, int \fIbg\fB);\fR +\fBint flash_sp(SCREEN* \fIsp\fB);\fR +\fBint flushinp_sp(SCREEN* \fIsp\fB);\fR +\fBint free_pair_sp(SCREEN* \fIsp\fB, int \fIpair\fB);\fR +\fBint get_escdelay_sp(SCREEN* \fIsp\fB);\fR +\fBint getmouse_sp(SCREEN* \fIsp\fB, MEVENT* \fBevent\fB);\fR +\fBWINDOW* getwin_sp(SCREEN* \fIsp\fB, FILE* \fIfilep\fB);\fR +\fBint halfdelay_sp(SCREEN* \fIsp\fB, int \fItenths\fB);\fR +\fBbool has_colors_sp(SCREEN* \fIsp\fB);\fR +.sp +\fBbool has_ic_sp(SCREEN* \fIsp\fB);\fR +\fBbool has_il_sp(SCREEN* \fIsp\fB);\fR +\fBint has_key_sp(SCREEN* \fIsp\fB, int \fIch\fB);\fR +\fBbool has_mouse_sp(SCREEN* \fIsp\fB);\fR +\fBint init_color_sp(SCREEN* \fIsp\fB, short \fIcolor\fB, short \fIr\fB, short \fIg\fB, short \fIb\fB);\fR +\fBint init_extended_color_sp(SCREEN* \fIsp\fB, int \fIcolor\fB, int \fIr\fB, int \fIg\fB, int \fIb\fB);\fR +\fBint init_extended_pair_sp(SCREEN* \fIsp\fB, int \fIpair\fB, int \fIfg\fB, int \fIbg\fB);\fR +\fBint init_pair_sp(SCREEN* \fIsp\fB, short \fIpair\fB, short \fIfg\fB, short \fIbg\fB);\fR +\fBint intrflush_sp(SCREEN* \fIsp\fB, WINDOW* \fIwin\fB, bool \fIbf\fB);\fR +\fBint is_cbreak_sp(SCREEN* \fIsp\fB);\fR +.sp +\fBint is_echo_sp(SCREEN* \fIsp\fB);\fR +\fBint is_nl_sp(SCREEN* \fIsp\fB);\fR +\fBint is_raw_sp(SCREEN* \fIsp\fB);\fR +\fBbool is_term_resized_sp(SCREEN* \fIsp\fB, int \fIlines\fB, int \fIcolumns\fB);\fR +\fBbool isendwin_sp(SCREEN* \fIsp\fB);\fR +\fBint key_defined_sp(SCREEN* \fIsp\fB, const char *\fIdefinition\fB);\fR +\fBchar* keybound_sp(SCREEN* \fIsp\fB, int \fIkeycode\fB, int \fIcount\fB);\fR +\fBNCURSES_CONST char* keyname_sp(SCREEN* \fIsp\fB, int \fIc\fB);\fR +\fBint keyok_sp(SCREEN* \fIsp\fB, int \fIkeycode\fB, bool \fIenable\fB);\fR +\fBchar killchar_sp(SCREEN* \fIsp\fB);\fR +.sp +\fBint killwchar_sp(SCREEN* \fIsp\fB, wchar_t *\fIch\fB);\fR +\fBchar* longname_sp(SCREEN* \fIsp\fB);\fR +\fBint mcprint_sp(SCREEN* \fIsp\fB, char *\fIdata\fB, int \fIlen\fB);\fR +\fBint mouseinterval_sp(SCREEN* \fIsp\fB, int \fIerval\fB);\fR +\fBmmask_t mousemask_sp(SCREEN* \fIsp\fB, mmask_t \fInewmask\fB, mmask_t *\fIoldmask\fB);\fR +\fBint mvcur_sp(SCREEN* \fIsp\fB, int \fIoldrow\fB, int \fIoldcol\fB, int \fInewrow\fB, int \fInewcol\fB);\fR +\fBint napms_sp(SCREEN* \fIsp\fB, int \fIms\fB);\fR +\fBWINDOW* newpad_sp(SCREEN* \fIsp\fB, int \fInrows\fB, int \fIncols\fB);\fR +\fBSCREEN* new_prescr(void);\fP +\fBSCREEN* newterm_sp(SCREEN* \fIsp\fB, const char *\fItype\fB, FILE *\fIoutfd\fB, FILE *\fIinfd\fB);\fR +.sp +\fBWINDOW* newwin_sp(SCREEN* \fIsp\fB, int \fInlines\fB, int \fIncols\fB, int \fIbegin_y\fB, int \fIbegin_x\fB);\fR +\fBint nl_sp(SCREEN* \fIsp\fB);\fR +\fBint nocbreak_sp(SCREEN* \fIsp\fB);\fR +\fBint noecho_sp(SCREEN* \fIsp\fB);\fR +\fBvoid nofilter_sp(SCREEN* \fIsp\fB);\fR +\fBint nonl_sp(SCREEN* \fIsp\fB);\fR +\fBvoid noqiflush_sp(SCREEN* \fIsp\fB);\fR +\fBint noraw_sp(SCREEN* \fIsp\fB);\fR +\fBint pair_content_sp(SCREEN* \fIsp\fB, short \fIpair\fB, short* \fIfg\fB, short* \fIbg\fB);\fR +\fBvoid qiflush_sp(SCREEN* \fIsp\fB);\fR +.sp +\fBint raw_sp(SCREEN* \fIsp\fB);\fR +\fBvoid reset_color_pairs_sp(SCREEN* \fIsp\fB);\fR +\fBint reset_prog_mode_sp(SCREEN* \fIsp\fB);\fR +\fBint reset_shell_mode_sp(SCREEN* \fIsp\fB);\fR +\fBint resetty_sp(SCREEN* \fIsp\fB);\fR +\fBint resize_term_sp(SCREEN* \fIsp\fB, int \fIlines\fB, int \fIcolumns\fB);\fR +\fBint resizeterm_sp(SCREEN* \fIsp\fB, int \fIlines\fB, int \fIcolumns\fB);\fR +\fBint ripoffline_sp(SCREEN* \fIsp\fB, int \fIline\fB, int (*\fIinit\fB)(WINDOW* \fIwin\fB, int \fIfmt\fB));\fR +\fBint savetty_sp(SCREEN* \fIsp\fB);\fR +\fBint scr_init_sp(SCREEN* \fIsp\fB, const char *\fIfilename\fB);\fR +.sp +\fBint scr_restore_sp(SCREEN* \fIsp\fB, const char *\fIfilename\fB);\fR +\fBint scr_set_sp(SCREEN* \fIsp\fB, const char *\fIfilename\fB);\fR +\fBint set_escdelay_sp(SCREEN* \fIsp\fB, int \fIms\fB);\fR +\fBint set_tabsize_sp(SCREEN* \fIsp\fB, int \fIcols\fB);\fR +\fBint slk_attrset_sp(SCREEN* \fIsp\fB, const chtype \fIa\fB);\fR +\fBint slk_attr_set_sp(SCREEN* \fIsp\fB, const attr_t \fIattrs\fB, short \fIpair\fB, void*\fIopts\fB);\fR +\fBint slk_attroff_sp(SCREEN* \fIsp\fB, const chtype \fIa\fB);\fR +\fBint slk_attron_sp(SCREEN* \fIsp\fB, const chtype \fIa\fB);\fR +\fBattr_t slk_attr_sp(SCREEN* \fIsp\fB);\fR +\fBint slk_clear_sp(SCREEN* \fIsp\fB);\fR +.sp +\fBint slk_color_sp(SCREEN* \fIsp\fB, short \fIpair\fB);\fR +\fBint slk_init_sp(SCREEN* \fIsp\fB, int \fIfmt\fB);\fR +\fBchar* slk_label_sp(SCREEN* \fIsp\fB, int \fIlabnum\fB);\fR +\fBint slk_noutrefresh_sp(SCREEN* \fIsp\fB);\fR +\fBint slk_refresh_sp(SCREEN* \fIsp\fB);\fR +\fBint slk_restore_sp(SCREEN* \fIsp\fB);\fR +\fBint slk_set_sp(SCREEN* \fIsp\fB, int \fIlabnum\fB, const char * \fIlabel\fB, int \fIfmt\fB);\fR +\fBint slk_touch_sp(SCREEN* \fIsp\fB);\fR +\fBint start_color_sp(SCREEN* \fIsp\fB);\fR +\fBattr_t term_attrs_sp(SCREEN* \fIsp\fB);\fR +.sp +\fBchtype termattrs_sp(SCREEN* \fIsp\fB);\fR +\fBchar* termname_sp(SCREEN* \fIsp\fB);\fR +\fBint typeahead_sp(SCREEN* \fIsp\fB, int \fIfd\fB);\fR +\fBint unget_wch_sp(SCREEN* \fIsp\fB, const wchar_t \fIwch\fB);\fR +\fBint ungetch_sp(SCREEN* \fIsp\fB, int \fIch\fB);\fR +\fBint ungetmouse_sp(SCREEN* \fIsp\fB,MEVENT * \fBevent\fB);\fR +\fBint use_default_colors_sp(SCREEN* \fIsp\fB);\fR +\fBvoid use_env_sp(SCREEN* \fIsp\fB, bool \fIbf\fB);\fR +\fBint use_legacy_coding_sp(SCREEN* \fIsp\fB, int \fIlevel\fB);\fR +\fBvoid use_tioctl_sp(SCREEN *\fIsp\fB, bool \fIbf\fB);\fR +.sp +\fBint vid_attr_sp(SCREEN* \fIsp\fB, attr_t \fIattrs\fB, short \fIpair\fB, void * \fIopts\fB);\fR +\fBint vid_puts_sp(SCREEN* \fIsp\fB, attr_t \fIattrs\fB, short \fIpair\fB, void * \fIopts\fB, NCURSES_SP_OUTC \fIputc\fB);\fR +\fBint vidattr_sp(SCREEN* \fIsp\fB, chtype \fIattrs\fB);\fR +\fBint vidputs_sp(SCREEN* \fIsp\fB, chtype \fIattrs\fB, NCURSES_SP_OUTC \fIputc\fB);\fR +\fBwchar_t* wunctrl_sp(SCREEN* \fIsp\fB, cchar_t *\fIch\fB);\fR +.ad +.sp +\fB#include \fP +.sp +\fBFORM* new_form_sp(SCREEN* \fIsp\fB, FIELD **\fIfields\fB);\fR +.sp +\fB#include \fP +.sp +\fBMENU* new_menu_sp(SCREEN* \fIsp\fB, ITEM **\fIitems\fB);\fR +.sp +\fB#include \fP +.sp +\fBPANEL* ceiling_panel(SCREEN* \fIsp\fB);\fR +.br +\fBPANEL* ground_panel(SCREEN* \fIsp\fB);\fR +.br +\fBvoid update_panels_sp(SCREEN* \fIsp\fB);\fR +.sp +\fB#include \fP +.sp +.na +\fBint del_curterm_sp(SCREEN* \fIsp\fB, TERMINAL *\fIoterm\fB);\fR +\fBint putp_sp(SCREEN* \fIsp\fB, const char *\fIstr\fB);\fR +\fBint restartterm_sp(SCREEN* \fIsp\fB, NCURSES_CONST char*\fIterm\fB, int \fIfiledes\fB, int *\fIerrret\fB);\fR +\fBTERMINAL* set_curterm_sp(SCREEN* \fIsp\fB, TERMINAL*\fInterm\fB);\fR +\fBint tgetent_sp(SCREEN* \fIsp\fB, char *\fIbp\fB, const char *\fIname\fB);\fR +\fBint tgetflag_sp(SCREEN* \fIsp\fB, const char *\fIcapname\fB);\fR +\fBint tgetnum_sp(SCREEN* \fIsp\fB, const char *\fIcapname\fB);\fR +\fBchar* tgetstr_sp(SCREEN* \fIsp\fB, const char *\fIcapname\fB, char **\fIarea\fB);\fR +\fBchar* tgoto_sp(SCREEN* \fIsp\fB, const char *\fIcapname\fB, int \fIcol\fB, int \fIrow\fB);\fR +\fBint tigetflag_sp(SCREEN* \fIsp\fB, const char *\fIcapname\fB);\fR +.sp +\fBint tigetnum_sp(SCREEN* \fIsp\fB, const char *\fIcapname\fB);\fR +\fBchar* tigetstr_sp(SCREEN* \fIsp\fB, const char *\fIcapname\fB);\fR +\fR/* may instead use 9 long parameters */\fR +\fBchar* tparm_sp(SCREEN* \fIsp\fB, const char *\fIstr\fB, ...);\fR +\fBint tputs_sp(SCREEN* \fIsp\fB, const char *\fIstr\fB, int \fIaffcnt\fB, NCURSES_SP_OUTC \fIputc\fB);\fR +.ad +.sp +\fB#include \fP +.sp +\fBNCURSES_CONST char* unctrl_sp(SCREEN* \fIsp\fB, chtype \fIc\fB);\fR +.ad +.SH DESCRIPTION +This implementation can be configured to provide a set of functions which +improve the ability to manage multiple screens. +This feature can be added to any of the configurations supported by ncurses; +it adds new entrypoints +without changing the meaning of any of the existing ones. +.\" *************************************************************************** +.SS IMPROVED FUNCTIONS +Most of the functions are new versions of existing functions. +A parameter is added at the front of the parameter list. +It is a SCREEN pointer. +.PP +The existing functions all use the current screen, +which is a static variable. +The extended functions use the specified screen, +thereby reducing the number of variables which must be modified +to update multiple screens. +.\" *************************************************************************** +.SS NEW FUNCTIONS +Here are the new functions: +.TP 5 +ceiling_panel +this returns a pointer to the topmost panel in the given screen. +.TP 5 +ground_panel +this returns a pointer to the lowest panel in the given screen. +.TP 5 +new_prescr +when creating a new screen, the library uses static variables which +have been preset, e.g., by \fBuse_env\fP(3), \fBfilter\fP(3), etc. +With the screen-pointer extension, +there are situations where it must create a current screen before +the unextended library does. +The \fBnew_prescr\fP function is used internally to handle these cases. +It is also provided as an entrypoint to allow applications to customize +the library initialization. +.\" *************************************************************************** +.SH NOTES +This extension introduces some new names: +.TP 5 +NCURSES_SP_FUNCS +This is set to the library patch-level number. +In the unextended library, this is zero (0), +to make it useful for checking if the extension is provided. +.TP 5 +NCURSES_SP_NAME +The new functions are named using the macro \fINCURSES_SP_NAME\fP, +which hides the actual implementation. +Currently this adds a \*(``_sp\*('' suffix +to the name of the unextended function. +This manual page indexes the extensions showing the full name. +However the proper usage of these functions uses the macro, +to provide for the possibility of changing the naming convention +for specific library configurations. +.TP 5 +NCURSES_SP_OUTC +This is a new function-pointer type to use in the screen-pointer functions +where an \fINCURSES_OUTC\fP is used in the unextended library. +.TP 5 +NCURSES_OUTC +This is a function-pointer type used for the cases where a function passes +characters to the output stream, e.g., \fBvidputs\fP(3). +.SH PORTABILITY +These routines are specific to ncurses. +They were not supported on Version 7, BSD or System V implementations. +It is recommended that any code depending on ncurses extensions +be conditioned using \fINCURSES_SP_FUNCS\fP. +.SH SEE ALSO +\fBcurses\fP(3), +\fBcurs_opaque\fP(3), +\fBcurs_threads\fP(3). diff --git a/lib/libcurses/curs_termattrs.3 b/lib/libcurses/curs_termattrs.3 index bbc9a1ffc8a..4b39e24e679 100644 --- a/lib/libcurses/curs_termattrs.3 +++ b/lib/libcurses/curs_termattrs.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_termattrs.3,v 1.8 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_termattrs.3,v 1.9 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2003,2007 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,109 +29,109 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_termattrs.3,v 1.8 2010/01/12 23:21:59 nicm Exp $ -.TH curs_termattrs 3 "" +.\" $Id: curs_termattrs.3,v 1.9 2023/10/17 09:52:08 nicm Exp $ +.TH curs_termattrs 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBbaudrate\fR, -\fBerasechar\fR, -\fBerasewchar\fR, -\fBhas_ic\fR, -\fBhas_il\fR, -\fBkillchar\fR, -\fBkillwchar\fR, -\fBlongname\fR, -\fBterm_attrs\fR, -\fBtermattrs\fR, -\fBtermname\fR - \fBcurses\fR environment query routines +\fBbaudrate\fP, +\fBerasechar\fP, +\fBerasewchar\fP, +\fBhas_ic\fP, +\fBhas_il\fP, +\fBkillchar\fP, +\fBkillwchar\fP, +\fBlongname\fP, +\fBterm_attrs\fP, +\fBtermattrs\fP, +\fBtermname\fP \- \fBcurses\fP environment query routines .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .PP -\fBint baudrate(void);\fR +\fBint baudrate(void);\fP .br -\fBchar erasechar(void);\fR +\fBchar erasechar(void);\fP .br -\fBint erasewchar(wchar_t *\fR\fIch\fR\fB);\fR +\fBint erasewchar(wchar_t *\fIch\fB);\fR .br -\fBbool has_ic(void);\fR +\fBbool has_ic(void);\fP .br -\fBbool has_il(void);\fR +\fBbool has_il(void);\fP .br -\fBchar killchar(void);\fR +\fBchar killchar(void);\fP .br -\fBint killwchar(wchar_t *\fR\fIch\fR\fB);\fR +\fBint killwchar(wchar_t *\fIch\fB);\fR .br -\fBchar *longname(void);\fR +\fBchar *longname(void);\fP .br -\fBattr_t term_attrs(void);\fR +\fBattr_t term_attrs(void);\fP .br -\fBchtype termattrs(void);\fR +\fBchtype termattrs(void);\fP .br -\fBchar *termname(void);\fR +\fBchar *termname(void);\fP .br .SH DESCRIPTION -The \fBbaudrate\fR routine returns the output speed of the terminal. The -number returned is in bits per second, for example \fB9600\fR, and is an +.SS baudrate +The \fBbaudrate\fP routine returns the output speed of the terminal. +The +number returned is in bits per second, for example \fB9600\fP, and is an integer. +.SS erasechar, erasewchar +The \fBerasechar\fP routine returns the user's current erase character. .PP -The \fBerasechar\fR routine returns the user's current erase character. -.PP -The \fBerasewchar\fR routine stores the current erase character -in the location referenced by \fIch\fR. +The \fBerasewchar\fP routine stores the current erase character +in the location referenced by \fIch\fP. If no erase character has been defined, the routine fails -and the location referenced by \fIch\fR is not changed. -.PP -The \fBhas_ic\fR routine is true if the terminal has insert- and delete- +and the location referenced by \fIch\fP is not changed. +.SS has_is, has_il +The \fBhas_ic\fP routine is true if the terminal has insert- and delete- character capabilities. .PP -The \fBhas_il\fR routine is true if the terminal has insert- and delete-line -capabilities, or can simulate them using scrolling regions. This might +The \fBhas_il\fP routine is true if the terminal has insert- and delete-line +capabilities, or can simulate them using scrolling regions. +This might be used to determine if it would be appropriate to turn on physical -scrolling using \fBscrollok\fR. -.PP -The \fBkillchar\fR routine returns the user's current line kill character. +scrolling using \fBscrollok\fP(3). +.SS killchar, killwchar +The \fBkillchar\fP routine returns the user's current line kill character. .PP -The \fBkillwchar\fR routine stores the current line-kill character -in the location referenced by \fIch\fR. +The \fBkillwchar\fP routine stores the current line-kill character +in the location referenced by \fIch\fP. If no line-kill character has been defined, -the routine fails and the location referenced by \fIch\fR is not changed. -.PP -The \fBlongname\fR routine returns a pointer to a static area -containing a verbose description of the current terminal. The maximum -length of a verbose description is 128 characters. It is defined only -after the call to \fBinitscr\fR or \fBnewterm\fR. The area is -overwritten by each call to \fBnewterm\fR and is not restored by -\fBset_term\fR, so the value should be saved between calls to -\fBnewterm\fR if \fBlongname\fR is going to be used with multiple +the routine fails and the location referenced by \fIch\fP is not changed. +.SS longname +The \fBlongname\fP routine returns a pointer to a static area +containing a verbose description of the current terminal. +The maximum +length of a verbose description is 128 characters. +It is defined only +after the call to \fBinitscr\fP or \fBnewterm\fP. The area is +overwritten by each call to \fBnewterm\fP and is not restored by +\fBset_term\fP, so the value should be saved between calls to +\fBnewterm\fP if \fBlongname\fP is going to be used with multiple terminals. -.PP +.SS termattrs, term_attrs If a given terminal does not support a video attribute that an -application program is trying to use, \fBcurses\fR may substitute a +application program is trying to use, \fBcurses\fP may substitute a different video attribute for it. -The \fBtermattrs\fR and \fBterm_attrs\fR functions -return a logical \fBOR\fR of all video attributes supported by the -terminal using \fIA_\fR and \fIWA_\fR constants respectively. -This information is useful when a \fBcurses\fR program +The \fBtermattrs\fP and \fBterm_attrs\fP functions +return a logical \fBOR\fP of all video attributes supported by the +terminal using \fBA_\fP and \fBWA_\fP constants respectively. +This information is useful when a \fBcurses\fP program needs complete control over the appearance of the screen. -.PP -The \fBtermname\fR routine returns the terminal name used by \fBsetupterm\fR. +.SS termname +The \fBtermname\fP routine returns the terminal name used by \fBsetupterm\fP. .SH RETURN VALUE -\fBlongname\fR and \fBtermname\fR return \fBNULL\fR on error. +\fBlongname\fP and \fBtermname\fP return \fBNULL\fP on error. .PP -Routines that return an integer return \fBERR\fR upon failure and \fBOK\fR -(SVr4 only specifies "an integer value other than \fBERR\fR") upon successful +Routines that return an integer return \fBERR\fP upon failure and \fBOK\fP +(SVr4 only specifies "an integer value other than \fBERR\fP") upon successful completion. .SH NOTES -Note that \fBtermattrs\fR may be a macro. +Note that \fBtermattrs\fP may be a macro. .SH PORTABILITY -The XSI Curses standard, Issue 4 describes these functions. It changes the -return type of \fBtermattrs\fR to the new type \fBattr_t\fR. -Most versions of curses truncate the result returned by \fBtermname\fR to +The XSI Curses standard, Issue 4 describes these functions. +It changes the +return type of \fBtermattrs\fP to the new type \fBattr_t\fP. +Most versions of curses truncate the result returned by \fBtermname\fP to 14 characters. .SH SEE ALSO -\fBcurses\fR(3), \fBcurs_initscr\fR(3), \fBcurs_outopts\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), \fBcurs_initscr\fP(3), \fBcurs_outopts\fP(3) diff --git a/lib/libcurses/curs_threads.3 b/lib/libcurses/curs_threads.3 new file mode 100644 index 00000000000..9d1b49c3e0f --- /dev/null +++ b/lib/libcurses/curs_threads.3 @@ -0,0 +1,604 @@ +'\" t +.\"*************************************************************************** +.\" Copyright 2021-2022,2023 Thomas E. Dickey * +.\" Copyright 2008-2015,2017 Free Software Foundation, Inc. * +.\" * +.\" Permission is hereby granted, free of charge, to any person obtaining a * +.\" copy of this software and associated documentation files (the * +.\" "Software"), to deal in the Software without restriction, including * +.\" without limitation the rights to use, copy, modify, merge, publish, * +.\" distribute, distribute with modifications, sublicense, and/or sell * +.\" copies of the Software, and to permit persons to whom the Software is * +.\" furnished to do so, subject to the following conditions: * +.\" * +.\" The above copyright notice and this permission notice shall be included * +.\" in all copies or substantial portions of the Software. * +.\" * +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * +.\" IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * +.\" DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * +.\" OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * +.\" THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +.\" * +.\" Except as contained in this notice, the name(s) of the above copyright * +.\" holders shall not be used in advertising or otherwise to promote the * +.\" sale, use or other dealings in this Software without prior written * +.\" authorization. * +.\"*************************************************************************** +.\" +.\" $Id: curs_threads.3,v 1.1 2023/10/17 09:52:08 nicm Exp $ +.TH curs_threads 3 2023-08-19 "ncurses 6.4" "Library calls" +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.na +.hy 0 +.SH NAME +\fBcurs_threads\fP \- \fBcurses\fP thread support +.ad +.hy +.SH SYNOPSIS +\fB#include \fP +.sp +\fBtypedef int (*NCURSES_WINDOW_CB)(WINDOW *, void *);\fP +.br +\fBtypedef int (*NCURSES_SCREEN_CB)(SCREEN *, void *);\fP +.sp +\fBint get_escdelay(void);\fP +.br +\fBint set_escdelay(int \fIms\fB);\fR +.br +\fBint set_tabsize(int \fIcols\fB);\fR +.sp +\fBint use_screen(SCREEN *\fIscr\fB, NCURSES_SCREEN_CB \fIfunc\fB, void *\fIdata\fB);\fR +.br +\fBint use_window(WINDOW *\fIwin\fB, NCURSES_WINDOW_CB \fIfunc\fB, void *\fIdata\fB);\fR +.SH DESCRIPTION +This implementation can be configured to provide rudimentary support +for multi-threaded applications. +This makes a different set of libraries, e.g., \fBlibncursest\fP since +the binary interfaces are different. +.PP +Rather than modify the interfaces to pass a thread specifier to +each function, it adds a few functions which can be used in any +configuration which hide the mutex's needed to prevent concurrent +use of the global variables when configured for threading. +.PP +In addition to forcing access to members of the \fBWINDOW\fP structure +to be via functions (see \fBcurs_opaque\fP(3)), +it makes functions of the common global variables, +e.g., +COLORS, +COLOR_PAIRS, +COLS, +ESCDELAY, +LINES, +TABSIZE +curscr, +newscr and +ttytype. +Those variables are maintained as read-only values, stored in the \fBSCREEN\fP +structure. +.PP +Even this is not enough to make a thread-safe application using curses. +A multi-threaded application would be expected to have threads updating +separate windows (within the same device), +or updating on separate screens (on different devices). +Also, a few of the global variables are considered writable by some +applications. +The functions described here address these special situations. +.PP +The ESCDELAY and TABSIZE global variables are modified by some applications. +To modify them in any configuration, +use the \fBset_escdelay\fP or \fBset_tabsize\fP functions. +Other global variables are not modifiable. +.PP +The \fBget_escdelay\fP function returns the value for ESCDELAY. +.PP +The \fBuse_window\fP and \fBuse_screen\fP functions provide coarse +granularity mutexes for their respective \fBWINDOW\fP and \fBSCREEN\fP +parameters, and call a user-supplied function, +passing it a \fIdata\fP parameter, +and returning the value from the user-supplied function to the application. +.\" *************************************************************************** +.SS USAGE +All of the ncurses library functions assume that the locale is not +altered during operation. +In addition, +they use data which is maintained within a hierarchy of scopes. +.RS 3 +.bP +global data, e.g., used in the low-level terminfo or termcap interfaces. +.bP +terminal data, e.g., associated with a call to \fBset_curterm\fP. +The terminal data are initialized when screens are created. +.bP +screen data, e.g., associated with a call to \fBnewterm\fP or \fBinitscr\fP. +.bP +window data, e.g., associated with a call to \fBnewwin\fP or \fBsubwin\fP. +Windows are associated with screens. +Pads are not necessarily associated with a particular screen. +.IP +Most curses applications operate on one or more windows within a single screen. +.bP +reentrant, i.e., it uses only the data passed as parameters. +.RE +.PP +This table lists the scope of data used for each symbol in the +ncurses library when it is configured to support threading: +.PP +.TS +center tab(/); +l l +l l . +Symbol/Scope += +BC/global +COLORS/screen (readonly) +COLOR_PAIR/reentrant +COLOR_PAIRS/screen (readonly) +COLS/screen (readonly) +ESCDELAY/screen (readonly, see \fBset_escdelay\fP) +LINES/screen (readonly) +PAIR_NUMBER/reentrant +PC/global +SP/global +TABSIZE/screen (readonly) +UP/global +acs_map/screen (readonly) +add_wch/window (stdscr) +add_wchnstr/window (stdscr) +add_wchstr/window (stdscr) +addch/window (stdscr) +addchnstr/window (stdscr) +addchstr/window (stdscr) +addnstr/window (stdscr) +addnwstr/window (stdscr) +addstr/window (stdscr) +addwstr/window (stdscr) +assume_default_colors/screen +attr_get/window (stdscr) +attr_off/window (stdscr) +attr_on/window (stdscr) +attr_set/window (stdscr) +attroff/window (stdscr) +attron/window (stdscr) +attrset/window (stdscr) +baudrate/screen +beep/screen +bkgd/window (stdscr) +bkgdset/window (stdscr) +bkgrnd/window (stdscr) +bkgrndset/window (stdscr) +boolcodes/global (readonly) +boolfnames/global (readonly) +boolnames/global (readonly) +border/window (stdscr) +border_set/window (stdscr) +box/window (stdscr) +box_set/window (stdscr) +can_change_color/terminal +cbreak/screen +chgat/window (stdscr) +clear/window (stdscr) +clearok/window +clrtobot/window (stdscr) +clrtoeol/window (stdscr) +color_content/screen +color_set/window (stdscr) +copywin/window locks(source, target) +cur_term/terminal +curs_set/screen +curscr/screen (readonly) +curses_version/global (readonly) +def_prog_mode/terminal +def_shell_mode/terminal +define_key/screen +del_curterm/screen +delay_output/screen +delch/window (stdscr) +deleteln/window (stdscr) +delscreen/global locks(screenlist, screen) +delwin/global locks(windowlist) +derwin/screen +doupdate/screen +dupwin/screen locks(window) +echo/screen +echo_wchar/window (stdscr) +echochar/window (stdscr) +endwin/screen +erase/window (stdscr) +erasechar/window (stdscr) +erasewchar/window (stdscr) +filter/global +flash/terminal +flushinp/screen +get_wch/screen (input-operation) +get_wstr/screen (input-operation) +getattrs/window +getbegx/window +getbegy/window +getbkgd/window +getbkgrnd/window +getcchar/reentrant +getch/screen (input-operation) +getcurx/window +getcury/window +getmaxx/window +getmaxy/window +getmouse/screen (input-operation) +getn_wstr/screen (input-operation) +getnstr/screen (input-operation) +getparx/window +getpary/window +getstr/screen (input-operation) +getwin/screen (input-operation) +halfdelay/screen +has_colors/terminal +has_ic/terminal +has_il/terminal +has_key/screen +hline/window (stdscr) +hline_set/window (stdscr) +idcok/window +idlok/window +immedok/window +in_wch/window (stdscr) +in_wchnstr/window (stdscr) +in_wchstr/window (stdscr) +inch/window (stdscr) +inchnstr/window (stdscr) +inchstr/window (stdscr) +init_color/screen +init_pair/screen +initscr/global locks(screenlist) +innstr/window (stdscr) +innwstr/window (stdscr) +ins_nwstr/window (stdscr) +ins_wch/window (stdscr) +ins_wstr/window (stdscr) +insch/window (stdscr) +insdelln/window (stdscr) +insertln/window (stdscr) +insnstr/window (stdscr) +insstr/window (stdscr) +instr/window (stdscr) +intrflush/terminal +inwstr/window (stdscr) +is_cleared/window +is_idcok/window +is_idlok/window +is_immedok/window +is_keypad/window +is_leaveok/window +is_linetouched/window +is_nodelay/window +is_notimeout/window +is_scrollok/window +is_syncok/window +is_term_resized/terminal +is_wintouched/window +isendwin/screen +key_defined/screen +key_name/global (static data) +keybound/screen +keyname/global (static data) +keyok/screen +keypad/window +killchar/terminal +killwchar/terminal +leaveok/window +longname/screen +mcprint/terminal +meta/screen +mouse_trafo/window (stdscr) +mouseinterval/screen +mousemask/screen +move/window (stdscr) +mvadd_wch/window (stdscr) +mvadd_wchnstr/window (stdscr) +mvadd_wchstr/window (stdscr) +mvaddch/window (stdscr) +mvaddchnstr/window (stdscr) +mvaddchstr/window (stdscr) +mvaddnstr/window (stdscr) +mvaddnwstr/window (stdscr) +mvaddstr/window (stdscr) +mvaddwstr/window (stdscr) +mvchgat/window (stdscr) +mvcur/screen +mvdelch/window (stdscr) +mvderwin/window (stdscr) +mvget_wch/screen (input-operation) +mvget_wstr/screen (input-operation) +mvgetch/screen (input-operation) +mvgetn_wstr/screen (input-operation) +mvgetnstr/screen (input-operation) +mvgetstr/screen (input-operation) +mvhline/window (stdscr) +mvhline_set/window (stdscr) +mvin_wch/window (stdscr) +mvin_wchnstr/window (stdscr) +mvin_wchstr/window (stdscr) +mvinch/window (stdscr) +mvinchnstr/window (stdscr) +mvinchstr/window (stdscr) +mvinnstr/window (stdscr) +mvinnwstr/window (stdscr) +mvins_nwstr/window (stdscr) +mvins_wch/window (stdscr) +mvins_wstr/window (stdscr) +mvinsch/window (stdscr) +mvinsnstr/window (stdscr) +mvinsstr/window (stdscr) +mvinstr/window (stdscr) +mvinwstr/window (stdscr) +mvprintw/window (stdscr) +mvscanw/screen +mvvline/window (stdscr) +mvvline_set/window (stdscr) +mvwadd_wch/window +mvwadd_wchnstr/window +mvwadd_wchstr/window +mvwaddch/window +mvwaddchnstr/window +mvwaddchstr/window +mvwaddnstr/window +mvwaddnwstr/window +mvwaddstr/window +mvwaddwstr/window +mvwchgat/window +mvwdelch/window +mvwget_wch/screen (input-operation) +mvwget_wstr/screen (input-operation) +mvwgetch/screen (input-operation) +mvwgetn_wstr/screen (input-operation) +mvwgetnstr/screen (input-operation) +mvwgetstr/screen (input-operation) +mvwhline/window +mvwhline_set/window +mvwin/window +mvwin_wch/window +mvwin_wchnstr/window +mvwin_wchstr/window +mvwinch/window +mvwinchnstr/window +mvwinchstr/window +mvwinnstr/window +mvwinnwstr/window +mvwins_nwstr/window +mvwins_wch/window +mvwins_wstr/window +mvwinsch/window +mvwinsnstr/window +mvwinsstr/window +mvwinstr/window +mvwinwstr/window +mvwprintw/window +mvwscanw/screen +mvwvline/window +mvwvline_set/window +napms/reentrant +newpad/global locks(windowlist) +newscr/screen (readonly) +newterm/global locks(screenlist) +newwin/global locks(windowlist) +nl/screen +nocbreak/screen +nodelay/window +noecho/screen +nofilter/global +nonl/screen +noqiflush/terminal +noraw/screen +notimeout/window +numcodes/global (readonly) +numfnames/global (readonly) +numnames/global (readonly) +ospeed/global +overlay/window locks(source, target) +overwrite/window locks(source, target) +pair_content/screen +pecho_wchar/screen +pechochar/screen +pnoutrefresh/screen +prefresh/screen +printw/window +putp/global +putwin/window +qiflush/terminal +raw/screen +redrawwin/window +refresh/screen +reset_prog_mode/screen +reset_shell_mode/screen +resetty/terminal +resize_term/screen locks(windowlist) +resizeterm/screen +restartterm/screen +ripoffline/global (static data) +savetty/terminal +scanw/screen +scr_dump/screen +scr_init/screen +scr_restore/screen +scr_set/screen +scrl/window (stdscr) +scroll/window +scrollok/window +set_curterm/screen +set_escdelay/screen +set_tabsize/screen +set_term/global locks(screenlist, screen) +setcchar/reentrant +setscrreg/window (stdscr) +setupterm/global +slk_attr/screen +slk_attr_off/screen +slk_attr_on/screen +slk_attr_set/screen +slk_attroff/screen +slk_attron/screen +slk_attrset/screen +slk_clear/screen +slk_color/screen +slk_init/screen +slk_label/screen +slk_noutrefresh/screen +slk_refresh/screen +slk_restore/screen +slk_set/screen +slk_touch/screen +slk_wset/screen +standend/window +standout/window +start_color/screen +stdscr/screen (readonly) +strcodes/global (readonly) +strfnames/global (readonly) +strnames/global (readonly) +subpad/window +subwin/window +syncok/window +term_attrs/screen +termattrs/screen +termname/terminal +tgetent/global +tgetflag/global +tgetnum/global +tgetstr/global +tgoto/global +tigetflag/terminal +tigetnum/terminal +tigetstr/terminal +timeout/window (stdscr) +touchline/window +touchwin/window +tparm/global (static data) +tputs/screen +trace/global (static data) +ttytype/screen (readonly) +typeahead/screen +unctrl/screen +unget_wch/screen (input-operation) +ungetch/screen (input-operation) +ungetmouse/screen (input-operation) +untouchwin/window +use_default_colors/screen +use_env/global (static data) +use_extended_names/global (static data) +use_legacy_coding/screen +use_screen/global locks(screenlist, screen) +use_window/global locks(windowlist, window) +vid_attr/screen +vid_puts/screen +vidattr/screen +vidputs/screen +vline/window (stdscr) +vline_set/window (stdscr) +vw_printw/window +vw_scanw/screen +vwprintw/window +vwscanw/screen +wadd_wch/window +wadd_wchnstr/window +wadd_wchstr/window +waddch/window +waddchnstr/window +waddchstr/window +waddnstr/window +waddnwstr/window +waddstr/window +waddwstr/window +wattr_get/window +wattr_off/window +wattr_on/window +wattr_set/window +wattroff/window +wattron/window +wattrset/window +wbkgd/window +wbkgdset/window +wbkgrnd/window +wbkgrndset/window +wborder/window +wborder_set/window +wchgat/window +wclear/window +wclrtobot/window +wclrtoeol/window +wcolor_set/window +wcursyncup/screen (affects window plus parents) +wdelch/window +wdeleteln/window +wecho_wchar/window +wechochar/window +wenclose/window +werase/window +wget_wch/screen (input-operation) +wget_wstr/screen (input-operation) +wgetbkgrnd/window +wgetch/screen (input-operation) +wgetdelay/window +wgetn_wstr/screen (input-operation) +wgetnstr/screen (input-operation) +wgetparent/window +wgetscrreg/window +wgetstr/screen (input-operation) +whline/window +whline_set/window +win_wch/window +win_wchnstr/window +win_wchstr/window +winch/window +winchnstr/window +winchstr/window +winnstr/window +winnwstr/window +wins_nwstr/window +wins_wch/window +wins_wstr/window +winsch/window +winsdelln/window +winsertln/window +winsnstr/window +winsstr/window +winstr/window +winwstr/window +wmouse_trafo/window +wmove/window +wnoutrefresh/screen +wprintw/window +wredrawln/window +wrefresh/screen +wresize/window locks(windowlist) +wscanw/screen +wscrl/window +wsetscrreg/window +wstandend/window +wstandout/window +wsyncdown/screen (affects window plus parents) +wsyncup/screen (affects window plus parents) +wtimeout/window +wtouchln/window +wunctrl/global (static data) +wvline/window +wvline_set/window +.TE +.\" *************************************************************************** +.SH RETURN VALUE +These functions all return \fBTRUE\fP or \fBFALSE\fP, except as noted. +.SH NOTES +Both a macro and a function are provided for each name. +.SH PORTABILITY +These routines are specific to ncurses. +They were not supported on Version 7, BSD or System V implementations. +It is recommended that any code depending on ncurses extensions +be conditioned using NCURSES_VERSION. +.SH SEE ALSO +\fBcurses\fP(3), +\fBcurs_opaque\fP(3), +\fBcurs_variables\fP(3). diff --git a/lib/libcurses/curs_touch.3 b/lib/libcurses/curs_touch.3 index e18a0bf7e42..19f420325cc 100644 --- a/lib/libcurses/curs_touch.3 +++ b/lib/libcurses/curs_touch.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_touch.3,v 1.7 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_touch.3,v 1.8 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2015,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,91 +29,101 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_touch.3,v 1.7 2010/01/12 23:21:59 nicm Exp $ -.TH curs_touch 3 "" +.\" $Id: curs_touch.3,v 1.8 2023/10/17 09:52:08 nicm Exp $ +.TH curs_touch 3 2023-07-01 "ncurses 6.4" "Library calls" .na .hy 0 .SH NAME -\fBtouchwin\fR, -\fBtouchline\fR, -\fBuntouchwin\fR, -\fBwtouchln\fR, -\fBis_linetouched\fR, -\fBis_wintouched\fR - \fBcurses\fR refresh control routines +\fBtouchwin\fP, +\fBtouchline\fP, +\fBuntouchwin\fP, +\fBwtouchln\fP, +\fBis_linetouched\fP, +\fBis_wintouched\fP \- \fBcurses\fP refresh control routines .ad .hy .SH SYNOPSIS -\fB#include \fR +\fB#include \fP +.sp +\fBint touchline(WINDOW *\fIwin\fB, int \fIstart\fB, int \fIcount\fB);\fR +.sp +\fBint touchwin(WINDOW *\fIwin\fB);\fR .br -\fBint touchwin(WINDOW *win);\fR -.br -\fBint touchline(WINDOW *win, int start, int count);\fR -.br -\fBint untouchwin(WINDOW *win);\fR -.br -\fBint wtouchln(WINDOW *win, int y, int n, int changed);\fR -.br -\fBbool is_linetouched(WINDOW *win, int line);\fR -.br -\fBbool is_wintouched(WINDOW *win);\fR +\fBint wtouchln(WINDOW *\fIwin\fB, int \fIy\fB, int \fIn\fB, int \fIchanged\fB);\fR +.sp +\fBint untouchwin(WINDOW *\fIwin\fB);\fR +.sp +\fBbool is_linetouched(WINDOW *\fIwin\fB, int \fIline\fB);\fR .br +\fBbool is_wintouched(WINDOW *\fIwin\fB);\fR .SH DESCRIPTION -The \fBtouchwin\fR and \fBtouchline\fR routines throw away all +The \fBtouchwin\fP and \fBtouchline\fP routines throw away all optimization information about which parts of the window have been -touched, by pretending that the entire window has been drawn on. This +touched, by pretending that the entire window has been drawn on. +This is sometimes necessary when using overlapping windows, since a change to one window affects the other window, but the records of which lines -have been changed in the other window do not reflect the change. The -routine \fBtouchline\fR only pretends that \fIcount\fR lines have been -changed, beginning with line \fIstart\fR. +have been changed in the other window do not reflect the change. +The +routine \fBtouchline\fP only pretends that \fIcount\fP lines have been +changed, beginning with line \fIstart\fP. .PP -The \fBuntouchwin\fR routine marks all lines in the window as unchanged since -the last call to \fBwrefresh\fR. +The \fBuntouchwin\fP routine marks all lines in the window as unchanged since +the last call to \fBwrefresh\fP. .PP -The \fBwtouchln\fR routine makes \fIn\fR lines in the window, starting -at line \fIy\fR, look as if they have (\fIchanged\fR\fB=1\fR) or have -not (\fIchanged\fR\fB=0\fR) been changed since the last call to -\fBwrefresh\fR. +The \fBwtouchln\fP routine makes \fIn\fP lines in the window, starting +at line \fIy\fR, look as if they have (\fIchanged\fB=1\fR) or have +not (\fIchanged\fB=0\fR) been changed since the last call to +\fBwrefresh\fP. .PP -The \fBis_linetouched\fR and \fBis_wintouched\fR routines return -\fBTRUE\fR if the specified line/window was modified since the last -call to \fBwrefresh\fR; otherwise they return \fBFALSE\fR. In -addition, \fBis_linetouched\fR returns \fBERR\fR if \fIline\fR is not +The \fBis_linetouched\fP and \fBis_wintouched\fP routines return +\fBTRUE\fP if the specified line/window was modified since the last +call to \fBwrefresh\fP; otherwise they return \fBFALSE\fP. In +addition, \fBis_linetouched\fP returns \fBERR\fP if \fIline\fP is not valid for the given window. .SH RETURN VALUE -All routines return the integer \fBERR\fR upon failure and an integer value -other than \fBERR\fR upon successful completion, unless otherwise noted in the +All routines return the integer \fBERR\fP upon failure and an integer value +other than \fBERR\fP upon successful completion, unless otherwise noted in the preceding routine descriptions. .PP X/Open does not define any error conditions. In this implementation -.RS +.RS 3 .TP 5 \fBis_linetouched\fP -returns an error +returns an error if the window pointer is null, or if the line number is outside the window. -Note that ERR is distinct from TRUE and FALSE, which are the normal return values of this function. +.IP +The constant \fBERR\fP is distinct from \fBTRUE\fP and \fBFALSE\fP, +which are the normal return values of this function. +Because the function returns a \fBbool\fP, +returning \fBERR\fP (which is neither \fBTRUE\fP nor \fBFALSE\fP) +may not be supported by the compiler. +.IP +To provide error-checking and also match the X/Open function prototype, +the \fBERR\fP is provided by a macro named \fBis_linetouched\fP. +The actual function returns \fBFALSE\fP when it detects an error. .TP 5 \fBwtouchln\fP -returns an error +returns an error if the window pointer is null, or if the line number is outside the window. .RE .SH PORTABILITY -The XSI Curses standard, Issue 4 describes these functions. +These functions were introduced by SVr4. +The Solaris curses header file, +for instance, defines both an actual function and macro for each. +The macros give the same result as the actual functions. +SVr4 curses does not check the window parameter \fIwin\fP to ensure +that it is not \fBNULL\fP; +otherwise this implementation behaves the same as SVr4. .PP -Some historic curses implementations had, as an undocumented feature, the -ability to do the equivalent of \fBclearok(..., 1)\fR by saying -\fBtouchwin(stdscr)\fR or \fBclear(stdscr)\fR. This will not work under -ncurses. +The XSI Curses standard, Issue 4 describes these functions, +but defines no error conditions. .SH NOTES -Note that all routines except \fBwtouchln\fR may be macros. +All of these routines except \fBwtouchln\fP may be macros. .SH SEE ALSO -\fBcurses\fR(3), \fBcurs_refresh\fR(3). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_refresh\fP(3), +\fBcurs_variables\fP(3). diff --git a/lib/libcurses/curs_util.3 b/lib/libcurses/curs_util.3 index d88cc4c5bc7..01a69466f84 100644 --- a/lib/libcurses/curs_util.3 +++ b/lib/libcurses/curs_util.3 @@ -1,7 +1,9 @@ -.\" $OpenBSD: curs_util.3,v 1.6 2010/01/12 23:21:59 nicm Exp $ +'\" t +.\" $OpenBSD: curs_util.3,v 1.7 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2015,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,98 +30,133 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_util.3,v 1.6 2010/01/12 23:21:59 nicm Exp $ -.TH curs_util 3 "" +.\" $Id: curs_util.3,v 1.7 2023/10/17 09:52:08 nicm Exp $ +.TH curs_util 3 2023-08-19 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .na .hy 0 .SH NAME -\fBdelay_output\fR, -\fBfilter\fR, -\fBflushinp\fR, -\fBgetwin\fR, -\fBkey_name\fR, -\fBkeyname\fR, -\fBnofilter\fR, -\fBputwin\fR, -\fBunctrl\fR, -\fBuse_env\fR, -\fBwunctrl\fR - miscellaneous \fBcurses\fR utility routines +\fBdelay_output\fP, +\fBfilter\fP, +\fBflushinp\fP, +\fBgetwin\fP, +\fBkey_name\fP, +\fBkeyname\fP, +\fBnofilter\fP, +\fBputwin\fP, +\fBunctrl\fP, +\fBuse_env\fP, +\fBuse_tioctl\fP, +\fBwunctrl\fP \- miscellaneous \fBcurses\fP utility routines .ad .hy .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBchar *unctrl(chtype c);\fR +\fBconst char *unctrl(chtype \fIc\fB);\fR .br -\fBwchar_t *wunctrl(cchar_t *c);\fR -.br -\fBchar *keyname(int c);\fR -.br -\fBchar *key_name(wchar_t w);\fR -.br -\fBvoid filter(void);\fR -.br -\fBvoid nofilter(void);\fR -.br -\fBvoid use_env(bool f);\fR +\fBwchar_t *wunctrl(cchar_t *\fIc\fB);\fR +.sp +\fBconst char *keyname(int \fIc\fB);\fR .br -\fBint putwin(WINDOW *win, FILE *filep);\fR +\fBconst char *key_name(wchar_t \fIw\fB);\fR +.sp +\fBvoid filter(void);\fP +.sp +\fBvoid use_env(bool \fIf\fB);\fR +.sp +\fBint putwin(WINDOW *\fIwin\fB, FILE *\fIfilep\fB);\fR .br -\fBWINDOW *getwin(FILE *filep);\fR +\fBWINDOW *getwin(FILE *\fIfilep\fB);\fR +.sp +\fBint delay_output(int \fIms\fB);\fR .br -\fBint delay_output(int ms);\fR +\fBint flushinp(void);\fP +.sp +/* extensions */ .br -\fBint flushinp(void);\fR +\fBvoid nofilter(void);\fP .br +\fBvoid use_tioctl(bool \fIf\fB);\fR .SH DESCRIPTION -The \fBunctrl\fR routine returns a character string which is a printable -representation of the character \fIc\fR, ignoring attributes. -Control characters are displayed in the \fB^\fR\fIX\fR notation. +.SS unctrl +The \fBunctrl\fP routine returns a character string which is a printable +representation of the character \fIc\fP: +.bP +Printable characters are displayed as themselves, +e.g., a one-character string containing the key. +.bP +Control characters are displayed in the \fB^\fIX\fR notation. +.bP Printing characters are displayed as is. -The corresponding \fBwunctrl\fR returns a printable representation of -a wide-character. -.PP -The \fBkeyname\fR routine returns a character string corresponding to the key \fIc\fR: -.RS 3 -.TP 3 -- -Printable characters are displayed as themselves, e.g., a one-character string containing the key. -.TP 3 -- -Control characters are displayed in the \fB^\fR\fIX\fR notation. -.TP 3 -- +.bP DEL (character 127) is displayed as \fB^?\fP. -.TP 3 -- +.bP Values above 128 are either meta characters (if the screen has not been initialized, -or if \fBmeta\fP has been called with a TRUE parameter), -shown in the \fBM-\fR\fIX\fR notation, +or if \fBmeta\fP(3) has been called with a \fBTRUE\fP parameter), +shown in the \fBM\-\fIX\fR notation, or are displayed as themselves. In the latter case, the values may not be printable; this follows the X/Open specification. -.TP 3 -- -Values above 256 may be the names of the names of function keys. -.TP 3 -- -Otherwise (if there is no corresponding name) the function returns null, -to denote an error. -X/Open also lists an "UNKNOWN KEY" return value, which some implementations -return rather than null. -.RE -.LP -The corresponding \fBkey_name\fR returns a character string corresponding -to the wide-character value \fIw\fR. -The two functions do not return the same set of strings; -the latter returns null where the former would display a meta character. .PP -The \fBfilter\fR routine, if used, must be called before \fBinitscr\fR or -\fBnewterm\fR are called. The effect is that, during those calls, \fBLINES\fR -is set to 1; the capabilities \fBclear\fR, \fBcup\fR, \fBcud\fR, \fBcud1\fR, -\fBcuu1\fR, \fBcuu\fR, \fBvpa\fR are disabled; and the \fBhome\fR string is -set to the value of \fBcr\fR. +The corresponding \fBwunctrl\fP returns a printable representation of +a complex character \fIc\fP. +.PP +In both \fBunctrl\fP and \fBwunctrl\fP the attributes and color associated +with the character parameter are ignored. +.SS keyname/key_name +The \fBkeyname\fP routine returns a character string +corresponding to the key \fIc\fP. +Key codes are different from character codes. +.bP +Key codes below 256 are characters. +They are displayed using \fBunctrl\fP. +.bP +Values above 256 may be the codes for function keys. +The function key name is displayed. +.bP +Otherwise (if there is no corresponding name and the key is not a character) +the function returns null, to denote an error. +X/Open also lists an \*(``UNKNOWN KEY\*('' return value, +which some implementations return rather than null. +.LP +The corresponding \fBkey_name\fP returns +a multibyte character string corresponding +to the wide-character value \fIw\fP. +The two functions (\fBkeyname\fP and \fBkey_name\fP) +do not return the same set of strings: +.bP +\fBkeyname\fP returns null where \fBkey_name\fP would display a meta character. +.bP +\fBkey_name\fP does not return the name of a function key. +.SS filter/nofilter +The \fBfilter\fP routine, if used, must be called before \fBinitscr\fP or +\fBnewterm\fP are called. +Calling \fBfilter\fP causes these changes in initialization: +.bP +\fBLINES\fP is set to 1; +.bP +the capabilities +\fBclear\fP, +\fBcud1\fP, +\fBcud\fP, +\fBcup\fP, +\fBcuu1\fP, +\fBcuu\fP, +\fBvpa\fP +are disabled; +.bP +the capability \fBed\fP is disabled if \fBbce\fP is set; +.bP +and the \fBhome\fP string is set to the value of \fBcr\fP. .PP The \fBnofilter\fP routine cancels the effect of a preceding \fBfilter\fP call. @@ -127,134 +164,248 @@ That allows the caller to initialize a screen on a different device, using a different value of \fB$TERM\fP. The limitation arises because the \fBfilter\fP routine modifies the in-memory copy of the terminal information. +.SS use_env +The \fBuse_env\fP routine, if used, +should be called before \fBinitscr\fP or +\fBnewterm\fP are called +(because those compute the screen size). +It modifies the way \fBncurses\fP treats environment variables +when determining the screen size. +.bP +Normally \fBncurses\fP looks first at the terminal database for the screen size. +.IP +If \fBuse_env\fP was called with \fBFALSE\fP for parameter, +it stops here unless +\fBuse_tioctl\fP was also called with \fBTRUE\fP for parameter. +.bP +Then it asks for the screen size via operating system calls. +If successful, +it overrides the values from the terminal database. +.bP +Finally (unless \fBuse_env\fP was called with \fBFALSE\fP parameter), +\fBncurses\fP examines the \fBLINES\fP or \fBCOLUMNS\fP environment variables, +using a value in those to override the results +from the operating system or terminal database. +.IP +\fBNcurses\fP also updates the screen size in response to \fBSIGWINCH\fP, +unless overridden by the \fBLINES\fP or \fBCOLUMNS\fP environment variables, +.SS use_tioctl +The \fBuse_tioctl\fP routine, if used, +should be called before \fBinitscr\fP or \fBnewterm\fP are called +(because those compute the screen size). +After \fBuse_tioctl\fP is called with \fBTRUE\fP as an argument, +\fBncurses\fP modifies the last step in its computation +of screen size as follows: +.bP +checks if the \fBLINES\fP and \fBCOLUMNS\fP environment variables +are set to a number greater than zero. +.bP +for each, \fBncurses\fP updates the corresponding environment variable +with the value that it has obtained via operating system call +or from the terminal database. +.bP +\fBncurses\fP re-fetches the value of the environment variables so that +it is still the environment variables which set the screen size. .PP -The \fBuse_env\fR routine, if used, is called before \fBinitscr\fR or -\fBnewterm\fR are called. When called with \fBFALSE\fR as an -argument, the values of \fBlines\fR and \fBcolumns\fR specified in the -\fIterminfo\fR database will be used, even if environment variables -\fBLINES\fR and \fBCOLUMNS\fR (used by default) are set, or if -\fBcurses\fR is running in a window (in which case default behavior -would be to use the window size if \fBLINES\fR and \fBCOLUMNS\fR are -not set). -Note that setting \fBLINES\fR or \fBCOLUMNS\fR overrides the -corresponding size which may be obtained from the operating system. -.PP -The \fBputwin\fR routine writes all data associated with window \fIwin\fR into -the file to which \fIfilep\fR points. This information can be later retrieved -using the \fBgetwin\fR function. +The \fBuse_env\fP and \fBuse_tioctl\fP routines combine as +summarized here: .PP -The \fBgetwin\fR routine reads window related data stored in the file by -\fBputwin\fR. The routine then creates and initializes a new window using that -data. It returns a pointer to the new window. +.TS +center tab(/); +l l l +_ _ _ +lw7 lw7 lw40. +\fBuse_env\fP/\fBuse_tioctl\fP/\fBSummary\fP +TRUE/FALSE/T{ +This is the default behavior. +\fBncurses\fP uses operating system calls +unless overridden by $LINES or $COLUMNS environment variables. +T} +TRUE/TRUE/T{ +\fBncurses\fP updates $LINES and $COLUMNS based on operating system calls. +T} +FALSE/TRUE/T{ +\fBncurses\fP ignores $LINES and $COLUMNS, +uses operating system calls to obtain size. +T} +FALSE/FALSE/T{ +\fBncurses\fP relies on the terminal database to determine size. +T} +.TE +.SS putwin/getwin +The \fBputwin\fP routine writes all data associated +with window (or pad) \fIwin\fP into +the file to which \fIfilep\fP points. +This information can be later retrieved +using the \fBgetwin\fP function. .PP -The \fBdelay_output\fR routine inserts an \fIms\fR millisecond pause -in output. This routine should not be used extensively because +The \fBgetwin\fP routine reads window related data stored in the file by +\fBputwin\fP. +The routine then creates and initializes a new window using that +data. +It returns a pointer to the new window. +There are a few caveats: +.bP +the data written is a copy of the \fBWINDOW\fP structure, +and its associated character cells. +The format differs between the wide-character (\fBncursesw\fP) and +non-wide (\fBncurses\fP) libraries. +You can transfer data between the two, however. +.bP +the retrieved window is always created as a top-level window (or pad), +rather than a subwindow. +.bP +the window's character cells contain the color pair \fIvalue\fP, +but not the actual color \fInumbers\fP. +If cells in the retrieved window use color pairs which have not been +created in the application using \fBinit_pair\fP, +they will not be colored when the window is refreshed. +.SS delay_output +The \fBdelay_output\fP routine inserts an \fIms\fP millisecond pause +in output. +This routine should not be used extensively because padding characters are used rather than a CPU pause. -If no padding character is specified, this uses \fBnapms\fR to perform the delay. -.PP -The \fBflushinp\fR routine throws away any typeahead that has been typed by the +If no padding character is specified, +this uses \fBnapms\fP to perform the delay. +.SS flushinp +The \fBflushinp\fP routine throws away any typeahead that has been typed by the user and has not yet been read by the program. .SH RETURN VALUE -Except for \fBflushinp\fR, routines that return an integer return \fBERR\fR -upon failure and \fBOK\fR (SVr4 specifies only "an integer value other than -\fBERR\fR") upon successful completion. +Except for \fBflushinp\fP, routines that return an integer return \fBERR\fP +upon failure and \fBOK\fP (SVr4 specifies only "an integer value other than +\fBERR\fP") upon successful completion. .PP -Routines that return pointers return \fBNULL\fR on error. +Routines that return pointers return \fBNULL\fP on error. .PP X/Open does not define any error conditions. In this implementation .RS 3 .TP 5 -\fBflushinp\fR -returns an error if the terminal was not initialized. -.TP 5 -\fBmeta\fR +\fBflushinp\fP returns an error if the terminal was not initialized. .TP 5 \fBputwin\fP returns an error if the associated \fBfwrite\fP calls return an error. .RE .SH PORTABILITY +.SS filter +The SVr4 documentation describes the action of \fBfilter\fP only in the vaguest +terms. +The description here is adapted from the XSI Curses standard (which +erroneously fails to describe the disabling of \fBcuu\fP). +.SS keyname +The \fBkeyname\fP function may return the names of user-defined +string capabilities which are defined in the terminfo entry via the \fB\-x\fP +option of \fBtic\fP. +This implementation automatically assigns at run-time keycodes to +user-defined strings which begin with \*(``k\*(''. +The keycodes start at KEY_MAX, but are not guaranteed to be +the same value for different runs because user-defined codes are +merged from all terminal descriptions which have been loaded. +The \fBuse_extended_names\fP(3) function controls whether this data is +loaded when the terminal description is read by the library. +.SS nofilter/use_tioctl +The \fBnofilter\fP and \fBuse_tioctl\fP routines are specific to \fBncurses\fP. +They were not supported on Version 7, BSD or System V implementations. +It is recommended that any code depending on \fBncurses\fP extensions +be conditioned using NCURSES_VERSION. +.SS putwin/getwin file-format +The \fBputwin\fP and \fBgetwin\fP functions have several issues with +portability: +.bP +The files written and read by these functions +use an implementation-specific format. +Although the format is an obvious target for standardization, +it has been overlooked. +.IP +Interestingly enough, according to the copyright dates in Solaris source, +the functions (along with \fBscr_init\fP, etc.) originated with +the University of California, Berkeley (in 1982) +and were later (in 1988) incorporated into SVr4. +Oddly, there are no such functions in the 4.3BSD curses sources. +.bP +Most implementations simply dump the binary \fBWINDOW\fP structure to the file. +These include SVr4 curses, NetBSD and PDCurses, +as well as older \fBncurses\fP versions. +This implementation +(as well as the X/Open variant of Solaris curses, dated 1995) +uses textual dumps. +.IP +The implementations which use binary dumps use block-I/O +(the \fBfwrite\fP and \fBfread\fP functions). +Those that use textual dumps use buffered-I/O. +A few applications may happen to write extra data in the file using +these functions. +Doing that can run into problems mixing block- and buffered-I/O. +This implementation reduces the problem on writes by flushing the output. +However, reading from a file written using mixed schemes may not be successful. +.SS unctrl/wunctrl The XSI Curses standard, Issue 4 describes these functions. -It states that \fBunctrl\fR and \fBwunctrl\fR will return a null pointer if +It states that \fBunctrl\fP and \fBwunctrl\fP will return a null pointer if unsuccessful, but does not define any error conditions. This implementation checks for three cases: -.RS -.TP 5 -- -the parameter is a 7-bit US-ASCII code. +.bP +the parameter is a 7-bit US\-ASCII code. This is the case that X/Open Curses documented. -.TP 5 -- -the parameter is in the range 128-159, i.e., a C1 control code. -If \fBuse_legacy_coding\fP has been called with a \fB2\fP parameter, +.bP +the parameter is in the range 128\-159, i.e., a C1 control code. +If \fBuse_legacy_coding\fP(3) has been called with a \fB2\fP parameter, \fBunctrl\fP returns the parameter, i.e., a one-character string with the parameter as the first character. -Otherwise, it returns ``~@'', ``~A'', etc., analogous to ``^@'', ``^A'', C0 controls. +Otherwise, it returns \*(``~@\*('', \*(``~A\*('', etc., +analogous to \*(``^@\*('', \*(``^A\*('', C0 controls. .IP X/Open Curses does not document whether \fBunctrl\fP can be called before initializing curses. This implementation permits that, -and returns the ``~@'', etc., values in that case. -.TP 5 -- +and returns the \*(``~@\*('', etc., values in that case. +.bP parameter values outside the 0 to 255 range. \fBunctrl\fP returns a null pointer. -.RE -.PP -The SVr4 documentation describes the action of \fBfilter\fR only in the vaguest -terms. The description here is adapted from the XSI Curses standard (which -erroneously fails to describe the disabling of \fBcuu\fR). .PP -The strings returned by \fBunctrl\fR in this implementation are determined +The strings returned by \fBunctrl\fP in this implementation are determined at compile time, -showing C1 controls from the upper-128 codes with a `~' prefix rather than `^'. +showing C1 controls from the upper-128 codes +with a \*(``~\*('' prefix rather than \*(``^\*(''. Other implementations have different conventions. -For example, they may show both sets of control characters with `^', +For example, they may show both sets of control characters with \*(``^\*('', and strip the parameter to 7 bits. Or they may ignore C1 controls and treat all of the upper-128 codes as printable. This implementation uses 8 bits but does not modify the string to reflect locale. -The \fBuse_legacy_coding\fP function allows the caller to +The \fBuse_legacy_coding\fP(3) function allows the caller to change the output of \fBunctrl\fP. .PP -Likewise, the \fBmeta\fP function allows the caller to change the +Likewise, the \fBmeta\fP(3) function allows the caller to change the output of \fBkeyname\fP, i.e., -it determines whether to use the `M-' prefix -for ``meta'' keys (codes in the range 128 to 255). -Both \fBuse_legacy_coding\fP and \fBmeta\fP succeed only after -curses is initialized. +it determines whether to use the \*(``M\-\*('' prefix +for \*(``meta\*('' keys (codes in the range 128 to 255). +Both \fBuse_legacy_coding\fP(3) and \fBmeta\fP(3) succeed only after +curses is initialized. X/Open Curses does not document the treatment of codes 128 to 159. -When treating them as ``meta'' keys +When treating them as \*(``meta\*('' keys (or if \fBkeyname\fP is called before initializing curses), -this implementation returns strings ``M-^@'', ``M-^A'', etc. -.PP -The \fBkeyname\fP function may return the names of user-defined -string capabilities which are defined in the terminfo entry via the \fB-x\fP -option of \fBtic\fP. -This implementation automatically assigns at run-time keycodes to -user-defined strings which begin with "k". -The keycodes start at KEY_MAX, but are not guaranteed to be -the same value for different runs because user-defined codes are -merged from all terminal descriptions which have been loaded. -The \fBuse_extended_names\fP function controls whether this data is -loaded when the terminal description is read by the library. +this implementation returns strings \*(``M\-^@\*('', \*(``M\-^A\*('', etc. .PP -The \fBnofilter\fP routine is specific to ncurses. -It was not supported on Version 7, BSD or System V implementations. -It is recommended that any code depending on ncurses extensions -be conditioned using NCURSES_VERSION. +X/Open Curses documents \fBunctrl\fP as declared in \fB\fP, +which \fBncurses\fP does. +However, \fBncurses\fP' \fB\fP includes \fB\fP, +matching the behavior of SVr4 curses. +Other implementations may not do that. +.SS use_env/use_tioctl +If \fBncurses\fP is configured to provide the sp-functions extension, +the state of \fBuse_env\fP and \fBuse_tioctl\fP may be updated before +creating each \fIscreen\fP rather than once only +(\fBcurs_sp_funcs\fP(3)). +This feature of \fBuse_env\fP +is not provided by other implementations of curses. .SH SEE ALSO -\fBlegacy_coding\fR(3), -\fBcurses\fR(3), -\fBcurs_initscr\fR(3), -\fBcurs_kernel\fR(3), -\fBcurs_scr_dump\fR(3), -\fBlegacy_coding\fR(3). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_initscr\fP(3), +\fBcurs_inopts\fP(3), +\fBcurs_kernel\fP(3), +\fBcurs_scr_dump\fP(3), +\fBcurs_sp_funcs\fP(3), +\fBcurs_variables\fP(3), +\fBlegacy_coding\fP(3). diff --git a/lib/libcurses/curs_variables.3 b/lib/libcurses/curs_variables.3 new file mode 100644 index 00000000000..658502b291e --- /dev/null +++ b/lib/libcurses/curs_variables.3 @@ -0,0 +1,188 @@ +.\"*************************************************************************** +.\" Copyright 2018-2020,2021 Thomas E. Dickey * +.\" Copyright 2010-2015,2017 Free Software Foundation, Inc. * +.\" * +.\" Permission is hereby granted, free of charge, to any person obtaining a * +.\" copy of this software and associated documentation files (the * +.\" "Software"), to deal in the Software without restriction, including * +.\" without limitation the rights to use, copy, modify, merge, publish, * +.\" distribute, distribute with modifications, sublicense, and/or sell * +.\" copies of the Software, and to permit persons to whom the Software is * +.\" furnished to do so, subject to the following conditions: * +.\" * +.\" The above copyright notice and this permission notice shall be included * +.\" in all copies or substantial portions of the Software. * +.\" * +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * +.\" IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * +.\" DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * +.\" OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * +.\" THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +.\" * +.\" Except as contained in this notice, the name(s) of the above copyright * +.\" holders shall not be used in advertising or otherwise to promote the * +.\" sale, use or other dealings in this Software without prior written * +.\" authorization. * +.\"*************************************************************************** +.\" +.\" $Id: curs_variables.3,v 1.1 2023/10/17 09:52:08 nicm Exp $ +.TH curs_variables 3 2021-12-25 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.ds n 5 +.na +.hy 0 +.SH NAME +\fBCOLORS\fP, +\fBCOLOR_PAIRS\fP, +\fBCOLS\fP, +\fBESCDELAY\fP, +\fBLINES\fP, +\fBTABSIZE\fP, +\fBcurscr\fP, +\fBnewscr\fP, +\fBstdscr\fP +\- \fBcurses\fP global variables +.ad +.hy +.SH SYNOPSIS +.nf +\fB#include \fP +.PP +\fBint COLOR_PAIRS;\fP +.br +\fBint COLORS;\fP +.br +\fBint COLS;\fP +.br +\fBint ESCDELAY;\fP +.br +\fBint LINES;\fP +.br +\fBint TABSIZE;\fP +.br +\fBWINDOW * curscr;\fP +.br +\fBWINDOW * newscr;\fP +.br +\fBWINDOW * stdscr;\fP +.fi +.SH DESCRIPTION +This page summarizes variables provided by the \fBcurses\fP library. +A more complete description is given in the \fBcurses\fP(3) manual page. +.PP +Depending on the configuration, these may be actual variables, +or macros (see \fBcurs_threads\fP(3) and \fBcurs_opaque\fP(3)) +which provide read-only access to \fIcurses\fP's state. +In either case, applications should treat them as read-only to avoid +confusing the library. +.SS COLOR_PAIRS +After initializing curses, this variable contains the number of color pairs +which the terminal can support. +Usually the number of color pairs will be the product \fBCOLORS\fP*\fBCOLORS\fP, +however this is not always true: +.bP +a few terminals use HLS colors, which do not follow this rule +.bP +terminals supporting a large number of colors are limited by the number +of color pairs that can be represented in a \fIsigned short\fP value. +.SS COLORS +After initializing curses, this variable contains the number of colors +which the terminal can support. +.SS COLS +After initializing curses, this variable contains the width of the screen, +i.e., the number of columns. +.SS ESCDELAY +This variable holds the number of milliseconds to wait after reading an +escape character, +to distinguish between an individual escape character entered on the +keyboard from escape sequences sent by cursor- and function-keys +(see curses(3)). +.SS LINES +After initializing curses, this variable contains the height of the screen, +i.e., the number of lines. +.SS TABSIZE +This variable holds the number of columns used by the \fIcurses\fP library +when converting a tab character to spaces as it adds the tab to a window +(see \fBcurs_addch\fP(3). +.SS The Current Screen +This implementation of curses uses a special window \fBcurscr\fP to +record its updates to the terminal screen. +.PP +This is referred to as the \*(``physical screen\*('' in the +\fBcurs_refresh\fP(3) and +\fBcurs_outopts\fP(3) manual pages. +.SS The New Screen +This implementation of curses uses a special window \fBnewscr\fP to +hold updates to the terminal screen before applying them to \fBcurscr\fP. +.PP +This is referred to as the \*(``virtual screen\*('' in the +\fBcurs_kernel\fP(3), +\fBcurs_refresh\fP(3) and +\fBcurs_outopts\fP(3) manual pages. +.SS The Standard Screen +Upon initializing curses, +a default window called \fBstdscr\fP, +which is the size of the terminal screen, is created. +Many curses functions use this window. +.SH NOTES +The curses library is initialized using either \fBinitscr\fP(3), +or \fBnewterm\fP(3). +.PP +If \fBcurses\fP is configured to use separate curses/terminfo libraries, +most of these variables reside in the curses library. +.SH PORTABILITY +\fBTABSIZE\fP is a feature of SVr4 curses +which is not documented by X/Open curses. +.bP +In SVr4 curses, \fBTABSIZE\fP is initially set from the terminal description's +\fBinit_tabs\fP capability. +After that, it can be altered by the applications using SVr4 curses. +.IP +SVr4 curses uses the current value of \fBTABSIZE\fP to +compute the position of tabstops for updating both +the virtual screen with \fBaddch\fP(3) as well as +the physical screen with \fBmvcur\fP(3). +.bP +This implementation uses the current value of \fBTABSIZE\fP only for +updating the virtual screen. +It uses the terminal description's \fBit\fP (\fBinit_tabs\fP) capability for +computing hardware tabs (i.e., tab stops on the physical screen). +.bP +Other implementations differ. +For instance, NetBSD curses allows \fBTABSIZE\fP to be set through +an environment variable. +This implementation does not. +.IP +NetBSD curses does not support hardware tabs; +it uses the \fBinit_tabs\fP capability and the \fBTABSIZE\fP variable +only for updating the virtual screen. +.PP +\fBESCDELAY\fP is an extension in AIX curses: +.bP +In AIX, the units for \fBESCDELAY\fP are \fIfifths\fP of a millisecond. +.bP +The default value for AIX's \fBESCDELAY\fP is 0.1 seconds. +.bP +AIX also enforces a limit of 10,000 seconds for \fBESCDELAY\fP; +this implementation currently has no upper limit. +.PP +This implementation has long used \fBESCDELAY\fP with units of milliseconds, +making it impossible to be completely compatible with AIX. +Likewise, most users have either decided to override the value, +or rely upon its default value. +.SH SEE ALSO +\fBcurses\fP(3), +\fBcurs_opaque\fP(3), +\fBterminfo\fP(3), +\fBcurs_threads\fP(3), +\fBterm_variables\fP(3), +\fBterminfo\fP(\*n). diff --git a/lib/libcurses/curs_window.3 b/lib/libcurses/curs_window.3 index f4d112bc6b4..845b25234b0 100644 --- a/lib/libcurses/curs_window.3 +++ b/lib/libcurses/curs_window.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: curs_window.3,v 1.10 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: curs_window.3,v 1.11 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2020-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2015,2016 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,120 +29,174 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curs_window.3,v 1.10 2010/01/12 23:21:59 nicm Exp $ -.TH curs_window 3 "" +.\" $Id: curs_window.3,v 1.11 2023/10/17 09:52:08 nicm Exp $ +.TH curs_window 3 2023-07-01 "ncurses 6.4" "Library calls" +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .na .hy 0 .SH NAME -\fBnewwin\fR, -\fBdelwin\fR, -\fBmvwin\fR, -\fBsubwin\fR, -\fBderwin\fR, -\fBmvderwin\fR, -\fBdupwin\fR, -\fBwsyncup\fR, -\fBsyncok\fR, -\fBwcursyncup\fR, -\fBwsyncdown\fR - create \fBcurses\fR windows +\fBnewwin\fP, +\fBdelwin\fP, +\fBmvwin\fP, +\fBsubwin\fP, +\fBderwin\fP, +\fBmvderwin\fP, +\fBdupwin\fP, +\fBwsyncup\fP, +\fBsyncok\fP, +\fBwcursyncup\fP, +\fBwsyncdown\fP \- create \fBcurses\fP windows .ad .hy .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBWINDOW *newwin(int nlines, int ncols, int begin_y,\fR - \fBint begin_x);\fR +\fBWINDOW *newwin(\fP + \fBint \fInlines\fB, int \fIncols\fB,\fR + \fBint \fIbegin_y\fB, int \fIbegin_x\fB);\fR .br -\fBint delwin(WINDOW *win);\fR +\fBint delwin(WINDOW *\fIwin\fB);\fR .br -\fBint mvwin(WINDOW *win, int y, int x);\fR +\fBint mvwin(WINDOW *\fIwin\fB, int \fIy\fB, int \fIx\fB);\fR .br -\fBWINDOW *subwin(WINDOW *orig, int nlines, int ncols,\fR - \fBint begin_y, int begin_x);\fR +\fBWINDOW *subwin(WINDOW *\fIorig\fB,\fR + \fBint \fInlines\fB, int \fIncols\fB,\fR + \fBint \fIbegin_y\fB, int \fIbegin_x\fB);\fR .br -\fBWINDOW *derwin(WINDOW *orig, int nlines, int ncols,\fR - \fBint begin_y, int begin_x);\fR +\fBWINDOW *derwin(WINDOW *\fIorig\fB,\fR + \fBint \fInlines\fB, int \fIncols\fB,\fR + \fBint \fIbegin_y\fB, int \fIbegin_x\fB);\fR .br -\fBint mvderwin(WINDOW *win, int par_y, int par_x);\fR +\fBint mvderwin(WINDOW *\fIwin\fB, int \fIpar_y\fB, int \fIpar_x\fB);\fR .br -\fBWINDOW *dupwin(WINDOW *win);\fR +\fBWINDOW *dupwin(WINDOW *\fIwin\fB);\fR .br -\fBvoid wsyncup(WINDOW *win);\fR +\fBvoid wsyncup(WINDOW *\fIwin\fB);\fR .br -\fBint syncok(WINDOW *win, bool bf);\fR +\fBint syncok(WINDOW *\fIwin\fB, bool \fIbf\fB);\fR .br -\fBvoid wcursyncup(WINDOW *win);\fR -.br -\fBvoid wsyncdown(WINDOW *win);\fR +\fBvoid wcursyncup(WINDOW *\fIwin\fB);\fR .br +\fBvoid wsyncdown(WINDOW *\fIwin\fB);\fR .SH DESCRIPTION -Calling \fBnewwin\fR creates and returns a pointer to a new window with the -given number of lines and columns. The upper left-hand corner of the window is -at line \fIbegin\fR_\fIy\fR, column \fIbegin\fR_\fIx\fR. If either -\fInlines\fR or \fIncols\fR is zero, they default to \fBLINES -\fR -\fIbegin\fR_\fIy\fR and \fBCOLS -\fR \fIbegin\fR_\fIx\fR. A new full-screen -window is created by calling \fBnewwin(0,0,0,0)\fR. +.SS newwin +Calling \fBnewwin\fP creates and returns a pointer to a new window with the +given number of lines and columns. +The upper left-hand corner of the window is +at +.RS +line \fIbegin\fR_\fIy\fP, +.br +column \fIbegin\fR_\fIx\fP +.RE .PP -Calling \fBdelwin\fR deletes the named window, freeing all memory -associated with it (it does not actually erase the window's screen -image). Subwindows must be deleted before the main window can be -deleted. +If either +\fInlines\fP or \fIncols\fP is zero, they default to +.RS +\fBLINES \-\fP \fIbegin\fR_\fIy\fP and +.br +\fBCOLS \-\fP \fIbegin\fR_\fIx\fP. +.RE .PP -Calling \fBmvwin\fR moves the window so that the upper left-hand -corner is at position (\fIx\fR, \fIy\fR). If the move would cause the -window to be off the screen, it is an error and the window is not -moved. Moving subwindows is allowed, but should be avoided. +A new full-screen window is created by calling \fBnewwin(0,0,0,0)\fP. .PP -Calling \fBsubwin\fR creates and returns a pointer to a new window -with the given number of lines, \fInlines\fR, and columns, -\fIncols\fR. The window is at position (\fIbegin\fR_\fIy\fR, -\fIbegin\fR_\fIx\fR) on the screen. (This position is relative to the -screen, and not to the window \fIorig\fR.) The window is made in the -middle of the window \fIorig\fR, so that changes made to one window -will affect both windows. The subwindow shares memory with the window -\fIorig\fR. When using this routine, it is necessary to call -\fBtouchwin\fR or \fBtouchline\fR on \fIorig\fR before calling -\fBwrefresh\fR on the subwindow. +Regardless of the function used for creating a new window +(e.g., \fBnewwin\fP, \fBsubwin\fP, \fBderwin\fP, \fBnewpad\fP), +rather than a duplicate (with \fBdupwin\fP), +all of the window modes are initialized to the default values. +These functions set window modes after a window is created: +.RS +.na .PP -Calling \fBderwin\fR is the same as calling \fBsubwin,\fR except that -\fIbegin\fR_\fIy\fR and \fIbegin\fR_\fIx\fR are relative to the origin -of the window \fIorig\fR rather than the screen. There is no -difference between the subwindows and the derived windows. +idcok, +idlok, +immedok, +keypad, +leaveok, +nodelay, +scrollok, +setscrreg, +syncok, +wbkgdset, +wbkgrndset, and +wtimeout +.RE +.ad +.SS delwin +Calling \fBdelwin\fP deletes the named window, freeing all memory +associated with it (it does not actually erase the window's screen +image). +Subwindows must be deleted before the main window can be deleted. +.SS mvwin +Calling \fBmvwin\fP moves the window so that the upper left-hand +corner is at position (\fIx\fP, \fIy\fP). +If the move would cause the window to be off the screen, +it is an error and the window is not moved. +Moving subwindows is allowed, but should be avoided. +.SS subwin +Calling \fBsubwin\fP creates and returns a pointer to a new window +with the given number of lines, \fInlines\fP, and columns, \fIncols\fP. +The window is at position (\fIbegin\fR_\fIy\fP, +\fIbegin\fR_\fIx\fP) on the screen. +The subwindow shares memory with the window \fIorig\fP, +so that changes made to one window +will affect both windows. +When using this routine, it is necessary to call +\fBtouchwin\fP or \fBtouchline\fP on \fIorig\fP before calling +\fBwrefresh\fP on the subwindow. +.SS derwin +Calling \fBderwin\fP is the same as calling \fBsubwin,\fP except that +\fIbegin\fR_\fIy\fP and \fIbegin\fR_\fIx\fP are relative to the origin +of the window \fIorig\fP rather than the screen. +There is no difference between the subwindows and the derived windows. .PP -Calling \fBmvderwin\fR moves a derived window (or subwindow) -inside its parent window. The screen-relative parameters of the -window are not changed. This routine is used to display different +Calling \fBmvderwin\fP moves a derived window (or subwindow) +inside its parent window. +The screen-relative parameters of the window are not changed. +This routine is used to display different parts of the parent window at the same physical position on the screen. -.PP -Calling \fBdupwin\fR creates an exact duplicate of the window \fIwin\fR. -.PP -Calling \fBwsyncup\fR touches all locations in ancestors of \fIwin\fR that are -changed in \fIwin\fR. If \fBsyncok\fR is called with second argument -\fBTRUE\fR then \fBwsyncup\fR is called automatically whenever there is a +.SS dupwin +Calling \fBdupwin\fP creates an exact duplicate of the window \fIwin\fP. +.SS wsyncup +Calling \fBwsyncup\fP touches all locations in ancestors of \fIwin\fP that are +changed in \fIwin\fP. +If \fBsyncok\fP is called with second argument +\fBTRUE\fP then \fBwsyncup\fP is called automatically whenever there is a change in the window. -.PP -The \fBwsyncdown\fR routine touches each location in \fIwin\fR that has been -touched in any of its ancestor windows. This routine is called by -\fBwrefresh\fR, so it should almost never be necessary to call it manually. -.PP -The routine \fBwcursyncup\fR updates the current cursor position of all the +.SS wsyncdown +The \fBwsyncdown\fP routine touches each location in \fIwin\fP that has been +touched in any of its ancestor windows. +This routine is called by +\fBwrefresh\fP, so it should almost never be necessary to call it manually. +.SS wcursyncup +The routine \fBwcursyncup\fP updates the current cursor position of all the ancestors of the window to reflect the current cursor position of the window. .SH RETURN VALUE -Routines that return an integer return the integer \fBERR\fR upon failure and -\fBOK\fR (SVr4 only specifies "an integer value other than \fBERR\fR") upon +Routines that return an integer return the integer \fBERR\fP upon failure and +\fBOK\fP (SVr4 only specifies "an integer value other than \fBERR\fP") upon successful completion. .PP -Routines that return pointers return \fBNULL\fR on error. +Routines that return pointers return \fBNULL\fP on error. .PP X/Open defines no error conditions. In this implementation -.RS .TP 5 -\fBdelwin\fR +\fBdelwin\fP returns an error if the window pointer is null, or if the window is the parent of another window. +.TP 5 +\fBderwin\fP +returns an error if the parent window pointer is null, or +if any of its ordinates or dimensions is negative, or +if the resulting window does not fit inside the parent window. +.TP 5 +\fBdupwin\fP +returns an error if the window pointer is null. .IP This implementation also maintains a list of windows, and checks that the pointer passed to \fBdelwin\fP is one that @@ -158,33 +213,63 @@ if the window pointer is null, or if the window is really a pad, or if some part of the window would be placed off-screen. .TP 5 +\fBnewwin\fP +will fail if either of its beginning ordinates is negative, or +if either the number of lines or columns is negative. +.TP 5 \fBsyncok\fP returns an error if the window pointer is null. -.RE +.TP 5 +\fBsubwin\fP +returns an error if the parent window pointer is null, or +if any of its ordinates or dimensions is negative, or +if the resulting window does not fit inside the parent window. +.PP +The functions which return a window pointer +may also fail if there is insufficient memory for its data structures. +Any of these functions will fail if the screen has not been initialized, +i.e., with \fBinitscr\fP or \fBnewterm\fP. .SH NOTES -If many small changes are made to the window, the \fBwsyncup\fR option could +If many small changes are made to the window, the \fBwsyncup\fP option could degrade performance. .PP -Note that \fBsyncok\fR may be a macro. +Note that \fBsyncok\fP may be a macro. .SH BUGS -The subwindow functions (\fIsubwin\fR, \fIderwin\fR, \fImvderwin\fR, -\fBwsyncup\fR, \fBwsyncdown\fR, \fBwcursyncup\fR, \fBsyncok\fR) are flaky, +The subwindow functions (\fBsubwin\fP, \fBderwin\fP, \fBmvderwin\fP, +\fBwsyncup\fP, \fBwsyncdown\fP, \fBwcursyncup\fP, \fBsyncok\fP) are flaky, incompletely implemented, and not well tested. .PP -The System V curses documentation is very unclear about what \fBwsyncup\fR -and \fBwsyncdown\fR actually do. It seems to imply that they are only +The System V curses documentation is very unclear about what \fBwsyncup\fP +and \fBwsyncdown\fP actually do. +It seems to imply that they are only supposed to touch exactly those lines that are affected by ancestor changes. -The language here, and the behavior of the \fBcurses\fR implementation, -is patterned on the XPG4 curses standard. The weaker XPG4 spec may result -in slower updates. +The language here, and the behavior of the \fBcurses\fP implementation, +is patterned on the XPG4 curses standard. +The weaker XPG4 spec may result in slower updates. .SH PORTABILITY The XSI Curses standard, Issue 4 describes these functions. +.PP +X/Open Curses states regarding \fBdelwin\fP: +.bP +It must delete subwindows before deleting their parent. +.bP +If \fBdelwin\fP is asked to delete a parent window, +it can only succeed if the curses library keeps a list of the subwindows. +SVr4 curses kept a count of the number of subwindows rather than a list. +It simply returned \fBERR\fP when asked to delete a subwindow. +Solaris X/Open curses does not even make that check, +and will delete a parent window which still has subwindows. +.bP +Since release 4.0 (1996), ncurses maintains a list of windows for each screen, +to ensure that a window has no subwindows before allowing deletion. +.bP +NetBSD copied this feature of ncurses in 2003. +.br +PDCurses follows the scheme used in Solaris X/Open curses. .SH SEE ALSO -\fBcurses\fR(3), \fBcurs_refresh\fR(3), \fBcurs_touch\fR(3) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_initscr\fP(3), +\fBcurs_refresh\fP(3), +\fBcurs_touch\fP(3), +\fBcurs_variables\fP(3) diff --git a/lib/libcurses/curses.3 b/lib/libcurses/curses.3 index 15844d049e6..e696cc926aa 100644 --- a/lib/libcurses/curses.3 +++ b/lib/libcurses/curses.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: curses.3,v 1.5 2019/02/13 07:18:57 nicm Exp $ +.\" $OpenBSD: curses.3,v 1.6 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * +.\" Copyright 2018-2021,2023 Thomas E. Dickey * +.\" Copyright 1998-2015,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,208 +30,243 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: curses.3,v 1.5 2019/02/13 07:18:57 nicm Exp $ +.\" $Id: curses.3,v 1.6 2023/10/17 09:52:08 nicm Exp $ .hy 0 -.TH ncurses 3 "" +.TH ncurses 3 2023-08-19 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.de NS +.ie n .sp +.el .sp .5 +.ie n .in +4 +.el .in +2 +.nf +.ft CR \" Courier +.. +.de NE +.fi +.ft R +.ie n .in -4 +.el .in -2 +.. .ds n 5 .ds d /usr/share/terminfo .SH NAME -\fBncurses\fR - CRT screen handling and optimization package +\fBncurses\fP \- CRT screen handling and optimization package .SH SYNOPSIS -\fB#include \fR -.br +\fB#include \fP .SH DESCRIPTION -The \fBncurses\fR library routines give the user a terminal-independent method +The \fBncurses\fP library routines give the user a terminal-independent method of updating character screens with reasonable optimization. -This implementation is ``new curses'' (ncurses) and +This implementation is \*(``new curses\*('' (ncurses) and is the approved replacement for 4.4BSD classic curses, which has been discontinued. -This describes \fBncurses\fR -version 5.7. +This describes \fBncurses\fP +version 6.4 (patch 20230826). .PP -The \fBncurses\fR library emulates the \fBcurses\fR(3) library of +The \fBncurses\fP library emulates the curses library of System V Release 4 UNIX, and XPG4 (X/Open Portability Guide) curses (also known as XSI curses). XSI stands for X/Open System Interfaces Extension. -The \fBncurses\fR library is freely redistributable in source form. +The \fBncurses\fP library is freely redistributable in source form. Differences from the SVr4 -curses are summarized under the \fBEXTENSIONS\fP and \fBPORTABILITY\fP sections below and -described in detail in the respective \fBEXTENSIONS\fP, \fBPORTABILITY\fP and \fBBUGS\fP sections +curses are summarized under the +\fIEXTENSIONS\fP and \fIPORTABILITY\fP sections below and +described in detail in the respective +\fIEXTENSIONS\fP, \fIPORTABILITY\fP and \fIBUGS\fP sections of individual man pages. .PP -The \fBncurses\fR library also provides many useful extensions, +The \fBncurses\fP library also provides many useful extensions, i.e., features which cannot be implemented by a simple add-on library but which require access to the internals of the library. .PP -A program using these routines must be linked with the \fB-lncurses\fR option. +A program using these routines must be linked with the \fB\-lncurses\fP option, +or (if it has been generated) with the debugging library \fB\-lncurses_g\fP. +(Your system integrator may also have installed these libraries under +the names \fB\-lcurses\fP and \fB\-lcurses_g\fP.) +The ncurses_g library generates trace logs +(in a file called \*(``trace\*('' in the current directory) +that describe curses actions. +See also the section on \fBALTERNATE CONFIGURATIONS\fP. .PP -The \fBncurses\fR package supports: overall screen, window and pad +The \fBncurses\fP package supports: overall screen, window and pad manipulation; output to windows and pads; reading terminal input; control over -terminal and \fBcurses\fR input and output options; environment query +terminal and \fBcurses\fP input and output options; environment query routines; color manipulation; use of soft label keys; terminfo capabilities; and access to low-level terminal-manipulation routines. -.PP +.SS Initialization The library uses the locale which the calling program has initialized. -That is normally done with \fBsetlocale\fP: -.sp - \fBsetlocale(LC_ALL, "");\fP -.sp +That is normally done with \fBsetlocale\fP(3): +.NS +\fBsetlocale(LC_ALL, "");\fP +.NE +.PP If the locale is not initialized, -the library assumes that characters are printable as in ISO-8859-1, +the library assumes that characters are printable as in ISO\-8859\-1, to work with certain legacy programs. You should initialize the locale and not rely on specific details of the library when the locale has not been setup. .PP -The function \fBinitscr\fR or \fBnewterm\fR +The function \fBinitscr\fP or \fBnewterm\fP must be called to initialize the library before any of the other routines that deal with windows and screens are used. -The routine \fBendwin\fR must be called before exiting. +The routine \fBendwin\fP(3) must be called before exiting. .PP To get character-at-a-time input without echoing (most interactive, screen oriented programs want this), the following sequence should be used: -.sp - \fBinitscr(); cbreak(); noecho();\fR -.sp +.NS +\fBinitscr(); cbreak(); noecho();\fP +.NE +.PP Most programs would additionally use the sequence: -.sp - \fBnonl();\fR - \fBintrflush(stdscr, FALSE);\fR - \fBkeypad(stdscr, TRUE);\fR -.sp -Before a \fBcurses\fR program is run, the tab stops of the terminal -should be set and its initialization strings, if defined, must be output. -This can be done by executing the \fBtput init\fR command -after the shell environment variable \fBTERM\fR has been exported. -\fBtset(1)\fR is usually responsible for doing this. -[See \fBterminfo\fR(\*n) for further details.] +.NS +\fBintrflush(stdscr, FALSE);\fP +\fBkeypad(stdscr, TRUE);\fP +.NE .PP -The \fBncurses\fR library permits manipulation of data structures, -called \fIwindows\fR, which can be thought of as two-dimensional +Before a \fBcurses\fP program is run, the tab stops of the terminal +should be set and its initialization strings, if defined, must be output. +This can be done by executing the \fBtput init\fP command +after the shell environment variable \fBTERM\fP has been exported. +\fBtset(1)\fP is usually responsible for doing this. +[See \fBterminfo\fP(\*n) for further details.] +.SS Datatypes +The \fBncurses\fP library permits manipulation of data structures, +called \fIwindows\fP, which can be thought of as two-dimensional arrays of characters representing all or part of a CRT screen. -A default window called \fBstdscr\fR, which is the size of the terminal +A default window called \fBstdscr\fP, which is the size of the terminal screen, is supplied. -Others may be created with \fBnewwin\fR. +Others may be created with \fBnewwin\fP. .PP -Note that \fBcurses\fR does not handle overlapping windows, that's done by -the \fBpanel\fR(3) library. +Note that \fBcurses\fP does not handle overlapping windows, that's done by +the \fBpanel\fP(3) library. This means that you can either use -\fBstdscr\fR or divide the screen into tiled windows and not using -\fBstdscr\fR at all. +\fBstdscr\fP or divide the screen into tiled windows and not using +\fBstdscr\fP at all. Mixing the two will result in unpredictable, and undesired, effects. .PP -Windows are referred to by variables declared as \fBWINDOW *\fR. +Windows are referred to by variables declared as \fBWINDOW *\fP. These data structures are manipulated with routines described here and -elsewhere in the \fBncurses\fR manual pages. +elsewhere in the \fBncurses\fP manual pages. Among those, the most basic -routines are \fBmove\fR and \fBaddch\fR. +routines are \fBmove\fP and \fBaddch\fP. More general versions of -these routines are included with names beginning with \fBw\fR, +these routines are included with names beginning with \fBw\fP, allowing the user to specify a window. The routines not beginning -with \fBw\fR affect \fBstdscr\fR. +with \fBw\fP affect \fBstdscr\fP. .PP -After using routines to manipulate a window, \fBrefresh\fR is called, -telling \fBcurses\fR to make the user's CRT screen look like -\fBstdscr\fR. +After using routines to manipulate a window, \fBrefresh\fP(3) is called, +telling \fBcurses\fP to make the user's CRT screen look like +\fBstdscr\fP. The characters in a window are actually of type -\fBchtype\fR, (character and attribute data) so that other information +\fBchtype\fP, (character and attribute data) so that other information about the character may also be stored with each character. .PP -Special windows called \fIpads\fR may also be manipulated. +Special windows called \fIpads\fP may also be manipulated. These are windows which are not constrained to the size of the screen and whose contents need not be completely displayed. -See \fBcurs_pad\fR(3) for more information. +See \fBcurs_pad\fP(3) for more information. .PP In addition to drawing characters on the screen, video attributes and colors may be supported, causing the characters to show up in such modes as underlined, in reverse video, or in color on terminals that support such display enhancements. Line drawing characters may be specified to be output. -On input, \fBcurses\fR is also able to translate arrow and function keys that +On input, \fBcurses\fP is also able to translate arrow and function keys that transmit escape sequences into single values. The video attributes, line -drawing characters, and input values use names, defined in \fB\fR, -such as \fBA_REVERSE\fR, \fBACS_HLINE\fR, and \fBKEY_LEFT\fR. -.PP -If the environment variables \fBLINES\fR and \fBCOLUMNS\fR are set, or if the +drawing characters, and input values use names, defined in \fB\fP, +such as \fBA_REVERSE\fP, \fBACS_HLINE\fP, and \fBKEY_LEFT\fP. +.SS Environment variables +If the environment variables \fBLINES\fP and \fBCOLUMNS\fP are set, or if the program is executing in a window environment, line and column information in -the environment will override information read by \fIterminfo\fR. +the environment will override information read by \fIterminfo\fP. This would affect a program running in an AT&T 630 layer, for example, where the size of a -screen is changeable (see \fBENVIRONMENT\fR). +screen is changeable (see \fBENVIRONMENT\fP). .PP -If the environment variable \fBTERMINFO\fR is defined, any program using -\fBcurses\fR checks for a local terminal definition before checking in the +If the environment variable \fBTERMINFO\fP is defined, any program using +\fBcurses\fP checks for a local terminal definition before checking in the standard place. -For example, if \fBTERM\fR is set to \fBatt4424\fR, then the +For example, if \fBTERM\fP is set to \fBatt4424\fP, then the compiled terminal definition is found in -.sp - \fB\*d/a/att4424\fR. -.sp -(The \fBa\fR is copied from the first letter of \fBatt4424\fR to avoid -creation of huge directories.) However, if \fBTERMINFO\fR is set to -\fB$HOME/myterms\fR, \fBcurses\fR first checks -.sp - \fB$HOME/myterms/a/att4424\fR, -.sp +.NS +\fB\*d/a/att4424\fP. +.NE +.PP +(The \fBa\fP is copied from the first letter of \fBatt4424\fP to avoid +creation of huge directories.) However, if \fBTERMINFO\fP is set to +\fB$HOME/myterms\fP, \fBcurses\fP first checks +.NS +\fB$HOME/myterms/a/att4424\fP, +.NE +.PP and if that fails, it then checks -.sp - \fB\*d/a/att4424\fR. -.sp +.NS +\fB\*d/a/att4424\fP. +.NE +.PP This is useful for developing experimental definitions or when write -permission in \fB\*d\fR is not available. +permission in \fB\*d\fP is not available. .PP -The integer variables \fBLINES\fR and \fBCOLS\fR are defined in -\fB\fR and will be filled in by \fBinitscr\fR with the size of the +The integer variables \fBLINES\fP and \fBCOLS\fP are defined in +\fB\fP and will be filled in by \fBinitscr\fP with the size of the screen. -The constants \fBTRUE\fR and \fBFALSE\fR have the values \fB1\fR and -\fB0\fR, respectively. +The constants \fBTRUE\fP and \fBFALSE\fP have the values \fB1\fP and +\fB0\fP, respectively. .PP -The \fBcurses\fR routines also define the \fBWINDOW *\fR variable \fBcurscr\fR +The \fBcurses\fP routines also define the \fBWINDOW *\fP variable \fBcurscr\fP which is used for certain low-level operations like clearing and redrawing a screen containing garbage. -The \fBcurscr\fR can be used in only a few routines. +The \fBcurscr\fP can be used in only a few routines. .\" .SS Routine and Argument Names -Many \fBcurses\fR routines have two or more versions. -The routines prefixed with \fBw\fR require a window argument. -The routines prefixed with \fBp\fR require a pad argument. -Those without a prefix generally use \fBstdscr\fR. +Many \fBcurses\fP routines have two or more versions. +The routines prefixed with \fIw\fP require a window argument. +The routines prefixed with \fIp\fP require a pad argument. +Those without a prefix generally use \fBstdscr\fP. .PP -The routines prefixed with \fBmv\fR require a \fIy\fR and \fIx\fR +The routines prefixed with \fBmv\fP require a \fIy\fP and \fIx\fP coordinate to move to before performing the appropriate action. -The \fBmv\fR routines imply a call to \fBmove\fR before the call to the +The \fBmv\fP routines imply a call to \fBmove\fP before the call to the other routine. -The coordinate \fIy\fR always refers to the row (of -the window), and \fIx\fR always refers to the column. +The coordinate \fIy\fP always refers to the row (of +the window), and \fIx\fP always refers to the column. The upper left-hand corner is always (0,0), not (1,1). .PP -The routines prefixed with \fBmvw\fR take both a window argument and -\fIx\fR and \fIy\fR coordinates. +The routines prefixed with \fBmvw\fP take both a window argument and +\fIx\fP and \fIy\fP coordinates. The window argument is always specified before the coordinates. .PP -In each case, \fIwin\fR is the window affected, and \fIpad\fR is the -pad affected; \fIwin\fR and \fIpad\fR are always pointers to type -\fBWINDOW\fR. +In each case, \fIwin\fP is the window affected, and \fIpad\fP is the +pad affected; \fIwin\fP and \fIpad\fP are always pointers to type +\fBWINDOW\fP. .PP -Option setting routines require a Boolean flag \fIbf\fR with the value -\fBTRUE\fR or \fBFALSE\fR; \fIbf\fR is always of type \fBbool\fR. +Option setting routines require a Boolean flag \fIbf\fP with the value +\fBTRUE\fP or \fBFALSE\fP; \fIbf\fP is always of type \fBbool\fP. Most of the data types used in the library routines, -such as \fBWINDOW\fR, \fBSCREEN\fR, \fBbool\fR, and \fBchtype\fR -are defined in \fB\fR. +such as \fBWINDOW\fP, \fBSCREEN\fP, \fBbool\fP, and \fBchtype\fP +are defined in \fB\fP. Types used for the terminfo routines such as -\fBTERMINAL\fR are defined in \fB\fR. +\fBTERMINAL\fP are defined in \fB\fP. .PP This manual page describes functions which may appear in any configuration of the library. There are two common configurations of the library: -.RS +.RS 3 .TP 5 -ncurses -the "normal" library, which handles 8-bit characters. +.I ncurses +the \*(``normal\*('' library, which handles 8-bit characters. The normal (8-bit) library stores characters combined with attributes in \fBchtype\fP data. .IP @@ -240,622 +276,689 @@ In either case, the data is stored in something like an integer. .IP Each cell (row and column) in a \fBWINDOW\fP is stored as a \fBchtype\fP. .TP 5 -ncursesw -the so-called "wide" library, which handles multibyte characters. -The "wide" library includes all of the calls from the "normal" library. +.I ncursesw +the so-called \*(``wide\*('' library, which handles multibyte characters +(see the section on \fBALTERNATE CONFIGURATIONS\fP). +The \*(``wide\*('' library includes all of the calls +from the \*(``normal\*('' library. It adds about one third more calls using data types which store multibyte characters: -.RS +.RS 5 .TP 5 .B cchar_t corresponds to \fBchtype\fP. However it is a structure, because more data is stored than can fit into an integer. -The characters are large enough to require a full integer value - and there +The characters are large enough to require a full integer value \- and there may be more than one character per cell. The video attributes and color are stored in separate fields of the structure. .IP Each cell (row and column) in a \fBWINDOW\fP is stored as a \fBcchar_t\fP. +.IP +The \fBsetcchar\fP(3) and \fBgetcchar\fP(3) +functions store and retrieve the data from +a \fBcchar_t\fP structure. .TP 5 .B wchar_t -stores a "wide" character. +stores a \*(``wide\*('' character. Like \fBchtype\fP, this may be an integer. .TP 5 .B wint_t -stores a \fBwchar_t\fP or \fBWEOF\fP - not the same, though both may have +stores a \fBwchar_t\fP or \fBWEOF\fP \- not the same, though both may have the same size. .RE .IP -The "wide" library provides new functions which are analogous to -functions in the "normal" library. +The \*(``wide\*('' library provides new functions which are analogous to +functions in the \*(``normal\*('' library. There is a naming convention which relates many of the normal/wide variants: -a "_w" is inserted into the name. +a \*(``_w\*('' is inserted into the name. For example, \fBwaddch\fP becomes \fBwadd_wch\fP. .RE -.PP .\" .SS Routine Name Index -The following table lists each \fBcurses\fR routine and the name of -the manual page on which it is described. -Routines flagged with `*' +The following table lists the \fBcurses\fP routines provided in +the \*(``normal\*('' and \*(``wide\*('' libraries and the names of +the manual pages on which they are described. +Routines flagged with \*(``*\*('' are ncurses-specific, not described by XPG4 or present in SVr4. .PP .TS center tab(/); l l l l . -\fBcurses\fR Routine Name/Manual Page Name +\fBcurses\fP Routine Name/Manual Page Name = -COLOR_PAIR/\fBcurs_color\fR(3) -PAIR_NUMBER/\fBcurs_attr\fR(3) -add_wch/\fBcurs_add_wch\fR(3) -add_wchnstr/\fBcurs_add_wchstr\fR(3) -add_wchstr/\fBcurs_add_wchstr\fR(3) -addch/\fBcurs_addch\fR(3) -addchnstr/\fBcurs_addchstr\fR(3) -addchstr/\fBcurs_addchstr\fR(3) -addnstr/\fBcurs_addstr\fR(3) -addnwstr/\fBcurs_addwstr\fR(3) -addstr/\fBcurs_addstr\fR(3) -addwstr/\fBcurs_addwstr\fR(3) -assume_default_colors/\fBdefault_colors\fR(3)* -attr_get/\fBcurs_attr\fR(3) -attr_off/\fBcurs_attr\fR(3) -attr_on/\fBcurs_attr\fR(3) -attr_set/\fBcurs_attr\fR(3) -attroff/\fBcurs_attr\fR(3) -attron/\fBcurs_attr\fR(3) -attrset/\fBcurs_attr\fR(3) -baudrate/\fBcurs_termattrs\fR(3) -beep/\fBcurs_beep\fR(3) -bkgd/\fBcurs_bkgd\fR(3) -bkgdset/\fBcurs_bkgd\fR(3) -bkgrnd/\fBcurs_bkgrnd\fR(3) -bkgrndset/\fBcurs_bkgrnd\fR(3) -border/\fBcurs_border\fR(3) -border_set/\fBcurs_border_set\fR(3) -box/\fBcurs_border\fR(3) -box_set/\fBcurs_border_set\fR(3) -can_change_color/\fBcurs_color\fR(3) -cbreak/\fBcurs_inopts\fR(3) -chgat/\fBcurs_attr\fR(3) -clear/\fBcurs_clear\fR(3) -clearok/\fBcurs_outopts\fR(3) -clrtobot/\fBcurs_clear\fR(3) -clrtoeol/\fBcurs_clear\fR(3) -color_content/\fBcurs_color\fR(3) -color_set/\fBcurs_attr\fR(3) -copywin/\fBcurs_overlay\fR(3) -curs_set/\fBcurs_kernel\fR(3) -curses_version/\fBcurs_extend\fR(3)* -def_prog_mode/\fBcurs_kernel\fR(3) -def_shell_mode/\fBcurs_kernel\fR(3) -define_key/\fBdefine_key\fR(3)* -del_curterm/\fBterminfo\fR(3) -delay_output/\fBcurs_util\fR(3) -delch/\fBcurs_delch\fR(3) -deleteln/\fBcurs_deleteln\fR(3) -delscreen/\fBcurs_initscr\fR(3) -delwin/\fBcurs_window\fR(3) -derwin/\fBcurs_window\fR(3) -doupdate/\fBcurs_refresh\fR(3) -dupwin/\fBcurs_window\fR(3) -echo/\fBcurs_inopts\fR(3) -echo_wchar/\fBcurs_add_wch\fR(3) -echochar/\fBcurs_addch\fR(3) -endwin/\fBcurs_initscr\fR(3) -erase/\fBcurs_clear\fR(3) -erasechar/\fBcurs_termattrs\fR(3) -erasewchar/\fBcurs_termattrs\fR(3) -filter/\fBcurs_util\fR(3) -flash/\fBcurs_beep\fR(3) -flushinp/\fBcurs_util\fR(3) -get_wch/\fBcurs_get_wch\fR(3) -get_wstr/\fBcurs_get_wstr\fR(3) -getattrs/\fBcurs_attr\fR(3) -getbegx/\fBcurs_legacy\fR(3)* -getbegy/\fBcurs_legacy\fR(3)* -getbegyx/\fBcurs_getyx\fR(3) -getbkgd/\fBcurs_bkgd\fR(3) -getbkgrnd/\fBcurs_bkgrnd\fR(3) -getcchar/\fBcurs_getcchar\fR(3) -getch/\fBcurs_getch\fR(3) -getcurx/\fBcurs_legacy\fR(3)* -getcury/\fBcurs_legacy\fR(3)* -getmaxx/\fBcurs_legacy\fR(3)* -getmaxy/\fBcurs_legacy\fR(3)* -getmaxyx/\fBcurs_getyx\fR(3) -getmouse/\fBcurs_mouse\fR(3)* -getn_wstr/\fBcurs_get_wstr\fR(3) -getnstr/\fBcurs_getstr\fR(3) -getparx/\fBcurs_legacy\fR(3)* -getpary/\fBcurs_legacy\fR(3)* -getparyx/\fBcurs_getyx\fR(3) -getstr/\fBcurs_getstr\fR(3) -getsyx/\fBcurs_kernel\fR(3) -getwin/\fBcurs_util\fR(3) -getyx/\fBcurs_getyx\fR(3) -halfdelay/\fBcurs_inopts\fR(3) -has_colors/\fBcurs_color\fR(3) -has_ic/\fBcurs_termattrs\fR(3) -has_il/\fBcurs_termattrs\fR(3) -has_key/\fBcurs_getch\fR(3)* -hline/\fBcurs_border\fR(3) -hline_set/\fBcurs_border_set\fR(3) -idcok/\fBcurs_outopts\fR(3) -idlok/\fBcurs_outopts\fR(3) -immedok/\fBcurs_outopts\fR(3) -in_wch/\fBcurs_in_wch\fR(3) -in_wchnstr/\fBcurs_in_wchstr\fR(3) -in_wchstr/\fBcurs_in_wchstr\fR(3) -inch/\fBcurs_inch\fR(3) -inchnstr/\fBcurs_inchstr\fR(3) -inchstr/\fBcurs_inchstr\fR(3) -init_color/\fBcurs_color\fR(3) -init_pair/\fBcurs_color\fR(3) -initscr/\fBcurs_initscr\fR(3) -innstr/\fBcurs_instr\fR(3) -innwstr/\fBcurs_inwstr\fR(3) -ins_nwstr/\fBcurs_ins_wstr\fR(3) -ins_wch/\fBcurs_ins_wch\fR(3) -ins_wstr/\fBcurs_ins_wstr\fR(3) -insch/\fBcurs_insch\fR(3) -insdelln/\fBcurs_deleteln\fR(3) -insertln/\fBcurs_deleteln\fR(3) -insnstr/\fBcurs_insstr\fR(3) -insstr/\fBcurs_insstr\fR(3) -instr/\fBcurs_instr\fR(3) -intrflush/\fBcurs_inopts\fR(3) -inwstr/\fBcurs_inwstr\fR(3) -is_cleared/\fBcurs_opaque\fR(3)* -is_idcok/\fBcurs_opaque\fR(3)* -is_idlok/\fBcurs_opaque\fR(3)* -is_immedok/\fBcurs_opaque\fR(3)* -is_keypad/\fBcurs_opaque\fR(3)* -is_leaveok/\fBcurs_opaque\fR(3)* -is_linetouched/\fBcurs_touch\fR(3) -is_nodelay/\fBcurs_opaque\fR(3)* -is_notimeout/\fBcurs_opaque\fR(3)* -is_scrollok/\fBcurs_opaque\fR(3)* -is_syncok/\fBcurs_opaque\fR(3)* -is_term_resized/\fBresizeterm\fR(3)* -is_wintouched/\fBcurs_touch\fR(3) -isendwin/\fBcurs_initscr\fR(3) -key_defined/\fBkey_defined\fR(3)* -key_name/\fBcurs_util\fR(3) -keybound/\fBkeybound\fR(3)* -keyname/\fBcurs_util\fR(3) -keyok/\fBkeyok\fR(3)* -keypad/\fBcurs_inopts\fR(3) -killchar/\fBcurs_termattrs\fR(3) -killwchar/\fBcurs_termattrs\fR(3) -leaveok/\fBcurs_outopts\fR(3) -longname/\fBcurs_termattrs\fR(3) -mcprint/\fBcurs_print\fR(3)* -meta/\fBcurs_inopts\fR(3) -mouse_trafo/\fBcurs_mouse\fR(3)* -mouseinterval/\fBcurs_mouse\fR(3)* -mousemask/\fBcurs_mouse\fR(3)* -move/\fBcurs_move\fR(3) -mvadd_wch/\fBcurs_add_wch\fR(3) -mvadd_wchnstr/\fBcurs_add_wchstr\fR(3) -mvadd_wchstr/\fBcurs_add_wchstr\fR(3) -mvaddch/\fBcurs_addch\fR(3) -mvaddchnstr/\fBcurs_addchstr\fR(3) -mvaddchstr/\fBcurs_addchstr\fR(3) -mvaddnstr/\fBcurs_addstr\fR(3) -mvaddnwstr/\fBcurs_addwstr\fR(3) -mvaddstr/\fBcurs_addstr\fR(3) -mvaddwstr/\fBcurs_addwstr\fR(3) -mvchgat/\fBcurs_attr\fR(3) -mvcur/\fBterminfo\fR(3) -mvdelch/\fBcurs_delch\fR(3) -mvderwin/\fBcurs_window\fR(3) -mvget_wch/\fBcurs_get_wch\fR(3) -mvget_wstr/\fBcurs_get_wstr\fR(3) -mvgetch/\fBcurs_getch\fR(3) -mvgetn_wstr/\fBcurs_get_wstr\fR(3) -mvgetnstr/\fBcurs_getstr\fR(3) -mvgetstr/\fBcurs_getstr\fR(3) -mvhline/\fBcurs_border\fR(3) -mvhline_set/\fBcurs_border_set\fR(3) -mvin_wch/\fBcurs_in_wch\fR(3) -mvin_wchnstr/\fBcurs_in_wchstr\fR(3) -mvin_wchstr/\fBcurs_in_wchstr\fR(3) -mvinch/\fBcurs_inch\fR(3) -mvinchnstr/\fBcurs_inchstr\fR(3) -mvinchstr/\fBcurs_inchstr\fR(3) -mvinnstr/\fBcurs_instr\fR(3) -mvinnwstr/\fBcurs_inwstr\fR(3) -mvins_nwstr/\fBcurs_ins_wstr\fR(3) -mvins_wch/\fBcurs_ins_wch\fR(3) -mvins_wstr/\fBcurs_ins_wstr\fR(3) -mvinsch/\fBcurs_insch\fR(3) -mvinsnstr/\fBcurs_insstr\fR(3) -mvinsstr/\fBcurs_insstr\fR(3) -mvinstr/\fBcurs_instr\fR(3) -mvinwstr/\fBcurs_inwstr\fR(3) -mvprintw/\fBcurs_printw\fR(3) -mvscanw/\fBcurs_scanw\fR(3) -mvvline/\fBcurs_border\fR(3) -mvvline_set/\fBcurs_border_set\fR(3) -mvwadd_wch/\fBcurs_add_wch\fR(3) -mvwadd_wchnstr/\fBcurs_add_wchstr\fR(3) -mvwadd_wchstr/\fBcurs_add_wchstr\fR(3) -mvwaddch/\fBcurs_addch\fR(3) -mvwaddchnstr/\fBcurs_addchstr\fR(3) -mvwaddchstr/\fBcurs_addchstr\fR(3) -mvwaddnstr/\fBcurs_addstr\fR(3) -mvwaddnwstr/\fBcurs_addwstr\fR(3) -mvwaddstr/\fBcurs_addstr\fR(3) -mvwaddwstr/\fBcurs_addwstr\fR(3) -mvwchgat/\fBcurs_attr\fR(3) -mvwdelch/\fBcurs_delch\fR(3) -mvwget_wch/\fBcurs_get_wch\fR(3) -mvwget_wstr/\fBcurs_get_wstr\fR(3) -mvwgetch/\fBcurs_getch\fR(3) -mvwgetn_wstr/\fBcurs_get_wstr\fR(3) -mvwgetnstr/\fBcurs_getstr\fR(3) -mvwgetstr/\fBcurs_getstr\fR(3) -mvwhline/\fBcurs_border\fR(3) -mvwhline_set/\fBcurs_border_set\fR(3) -mvwin/\fBcurs_window\fR(3) -mvwin_wch/\fBcurs_in_wch\fR(3) -mvwin_wchnstr/\fBcurs_in_wchstr\fR(3) -mvwin_wchstr/\fBcurs_in_wchstr\fR(3) -mvwinch/\fBcurs_inch\fR(3) -mvwinchnstr/\fBcurs_inchstr\fR(3) -mvwinchstr/\fBcurs_inchstr\fR(3) -mvwinnstr/\fBcurs_instr\fR(3) -mvwinnwstr/\fBcurs_inwstr\fR(3) -mvwins_nwstr/\fBcurs_ins_wstr\fR(3) -mvwins_wch/\fBcurs_ins_wch\fR(3) -mvwins_wstr/\fBcurs_ins_wstr\fR(3) -mvwinsch/\fBcurs_insch\fR(3) -mvwinsnstr/\fBcurs_insstr\fR(3) -mvwinsstr/\fBcurs_insstr\fR(3) -mvwinstr/\fBcurs_instr\fR(3) -mvwinwstr/\fBcurs_inwstr\fR(3) -mvwprintw/\fBcurs_printw\fR(3) -mvwscanw/\fBcurs_scanw\fR(3) -mvwvline/\fBcurs_border\fR(3) -mvwvline_set/\fBcurs_border_set\fR(3) -napms/\fBcurs_kernel\fR(3) -newpad/\fBcurs_pad\fR(3) -newterm/\fBcurs_initscr\fR(3) -newwin/\fBcurs_window\fR(3) -nl/\fBcurs_outopts\fR(3) -nocbreak/\fBcurs_inopts\fR(3) -nodelay/\fBcurs_inopts\fR(3) -noecho/\fBcurs_inopts\fR(3) -nofilter/\fBcurs_util\fR(3)* -nonl/\fBcurs_outopts\fR(3) -noqiflush/\fBcurs_inopts\fR(3) -noraw/\fBcurs_inopts\fR(3) -notimeout/\fBcurs_inopts\fR(3) -overlay/\fBcurs_overlay\fR(3) -overwrite/\fBcurs_overlay\fR(3) -pair_content/\fBcurs_color\fR(3) -pechochar/\fBcurs_pad\fR(3) -pnoutrefresh/\fBcurs_pad\fR(3) -prefresh/\fBcurs_pad\fR(3) -printw/\fBcurs_printw\fR(3) -putp/\fBterminfo\fR(3) -putwin/\fBcurs_util\fR(3) -qiflush/\fBcurs_inopts\fR(3) -raw/\fBcurs_inopts\fR(3) -redrawwin/\fBcurs_refresh\fR(3) -refresh/\fBcurs_refresh\fR(3) -reset_prog_mode/\fBcurs_kernel\fR(3) -reset_shell_mode/\fBcurs_kernel\fR(3) -resetty/\fBcurs_kernel\fR(3) -resizeterm/\fBresizeterm\fR(3)* -restartterm/\fBterminfo\fR(3) -ripoffline/\fBcurs_kernel\fR(3) -savetty/\fBcurs_kernel\fR(3) -scanw/\fBcurs_scanw\fR(3) -scr_dump/\fBcurs_scr_dump\fR(3) -scr_init/\fBcurs_scr_dump\fR(3) -scr_restore/\fBcurs_scr_dump\fR(3) -scr_set/\fBcurs_scr_dump\fR(3) -scrl/\fBcurs_scroll\fR(3) -scroll/\fBcurs_scroll\fR(3) -scrollok/\fBcurs_outopts\fR(3) -set_curterm/\fBterminfo\fR(3) -set_term/\fBcurs_initscr\fR(3) -setcchar/\fBcurs_getcchar\fR(3) -setscrreg/\fBcurs_outopts\fR(3) -setsyx/\fBcurs_kernel\fR(3) -setterm/\fBterminfo\fR(3) -setupterm/\fBterminfo\fR(3) -slk_attr/\fBcurs_slk\fR(3)* -slk_attr_off/\fBcurs_slk\fR(3) -slk_attr_on/\fBcurs_slk\fR(3) -slk_attr_set/\fBcurs_slk\fR(3) -slk_attroff/\fBcurs_slk\fR(3) -slk_attron/\fBcurs_slk\fR(3) -slk_attrset/\fBcurs_slk\fR(3) -slk_clear/\fBcurs_slk\fR(3) -slk_color/\fBcurs_slk\fR(3) -slk_init/\fBcurs_slk\fR(3) -slk_label/\fBcurs_slk\fR(3) -slk_noutrefresh/\fBcurs_slk\fR(3) -slk_refresh/\fBcurs_slk\fR(3) -slk_restore/\fBcurs_slk\fR(3) -slk_set/\fBcurs_slk\fR(3) -slk_touch/\fBcurs_slk\fR(3) -standend/\fBcurs_attr\fR(3) -standout/\fBcurs_attr\fR(3) -start_color/\fBcurs_color\fR(3) -subpad/\fBcurs_pad\fR(3) -subwin/\fBcurs_window\fR(3) -syncok/\fBcurs_window\fR(3) -term_attrs/\fBcurs_termattrs\fR(3) -termattrs/\fBcurs_termattrs\fR(3) -termname/\fBcurs_termattrs\fR(3) -tgetent/\fBtermcap\fR(3) -tgetflag/\fBtermcap\fR(3) -tgetnum/\fBtermcap\fR(3) -tgetstr/\fBtermcap\fR(3) -tgoto/\fBtermcap\fR(3) -tigetflag/\fBterminfo\fR(3) -tigetnum/\fBterminfo\fR(3) -tigetstr/\fBterminfo\fR(3) -timeout/\fBcurs_inopts\fR(3) -touchline/\fBcurs_touch\fR(3) -touchwin/\fBcurs_touch\fR(3) -tparm/\fBterminfo\fR(3) -tputs/\fBtermcap\fR(3) -tputs/\fBterminfo\fR(3) -typeahead/\fBcurs_inopts\fR(3) -unctrl/\fBcurs_util\fR(3) -unget_wch/\fBcurs_get_wch\fR(3) -ungetch/\fBcurs_getch\fR(3) -ungetmouse/\fBcurs_mouse\fR(3)* -untouchwin/\fBcurs_touch\fR(3) -use_default_colors/\fBdefault_colors\fR(3)* -use_env/\fBcurs_util\fR(3) -use_extended_names/\fBcurs_extend\fR(3)* -use_legacy_coding/\fBlegacy_coding\fR(3)* -vid_attr/\fBterminfo\fR(3) -vid_puts/\fBterminfo\fR(3) -vidattr/\fBterminfo\fR(3) -vidputs/\fBterminfo\fR(3) -vline/\fBcurs_border\fR(3) -vline_set/\fBcurs_border_set\fR(3) -vw_printw/\fBcurs_printw\fR(3) -vw_scanw/\fBcurs_scanw\fR(3) -vwprintw/\fBcurs_printw\fR(3) -vwscanw/\fBcurs_scanw\fR(3) -wadd_wch/\fBcurs_add_wch\fR(3) -wadd_wchnstr/\fBcurs_add_wchstr\fR(3) -wadd_wchstr/\fBcurs_add_wchstr\fR(3) -waddch/\fBcurs_addch\fR(3) -waddchnstr/\fBcurs_addchstr\fR(3) -waddchstr/\fBcurs_addchstr\fR(3) -waddnstr/\fBcurs_addstr\fR(3) -waddnwstr/\fBcurs_addwstr\fR(3) -waddstr/\fBcurs_addstr\fR(3) -waddwstr/\fBcurs_addwstr\fR(3) -wattr_get/\fBcurs_attr\fR(3) -wattr_off/\fBcurs_attr\fR(3) -wattr_on/\fBcurs_attr\fR(3) -wattr_set/\fBcurs_attr\fR(3) -wattroff/\fBcurs_attr\fR(3) -wattron/\fBcurs_attr\fR(3) -wattrset/\fBcurs_attr\fR(3) -wbkgd/\fBcurs_bkgd\fR(3) -wbkgdset/\fBcurs_bkgd\fR(3) -wbkgrnd/\fBcurs_bkgrnd\fR(3) -wbkgrndset/\fBcurs_bkgrnd\fR(3) -wborder/\fBcurs_border\fR(3) -wborder_set/\fBcurs_border_set\fR(3) -wchgat/\fBcurs_attr\fR(3) -wclear/\fBcurs_clear\fR(3) -wclrtobot/\fBcurs_clear\fR(3) -wclrtoeol/\fBcurs_clear\fR(3) -wcolor_set/\fBcurs_attr\fR(3) -wcursyncup/\fBcurs_window\fR(3) -wdelch/\fBcurs_delch\fR(3) -wdeleteln/\fBcurs_deleteln\fR(3) -wecho_wchar/\fBcurs_add_wch\fR(3) -wechochar/\fBcurs_addch\fR(3) -wenclose/\fBcurs_mouse\fR(3)* -werase/\fBcurs_clear\fR(3) -wget_wch/\fBcurs_get_wch\fR(3) -wget_wstr/\fBcurs_get_wstr\fR(3) -wgetbkgrnd/\fBcurs_bkgrnd\fR(3) -wgetch/\fBcurs_getch\fR(3) -wgetn_wstr/\fBcurs_get_wstr\fR(3) -wgetnstr/\fBcurs_getstr\fR(3) -wgetstr/\fBcurs_getstr\fR(3) -whline/\fBcurs_border\fR(3) -whline_set/\fBcurs_border_set\fR(3) -win_wch/\fBcurs_in_wch\fR(3) -win_wchnstr/\fBcurs_in_wchstr\fR(3) -win_wchstr/\fBcurs_in_wchstr\fR(3) -winch/\fBcurs_inch\fR(3) -winchnstr/\fBcurs_inchstr\fR(3) -winchstr/\fBcurs_inchstr\fR(3) -winnstr/\fBcurs_instr\fR(3) -winnwstr/\fBcurs_inwstr\fR(3) -wins_nwstr/\fBcurs_ins_wstr\fR(3) -wins_wch/\fBcurs_ins_wch\fR(3) -wins_wstr/\fBcurs_ins_wstr\fR(3) -winsch/\fBcurs_insch\fR(3) -winsdelln/\fBcurs_deleteln\fR(3) -winsertln/\fBcurs_deleteln\fR(3) -winsnstr/\fBcurs_insstr\fR(3) -winsstr/\fBcurs_insstr\fR(3) -winstr/\fBcurs_instr\fR(3) -winwstr/\fBcurs_inwstr\fR(3) -wmouse_trafo/\fBcurs_mouse\fR(3)* -wmove/\fBcurs_move\fR(3) -wnoutrefresh/\fBcurs_refresh\fR(3) -wprintw/\fBcurs_printw\fR(3) -wredrawln/\fBcurs_refresh\fR(3) -wrefresh/\fBcurs_refresh\fR(3) -wresize/\fBwresize\fR(3)* -wscanw/\fBcurs_scanw\fR(3) -wscrl/\fBcurs_scroll\fR(3) -wsetscrreg/\fBcurs_outopts\fR(3) -wstandend/\fBcurs_attr\fR(3) -wstandout/\fBcurs_attr\fR(3) -wsyncdown/\fBcurs_window\fR(3) -wsyncup/\fBcurs_window\fR(3) -wtimeout/\fBcurs_inopts\fR(3) -wtouchln/\fBcurs_touch\fR(3) -wunctrl/\fBcurs_util\fR(3) -wvline/\fBcurs_border\fR(3) -wvline_set/\fBcurs_border_set\fR(3) +COLOR_PAIR/\fBcurs_color\fP(3) +PAIR_NUMBER/\fBcurs_attr\fP(3) +add_wch/\fBcurs_add_wch\fP(3) +add_wchnstr/\fBcurs_add_wchstr\fP(3) +add_wchstr/\fBcurs_add_wchstr\fP(3) +addch/\fBcurs_addch\fP(3) +addchnstr/\fBcurs_addchstr\fP(3) +addchstr/\fBcurs_addchstr\fP(3) +addnstr/\fBcurs_addstr\fP(3) +addnwstr/\fBcurs_addwstr\fP(3) +addstr/\fBcurs_addstr\fP(3) +addwstr/\fBcurs_addwstr\fP(3) +alloc_pair/\fBnew_pair\fP(3)* +assume_default_colors/\fBdefault_colors\fP(3)* +attr_get/\fBcurs_attr\fP(3) +attr_off/\fBcurs_attr\fP(3) +attr_on/\fBcurs_attr\fP(3) +attr_set/\fBcurs_attr\fP(3) +attroff/\fBcurs_attr\fP(3) +attron/\fBcurs_attr\fP(3) +attrset/\fBcurs_attr\fP(3) +baudrate/\fBcurs_termattrs\fP(3) +beep/\fBcurs_beep\fP(3) +bkgd/\fBcurs_bkgd\fP(3) +bkgdset/\fBcurs_bkgd\fP(3) +bkgrnd/\fBcurs_bkgrnd\fP(3) +bkgrndset/\fBcurs_bkgrnd\fP(3) +border/\fBcurs_border\fP(3) +border_set/\fBcurs_border_set\fP(3) +box/\fBcurs_border\fP(3) +box_set/\fBcurs_border_set\fP(3) +can_change_color/\fBcurs_color\fP(3) +cbreak/\fBcurs_inopts\fP(3) +chgat/\fBcurs_attr\fP(3) +clear/\fBcurs_clear\fP(3) +clearok/\fBcurs_outopts\fP(3) +clrtobot/\fBcurs_clear\fP(3) +clrtoeol/\fBcurs_clear\fP(3) +color_content/\fBcurs_color\fP(3) +color_set/\fBcurs_attr\fP(3) +copywin/\fBcurs_overlay\fP(3) +curs_set/\fBcurs_kernel\fP(3) +curses_trace/\fBcurs_trace\fP(3)* +curses_version/\fBcurs_extend\fP(3)* +def_prog_mode/\fBcurs_kernel\fP(3) +def_shell_mode/\fBcurs_kernel\fP(3) +define_key/\fBdefine_key\fP(3)* +del_curterm/\fBterminfo\fP(3) +delay_output/\fBcurs_util\fP(3) +delch/\fBcurs_delch\fP(3) +deleteln/\fBcurs_deleteln\fP(3) +delscreen/\fBcurs_initscr\fP(3) +delwin/\fBcurs_window\fP(3) +derwin/\fBcurs_window\fP(3) +doupdate/\fBcurs_refresh\fP(3) +dupwin/\fBcurs_window\fP(3) +echo/\fBcurs_inopts\fP(3) +echo_wchar/\fBcurs_add_wch\fP(3) +echochar/\fBcurs_addch\fP(3) +endwin/\fBcurs_initscr\fP(3) +erase/\fBcurs_clear\fP(3) +erasechar/\fBcurs_termattrs\fP(3) +erasewchar/\fBcurs_termattrs\fP(3) +exit_curses/\fBcurs_memleaks\fP(3)* +exit_terminfo/\fBcurs_memleaks\fP(3)* +extended_color_content/\fBcurs_color\fP(3)* +extended_pair_content/\fBcurs_color\fP(3)* +extended_slk_color/\fBcurs_slk\fP(3)* +filter/\fBcurs_util\fP(3) +find_pair/\fBnew_pair\fP(3)* +flash/\fBcurs_beep\fP(3) +flushinp/\fBcurs_util\fP(3) +free_pair/\fBnew_pair\fP(3)* +get_wch/\fBcurs_get_wch\fP(3) +get_wstr/\fBcurs_get_wstr\fP(3) +getattrs/\fBcurs_attr\fP(3) +getbegx/\fBcurs_legacy\fP(3)* +getbegy/\fBcurs_legacy\fP(3)* +getbegyx/\fBcurs_getyx\fP(3) +getbkgd/\fBcurs_bkgd\fP(3) +getbkgrnd/\fBcurs_bkgrnd\fP(3) +getcchar/\fBcurs_getcchar\fP(3) +getch/\fBcurs_getch\fP(3) +getcurx/\fBcurs_legacy\fP(3)* +getcury/\fBcurs_legacy\fP(3)* +getmaxx/\fBcurs_legacy\fP(3)* +getmaxy/\fBcurs_legacy\fP(3)* +getmaxyx/\fBcurs_getyx\fP(3) +getmouse/\fBcurs_mouse\fP(3)* +getn_wstr/\fBcurs_get_wstr\fP(3) +getnstr/\fBcurs_getstr\fP(3) +getparx/\fBcurs_legacy\fP(3)* +getpary/\fBcurs_legacy\fP(3)* +getparyx/\fBcurs_getyx\fP(3) +getstr/\fBcurs_getstr\fP(3) +getsyx/\fBcurs_kernel\fP(3) +getwin/\fBcurs_util\fP(3) +getyx/\fBcurs_getyx\fP(3) +halfdelay/\fBcurs_inopts\fP(3) +has_colors/\fBcurs_color\fP(3) +has_ic/\fBcurs_termattrs\fP(3) +has_il/\fBcurs_termattrs\fP(3) +has_key/\fBcurs_getch\fP(3)* +has_mouse/\fBcurs_mouse\fP(3)* +hline/\fBcurs_border\fP(3) +hline_set/\fBcurs_border_set\fP(3) +idcok/\fBcurs_outopts\fP(3) +idlok/\fBcurs_outopts\fP(3) +immedok/\fBcurs_outopts\fP(3) +in_wch/\fBcurs_in_wch\fP(3) +in_wchnstr/\fBcurs_in_wchstr\fP(3) +in_wchstr/\fBcurs_in_wchstr\fP(3) +inch/\fBcurs_inch\fP(3) +inchnstr/\fBcurs_inchstr\fP(3) +inchstr/\fBcurs_inchstr\fP(3) +init_color/\fBcurs_color\fP(3) +init_extended_color/\fBcurs_color\fP(3)* +init_extended_pair/\fBcurs_color\fP(3)* +init_pair/\fBcurs_color\fP(3) +initscr/\fBcurs_initscr\fP(3) +innstr/\fBcurs_instr\fP(3) +innwstr/\fBcurs_inwstr\fP(3) +ins_nwstr/\fBcurs_ins_wstr\fP(3) +ins_wch/\fBcurs_ins_wch\fP(3) +ins_wstr/\fBcurs_ins_wstr\fP(3) +insch/\fBcurs_insch\fP(3) +insdelln/\fBcurs_deleteln\fP(3) +insertln/\fBcurs_deleteln\fP(3) +insnstr/\fBcurs_insstr\fP(3) +insstr/\fBcurs_insstr\fP(3) +instr/\fBcurs_instr\fP(3) +intrflush/\fBcurs_inopts\fP(3) +inwstr/\fBcurs_inwstr\fP(3) +is_cbreak/\fBcurs_inopts\fP(3)* +is_cleared/\fBcurs_opaque\fP(3)* +is_echo/\fBcurs_inopts\fP(3)* +is_idcok/\fBcurs_opaque\fP(3)* +is_idlok/\fBcurs_opaque\fP(3)* +is_immedok/\fBcurs_opaque\fP(3)* +is_keypad/\fBcurs_opaque\fP(3)* +is_leaveok/\fBcurs_opaque\fP(3)* +is_linetouched/\fBcurs_touch\fP(3) +is_nl/\fBcurs_inopts\fP(3)* +is_nodelay/\fBcurs_opaque\fP(3)* +is_notimeout/\fBcurs_opaque\fP(3)* +is_pad/\fBcurs_opaque\fP(3)* +is_raw/\fBcurs_inopts\fP(3)* +is_scrollok/\fBcurs_opaque\fP(3)* +is_subwin/\fBcurs_opaque\fP(3)* +is_syncok/\fBcurs_opaque\fP(3)* +is_term_resized/\fBresizeterm\fP(3)* +is_wintouched/\fBcurs_touch\fP(3) +isendwin/\fBcurs_initscr\fP(3) +key_defined/\fBkey_defined\fP(3)* +key_name/\fBcurs_util\fP(3) +keybound/\fBkeybound\fP(3)* +keyname/\fBcurs_util\fP(3) +keyok/\fBkeyok\fP(3)* +keypad/\fBcurs_inopts\fP(3) +killchar/\fBcurs_termattrs\fP(3) +killwchar/\fBcurs_termattrs\fP(3) +leaveok/\fBcurs_outopts\fP(3) +longname/\fBcurs_termattrs\fP(3) +mcprint/\fBcurs_print\fP(3)* +meta/\fBcurs_inopts\fP(3) +mouse_trafo/\fBcurs_mouse\fP(3)* +mouseinterval/\fBcurs_mouse\fP(3)* +mousemask/\fBcurs_mouse\fP(3)* +move/\fBcurs_move\fP(3) +mvadd_wch/\fBcurs_add_wch\fP(3) +mvadd_wchnstr/\fBcurs_add_wchstr\fP(3) +mvadd_wchstr/\fBcurs_add_wchstr\fP(3) +mvaddch/\fBcurs_addch\fP(3) +mvaddchnstr/\fBcurs_addchstr\fP(3) +mvaddchstr/\fBcurs_addchstr\fP(3) +mvaddnstr/\fBcurs_addstr\fP(3) +mvaddnwstr/\fBcurs_addwstr\fP(3) +mvaddstr/\fBcurs_addstr\fP(3) +mvaddwstr/\fBcurs_addwstr\fP(3) +mvchgat/\fBcurs_attr\fP(3) +mvcur/\fBterminfo\fP(3) +mvdelch/\fBcurs_delch\fP(3) +mvderwin/\fBcurs_window\fP(3) +mvget_wch/\fBcurs_get_wch\fP(3) +mvget_wstr/\fBcurs_get_wstr\fP(3) +mvgetch/\fBcurs_getch\fP(3) +mvgetn_wstr/\fBcurs_get_wstr\fP(3) +mvgetnstr/\fBcurs_getstr\fP(3) +mvgetstr/\fBcurs_getstr\fP(3) +mvhline/\fBcurs_border\fP(3) +mvhline_set/\fBcurs_border_set\fP(3) +mvin_wch/\fBcurs_in_wch\fP(3) +mvin_wchnstr/\fBcurs_in_wchstr\fP(3) +mvin_wchstr/\fBcurs_in_wchstr\fP(3) +mvinch/\fBcurs_inch\fP(3) +mvinchnstr/\fBcurs_inchstr\fP(3) +mvinchstr/\fBcurs_inchstr\fP(3) +mvinnstr/\fBcurs_instr\fP(3) +mvinnwstr/\fBcurs_inwstr\fP(3) +mvins_nwstr/\fBcurs_ins_wstr\fP(3) +mvins_wch/\fBcurs_ins_wch\fP(3) +mvins_wstr/\fBcurs_ins_wstr\fP(3) +mvinsch/\fBcurs_insch\fP(3) +mvinsnstr/\fBcurs_insstr\fP(3) +mvinsstr/\fBcurs_insstr\fP(3) +mvinstr/\fBcurs_instr\fP(3) +mvinwstr/\fBcurs_inwstr\fP(3) +mvprintw/\fBcurs_printw\fP(3) +mvscanw/\fBcurs_scanw\fP(3) +mvvline/\fBcurs_border\fP(3) +mvvline_set/\fBcurs_border_set\fP(3) +mvwadd_wch/\fBcurs_add_wch\fP(3) +mvwadd_wchnstr/\fBcurs_add_wchstr\fP(3) +mvwadd_wchstr/\fBcurs_add_wchstr\fP(3) +mvwaddch/\fBcurs_addch\fP(3) +mvwaddchnstr/\fBcurs_addchstr\fP(3) +mvwaddchstr/\fBcurs_addchstr\fP(3) +mvwaddnstr/\fBcurs_addstr\fP(3) +mvwaddnwstr/\fBcurs_addwstr\fP(3) +mvwaddstr/\fBcurs_addstr\fP(3) +mvwaddwstr/\fBcurs_addwstr\fP(3) +mvwchgat/\fBcurs_attr\fP(3) +mvwdelch/\fBcurs_delch\fP(3) +mvwget_wch/\fBcurs_get_wch\fP(3) +mvwget_wstr/\fBcurs_get_wstr\fP(3) +mvwgetch/\fBcurs_getch\fP(3) +mvwgetn_wstr/\fBcurs_get_wstr\fP(3) +mvwgetnstr/\fBcurs_getstr\fP(3) +mvwgetstr/\fBcurs_getstr\fP(3) +mvwhline/\fBcurs_border\fP(3) +mvwhline_set/\fBcurs_border_set\fP(3) +mvwin/\fBcurs_window\fP(3) +mvwin_wch/\fBcurs_in_wch\fP(3) +mvwin_wchnstr/\fBcurs_in_wchstr\fP(3) +mvwin_wchstr/\fBcurs_in_wchstr\fP(3) +mvwinch/\fBcurs_inch\fP(3) +mvwinchnstr/\fBcurs_inchstr\fP(3) +mvwinchstr/\fBcurs_inchstr\fP(3) +mvwinnstr/\fBcurs_instr\fP(3) +mvwinnwstr/\fBcurs_inwstr\fP(3) +mvwins_nwstr/\fBcurs_ins_wstr\fP(3) +mvwins_wch/\fBcurs_ins_wch\fP(3) +mvwins_wstr/\fBcurs_ins_wstr\fP(3) +mvwinsch/\fBcurs_insch\fP(3) +mvwinsnstr/\fBcurs_insstr\fP(3) +mvwinsstr/\fBcurs_insstr\fP(3) +mvwinstr/\fBcurs_instr\fP(3) +mvwinwstr/\fBcurs_inwstr\fP(3) +mvwprintw/\fBcurs_printw\fP(3) +mvwscanw/\fBcurs_scanw\fP(3) +mvwvline/\fBcurs_border\fP(3) +mvwvline_set/\fBcurs_border_set\fP(3) +napms/\fBcurs_kernel\fP(3) +newpad/\fBcurs_pad\fP(3) +newterm/\fBcurs_initscr\fP(3) +newwin/\fBcurs_window\fP(3) +nl/\fBcurs_inopts\fP(3) +nocbreak/\fBcurs_inopts\fP(3) +nodelay/\fBcurs_inopts\fP(3) +noecho/\fBcurs_inopts\fP(3) +nofilter/\fBcurs_util\fP(3)* +nonl/\fBcurs_inopts\fP(3) +noqiflush/\fBcurs_inopts\fP(3) +noraw/\fBcurs_inopts\fP(3) +notimeout/\fBcurs_inopts\fP(3) +overlay/\fBcurs_overlay\fP(3) +overwrite/\fBcurs_overlay\fP(3) +pair_content/\fBcurs_color\fP(3) +pecho_wchar/\fBcurs_pad\fP(3)* +pechochar/\fBcurs_pad\fP(3) +pnoutrefresh/\fBcurs_pad\fP(3) +prefresh/\fBcurs_pad\fP(3) +printw/\fBcurs_printw\fP(3) +putp/\fBterminfo\fP(3) +putwin/\fBcurs_util\fP(3) +qiflush/\fBcurs_inopts\fP(3) +raw/\fBcurs_inopts\fP(3) +redrawwin/\fBcurs_refresh\fP(3) +refresh/\fBcurs_refresh\fP(3) +reset_color_pairs/\fBcurs_color\fP(3)* +reset_prog_mode/\fBcurs_kernel\fP(3) +reset_shell_mode/\fBcurs_kernel\fP(3) +resetty/\fBcurs_kernel\fP(3) +resize_term/\fBresizeterm\fP(3)* +resizeterm/\fBresizeterm\fP(3)* +restartterm/\fBterminfo\fP(3) +ripoffline/\fBcurs_kernel\fP(3) +savetty/\fBcurs_kernel\fP(3) +scanw/\fBcurs_scanw\fP(3) +scr_dump/\fBcurs_scr_dump\fP(3) +scr_init/\fBcurs_scr_dump\fP(3) +scr_restore/\fBcurs_scr_dump\fP(3) +scr_set/\fBcurs_scr_dump\fP(3) +scrl/\fBcurs_scroll\fP(3) +scroll/\fBcurs_scroll\fP(3) +scrollok/\fBcurs_outopts\fP(3) +set_curterm/\fBterminfo\fP(3) +set_term/\fBcurs_initscr\fP(3) +setcchar/\fBcurs_getcchar\fP(3) +setscrreg/\fBcurs_outopts\fP(3) +setsyx/\fBcurs_kernel\fP(3) +setupterm/\fBterminfo\fP(3) +slk_attr/\fBcurs_slk\fP(3)* +slk_attr_off/\fBcurs_slk\fP(3) +slk_attr_on/\fBcurs_slk\fP(3) +slk_attr_set/\fBcurs_slk\fP(3) +slk_attroff/\fBcurs_slk\fP(3) +slk_attron/\fBcurs_slk\fP(3) +slk_attrset/\fBcurs_slk\fP(3) +slk_clear/\fBcurs_slk\fP(3) +slk_color/\fBcurs_slk\fP(3) +slk_init/\fBcurs_slk\fP(3) +slk_label/\fBcurs_slk\fP(3) +slk_noutrefresh/\fBcurs_slk\fP(3) +slk_refresh/\fBcurs_slk\fP(3) +slk_restore/\fBcurs_slk\fP(3) +slk_set/\fBcurs_slk\fP(3) +slk_touch/\fBcurs_slk\fP(3) +slk_wset/\fBcurs_slk\fP(3)* +standend/\fBcurs_attr\fP(3) +standout/\fBcurs_attr\fP(3) +start_color/\fBcurs_color\fP(3) +subpad/\fBcurs_pad\fP(3) +subwin/\fBcurs_window\fP(3) +syncok/\fBcurs_window\fP(3) +term_attrs/\fBcurs_termattrs\fP(3) +termattrs/\fBcurs_termattrs\fP(3) +termname/\fBcurs_termattrs\fP(3) +tgetent/\fBtermcap\fP(3) +tgetflag/\fBtermcap\fP(3) +tgetnum/\fBtermcap\fP(3) +tgetstr/\fBtermcap\fP(3) +tgoto/\fBtermcap\fP(3) +tigetflag/\fBterminfo\fP(3) +tigetnum/\fBterminfo\fP(3) +tigetstr/\fBterminfo\fP(3) +timeout/\fBcurs_inopts\fP(3) +tiparm/\fBterminfo\fP(3)* +tiparm_s/\fBterminfo\fP(3)* +tiscan_s/\fBterminfo\fP(3)* +touchline/\fBcurs_touch\fP(3) +touchwin/\fBcurs_touch\fP(3) +tparm/\fBterminfo\fP(3) +tputs/\fBtermcap\fP(3) +tputs/\fBterminfo\fP(3) +trace/\fBcurs_trace\fP(3)* +typeahead/\fBcurs_inopts\fP(3) +unctrl/\fBcurs_util\fP(3) +unget_wch/\fBcurs_get_wch\fP(3) +ungetch/\fBcurs_getch\fP(3) +ungetmouse/\fBcurs_mouse\fP(3)* +untouchwin/\fBcurs_touch\fP(3) +use_default_colors/\fBdefault_colors\fP(3)* +use_env/\fBcurs_util\fP(3) +use_extended_names/\fBcurs_extend\fP(3)* +use_legacy_coding/\fBlegacy_coding\fP(3)* +use_tioctl/\fBcurs_util\fP(3)* +vid_attr/\fBterminfo\fP(3) +vid_puts/\fBterminfo\fP(3) +vidattr/\fBterminfo\fP(3) +vidputs/\fBterminfo\fP(3) +vline/\fBcurs_border\fP(3) +vline_set/\fBcurs_border_set\fP(3) +vw_printw/\fBcurs_printw\fP(3) +vw_scanw/\fBcurs_scanw\fP(3) +vwprintw/\fBcurs_printw\fP(3) +vwscanw/\fBcurs_scanw\fP(3) +wadd_wch/\fBcurs_add_wch\fP(3) +wadd_wchnstr/\fBcurs_add_wchstr\fP(3) +wadd_wchstr/\fBcurs_add_wchstr\fP(3) +waddch/\fBcurs_addch\fP(3) +waddchnstr/\fBcurs_addchstr\fP(3) +waddchstr/\fBcurs_addchstr\fP(3) +waddnstr/\fBcurs_addstr\fP(3) +waddnwstr/\fBcurs_addwstr\fP(3) +waddstr/\fBcurs_addstr\fP(3) +waddwstr/\fBcurs_addwstr\fP(3) +wattr_get/\fBcurs_attr\fP(3) +wattr_off/\fBcurs_attr\fP(3) +wattr_on/\fBcurs_attr\fP(3) +wattr_set/\fBcurs_attr\fP(3) +wattroff/\fBcurs_attr\fP(3) +wattron/\fBcurs_attr\fP(3) +wattrset/\fBcurs_attr\fP(3) +wbkgd/\fBcurs_bkgd\fP(3) +wbkgdset/\fBcurs_bkgd\fP(3) +wbkgrnd/\fBcurs_bkgrnd\fP(3) +wbkgrndset/\fBcurs_bkgrnd\fP(3) +wborder/\fBcurs_border\fP(3) +wborder_set/\fBcurs_border_set\fP(3) +wchgat/\fBcurs_attr\fP(3) +wclear/\fBcurs_clear\fP(3) +wclrtobot/\fBcurs_clear\fP(3) +wclrtoeol/\fBcurs_clear\fP(3) +wcolor_set/\fBcurs_attr\fP(3) +wcursyncup/\fBcurs_window\fP(3) +wdelch/\fBcurs_delch\fP(3) +wdeleteln/\fBcurs_deleteln\fP(3) +wecho_wchar/\fBcurs_add_wch\fP(3) +wechochar/\fBcurs_addch\fP(3) +wenclose/\fBcurs_mouse\fP(3)* +werase/\fBcurs_clear\fP(3) +wget_wch/\fBcurs_get_wch\fP(3) +wget_wstr/\fBcurs_get_wstr\fP(3) +wgetbkgrnd/\fBcurs_bkgrnd\fP(3) +wgetch/\fBcurs_getch\fP(3) +wgetdelay/\fBcurs_opaque\fP(3)* +wgetn_wstr/\fBcurs_get_wstr\fP(3) +wgetnstr/\fBcurs_getstr\fP(3) +wgetparent/\fBcurs_opaque\fP(3)* +wgetscrreg/\fBcurs_opaque\fP(3)* +wgetstr/\fBcurs_getstr\fP(3) +whline/\fBcurs_border\fP(3) +whline_set/\fBcurs_border_set\fP(3) +win_wch/\fBcurs_in_wch\fP(3) +win_wchnstr/\fBcurs_in_wchstr\fP(3) +win_wchstr/\fBcurs_in_wchstr\fP(3) +winch/\fBcurs_inch\fP(3) +winchnstr/\fBcurs_inchstr\fP(3) +winchstr/\fBcurs_inchstr\fP(3) +winnstr/\fBcurs_instr\fP(3) +winnwstr/\fBcurs_inwstr\fP(3) +wins_nwstr/\fBcurs_ins_wstr\fP(3) +wins_wch/\fBcurs_ins_wch\fP(3) +wins_wstr/\fBcurs_ins_wstr\fP(3) +winsch/\fBcurs_insch\fP(3) +winsdelln/\fBcurs_deleteln\fP(3) +winsertln/\fBcurs_deleteln\fP(3) +winsnstr/\fBcurs_insstr\fP(3) +winsstr/\fBcurs_insstr\fP(3) +winstr/\fBcurs_instr\fP(3) +winwstr/\fBcurs_inwstr\fP(3) +wmouse_trafo/\fBcurs_mouse\fP(3)* +wmove/\fBcurs_move\fP(3) +wnoutrefresh/\fBcurs_refresh\fP(3) +wprintw/\fBcurs_printw\fP(3) +wredrawln/\fBcurs_refresh\fP(3) +wrefresh/\fBcurs_refresh\fP(3) +wresize/\fBwresize\fP(3)* +wscanw/\fBcurs_scanw\fP(3) +wscrl/\fBcurs_scroll\fP(3) +wsetscrreg/\fBcurs_outopts\fP(3) +wstandend/\fBcurs_attr\fP(3) +wstandout/\fBcurs_attr\fP(3) +wsyncdown/\fBcurs_window\fP(3) +wsyncup/\fBcurs_window\fP(3) +wtimeout/\fBcurs_inopts\fP(3) +wtouchln/\fBcurs_touch\fP(3) +wunctrl/\fBcurs_util\fP(3) +wvline/\fBcurs_border\fP(3) +wvline_set/\fBcurs_border_set\fP(3) .TE +.PP +Depending on the configuration, +additional sets of functions may be available: +.RS 3 +.TP 5 +\fBcurs_memleaks\fP(3) - curses memory-leak checking +.TP 5 +\fBcurs_sp_funcs\fP(3) - curses screen-pointer extension +.TP 5 +\fBcurs_threads\fP(3) - curses thread support +.TP 5 +\fBcurs_trace\fP(3) - curses debugging routines +.RE .SH RETURN VALUE -Routines that return an integer return \fBERR\fR upon failure and an -integer value other than \fBERR\fR upon successful completion, unless +Routines that return an integer return \fBERR\fP upon failure and an +integer value other than \fBERR\fP upon successful completion, unless otherwise noted in the routine descriptions. .PP -All macros return the value of the \fBw\fR version, except \fBsetscrreg\fR, -\fBwsetscrreg\fR, \fBgetyx\fR, \fBgetbegyx\fR, and \fBgetmaxyx\fR. -The return values of \fBsetscrreg\fR, \fBwsetscrreg\fR, \fBgetyx\fR, \fBgetbegyx\fR, and -\fBgetmaxyx\fR are undefined (i.e., these should not be used as the +As a general rule, routines check for null pointers passed as parameters, +and handle this as an error. +.PP +All macros return the value of the \fBw\fP version, except \fBsetscrreg\fP, +\fBwsetscrreg\fP, \fBgetyx\fP, \fBgetbegyx\fP, and \fBgetmaxyx\fP. +The return values of +\fBsetscrreg\fP, +\fBwsetscrreg\fP, +\fBgetyx\fP, +\fBgetbegyx\fP, and +\fBgetmaxyx\fP are undefined (i.e., these should not be used as the right-hand side of assignment statements). .PP -Routines that return pointers return \fBNULL\fR on error. +Functions with a \*(``mv\*('' prefix first perform a cursor movement using +\fBwmove\fP, and return an error if the position is outside the window, +or if the window pointer is null. +Most \*(``mv\*(''-prefixed functions +(except variadic functions such as \fBmvprintw\fP) +are provided both as macros and functions. +.PP +Routines that return pointers return \fBNULL\fP on error. .SH ENVIRONMENT The following environment symbols are useful for customizing the -runtime behavior of the \fBncurses\fR library. +runtime behavior of the \fBncurses\fP library. The most important ones have been already discussed in detail. -.TP 5 -BAUDRATE -The debugging library checks this environment symbol when the application -has redirected output to a file. -The symbol's numeric value is used for the baudrate. -If no value is found, \fBncurses\fR uses 9600. -This allows testers to construct repeatable test-cases -that take into account costs that depend on baudrate. -.TP 5 -CC +.SS CC command-character When set, change occurrences of the command_character (i.e., the \fBcmdch\fP capability) -of the loaded terminfo entries to the value of this symbol. +of the loaded terminfo entries to the value of this variable. Very few terminfo entries provide this feature. -.TP 5 -COLUMNS +.PP +Because this name is also used in development environments to represent +the C compiler's name, \fBncurses\fP ignores it if it does not happen to +be a single character. +.SS BAUDRATE +The debugging library checks this environment variable when the application +has redirected output to a file. +The variable's numeric value is used for the baudrate. +If no value is found, \fBncurses\fP uses 9600. +This allows testers to construct repeatable test-cases +that take into account costs that depend on baudrate. +.SS COLUMNS Specify the width of the screen in characters. Applications running in a windowing environment usually are able to obtain the width of the window in which they are executing. If neither the \fBCOLUMNS\fP value nor the terminal's screen size is available, -\fBncurses\fR uses the size which may be specified in the terminfo database -(i.e., the \fBcols\fR capability). -.IP +\fBncurses\fP uses the size which may be specified in the terminfo database +(i.e., the \fBcols\fP capability). +.PP It is important that your application use a correct size for the screen. This is not always possible because your application may be running on a host which does not honor NAWS (Negotiations About Window Size), or because you are temporarily running as another user. However, setting \fBCOLUMNS\fP and/or \fBLINES\fP overrides the library's use of the screen size obtained from the operating system. -.IP +.PP Either \fBCOLUMNS\fP or \fBLINES\fP symbols may be specified independently. This is mainly useful to circumvent legacy misfeatures of terminal descriptions, e.g., xterm which commonly specifies a 65 line screen. -For best results, \fBlines\fR and \fBcols\fR should not be specified in +For best results, \fBlines\fP and \fBcols\fP should not be specified in a terminal description for terminals which are run as emulations. -.IP -Use the \fBuse_env\fR function to disable all use of external environment -(including system calls) to determine the screen size. -.TP 5 -ESCDELAY +.PP +Use the \fBuse_env\fP function to disable all use of external environment +(but not including system calls) to determine the screen size. +Use the \fBuse_tioctl\fP function to update \fBCOLUMNS\fP or \fBLINES\fP +to match the screen size obtained from system calls or the terminal database. +.SS ESCDELAY Specifies the total time, in milliseconds, for which ncurses will await a character sequence, e.g., a function key. The default value, 1000 milliseconds, is enough for most uses. However, it is made a variable to accommodate unusual applications. -.IP +.PP The most common instance where you may wish to change this value is to work with slow hosts, e.g., running on a network. If the host cannot read characters rapidly enough, it will have the same effect as if the terminal did not send characters rapidly enough. The library will still see a timeout. -.IP +.PP Note that xterm mouse events are built up from character sequences received from the xterm. If your application makes heavy use of multiple-clicking, you may wish to lengthen this default value because the timeout applies to the composed multi-click event as well as the individual clicks. -.IP +.PP In addition to the environment variable, this implementation provides a global variable with the same name. Portable applications should not rely upon the presence of ESCDELAY in either form, but setting the environment variable rather than the global variable does not create problems when compiling an application. -.TP 5 -HOME -Tells \fBncurses\fR where your home directory is. +.SS HOME +Tells \fBncurses\fP where your home directory is. That is where it may read and write auxiliary terminal descriptions: -.IP +.NS $HOME/.termcap -.br $HOME/.terminfo -.TP 5 -LINES +.NE +.SS LINES Like COLUMNS, specify the height of the screen in characters. See COLUMNS for a detailed description. -.TP 5 -MOUSE_BUTTONS_123 +.SS MOUSE_BUTTONS_123 This applies only to the OS/2 EMX port. It specifies the order of buttons on the mouse. OS/2 numbers a 3-button mouse inconsistently from other platforms: -.sp +.NS 1 = left .br 2 = right .br 3 = middle. -.sp -This symbol lets you customize the mouse. -The symbol must be three numeric digits 1-3 in any order, e.g., 123 or 321. -If it is not specified, \fBncurses\fR uses 132. -.TP 5 -NCURSES_ASSUMED_COLORS +.NE +.PP +This variable lets you customize the mouse. +The variable must be three numeric digits 1\-3 in any order, e.g., 123 or 321. +If it is not specified, \fBncurses\fP uses 132. +.SS NCURSES_ASSUMED_COLORS Override the compiled-in assumption that the terminal's default colors are white-on-black -(see \fBdefault_colors\fR(3)). +(see \fBdefault_colors\fP(3)). You may set the foreground and background color values with this environment variable by proving a 2-element list: foreground,background. For example, to tell ncurses to not assume anything -about the colors, set this to "-1,-1". +about the colors, set this to "\-1,\-1". To make it green-on-black, set it to "2,0". -Any positive value from zero to the terminfo \fBmax_colors\fR value is allowed. -.TP 5 -NCURSES_GPM_TERMS +Any positive value from zero to the terminfo \fBmax_colors\fP value is allowed. +.SS NCURSES_CONSOLE2 +This applies only to the MinGW port of ncurses. +.PP +The \fBConsole2\fP program's handling of the Microsoft Console API call +\fBCreateConsoleScreenBuffer\fP is defective. +Applications which use this will hang. +However, it is possible to simulate the action of this call by +mapping coordinates, +explicitly saving and restoring the original screen contents. +Setting the environment variable \fBNCGDB\fP has the same effect. +.SS NCURSES_GPM_TERMS This applies only to ncurses configured to use the GPM interface. -.IP +.PP If present, the environment variable is a list of one or more terminal names -against which the TERM environment variable is matched. +against which the \fBTERM\fP environment variable is matched. Setting it to an empty value disables the GPM interface; using the built-in support for xterm, etc. -.IP +.PP If the environment variable is absent, -ncurses will attempt to open GPM if TERM contains "linux". -.TP 5 -NCURSES_NO_HARD_TABS +ncurses will attempt to open GPM if \fBTERM\fP contains \*(``linux\*(''. +.SS NCURSES_NO_HARD_TABS \fBNcurses\fP may use tabs as part of the cursor movement optimization. In some cases, your terminal driver may not handle these properly. Set this environment variable to disable the feature. -You can also adjust your \fBstty\fP settings to avoid the problem. -.TP 5 -NCURSES_NO_MAGIC_COOKIES +You can also adjust your \fBstty\fP(1) settings to avoid the problem. +.SS NCURSES_NO_MAGIC_COOKIE Some terminals use a magic-cookie feature which requires special handling to make highlighting and other video attributes display properly. You can suppress the highlighting entirely for these terminals by setting this environment variable. -.TP 5 -NCURSES_NO_PADDING +.SS NCURSES_NO_PADDING Most of the terminal descriptions in the terminfo database are written -for real "hardware" terminals. +for real \*(``hardware\*('' terminals. Many people use terminal emulators which run in a windowing environment and use curses-based applications. Terminal emulators can duplicate @@ -869,112 +972,354 @@ it (or your application) must manage dataflow, preventing overruns. The cheapest solution (no hardware cost) is for your program to do this by pausing after operations that the terminal does slowly, such as clearing the display. -.IP +.PP As a result, many terminal descriptions (including the vt100) have delay times embedded. You may wish to use these descriptions, but not want to pay the performance penalty. -.IP -Set the NCURSES_NO_PADDING symbol to disable all but mandatory +.PP +Set the NCURSES_NO_PADDING environment variable to disable all but mandatory padding. Mandatory padding is used as a part of special control -sequences such as \fIflash\fR. -.TP 5 -NCURSES_NO_SETBUF -Normally \fBncurses\fR enables buffered output during terminal initialization. -This is done (as in SVr4 curses) for performance reasons. -For testing purposes, both of \fBncurses\fR and certain applications, -this feature is made optional. +sequences such as \fBflash\fP. +.SS NCURSES_NO_SETBUF +This setting is obsolete. +Before changes +.RS 3 +.bP +started with 5.9 patch 20120825 +and +.bP +continued +though 5.9 patch 20130126 +.RE +.PP +\fBncurses\fP enabled buffered output during terminal initialization. +This was done (as in SVr4 curses) for performance reasons. +For testing purposes, both of \fBncurses\fP and certain applications, +this feature was made optional. Setting the NCURSES_NO_SETBUF variable -disables output buffering, leaving the output in the original (usually +disabled output buffering, leaving the output in the original (usually line buffered) mode. -.TP 5 -NCURSES_NO_UTF8_ACS -During initialization, the \fBncurses\fR library +.PP +In the current implementation, +ncurses performs its own buffering and does not require this workaround. +It does not modify the buffering of the standard output. +.PP +The reason for the change was to make the behavior for interrupts and +other signals more robust. +One drawback is that certain nonconventional programs would mix +ordinary stdio calls with ncurses calls and (usually) work. +This is no longer possible since ncurses is not using +the buffered standard output but its own output (to the same file descriptor). +As a special case, the low-level calls such as \fBputp\fP still use the +standard output. +But high-level curses calls do not. +.SS NCURSES_NO_UTF8_ACS +During initialization, the \fBncurses\fP library checks for special cases where VT100 line-drawing (and the corresponding alternate character set capabilities) described in the terminfo are known to be missing. -Specifically, when running in a UTF-8 locale, +Specifically, when running in a UTF\-8 locale, the Linux console emulator and the GNU screen program ignore these. -Ncurses checks the TERM environment variable for these. +Ncurses checks the \fBTERM\fP environment variable for these. For other special cases, you should set this environment variable. Doing this tells ncurses to use Unicode values which correspond to the VT100 line-drawing glyphs. That works for the special cases cited, and is likely to work for terminal emulators. -.IP +.PP When setting this variable, you should set it to a nonzero value. Setting it to zero (or to a nonnumber) -disables the special check for Linux and screen. -.TP 5 -NCURSES_TRACE -During initialization, the \fBncurses\fR debugging library -checks the NCURSES_TRACE symbol. -If it is defined, to a numeric value, \fBncurses\fR calls the \fBtrace\fR +disables the special check for \*(``linux\*('' and \*(``screen\*(''. +.PP +As an alternative to the environment variable, +ncurses checks for an extended terminfo capability \fBU8\fP. +This is a numeric capability which can be compiled using \fBtic\ \-x\fP. +For example +.RS 3 +.ft CW +.sp +.nf +# linux console, if patched to provide working +# VT100 shift-in/shift-out, with corresponding font. +linux-vt100|linux console with VT100 line-graphics, + U8#0, use=linux, +.sp +# uxterm with vt100Graphics resource set to false +xterm-utf8|xterm relying on UTF-8 line-graphics, + U8#1, use=xterm, +.fi +.ft +.RE +.PP +The name \*(``U8\*('' is chosen to be two characters, +to permit it to be used by applications that use ncurses' +termcap interface. +.SS NCURSES_TRACE +During initialization, the \fBncurses\fP debugging library +checks the NCURSES_TRACE environment variable. +If it is defined, to a numeric value, \fBncurses\fP calls the \fBtrace\fP function, using that value as the argument. -.IP -The argument values, which are defined in \fBcurses.h\fR, provide several +.PP +The argument values, which are defined in \fBcurses.h\fP, provide several types of information. When running with traces enabled, your application will write the -file \fBtrace\fR to the current directory. -.TP 5 -TERM +file \fBtrace\fP to the current directory. +.PP +See \fBcurs_trace\fP(3) for more information. +.SS TERM Denotes your terminal type. Each terminal type is distinct, though many are similar. -.TP 5 -TERMCAP -If the \fBncurses\fR library has been configured with \fItermcap\fR -support, \fBncurses\fR will check for a terminal's description in +.PP +\fBTERM\fP is commonly set by terminal emulators to help +applications find a workable terminal description. +Some of those choose a popular approximation, e.g., +\*(``ansi\*('', \*(``vt100\*('', \*(``xterm\*('' rather than an exact fit. +Not infrequently, your application will have problems with that approach, +e.g., incorrect function-key definitions. +.PP +If you set \fBTERM\fP in your environment, +it has no effect on the operation of the terminal emulator. +It only affects the way applications work within the terminal. +Likewise, as a general rule (\fBxterm\fP(1) being a rare exception), +terminal emulators which allow you to +specify \fBTERM\fP as a parameter or configuration value do +not change their behavior to match that setting. +.SS TERMCAP +If the \fBncurses\fP library has been configured with \fItermcap\fP +support, \fBncurses\fP will check for a terminal's description in termcap form if it is not available in the terminfo database. -.IP -The TERMCAP symbol contains either a terminal description (with -newlines stripped out), -or a file name telling where the information denoted by the TERM symbol exists. -In either case, setting it directs \fBncurses\fR to ignore +.PP +The \fBTERMCAP\fP environment variable contains +either a terminal description (with newlines stripped out), +or a file name telling where the information denoted by +the \fBTERM\fP environment variable exists. +In either case, setting it directs \fBncurses\fP to ignore the usual place for this information, e.g., /etc/termcap. -.TP 5 -TERMINFO -Overrides the directory in which \fBncurses\fR searches for your terminal +.SS TERMINFO +\fBncurses\fP can be configured to read from multiple terminal databases. +The \fBTERMINFO\fP variable overrides the location for +the default terminal database. +Terminal descriptions (in terminal format) are stored in terminal databases: +.bP +Normally these are stored in a directory tree, +using subdirectories named by the first letter of the terminal names therein. +.IP +This is the scheme used in System V, which legacy Unix systems use, +and the \fBTERMINFO\fP variable is used by \fIcurses\fP applications on those +systems to override the default location of the terminal database. +.bP +If \fBncurses\fP is built to use hashed databases, +then each entry in this list may be the path of a hashed database file, e.g., +.NS +/usr/share/terminfo.db +.NE +.IP +rather than +.NS +/usr/share/terminfo/ +.NE +.IP +The hashed database uses less disk-space and is a little faster than the +directory tree. +However, +some applications assume the existence of the directory tree, +reading it directly +rather than using the terminfo library calls. +.bP +If \fBncurses\fP is built with a support for reading termcap files +directly, then an entry in this list may be the path of a termcap file. +.bP +If the \fBTERMINFO\fP variable begins with +\*(``hex:\*('' or \*(``b64:\*('', +\fBncurses\fP uses the remainder of that variable as a compiled terminal description. -This is the simplest, but not the only way to change the list of directories. -The complete list of directories in order follows: -.RS -.TP 3 -- -the last directory to which \fBncurses\fR wrote, if any, is searched first -.TP 3 -- -the directory specified by the TERMINFO symbol -.TP 3 -- +You might produce the base64 format using \fBinfocmp\fP(1): +.NS +TERMINFO="$(infocmp -0 -Q2 -q)" +export TERMINFO +.NE +.IP +The compiled description is used if it corresponds to the terminal identified +by the \fBTERM\fP variable. +.PP +Setting \fBTERMINFO\fP is the simplest, +but not the only way to set location of the default terminal database. +The complete list of database locations in order follows: +.RS 3 +.bP +the last terminal database to which \fBncurses\fP wrote, +if any, is searched first +.bP +the location specified by the TERMINFO environment variable +.bP $HOME/.terminfo -.TP 3 -- -directories listed in the TERMINFO_DIRS symbol -.TP 3 -- -one or more directories whose names are configured and compiled into the -ncurses library, e.g., -/usr/share/terminfo +.bP +locations listed in the TERMINFO_DIRS environment variable +.bP +one or more locations whose names are configured and compiled into the +ncurses library, i.e., +.RS 3 +.bP +? (corresponding to the TERMINFO_DIRS variable) +.bP +/usr/share/terminfo (corresponding to the TERMINFO variable) .RE -.TP 5 -TERMINFO_DIRS -Specifies a list of directories to search for terminal descriptions. +.RE +.SS TERMINFO_DIRS +Specifies a list of locations to search for terminal descriptions. +Each location in the list is a terminal database as described in +the section on the \fBTERMINFO\fP variable. The list is separated by colons (i.e., ":") on Unix, semicolons on OS/2 EMX. -All of the terminal descriptions are in terminfo form, which makes -a subdirectory named for the first letter of the terminal names therein. -.TP 5 -TERMPATH -If TERMCAP does not hold a file name then \fBncurses\fR checks -the TERMPATH symbol. -This is a list of filenames separated by spaces or colons (i.e., ":") on Unix, semicolons on OS/2 EMX. -If the TERMPATH symbol is not set, \fBncurses\fR looks in the files -/etc/termcap, /usr/share/misc/termcap and $HOME/.termcap, in that order. +.PP +There is no corresponding feature in System V terminfo; +it is an extension developed for \fBncurses\fP. +.SS TERMPATH +If \fBTERMCAP\fP does not hold a file name then \fBncurses\fP checks +the \fBTERMPATH\fP environment variable. +This is a list of filenames separated by spaces or colons (i.e., ":") on Unix, +semicolons on OS/2 EMX. +.PP +If the \fBTERMPATH\fP environment variable is not set, +\fBncurses\fP looks in the files +.NS +/etc/termcap, /usr/share/misc/termcap and $HOME/.termcap, +.NE +.PP +in that order. .PP The library may be configured to disregard the following variables when the current user is the superuser (root), or if the application uses setuid or setgid permissions: +.NS $TERMINFO, $TERMINFO_DIRS, $TERMPATH, as well as $HOME. +.NE +.SH ALTERNATE CONFIGURATIONS +Several different configurations are possible, +depending on the configure script options used when building \fBncurses\fP. +There are a few main options whose effects are visible to the applications +developer using \fBncurses\fP: +.TP 5 +\-\-disable\-overwrite +The standard include for \fBncurses\fP is as noted in \fBSYNOPSIS\fP: +.NS +\fB#include \fP +.NE +.IP +This option is used to avoid filename conflicts when \fBncurses\fP +is not the main implementation of curses of the computer. +If \fBncurses\fP is installed disabling overwrite, it puts its headers in +a subdirectory, e.g., +.NS +\fB#include \fP +.NE +.IP +It also omits a symbolic link which would allow you to use \fB\-lcurses\fP +to build executables. +.TP 5 +\-\-enable\-widec +The configure script renames the library and +(if the \fB\-\-disable\-overwrite\fP option is used) +puts the header files in a different subdirectory. +All of the library names have a \*(``w\*('' appended to them, +i.e., instead of +.NS +\fB\-lncurses\fP +.NE +.IP +you link with +.NS +\fB\-lncursesw\fP +.NE +.IP +You must also enable the wide-character features in the header file +when compiling for the wide-character library +to use the extended (wide-character) functions. +The symbol which enables these features has changed since XSI Curses, Issue 4: +.RS +.bP +Originally, the wide-character feature required the symbol +\fB_XOPEN_SOURCE_EXTENDED\fP +but that was only valid for XPG4 (1996). +.bP +Later, that was deemed conflicting with \fB_XOPEN_SOURCE\fP defined to 500. +.bP +As of mid-2018, +none of the features in this implementation require a \fB_XOPEN_SOURCE\fP +feature greater than 600. +However, X/Open Curses, Issue 7 (2009) recommends defining it to 700. +.bP +Alternatively, you can enable the feature by defining \fBNCURSES_WIDECHAR\fP +with the caveat that some other header file than \fBcurses.h\fP +may require a specific value for \fB_XOPEN_SOURCE\fP +(or a system-specific symbol). +.RE +.IP +The \fBcurses.h\fP file which is installed for the wide-character +library is designed to be compatible with the normal library's header. +Only the size of the \fBWINDOW\fP structure differs, and very few +applications require more than a pointer to \fBWINDOW\fPs. +.IP +If the headers are installed allowing overwrite, +the wide-character library's headers should be installed last, +to allow applications to be built using either library +from the same set of headers. +.TP 5 +\-\-with\-pthread +The configure script renames the library. +All of the library names have a \*(``t\*('' appended to them +(before any \*(``w\*('' added by \fB\-\-enable\-widec\fP). +.IP +The global variables such as \fBLINES\fP are replaced by macros to +allow read-only access. +At the same time, setter-functions are provided to set these values. +Some applications (very few) may require changes to work with this convention. +.TP 5 +\-\-with\-shared +.TP +\-\-with\-normal +.TP +\-\-with\-debug +.TP +\-\-with\-profile +The shared and normal (static) library names differ by their suffixes, +e.g., \fBlibncurses.so\fP and \fBlibncurses.a\fP. +The debug and profiling libraries add a \*(``_g\*('' +and a \*(``_p\*('' to the root names respectively, +e.g., \fBlibncurses_g.a\fP and \fBlibncurses_p.a\fP. +.TP 5 +\-\-with\-termlib +Low-level functions which do not depend upon whether the library +supports wide-characters, are provided in the tinfo library. +.IP +By doing this, it is possible to share the tinfo library between +wide/normal configurations as well as reduce the size of the library +when only low-level functions are needed. +.IP +Those functions are described in these pages: +.RS +.bP +\fBcurs_extend\fP(3) \- miscellaneous curses extensions +.bP +\fBcurs_inopts\fP(3) \- \fBcurses\fP input options +.bP +\fBcurs_kernel\fP(3) \- low-level \fBcurses\fP routines +.bP +\fBcurs_termattrs\fP(3) \- \fBcurses\fP environment query routines +.bP +\fBtermcap\fP(3) \- \fBcurses\fP emulation of termcap +.bP +\fBterminfo\fP(3) \- \fBcurses\fP interfaces to terminfo database +.bP +\fBcurs_util\fP(3) \- miscellaneous \fBcurses\fP utility routines +.RE +.TP 5 +\-\-with\-trace +The \fBtrace\fP function normally resides in the debug library, +but it is sometimes useful to configure this in the shared library. +Configure scripts should check for the function's existence rather +than assuming it is always in the debug library. .SH FILES .TP 5 /usr/share/tabset @@ -982,100 +1327,211 @@ directory containing initialization files for the terminal capability database /usr/share/terminfo terminal capability database .SH SEE ALSO -\fBterminfo\fR(\*n) and related pages whose names begin "curs_" for detailed routine -descriptions. +\fBterminfo\fP(\*n) and related pages whose names begin +\*(``curs_\*('' for detailed routine descriptions. +.br +\fBcurs_variables\fP(3) +.br +\fBuser_caps\fP(5) for user-defined capabilities .SH EXTENSIONS -The \fBncurses\fR library can be compiled with an option (\fB-DUSE_GETCAP\fR) +The \fBncurses\fP library can be compiled with an option (\fB\-DUSE_GETCAP\fP) that falls back to the old-style /etc/termcap file if the terminal setup code -cannot find a terminfo entry corresponding to \fBTERM\fR. +cannot find a terminfo entry corresponding to \fBTERM\fP. Use of this feature is not recommended, as it essentially includes an entire termcap compiler in -the \fBncurses\fR startup code, at significant cost in core and startup cycles. +the \fBncurses\fP startup code, at significant cost in core and startup cycles. .PP -The \fBncurses\fR library includes facilities for capturing mouse events on +The \fBncurses\fP library includes facilities for capturing mouse events on certain terminals (including xterm). -See the \fBcurs_mouse\fR(3) +See the \fBcurs_mouse\fP(3) manual page for details. .PP -The \fBncurses\fR library includes facilities for responding to window +The \fBncurses\fP library includes facilities for responding to window resizing events, e.g., when running in an xterm. -See the \fBresizeterm\fR(3) -and \fBwresize\fR(3) manual pages for details. -In addition, the library may be configured with a SIGWINCH handler. +See the \fBresizeterm\fP(3) +and \fBwresize\fP(3) manual pages for details. +In addition, the library may be configured with a \fBSIGWINCH\fP handler. .PP -The \fBncurses\fR library extends the fixed set of function key capabilities +The \fBncurses\fP library extends the fixed set of function key capabilities of terminals by allowing the application designer to define additional key sequences at runtime. -See the \fBdefine_key\fR(3) -\fBkey_defined\fR(3), -and \fBkeyok\fR(3) manual pages for details. +See the \fBdefine_key\fP(3) +\fBkey_defined\fP(3), +and \fBkeyok\fP(3) manual pages for details. .PP -The \fBncurses\fR library can exploit the capabilities of terminals which -implement the ISO-6429 SGR 39 and SGR 49 controls, which allow an application +The \fBncurses\fP library can exploit the capabilities of terminals which +implement the ISO\-6429 SGR 39 and SGR 49 controls, which allow an application to reset the terminal to its original foreground and background colors. From the users' perspective, the application is able to draw colored text on a background whose color is set independently, providing better control over color contrasts. -See the \fBdefault_colors\fR(3) manual page for details. +See the \fBdefault_colors\fP(3) manual page for details. .PP -The \fBncurses\fR library includes a function for directing application output +The \fBncurses\fP library includes a function for directing application output to a printer attached to the terminal device. -See the \fBcurs_print\fR(3) manual page for details. +See the \fBcurs_print\fP(3) manual page for details. .SH PORTABILITY -The \fBncurses\fR library is intended to be BASE-level conformant with XSI +The \fBncurses\fP library is intended to be BASE-level conformant with XSI Curses. The EXTENDED XSI Curses functionality (including color support) is supported. .PP A small number of local differences (that is, individual differences between -the XSI Curses and \fBncurses\fR calls) are described in \fBPORTABILITY\fR +the XSI Curses and \fBncurses\fP calls) are described in \fBPORTABILITY\fP sections of the library man pages. +.SS Error checking +In many cases, X/Open Curses is vague about error conditions, +omitting some of the SVr4 documentation. .PP -This implementation also contains several extensions: -.RS 5 -.PP -The routine \fBhas_key\fR is not part of XPG4, nor is it present in SVr4. -See the \fBcurs_getch\fR(3) manual page for details. -.PP -The routine \fBslk_attr\fR is not part of XPG4, nor is it present in SVr4. -See the \fBcurs_slk\fR(3) manual page for details. -.PP -The routines \fBgetmouse\fR, \fBmousemask\fR, \fBungetmouse\fR, -\fBmouseinterval\fR, and \fBwenclose\fR relating to mouse interfacing are not +Unlike other implementations, this one checks parameters such as pointers +to WINDOW structures to ensure they are not null. +The main reason for providing this behavior is to guard against programmer +error. +The standard interface does not provide a way for the library +to tell an application which of several possible errors were detected. +Relying on this (or some other) extension will adversely affect the +portability of curses applications. +.SS Extensions versus portability +Most of the extensions provided by ncurses have not been standardized. +Some have been incorporated into other implementations, such as +PDCurses or NetBSD curses. +Here are a few to consider: +.bP +The routine \fBhas_key\fP is not part of XPG4, nor is it present in SVr4. +See the \fBcurs_getch\fP(3) manual page for details. +.bP +The routine \fBslk_attr\fP is not part of XPG4, nor is it present in SVr4. +See the \fBcurs_slk\fP(3) manual page for details. +.bP +The routines \fBgetmouse\fP, \fBmousemask\fP, \fBungetmouse\fP, +\fBmouseinterval\fP, and \fBwenclose\fP relating to mouse interfacing are not part of XPG4, nor are they present in SVr4. -See the \fBcurs_mouse\fR(3) manual page for details. -.PP -The routine \fBmcprint\fR was not present in any previous curses implementation. -See the \fBcurs_print\fR(3) manual page for details. -.PP -The routine \fBwresize\fR is not part of XPG4, nor is it present in SVr4. -See the \fBwresize\fR(3) manual page for details. -.PP +See the \fBcurs_mouse\fP(3) manual page for details. +.bP +The routine \fBmcprint\fP was not present in any previous curses implementation. +See the \fBcurs_print\fP(3) manual page for details. +.bP +The routine \fBwresize\fP is not part of XPG4, nor is it present in SVr4. +See the \fBwresize\fP(3) manual page for details. +.bP The WINDOW structure's internal details can be hidden from application programs. -See \fBcurs_opaque\fR(3) for the discussion of \fBis_scrollok\fR, etc. -.RE -.PP -In historic curses versions, delays embedded in the capabilities \fBcr\fR, -\fBind\fR, \fBcub1\fR, \fBff\fR and \fBtab\fR activated corresponding delay +See \fBcurs_opaque\fP(3) for the discussion of \fBis_scrollok\fP, etc. +.bP +This implementation can be configured to provide rudimentary support +for multi-threaded applications. +See \fBcurs_threads\fP(3) for details. +.bP +This implementation can also be configured to provide a set of functions which +improve the ability to manage multiple screens. +See \fBcurs_sp_funcs\fP(3) for details. +.SS Padding differences +In historic curses versions, delays embedded in the capabilities \fBcr\fP, +\fBind\fP, \fBcub1\fP, \fBff\fP and \fBtab\fP activated corresponding delay bits in the UNIX tty driver. In this implementation, all padding is done by sending NUL bytes. This method is slightly more expensive, but narrows the interface to the UNIX kernel significantly and increases the package's portability correspondingly. -.SH NOTES -The header file \fB\fR automatically includes the header files -\fB\fR and \fB\fR. +.SS Header files +The header file \fB\fP automatically includes the header files +\fB\fP and \fB\fP. +.PP +X/Open Curses has more to say, +but does not finish the story: +.RS 4 +.PP +The inclusion of may make visible all symbols +from the headers , , , and . +.RE .PP -If standard output from a \fBncurses\fR program is re-directed to something +Here is a more complete story: +.bP +Starting with BSD curses, all implementations have included . +.IP +BSD curses included and from an internal header +"curses.ext" ("ext" was a short name for \fIexterns\fP). +.IP +BSD curses used internally (for \fBprintw\fP and \fBscanw\fP), +but nothing in itself relied upon . +.bP +SVr2 curses added \fBnewterm\fP(3), which relies upon . +That is, the function prototype uses \fBFILE\fP. +.IP +SVr4 curses added \fBputwin\fP and \fBgetwin\fP, which also use . +.IP +X/Open Curses documents all three of these functions. +.IP +SVr4 curses and X/Open Curses do not require the developer to +include before including . +Both document curses showing as the only required header. +.IP +As a result, standard will always include . +.bP +X/Open Curses is inconsistent with respect to SVr4 regarding . +.IP +As noted in \fBcurs_util\fP(3), ncurses includes from + (like SVr4). +.bP +X/Open's comments about and may refer to HP-UX and AIX: +.IP +HP-UX curses includes from +to declare \fBsetupterm\fP in curses.h, +but ncurses (and Solaris curses) do not. +.IP +AIX curses includes and . +Again, ncurses (and Solaris curses) do not. +.bP +X/Open says that \fImay\fP include , +but there is no requirement that it do that. +.IP +Some programs use functions declared in both and , +and must include both headers in the same module. +Very old versions of AIX curses required including +before including . +.IP +Because ncurses header files include the headers needed to +define datatypes used in the headers, +ncurses header files can be included in any order. +But for portability, you should include before . +.bP +X/Open Curses says \fI"may make visible"\fP +because including a header file does not necessarily make all symbols +in it visible (there are ifdef's to consider). +.IP +For instance, in ncurses \fImay\fP be included if +the proper symbol is defined, and if ncurses is configured for +wide-character support. +If the header is included, its symbols may be made visible. +That depends on the value used for \fB_XOPEN_SOURCE\fP +feature test macro. +.bP +X/Open Curses documents one required header, +in a special case: before to prototype +the \fBvw_printw\fP and \fBvw_scanw\fP functions +(as well as the obsolete +the \fBvwprintw\fP and \fBvwscanw\fP functions). +Each of those uses a \fBva_list\fP parameter. +.IP +The two obsolete functions were introduced in SVr3. +The other functions were introduced in X/Open Curses. +In between, SVr4 curses provided for the possibility that +an application might include either or . +Initially, that was done by using \fBvoid*\fP for the \fBva_list\fP +parameter. +Later, a special type (defined in ) was introduced, +to allow for compiler type-checking. +That special type is always available, +because is always included by . +.IP +None of the X/Open Curses implementations require an application +to include before because they either +have allowed for a special type, or (like ncurses) include +directly to provide a portable interface. +.SH NOTES +If standard output from a \fBncurses\fP program is re-directed to something which is not a tty, screen updates will be directed to standard error. This was an undocumented feature of AT&T System V Release 3 curses. .SH AUTHORS Zeyd M. Ben-Halim, Eric S. Raymond, Thomas E. Dickey. -Based on pcurses by Pavel Curtis. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Based on \fIpcurses\fP by Pavel Curtis. diff --git a/lib/libcurses/curses.h b/lib/libcurses/curses.h index 5a7b6913b60..4086d75e260 100644 --- a/lib/libcurses/curses.h +++ b/lib/libcurses/curses.h @@ -1,7 +1,8 @@ -/* $OpenBSD: curses.h,v 1.63 2022/10/10 09:03:08 nicm Exp $ */ +/* $OpenBSD: curses.h,v 1.64 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2021,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -34,46 +35,76 @@ * and: Thomas E. Dickey 1996-on * ****************************************************************************/ -/* $Id: curses.h,v 1.63 2022/10/10 09:03:08 nicm Exp $ */ +/* $Id: curses.h,v 1.64 2023/10/17 09:52:08 nicm Exp $ */ #ifndef __NCURSES_H #define __NCURSES_H +/* + The symbols beginning NCURSES_ or USE_ are configuration choices. + A few of the former can be overridden by applications at compile-time. + Most of the others correspond to configure-script options (or checks + by the configure-script for features of the system on which it is built). + + These symbols can be overridden by applications at compile-time: + NCURSES_NOMACROS suppresses macro definitions in favor of functions + NCURSES_WATTR_MACROS suppresses wattr_* macro definitions + NCURSES_WIDECHAR is an alternative for declaring wide-character functions. + + These symbols are used only when building ncurses: + NCURSES_ATTR_T + NCURSES_FIELD_INTERNALS + NCURSES_INTERNALS + + These symbols are set by the configure script: + NCURSES_ENABLE_STDBOOL_H + NCURSES_EXPANDED + NCURSES_EXT_COLORS + NCURSES_EXT_FUNCS + NCURSES_EXT_PUTWIN + NCURSES_NO_PADDING + NCURSES_OSPEED_COMPAT + NCURSES_PATHSEP + NCURSES_REENTRANT + */ + #define CURSES 1 #define CURSES_H 1 -/* This should be defined for the enhanced functionality to be visible. - * However, some of the wide-character (enhanced) functionality is missing. - * So we do not define it (yet). -#define _XOPEN_CURSES 1 - */ - /* These are defined only in curses.h, and are used for conditional compiles */ -#define NCURSES_VERSION_MAJOR 5 -#define NCURSES_VERSION_MINOR 7 -#define NCURSES_VERSION_PATCH 20081102 +#define NCURSES_VERSION_MAJOR 6 +#define NCURSES_VERSION_MINOR 4 +#define NCURSES_VERSION_PATCH 20230826 /* This is defined in more than one ncurses header, for identification */ #undef NCURSES_VERSION -#define NCURSES_VERSION "5.7" - -#if !defined(NCURSES_IMPEXP) -# define NCURSES_IMPEXP /* nothing */ -#endif -#if !defined(NCURSES_API) -# define NCURSES_API /* nothing */ -#endif -#if !defined(NCURSES_EXPORT) -# define NCURSES_EXPORT(type) NCURSES_IMPEXP type NCURSES_API -#endif -#if !defined(NCURSES_EXPORT_VAR) -# define NCURSES_EXPORT_VAR(type) NCURSES_IMPEXP type -#endif +#define NCURSES_VERSION "6.4" /* * Identify the mouse encoding version. */ -#define NCURSES_MOUSE_VERSION 1 +#define NCURSES_MOUSE_VERSION 2 + +/* + * Definitions to facilitate DLL's. + */ +#include + +/* + * Extra headers. + */ +#if 1 +#include +#endif + +#ifdef __cplusplus +#else +#if 0 +#include +#undef GCC_NORETURN +#define GCC_NORETURN _Noreturn +#endif +#endif /* * User-definable tweak to disable the include of . @@ -86,12 +117,6 @@ * NCURSES_ATTR_T is used to quiet compiler warnings when building ncurses * configured using --disable-macros. */ -#ifdef NCURSES_NOMACROS -#ifndef NCURSES_ATTR_T -#define NCURSES_ATTR_T attr_t -#endif -#endif /* NCURSES_NOMACROS */ - #ifndef NCURSES_ATTR_T #define NCURSES_ATTR_T int #endif @@ -107,18 +132,60 @@ #define NCURSES_INLINE inline /* - * The internal type used for color values + * The standard type used for color values, and for color-pairs. The latter + * allows the curses library to enumerate the combinations of foreground and + * background colors used by an application, and is normally the product of the + * total foreground and background colors. + * + * X/Open uses "short" for both of these types, ultimately because they are + * numbers from the SVr4 terminal database, which uses 16-bit signed values. */ #undef NCURSES_COLOR_T #define NCURSES_COLOR_T short +#undef NCURSES_PAIRS_T +#define NCURSES_PAIRS_T short + +/* + * Definitions used to make WINDOW and similar structs opaque. + */ +#ifndef NCURSES_INTERNALS +#define NCURSES_OPAQUE 0 +#define NCURSES_OPAQUE_FORM 0 +#define NCURSES_OPAQUE_MENU 0 +#define NCURSES_OPAQUE_PANEL 0 +#endif + /* - * Definition used to make WINDOW and similar structs opaque. + * Definition used to optionally suppress wattr* macros to help with the + * transition from ncurses5 to ncurses6 by allowing the header files to + * be shared across development packages for ncursesw in both ABIs. */ -#ifndef NCURSES_OPAQUE -#define NCURSES_OPAQUE 0 +#ifndef NCURSES_WATTR_MACROS +#define NCURSES_WATTR_MACROS 0 #endif +/* + * The reentrant code relies on the opaque setting, but adds features. + */ +#ifndef NCURSES_REENTRANT +#define NCURSES_REENTRANT 0 +#endif + +/* + * In certain environments, we must work around linker problems for data + */ +#undef NCURSES_BROKEN_LINKER +#if 0 +#define NCURSES_BROKEN_LINKER 1 +#endif + +/* + * Control whether bindings for interop support are added. + */ +#undef NCURSES_INTEROP_FUNCS +#define NCURSES_INTEROP_FUNCS 1 + /* * The internal type used for window dimensions. */ @@ -131,6 +198,20 @@ #undef NCURSES_TPARM_VARARGS #define NCURSES_TPARM_VARARGS 1 +/* + * Control type used for tparm's arguments. While X/Open equates long and + * char* values, this is not always workable for 64-bit platforms. + */ +#undef NCURSES_TPARM_ARG +#define NCURSES_TPARM_ARG intptr_t + +/* + * Control whether ncurses uses wcwidth() for checking width of line-drawing + * characters. + */ +#undef NCURSES_WCWIDTH_GRAPHICS +#define NCURSES_WCWIDTH_GRAPHICS 1 + /* * NCURSES_CH_T is used in building the library, but not used otherwise in * this header file, since that would make the normal/wide-character versions @@ -139,16 +220,18 @@ #undef NCURSES_CH_T #define NCURSES_CH_T cchar_t -#if 0 && defined(_LP64) +#if 1 && defined(_LP64) typedef unsigned chtype; typedef unsigned mmask_t; #else -typedef unsigned int chtype; -typedef unsigned long mmask_t; +typedef uint32_t chtype; +typedef uint32_t mmask_t; #endif +/* + * We need FILE, etc. Include this before checking any feature symbols. + */ #include -#include /* * With XPG4, you must define _XOPEN_SOURCE_EXTENDED, it is redundant (or @@ -165,9 +248,9 @@ typedef unsigned long mmask_t; #endif #endif /* NCURSES_WIDECHAR */ -#include /* we need va_list */ +#include /* we need va_list */ #if NCURSES_WIDECHAR -#include /* we want wchar_t */ +#include /* we want wchar_t */ #endif /* X/Open and SVr4 specify that curses implements 'bool'. However, C++ may also @@ -216,6 +299,8 @@ extern "C" { #define NCURSES_CAST(type,value) (type)(value) #endif +#define NCURSES_OK_ADDR(p) (0 != NCURSES_CAST(const void *, (p))) + /* * X/Open attributes. In the ncurses implementation, they are identical to the * A_ attributes. @@ -238,6 +323,10 @@ extern "C" { #define WA_TOP A_TOP #define WA_VERTICAL A_VERTICAL +#if 1 +#define WA_ITALIC A_ITALIC /* ncurses extension */ +#endif + /* colors */ #define COLOR_BLACK 0 #define COLOR_RED 1 @@ -250,14 +339,14 @@ extern "C" { /* line graphics */ -#if 0 || 0 +#if 0 || NCURSES_REENTRANT NCURSES_WRAPPED_VAR(chtype*, acs_map); -#define acs_map (_nc_acs_map()) +#define acs_map NCURSES_PUBLIC_VAR(acs_map()) #else extern NCURSES_EXPORT_VAR(chtype) acs_map[]; #endif -#define NCURSES_ACS(c) (acs_map[NCURSES_CAST(unsigned char,c)]) +#define NCURSES_ACS(c) (acs_map[NCURSES_CAST(unsigned char,(c))]) /* VT100 symbols begin here */ #define ACS_ULCORNER NCURSES_ACS('l') /* upper left corner */ @@ -344,7 +433,14 @@ extern NCURSES_EXPORT_VAR(chtype) acs_map[]; */ #define _NEWINDEX -1 +#ifdef NCURSES_INTERNALS +#undef SCREEN +#define SCREEN struct screen +SCREEN; +#else typedef struct screen SCREEN; +#endif + typedef struct _win_st WINDOW; typedef chtype attr_t; /* ...must be at least as wide as chtype */ @@ -363,21 +459,27 @@ typedef chtype attr_t; /* ...must be at least as wide as chtype */ #endif #if 0 -typedef unsigned short wchar_t; +typedef unsigned short wchar_t1; #endif #if 0 -typedef unsigned int wint_t; +typedef unsigned int wint_t1; #endif +/* + * cchar_t stores an array of CCHARW_MAX wide characters. The first is + * normally a spacing character. The others are non-spacing. If those + * (spacing and nonspacing) do not fill the array, a null L'\0' follows. + * Otherwise, a null is assumed to follow when extracting via getcchar(). + */ #define CCHARW_MAX 5 typedef struct { attr_t attr; wchar_t chars[CCHARW_MAX]; -#if 0 +#if 1 #undef NCURSES_EXT_COLORS -#define NCURSES_EXT_COLORS 20081102 +#define NCURSES_EXT_COLORS 20230826 int ext_color; /* color pair, must be more than 16-bits */ #endif } @@ -437,62 +539,13 @@ struct _win_st #if NCURSES_WIDECHAR cchar_t _bkgrnd; /* current background char/attribute pair */ -#if 0 +#if 1 int _color; /* current color-pair for non-space character */ #endif #endif }; #endif /* NCURSES_OPAQUE */ -/* - * This is an extension to support events... - */ -#if 1 -#ifdef NCURSES_WGETCH_EVENTS -#if !defined(__BEOS__) || defined(__HAIKU__) - /* Fix _nc_timed_wait() on BEOS... */ -# define NCURSES_EVENT_VERSION 1 -#endif /* !defined(__BEOS__) */ - -/* - * Bits to set in _nc_event.data.flags - */ -# define _NC_EVENT_TIMEOUT_MSEC 1 -# define _NC_EVENT_FILE 2 -# define _NC_EVENT_FILE_READABLE 2 -# if 0 /* Not supported yet... */ -# define _NC_EVENT_FILE_WRITABLE 4 -# define _NC_EVENT_FILE_EXCEPTION 8 -# endif - -typedef struct -{ - int type; - union - { - long timeout_msec; /* _NC_EVENT_TIMEOUT_MSEC */ - struct - { - unsigned int flags; - int fd; - unsigned int result; - } fev; /* _NC_EVENT_FILE */ - } data; -} _nc_event; - -typedef struct -{ - int count; - int result_flags; /* _NC_EVENT_TIMEOUT_MSEC or _NC_EVENT_FILE_READABLE */ - _nc_event *events[1]; -} _nc_eventlist; - -extern NCURSES_EXPORT(int) wgetch_events(WINDOW *, _nc_eventlist *); /* experimental */ -extern NCURSES_EXPORT(int) wgetnstr_events(WINDOW *,char *,int,_nc_eventlist *);/* experimental */ - -#endif /* NCURSES_WGETCH_EVENTS */ -#endif /* NCURSES_EXT_FUNCS */ - /* * GCC (and some other compilers) define '__attribute__'; we're using this * macro to alert the compiler to flag inconsistencies in printf/scanf-like @@ -506,23 +559,19 @@ extern NCURSES_EXPORT(int) wgetnstr_events(WINDOW *,char *,int,_nc_eventlist *); /* * We cannot define these in ncurses_cfg.h, since they require parameters to be - * passed (that is non-portable). If you happen to be using gcc with warnings - * enabled, define - * GCC_PRINTF - * GCC_SCANF - * to improve checking of calls to printw(), etc. + * passed (that is non-portable). */ #ifndef GCC_PRINTFLIKE -#if defined(GCC_PRINTF) && !defined(printf) -#define GCC_PRINTFLIKE(fmt,var) __attribute__((__format__(printf,fmt,var))) +#ifndef printf +#define GCC_PRINTFLIKE(fmt,var) __attribute__((format(printf,fmt,var))) #else #define GCC_PRINTFLIKE(fmt,var) /*nothing*/ #endif #endif #ifndef GCC_SCANFLIKE -#if defined(GCC_SCANF) && !defined(scanf) -#define GCC_SCANFLIKE(fmt,var) __attribute__((__format__(scanf,fmt,var))) +#ifndef scanf +#define GCC_SCANFLIKE(fmt,var) __attribute__((format(scanf,fmt,var))) #else #define GCC_SCANFLIKE(fmt,var) /*nothing*/ #endif @@ -536,6 +585,19 @@ extern NCURSES_EXPORT(int) wgetnstr_events(WINDOW *,char *,int,_nc_eventlist *); #define GCC_UNUSED /* nothing */ #endif +#undef GCC_DEPRECATED +#if (__GNUC__ - 0 > 3 || (__GNUC__ - 0 == 3 && __GNUC_MINOR__ - 0 >= 2)) && !defined(NCURSES_INTERNALS) +#define GCC_DEPRECATED(msg) __attribute__((deprecated)) +#else +#define GCC_DEPRECATED(msg) /* nothing */ +#endif + +/* + * Curses uses a helper function. Define our type for this to simplify + * extending it for the sp-funcs feature. + */ +typedef int (*NCURSES_OUTC)(int); + /* * Function prototypes. This is the complete X/Open Curses list of required * functions. Those marked `generated' will have sources generated from the @@ -551,10 +613,10 @@ extern NCURSES_EXPORT(int) addstr (const char *); /* generated */ extern NCURSES_EXPORT(int) attroff (NCURSES_ATTR_T); /* generated */ extern NCURSES_EXPORT(int) attron (NCURSES_ATTR_T); /* generated */ extern NCURSES_EXPORT(int) attrset (NCURSES_ATTR_T); /* generated */ -extern NCURSES_EXPORT(int) attr_get (attr_t *, short *, void *); /* generated */ +extern NCURSES_EXPORT(int) attr_get (attr_t *, NCURSES_PAIRS_T *, void *); /* generated */ extern NCURSES_EXPORT(int) attr_off (attr_t, void *); /* generated */ extern NCURSES_EXPORT(int) attr_on (attr_t, void *); /* generated */ -extern NCURSES_EXPORT(int) attr_set (attr_t, short, void *); /* generated */ +extern NCURSES_EXPORT(int) attr_set (attr_t, NCURSES_PAIRS_T, void *); /* generated */ extern NCURSES_EXPORT(int) baudrate (void); /* implemented */ extern NCURSES_EXPORT(int) beep (void); /* implemented */ extern NCURSES_EXPORT(int) bkgd (chtype); /* generated */ @@ -563,13 +625,13 @@ extern NCURSES_EXPORT(int) border (chtype,chtype,chtype,chtype,chtype,chtype,cht extern NCURSES_EXPORT(int) box (WINDOW *, chtype, chtype); /* generated */ extern NCURSES_EXPORT(bool) can_change_color (void); /* implemented */ extern NCURSES_EXPORT(int) cbreak (void); /* implemented */ -extern NCURSES_EXPORT(int) chgat (int, attr_t, short, const void *); /* generated */ +extern NCURSES_EXPORT(int) chgat (int, attr_t, NCURSES_PAIRS_T, const void *); /* generated */ extern NCURSES_EXPORT(int) clear (void); /* generated */ extern NCURSES_EXPORT(int) clearok (WINDOW *,bool); /* implemented */ extern NCURSES_EXPORT(int) clrtobot (void); /* generated */ extern NCURSES_EXPORT(int) clrtoeol (void); /* generated */ -extern NCURSES_EXPORT(int) color_content (short,short*,short*,short*); /* implemented */ -extern NCURSES_EXPORT(int) color_set (short,void*); /* generated */ +extern NCURSES_EXPORT(int) color_content (NCURSES_COLOR_T,NCURSES_COLOR_T*,NCURSES_COLOR_T*,NCURSES_COLOR_T*); /* implemented */ +extern NCURSES_EXPORT(int) color_set (NCURSES_PAIRS_T,void*); /* generated */ extern NCURSES_EXPORT(int) COLOR_PAIR (int); /* generated */ extern NCURSES_EXPORT(int) copywin (const WINDOW*,WINDOW*,int,int,int,int,int,int,int); /* implemented */ extern NCURSES_EXPORT(int) curs_set (int); /* implemented */ @@ -608,8 +670,8 @@ extern NCURSES_EXPORT(chtype) inch (void); /* generated */ extern NCURSES_EXPORT(int) inchnstr (chtype *, int); /* generated */ extern NCURSES_EXPORT(int) inchstr (chtype *); /* generated */ extern NCURSES_EXPORT(WINDOW *) initscr (void); /* implemented */ -extern NCURSES_EXPORT(int) init_color (short,short,short,short); /* implemented */ -extern NCURSES_EXPORT(int) init_pair (short,short,short); /* implemented */ +extern NCURSES_EXPORT(int) init_color (NCURSES_COLOR_T,NCURSES_COLOR_T,NCURSES_COLOR_T,NCURSES_COLOR_T); /* implemented */ +extern NCURSES_EXPORT(int) init_pair (NCURSES_PAIRS_T,NCURSES_COLOR_T,NCURSES_COLOR_T); /* implemented */ extern NCURSES_EXPORT(int) innstr (char *, int); /* generated */ extern NCURSES_EXPORT(int) insch (chtype); /* generated */ extern NCURSES_EXPORT(int) insdelln (int); /* generated */ @@ -633,7 +695,7 @@ extern NCURSES_EXPORT(int) mvaddchnstr (int, int, const chtype *, int); /* gener extern NCURSES_EXPORT(int) mvaddchstr (int, int, const chtype *); /* generated */ extern NCURSES_EXPORT(int) mvaddnstr (int, int, const char *, int); /* generated */ extern NCURSES_EXPORT(int) mvaddstr (int, int, const char *); /* generated */ -extern NCURSES_EXPORT(int) mvchgat (int, int, int, attr_t, short, const void *); /* generated */ +extern NCURSES_EXPORT(int) mvchgat (int, int, int, attr_t, NCURSES_PAIRS_T, const void *); /* generated */ extern NCURSES_EXPORT(int) mvcur (int,int,int,int); /* implemented */ extern NCURSES_EXPORT(int) mvdelch (int, int); /* generated */ extern NCURSES_EXPORT(int) mvderwin (WINDOW *, int, int); /* implemented */ @@ -651,7 +713,7 @@ extern NCURSES_EXPORT(int) mvinsstr (int, int, const char *); /* generated */ extern NCURSES_EXPORT(int) mvinstr (int, int, char *); /* generated */ extern NCURSES_EXPORT(int) mvprintw (int,int, const char *,...) /* implemented */ GCC_PRINTFLIKE(3,4); -extern NCURSES_EXPORT(int) mvscanw (int,int, NCURSES_CONST char *,...) /* implemented */ +extern NCURSES_EXPORT(int) mvscanw (int,int, const char *,...) /* implemented */ GCC_SCANFLIKE(3,4); extern NCURSES_EXPORT(int) mvvline (int, int, chtype, int); /* generated */ extern NCURSES_EXPORT(int) mvwaddch (WINDOW *, int, int, const chtype); /* generated */ @@ -659,7 +721,7 @@ extern NCURSES_EXPORT(int) mvwaddchnstr (WINDOW *, int, int, const chtype *, int extern NCURSES_EXPORT(int) mvwaddchstr (WINDOW *, int, int, const chtype *); /* generated */ extern NCURSES_EXPORT(int) mvwaddnstr (WINDOW *, int, int, const char *, int); /* generated */ extern NCURSES_EXPORT(int) mvwaddstr (WINDOW *, int, int, const char *); /* generated */ -extern NCURSES_EXPORT(int) mvwchgat (WINDOW *, int, int, int, attr_t, short, const void *);/* generated */ +extern NCURSES_EXPORT(int) mvwchgat (WINDOW *, int, int, int, attr_t, NCURSES_PAIRS_T, const void *);/* generated */ extern NCURSES_EXPORT(int) mvwdelch (WINDOW *, int, int); /* generated */ extern NCURSES_EXPORT(int) mvwgetch (WINDOW *, int, int); /* generated */ extern NCURSES_EXPORT(int) mvwgetnstr (WINDOW *, int, int, char *, int); /* generated */ @@ -672,17 +734,17 @@ extern NCURSES_EXPORT(int) mvwinchstr (WINDOW *, int, int, chtype *); /* genera extern NCURSES_EXPORT(int) mvwinnstr (WINDOW *, int, int, char *, int); /* generated */ extern NCURSES_EXPORT(int) mvwinsch (WINDOW *, int, int, chtype); /* generated */ extern NCURSES_EXPORT(int) mvwinsnstr (WINDOW *, int, int, const char *, int); /* generated */ -extern NCURSES_EXPORT(int) mvwinsstr (WINDOW *, int, int, const char *); /* generated */ +extern NCURSES_EXPORT(int) mvwinsstr (WINDOW *, int, int, const char *); /* generated */ extern NCURSES_EXPORT(int) mvwinstr (WINDOW *, int, int, char *); /* generated */ extern NCURSES_EXPORT(int) mvwprintw (WINDOW*,int,int, const char *,...) /* implemented */ GCC_PRINTFLIKE(4,5); -extern NCURSES_EXPORT(int) mvwscanw (WINDOW *,int,int, NCURSES_CONST char *,...) /* implemented */ +extern NCURSES_EXPORT(int) mvwscanw (WINDOW *,int,int, const char *,...) /* implemented */ GCC_SCANFLIKE(4,5); extern NCURSES_EXPORT(int) mvwvline (WINDOW *,int, int, chtype, int); /* generated */ extern NCURSES_EXPORT(int) napms (int); /* implemented */ -extern NCURSES_EXPORT(WINDOW *) newpad (int,int); /* implemented */ -extern NCURSES_EXPORT(SCREEN *) newterm (NCURSES_CONST char *,FILE *,FILE *); /* implemented */ -extern NCURSES_EXPORT(WINDOW *) newwin (int,int,int,int); /* implemented */ +extern NCURSES_EXPORT(WINDOW *) newpad (int,int); /* implemented */ +extern NCURSES_EXPORT(SCREEN *) newterm (const char *,FILE *,FILE *); /* implemented */ +extern NCURSES_EXPORT(WINDOW *) newwin (int,int,int,int); /* implemented */ extern NCURSES_EXPORT(int) nl (void); /* implemented */ extern NCURSES_EXPORT(int) nocbreak (void); /* implemented */ extern NCURSES_EXPORT(int) nodelay (WINDOW *,bool); /* implemented */ @@ -693,7 +755,7 @@ extern NCURSES_EXPORT(int) noraw (void); /* implemented */ extern NCURSES_EXPORT(int) notimeout (WINDOW *,bool); /* implemented */ extern NCURSES_EXPORT(int) overlay (const WINDOW*,WINDOW *); /* implemented */ extern NCURSES_EXPORT(int) overwrite (const WINDOW*,WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) pair_content (short,short*,short*); /* implemented */ +extern NCURSES_EXPORT(int) pair_content (NCURSES_PAIRS_T,NCURSES_COLOR_T*,NCURSES_COLOR_T*); /* implemented */ extern NCURSES_EXPORT(int) PAIR_NUMBER (int); /* generated */ extern NCURSES_EXPORT(int) pechochar (WINDOW *, const chtype); /* implemented */ extern NCURSES_EXPORT(int) pnoutrefresh (WINDOW*,int,int,int,int,int,int);/* implemented */ @@ -710,7 +772,7 @@ extern NCURSES_EXPORT(int) reset_prog_mode (void); /* implemented */ extern NCURSES_EXPORT(int) reset_shell_mode (void); /* implemented */ extern NCURSES_EXPORT(int) ripoffline (int, int (*)(WINDOW *, int)); /* implemented */ extern NCURSES_EXPORT(int) savetty (void); /* implemented */ -extern NCURSES_EXPORT(int) scanw (NCURSES_CONST char *,...) /* implemented */ +extern NCURSES_EXPORT(int) scanw (const char *,...) /* implemented */ GCC_SCANFLIKE(1,2); extern NCURSES_EXPORT(int) scr_dump (const char *); /* implemented */ extern NCURSES_EXPORT(int) scr_init (const char *); /* implemented */ @@ -727,9 +789,9 @@ extern NCURSES_EXPORT(int) slk_attron (const chtype); /* implemented */ extern NCURSES_EXPORT(int) slk_attr_on (attr_t,void*); /* generated:WIDEC */ extern NCURSES_EXPORT(int) slk_attrset (const chtype); /* implemented */ extern NCURSES_EXPORT(attr_t) slk_attr (void); /* implemented */ -extern NCURSES_EXPORT(int) slk_attr_set (const attr_t,short,void*); /* implemented */ +extern NCURSES_EXPORT(int) slk_attr_set (const attr_t,NCURSES_PAIRS_T,void*); /* implemented */ extern NCURSES_EXPORT(int) slk_clear (void); /* implemented */ -extern NCURSES_EXPORT(int) slk_color (short); /* implemented */ +extern NCURSES_EXPORT(int) slk_color (NCURSES_PAIRS_T); /* implemented */ extern NCURSES_EXPORT(int) slk_init (int); /* implemented */ extern NCURSES_EXPORT(char *) slk_label (int); /* implemented */ extern NCURSES_EXPORT(int) slk_noutrefresh (void); /* implemented */ @@ -752,13 +814,18 @@ extern NCURSES_EXPORT(int) typeahead (int); /* implemented */ extern NCURSES_EXPORT(int) ungetch (int); /* implemented */ extern NCURSES_EXPORT(int) untouchwin (WINDOW *); /* generated */ extern NCURSES_EXPORT(void) use_env (bool); /* implemented */ +extern NCURSES_EXPORT(void) use_tioctl (bool); /* implemented */ extern NCURSES_EXPORT(int) vidattr (chtype); /* implemented */ -extern NCURSES_EXPORT(int) vidputs (chtype, int (*)(int)); /* implemented */ +extern NCURSES_EXPORT(int) vidputs (chtype, NCURSES_OUTC); /* implemented */ extern NCURSES_EXPORT(int) vline (chtype, int); /* generated */ -extern NCURSES_EXPORT(int) vwprintw (WINDOW *, const char *,va_list); /* implemented */ -extern NCURSES_EXPORT(int) vw_printw (WINDOW *, const char *,va_list); /* generated */ -extern NCURSES_EXPORT(int) vwscanw (WINDOW *, NCURSES_CONST char *,va_list); /* implemented */ -extern NCURSES_EXPORT(int) vw_scanw (WINDOW *, NCURSES_CONST char *,va_list); /* generated */ +extern NCURSES_EXPORT(int) vwprintw (WINDOW *, const char *, va_list) GCC_DEPRECATED(use vw_printw) /* implemented */ + GCC_PRINTFLIKE(2,0); +extern NCURSES_EXPORT(int) vw_printw (WINDOW *, const char *, va_list) /* implemented */ + GCC_PRINTFLIKE(2,0); +extern NCURSES_EXPORT(int) vwscanw (WINDOW *, const char *, va_list) GCC_DEPRECATED(use vw_scanw) /* implemented */ + GCC_SCANFLIKE(2,0); +extern NCURSES_EXPORT(int) vw_scanw (WINDOW *, const char *, va_list) /* implemented */ + GCC_SCANFLIKE(2,0); extern NCURSES_EXPORT(int) waddch (WINDOW *, const chtype); /* implemented */ extern NCURSES_EXPORT(int) waddchnstr (WINDOW *,const chtype *,int); /* implemented */ extern NCURSES_EXPORT(int) waddchstr (WINDOW *,const chtype *); /* generated */ @@ -767,18 +834,18 @@ extern NCURSES_EXPORT(int) waddstr (WINDOW *,const char *); /* generated */ extern NCURSES_EXPORT(int) wattron (WINDOW *, int); /* generated */ extern NCURSES_EXPORT(int) wattroff (WINDOW *, int); /* generated */ extern NCURSES_EXPORT(int) wattrset (WINDOW *, int); /* generated */ -extern NCURSES_EXPORT(int) wattr_get (WINDOW *, attr_t *, short *, void *); /* generated */ +extern NCURSES_EXPORT(int) wattr_get (WINDOW *, attr_t *, NCURSES_PAIRS_T *, void *); /* generated */ extern NCURSES_EXPORT(int) wattr_on (WINDOW *, attr_t, void *); /* implemented */ extern NCURSES_EXPORT(int) wattr_off (WINDOW *, attr_t, void *); /* implemented */ -extern NCURSES_EXPORT(int) wattr_set (WINDOW *, attr_t, short, void *); /* generated */ +extern NCURSES_EXPORT(int) wattr_set (WINDOW *, attr_t, NCURSES_PAIRS_T, void *); /* generated */ extern NCURSES_EXPORT(int) wbkgd (WINDOW *, chtype); /* implemented */ extern NCURSES_EXPORT(void) wbkgdset (WINDOW *,chtype); /* implemented */ extern NCURSES_EXPORT(int) wborder (WINDOW *,chtype,chtype,chtype,chtype,chtype,chtype,chtype,chtype); /* implemented */ -extern NCURSES_EXPORT(int) wchgat (WINDOW *, int, attr_t, short, const void *);/* implemented */ +extern NCURSES_EXPORT(int) wchgat (WINDOW *, int, attr_t, NCURSES_PAIRS_T, const void *);/* implemented */ extern NCURSES_EXPORT(int) wclear (WINDOW *); /* implemented */ extern NCURSES_EXPORT(int) wclrtobot (WINDOW *); /* implemented */ extern NCURSES_EXPORT(int) wclrtoeol (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) wcolor_set (WINDOW*,short,void*); /* implemented */ +extern NCURSES_EXPORT(int) wcolor_set (WINDOW*,NCURSES_PAIRS_T,void*); /* implemented */ extern NCURSES_EXPORT(void) wcursyncup (WINDOW *); /* implemented */ extern NCURSES_EXPORT(int) wdelch (WINDOW *); /* implemented */ extern NCURSES_EXPORT(int) wdeleteln (WINDOW *); /* generated */ @@ -804,7 +871,7 @@ extern NCURSES_EXPORT(int) wprintw (WINDOW *, const char *,...) /* implemented GCC_PRINTFLIKE(2,3); extern NCURSES_EXPORT(int) wredrawln (WINDOW *,int,int); /* implemented */ extern NCURSES_EXPORT(int) wrefresh (WINDOW *); /* implemented */ -extern NCURSES_EXPORT(int) wscanw (WINDOW *, NCURSES_CONST char *,...) /* implemented */ +extern NCURSES_EXPORT(int) wscanw (WINDOW *, const char *,...) /* implemented */ GCC_SCANFLIKE(2,3); extern NCURSES_EXPORT(int) wscrl (WINDOW *,int); /* implemented */ extern NCURSES_EXPORT(int) wsetscrreg (WINDOW *,int,int); /* implemented */ @@ -819,18 +886,21 @@ extern NCURSES_EXPORT(int) wvline (WINDOW *,chtype,int); /* implemented */ /* * These are also declared in : */ -extern NCURSES_EXPORT(int) tigetflag (NCURSES_CONST char *); /* implemented */ -extern NCURSES_EXPORT(int) tigetnum (NCURSES_CONST char *); /* implemented */ -extern NCURSES_EXPORT(char *) tigetstr (NCURSES_CONST char *); /* implemented */ +extern NCURSES_EXPORT(int) tigetflag (const char *); /* implemented */ +extern NCURSES_EXPORT(int) tigetnum (const char *); /* implemented */ +extern NCURSES_EXPORT(char *) tigetstr (const char *); /* implemented */ extern NCURSES_EXPORT(int) putp (const char *); /* implemented */ #if NCURSES_TPARM_VARARGS -extern NCURSES_EXPORT(char *) tparm (NCURSES_CONST char *, ...); /* special */ +extern NCURSES_EXPORT(char *) tparm (const char *, ...); /* special */ #else -extern NCURSES_EXPORT(char *) tparm (NCURSES_CONST char *, long,long,long,long,long,long,long,long,long); /* special */ -extern NCURSES_EXPORT(char *) tparm_varargs (NCURSES_CONST char *, ...); /* special */ +extern NCURSES_EXPORT(char *) tparm (const char *, NCURSES_TPARM_ARG,NCURSES_TPARM_ARG,NCURSES_TPARM_ARG,NCURSES_TPARM_ARG,NCURSES_TPARM_ARG,NCURSES_TPARM_ARG,NCURSES_TPARM_ARG,NCURSES_TPARM_ARG,NCURSES_TPARM_ARG); /* special */ #endif +extern NCURSES_EXPORT(char *) tiparm (const char *, ...); /* special */ +extern NCURSES_EXPORT(char *) tiparm_s (int, int, const char *, ...); /* special */ +extern NCURSES_EXPORT(int) tiscan_s (int *, int *, const char *); /* special */ + /* * These functions are not in X/Open, but we use them in macro definitions: */ @@ -856,27 +926,46 @@ extern NCURSES_EXPORT(int) getpary (const WINDOW *); /* generated */ */ #if 1 #undef NCURSES_EXT_FUNCS -#define NCURSES_EXT_FUNCS 20081102 +#define NCURSES_EXT_FUNCS 20230826 typedef int (*NCURSES_WINDOW_CB)(WINDOW *, void *); typedef int (*NCURSES_SCREEN_CB)(SCREEN *, void *); -extern NCURSES_EXPORT(bool) is_term_resized (int, int); -extern NCURSES_EXPORT(char *) keybound (int, int); -extern NCURSES_EXPORT(const char *) curses_version (void); +extern NCURSES_EXPORT(int) alloc_pair (int, int); extern NCURSES_EXPORT(int) assume_default_colors (int, int); +extern NCURSES_EXPORT(const char *) curses_version (void); extern NCURSES_EXPORT(int) define_key (const char *, int); +extern NCURSES_EXPORT(int) extended_color_content(int, int *, int *, int *); +extern NCURSES_EXPORT(int) extended_pair_content(int, int *, int *); +extern NCURSES_EXPORT(int) extended_slk_color(int); +extern NCURSES_EXPORT(int) find_pair (int, int); +extern NCURSES_EXPORT(int) free_pair (int); +extern NCURSES_EXPORT(int) get_escdelay (void); +extern NCURSES_EXPORT(int) init_extended_color(int, int, int, int); +extern NCURSES_EXPORT(int) init_extended_pair(int, int, int); +extern NCURSES_EXPORT(int) is_cbreak(void); +extern NCURSES_EXPORT(int) is_echo(void); +extern NCURSES_EXPORT(int) is_nl(void); +extern NCURSES_EXPORT(int) is_raw(void); +extern NCURSES_EXPORT(bool) is_term_resized (int, int); extern NCURSES_EXPORT(int) key_defined (const char *); +extern NCURSES_EXPORT(char *) keybound (int, int); extern NCURSES_EXPORT(int) keyok (int, bool); +extern NCURSES_EXPORT(void) nofilter(void); +extern NCURSES_EXPORT(void) reset_color_pairs (void); extern NCURSES_EXPORT(int) resize_term (int, int); extern NCURSES_EXPORT(int) resizeterm (int, int); extern NCURSES_EXPORT(int) set_escdelay (int); extern NCURSES_EXPORT(int) set_tabsize (int); extern NCURSES_EXPORT(int) use_default_colors (void); -extern NCURSES_EXPORT(int) use_extended_names (bool); extern NCURSES_EXPORT(int) use_legacy_coding (int); extern NCURSES_EXPORT(int) use_screen (SCREEN *, NCURSES_SCREEN_CB, void *); extern NCURSES_EXPORT(int) use_window (WINDOW *, NCURSES_WINDOW_CB, void *); extern NCURSES_EXPORT(int) wresize (WINDOW *, int, int); -extern NCURSES_EXPORT(void) nofilter(void); + +#if 1 +#undef NCURSES_XNAMES +#define NCURSES_XNAMES 1 +extern NCURSES_EXPORT(int) use_extended_names (bool); +#endif /* * These extensions provide access to information stored in the WINDOW even @@ -891,18 +980,145 @@ extern NCURSES_EXPORT(bool) is_keypad (const WINDOW *); /* generated */ extern NCURSES_EXPORT(bool) is_leaveok (const WINDOW *); /* generated */ extern NCURSES_EXPORT(bool) is_nodelay (const WINDOW *); /* generated */ extern NCURSES_EXPORT(bool) is_notimeout (const WINDOW *); /* generated */ +extern NCURSES_EXPORT(bool) is_pad (const WINDOW *); /* generated */ extern NCURSES_EXPORT(bool) is_scrollok (const WINDOW *); /* generated */ +extern NCURSES_EXPORT(bool) is_subwin (const WINDOW *); /* generated */ extern NCURSES_EXPORT(bool) is_syncok (const WINDOW *); /* generated */ +extern NCURSES_EXPORT(int) wgetdelay (const WINDOW *); /* generated */ extern NCURSES_EXPORT(int) wgetscrreg (const WINDOW *, int *, int *); /* generated */ #else #define curses_version() NCURSES_VERSION #endif +/* + * Extra extension-functions, which pass a SCREEN pointer rather than using + * a global variable SP. + */ +#if 1 +#undef NCURSES_SP_FUNCS +#define NCURSES_SP_FUNCS 20230826 +#define NCURSES_SP_NAME(name) name##_sp + +/* Define the sp-funcs helper function */ +#define NCURSES_SP_OUTC NCURSES_SP_NAME(NCURSES_OUTC) +typedef int (*NCURSES_SP_OUTC)(SCREEN*, int); + +extern NCURSES_EXPORT(SCREEN *) new_prescr (void); /* implemented:SP_FUNC */ + +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(baudrate) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(beep) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(can_change_color) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(cbreak) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(curs_set) (SCREEN*, int); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(color_content) (SCREEN*, NCURSES_PAIRS_T, NCURSES_COLOR_T*, NCURSES_COLOR_T*, NCURSES_COLOR_T*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(def_prog_mode) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(def_shell_mode) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(delay_output) (SCREEN*, int); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(doupdate) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(echo) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(endwin) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(char) NCURSES_SP_NAME(erasechar) (SCREEN*);/* implemented:SP_FUNC */ +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(filter) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(flash) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(flushinp) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(WINDOW *) NCURSES_SP_NAME(getwin) (SCREEN*, FILE *); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(halfdelay) (SCREEN*, int); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(has_colors) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(has_ic) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(has_il) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(init_color) (SCREEN*, NCURSES_COLOR_T, NCURSES_COLOR_T, NCURSES_COLOR_T, NCURSES_COLOR_T); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(init_pair) (SCREEN*, NCURSES_PAIRS_T, NCURSES_COLOR_T, NCURSES_COLOR_T); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(intrflush) (SCREEN*, WINDOW*, bool); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(isendwin) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(NCURSES_CONST char *) NCURSES_SP_NAME(keyname) (SCREEN*, int); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(char) NCURSES_SP_NAME(killchar) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(longname) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(mvcur) (SCREEN*, int, int, int, int); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(napms) (SCREEN*, int); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(WINDOW *) NCURSES_SP_NAME(newpad) (SCREEN*, int, int); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(SCREEN *) NCURSES_SP_NAME(newterm) (SCREEN*, const char *, FILE *, FILE *); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(WINDOW *) NCURSES_SP_NAME(newwin) (SCREEN*, int, int, int, int); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(nl) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(nocbreak) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(noecho) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(nonl) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(noqiflush) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(noraw) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(pair_content) (SCREEN*, NCURSES_PAIRS_T, NCURSES_COLOR_T*, NCURSES_COLOR_T*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(qiflush) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(raw) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(reset_prog_mode) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(reset_shell_mode) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(resetty) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(ripoffline) (SCREEN*, int, int (*)(WINDOW *, int)); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(savetty) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(scr_init) (SCREEN*, const char *); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(scr_restore) (SCREEN*, const char *); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(scr_set) (SCREEN*, const char *); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_attroff) (SCREEN*, const chtype); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_attron) (SCREEN*, const chtype); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_attrset) (SCREEN*, const chtype); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(attr_t) NCURSES_SP_NAME(slk_attr) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_attr_set) (SCREEN*, const attr_t, NCURSES_PAIRS_T, void*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_clear) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_color) (SCREEN*, NCURSES_PAIRS_T); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_init) (SCREEN*, int); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(slk_label) (SCREEN*, int); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_noutrefresh) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_refresh) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_restore) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_set) (SCREEN*, int, const char *, int); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(slk_touch) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(start_color) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(chtype) NCURSES_SP_NAME(termattrs) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(termname) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(typeahead) (SCREEN*, int); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(ungetch) (SCREEN*, int); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(use_env) (SCREEN*, bool); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(use_tioctl) (SCREEN*, bool); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(vidattr) (SCREEN*, chtype); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(vidputs) (SCREEN*, chtype, NCURSES_SP_OUTC); /* implemented:SP_FUNC */ +#if 1 +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(alloc_pair) (SCREEN*, int, int); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(assume_default_colors) (SCREEN*, int, int); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(define_key) (SCREEN*, const char *, int); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(extended_color_content) (SCREEN*, int, int *, int *, int *); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(extended_pair_content) (SCREEN*, int, int *, int *); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(extended_slk_color) (SCREEN*, int); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(find_pair) (SCREEN*, int, int); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(free_pair) (SCREEN*, int); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(get_escdelay) (SCREEN*); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(init_extended_color) (SCREEN*, int, int, int, int); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(init_extended_pair) (SCREEN*, int, int, int); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(is_cbreak) (SCREEN*); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(is_echo) (SCREEN*); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(is_nl) (SCREEN*); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(is_raw) (SCREEN*); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(is_term_resized) (SCREEN*, int, int); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(key_defined) (SCREEN*, const char *); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(keybound) (SCREEN*, int, int); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(keyok) (SCREEN*, int, bool); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(nofilter) (SCREEN*); /* implemented */ /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(reset_color_pairs) (SCREEN*); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(resize_term) (SCREEN*, int, int); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(resizeterm) (SCREEN*, int, int); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(set_escdelay) (SCREEN*, int); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(set_tabsize) (SCREEN*, int); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(use_default_colors) (SCREEN*); /* implemented:EXT_SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(use_legacy_coding) (SCREEN*, int); /* implemented:EXT_SP_FUNC */ +#endif +#else +#undef NCURSES_SP_FUNCS +#define NCURSES_SP_FUNCS 0 +#define NCURSES_SP_NAME(name) name +#define NCURSES_SP_OUTC NCURSES_OUTC +#endif + /* attributes */ #define NCURSES_ATTR_SHIFT 8 -#define NCURSES_BITS(mask,shift) ((mask) << ((shift) + NCURSES_ATTR_SHIFT)) +#define NCURSES_BITS(mask,shift) (NCURSES_CAST(chtype,(mask)) << ((shift) + NCURSES_ATTR_SHIFT)) #define A_NORMAL (1U - 1U) #define A_ATTRIBUTES NCURSES_BITS(~(1U - 1U),0) @@ -924,6 +1140,10 @@ extern NCURSES_EXPORT(int) wgetscrreg (const WINDOW *, int *, int *); /* generat #define A_TOP NCURSES_BITS(1U,21) #define A_VERTICAL NCURSES_BITS(1U,22) +#if 1 +#define A_ITALIC NCURSES_BITS(1U,23) /* ncurses extension */ +#endif + /* * Most of the pseudo functions are macros that either provide compatibility * with older versions of curses, or provide inline functionality to improve @@ -934,7 +1154,7 @@ extern NCURSES_EXPORT(int) wgetscrreg (const WINDOW *, int *, int *); /* generat * These pseudo functions are always implemented as macros: */ -#define getyx(win,y,x) (y = getcury(win), x = getcurx(win)) +#define getyx(win,y,x) (y = getcury(win), x = getcurx(win)) #define getbegyx(win,y,x) (y = getbegy(win), x = getbegx(win)) #define getmaxyx(win,y,x) (y = getmaxy(win), x = getmaxx(win)) #define getparyx(win,y,x) (y = getpary(win), x = getparx(win)) @@ -964,7 +1184,7 @@ extern NCURSES_EXPORT(int) wgetscrreg (const WINDOW *, int *, int *); /* generat */ #define wgetstr(w, s) wgetnstr(w, s, -1) -#define getnstr(s, n) wgetnstr(stdscr, s, n) +#define getnstr(s, n) wgetnstr(stdscr, s, (n)) #define setterm(term) setupterm(term, 1, (int *)0) @@ -977,30 +1197,40 @@ extern NCURSES_EXPORT(int) wgetscrreg (const WINDOW *, int *, int *); /* generat /* It seems older SYSV curses versions define these */ #if !NCURSES_OPAQUE -#define getattrs(win) ((win) ? (win)->_attrs : A_NORMAL) -#define getcurx(win) ((win) ? (win)->_curx : ERR) -#define getcury(win) ((win) ? (win)->_cury : ERR) -#define getbegx(win) ((win) ? (win)->_begx : ERR) -#define getbegy(win) ((win) ? (win)->_begy : ERR) -#define getmaxx(win) ((win) ? ((win)->_maxx + 1) : ERR) -#define getmaxy(win) ((win) ? ((win)->_maxy + 1) : ERR) -#define getparx(win) ((win) ? (win)->_parx : ERR) -#define getpary(win) ((win) ? (win)->_pary : ERR) +#define getattrs(win) NCURSES_CAST(int, NCURSES_OK_ADDR(win) ? (win)->_attrs : A_NORMAL) +#define getcurx(win) (NCURSES_OK_ADDR(win) ? (win)->_curx : ERR) +#define getcury(win) (NCURSES_OK_ADDR(win) ? (win)->_cury : ERR) +#define getbegx(win) (NCURSES_OK_ADDR(win) ? (win)->_begx : ERR) +#define getbegy(win) (NCURSES_OK_ADDR(win) ? (win)->_begy : ERR) +#define getmaxx(win) (NCURSES_OK_ADDR(win) ? ((win)->_maxx + 1) : ERR) +#define getmaxy(win) (NCURSES_OK_ADDR(win) ? ((win)->_maxy + 1) : ERR) +#define getparx(win) (NCURSES_OK_ADDR(win) ? (win)->_parx : ERR) +#define getpary(win) (NCURSES_OK_ADDR(win) ? (win)->_pary : ERR) #endif /* NCURSES_OPAQUE */ -#define wstandout(win) (wattrset(win,A_STANDOUT)) -#define wstandend(win) (wattrset(win,A_NORMAL)) +#define wstandout(win) (wattrset(win,A_STANDOUT)) +#define wstandend(win) (wattrset(win,A_NORMAL)) #define wattron(win,at) wattr_on(win, NCURSES_CAST(attr_t, at), NULL) #define wattroff(win,at) wattr_off(win, NCURSES_CAST(attr_t, at), NULL) #if !NCURSES_OPAQUE -#if NCURSES_WIDECHAR && 0 -#define wattrset(win,at) ((win)->_color = PAIR_NUMBER(at), \ - (win)->_attrs = (at)) +#if NCURSES_WATTR_MACROS +#if NCURSES_WIDECHAR && 1 +#define wattrset(win,at) \ + (NCURSES_OK_ADDR(win) \ + ? ((win)->_color = NCURSES_CAST(int, PAIR_NUMBER(at)), \ + (win)->_attrs = NCURSES_CAST(attr_t, at), \ + OK) \ + : ERR) #else -#define wattrset(win,at) ((win)->_attrs = (at)) +#define wattrset(win,at) \ + (NCURSES_OK_ADDR(win) \ + ? ((win)->_attrs = NCURSES_CAST(attr_t, at), \ + OK) \ + : ERR) #endif +#endif /* NCURSES_WATTR_MACROS */ #endif /* NCURSES_OPAQUE */ #define scroll(win) wscrl(win,1) @@ -1011,15 +1241,15 @@ extern NCURSES_EXPORT(int) wgetscrreg (const WINDOW *, int *, int *); /* generat #define box(win, v, h) wborder(win, v, v, h, h, 0, 0, 0, 0) #define border(ls, rs, ts, bs, tl, tr, bl, br) wborder(stdscr, ls, rs, ts, bs, tl, tr, bl, br) -#define hline(ch, n) whline(stdscr, ch, n) -#define vline(ch, n) wvline(stdscr, ch, n) +#define hline(ch, n) whline(stdscr, ch, (n)) +#define vline(ch, n) wvline(stdscr, ch, (n)) #define winstr(w, s) winnstr(w, s, -1) #define winchstr(w, s) winchnstr(w, s, -1) #define winsstr(w, s) winsnstr(w, s, -1) #if !NCURSES_OPAQUE -#define redrawwin(win) wredrawln(win, 0, (win)->_maxy+1) +#define redrawwin(win) wredrawln(win, 0, (NCURSES_OK_ADDR(win) ? (win)->_maxy+1 : -1)) #endif /* NCURSES_OPAQUE */ #define waddstr(win,str) waddnstr(win,str,-1) @@ -1028,55 +1258,55 @@ extern NCURSES_EXPORT(int) wgetscrreg (const WINDOW *, int *, int *); /* generat /* * These apply to the first 256 color pairs. */ -#define COLOR_PAIR(n) NCURSES_BITS(n, 0) -#define PAIR_NUMBER(a) (NCURSES_CAST(int,(((a) & A_COLOR) >> NCURSES_ATTR_SHIFT))) +#define COLOR_PAIR(n) (NCURSES_BITS((n), 0) & A_COLOR) +#define PAIR_NUMBER(a) (NCURSES_CAST(int,((NCURSES_CAST(unsigned long,(a)) & A_COLOR) >> NCURSES_ATTR_SHIFT))) /* * pseudo functions for standard screen */ -#define addch(ch) waddch(stdscr,ch) -#define addchnstr(str,n) waddchnstr(stdscr,str,n) -#define addchstr(str) waddchstr(stdscr,str) -#define addnstr(str,n) waddnstr(stdscr,str,n) -#define addstr(str) waddnstr(stdscr,str,-1) -#define attroff(at) wattroff(stdscr,at) -#define attron(at) wattron(stdscr,at) -#define attrset(at) wattrset(stdscr,at) -#define attr_get(ap,cp,o) wattr_get(stdscr,ap,cp,o) -#define attr_off(a,o) wattr_off(stdscr,a,o) -#define attr_on(a,o) wattr_on(stdscr,a,o) -#define attr_set(a,c,o) wattr_set(stdscr,a,c,o) -#define bkgd(ch) wbkgd(stdscr,ch) -#define bkgdset(ch) wbkgdset(stdscr,ch) -#define chgat(n,a,c,o) wchgat(stdscr,n,a,c,o) +#define addch(ch) waddch(stdscr,(ch)) +#define addchnstr(str,n) waddchnstr(stdscr,(str),(n)) +#define addchstr(str) waddchstr(stdscr,(str)) +#define addnstr(str,n) waddnstr(stdscr,(str),(n)) +#define addstr(str) waddnstr(stdscr,(str),-1) +#define attr_get(ap,cp,o) wattr_get(stdscr,(ap),(cp),(o)) +#define attr_off(a,o) wattr_off(stdscr,(a),(o)) +#define attr_on(a,o) wattr_on(stdscr,(a),(o)) +#define attr_set(a,c,o) wattr_set(stdscr,(a),(c),(o)) +#define attroff(at) wattroff(stdscr,(at)) +#define attron(at) wattron(stdscr,(at)) +#define attrset(at) wattrset(stdscr,(at)) +#define bkgd(ch) wbkgd(stdscr,(ch)) +#define bkgdset(ch) wbkgdset(stdscr,(ch)) +#define chgat(n,a,c,o) wchgat(stdscr,(n),(a),(c),(o)) #define clear() wclear(stdscr) #define clrtobot() wclrtobot(stdscr) #define clrtoeol() wclrtoeol(stdscr) -#define color_set(c,o) wcolor_set(stdscr,c,o) +#define color_set(c,o) wcolor_set(stdscr,(c),(o)) #define delch() wdelch(stdscr) #define deleteln() winsdelln(stdscr,-1) -#define echochar(c) wechochar(stdscr,c) +#define echochar(c) wechochar(stdscr,(c)) #define erase() werase(stdscr) #define getch() wgetch(stdscr) -#define getstr(str) wgetstr(stdscr,str) +#define getstr(str) wgetstr(stdscr,(str)) #define inch() winch(stdscr) -#define inchnstr(s,n) winchnstr(stdscr,s,n) -#define inchstr(s) winchstr(stdscr,s) -#define innstr(s,n) winnstr(stdscr,s,n) -#define insch(c) winsch(stdscr,c) -#define insdelln(n) winsdelln(stdscr,n) +#define inchnstr(s,n) winchnstr(stdscr,(s),(n)) +#define inchstr(s) winchstr(stdscr,(s)) +#define innstr(s,n) winnstr(stdscr,(s),(n)) +#define insch(c) winsch(stdscr,(c)) +#define insdelln(n) winsdelln(stdscr,(n)) #define insertln() winsdelln(stdscr,1) -#define insnstr(s,n) winsnstr(stdscr,s,n) -#define insstr(s) winsstr(stdscr,s) -#define instr(s) winstr(stdscr,s) -#define move(y,x) wmove(stdscr,y,x) +#define insnstr(s,n) winsnstr(stdscr,(s),(n)) +#define insstr(s) winsstr(stdscr,(s)) +#define instr(s) winstr(stdscr,(s)) +#define move(y,x) wmove(stdscr,(y),(x)) #define refresh() wrefresh(stdscr) -#define scrl(n) wscrl(stdscr,n) -#define setscrreg(t,b) wsetscrreg(stdscr,t,b) +#define scrl(n) wscrl(stdscr,(n)) +#define setscrreg(t,b) wsetscrreg(stdscr,(t),(b)) #define standend() wstandend(stdscr) #define standout() wstandout(stdscr) -#define timeout(delay) wtimeout(stdscr,delay) +#define timeout(delay) wtimeout(stdscr,(delay)) #define wdeleteln(win) winsdelln(win,-1) #define winsertln(win) winsdelln(win,1) @@ -1084,72 +1314,99 @@ extern NCURSES_EXPORT(int) wgetscrreg (const WINDOW *, int *, int *); /* generat * mv functions */ -#define mvwaddch(win,y,x,ch) (wmove(win,y,x) == ERR ? ERR : waddch(win,ch)) -#define mvwaddchnstr(win,y,x,str,n) (wmove(win,y,x) == ERR ? ERR : waddchnstr(win,str,n)) -#define mvwaddchstr(win,y,x,str) (wmove(win,y,x) == ERR ? ERR : waddchnstr(win,str,-1)) -#define mvwaddnstr(win,y,x,str,n) (wmove(win,y,x) == ERR ? ERR : waddnstr(win,str,n)) -#define mvwaddstr(win,y,x,str) (wmove(win,y,x) == ERR ? ERR : waddnstr(win,str,-1)) -#define mvwdelch(win,y,x) (wmove(win,y,x) == ERR ? ERR : wdelch(win)) -#define mvwchgat(win,y,x,n,a,c,o) (wmove(win,y,x) == ERR ? ERR : wchgat(win,n,a,c,o)) -#define mvwgetch(win,y,x) (wmove(win,y,x) == ERR ? ERR : wgetch(win)) -#define mvwgetnstr(win,y,x,str,n) (wmove(win,y,x) == ERR ? ERR : wgetnstr(win,str,n)) -#define mvwgetstr(win,y,x,str) (wmove(win,y,x) == ERR ? ERR : wgetstr(win,str)) -#define mvwhline(win,y,x,c,n) (wmove(win,y,x) == ERR ? ERR : whline(win,c,n)) -#define mvwinch(win,y,x) (wmove(win,y,x) == ERR ? NCURSES_CAST(chtype, ERR) : winch(win)) -#define mvwinchnstr(win,y,x,s,n) (wmove(win,y,x) == ERR ? ERR : winchnstr(win,s,n)) -#define mvwinchstr(win,y,x,s) (wmove(win,y,x) == ERR ? ERR : winchstr(win,s)) -#define mvwinnstr(win,y,x,s,n) (wmove(win,y,x) == ERR ? ERR : winnstr(win,s,n)) -#define mvwinsch(win,y,x,c) (wmove(win,y,x) == ERR ? ERR : winsch(win,c)) -#define mvwinsnstr(win,y,x,s,n) (wmove(win,y,x) == ERR ? ERR : winsnstr(win,s,n)) -#define mvwinsstr(win,y,x,s) (wmove(win,y,x) == ERR ? ERR : winsstr(win,s)) -#define mvwinstr(win,y,x,s) (wmove(win,y,x) == ERR ? ERR : winstr(win,s)) -#define mvwvline(win,y,x,c,n) (wmove(win,y,x) == ERR ? ERR : wvline(win,c,n)) - -#define mvaddch(y,x,ch) mvwaddch(stdscr,y,x,ch) -#define mvaddchnstr(y,x,str,n) mvwaddchnstr(stdscr,y,x,str,n) -#define mvaddchstr(y,x,str) mvwaddchstr(stdscr,y,x,str) -#define mvaddnstr(y,x,str,n) mvwaddnstr(stdscr,y,x,str,n) -#define mvaddstr(y,x,str) mvwaddstr(stdscr,y,x,str) -#define mvchgat(y,x,n,a,c,o) mvwchgat(stdscr,y,x,n,a,c,o) -#define mvdelch(y,x) mvwdelch(stdscr,y,x) -#define mvgetch(y,x) mvwgetch(stdscr,y,x) -#define mvgetnstr(y,x,str,n) mvwgetnstr(stdscr,y,x,str,n) -#define mvgetstr(y,x,str) mvwgetstr(stdscr,y,x,str) -#define mvhline(y,x,c,n) mvwhline(stdscr,y,x,c,n) -#define mvinch(y,x) mvwinch(stdscr,y,x) -#define mvinchnstr(y,x,s,n) mvwinchnstr(stdscr,y,x,s,n) -#define mvinchstr(y,x,s) mvwinchstr(stdscr,y,x,s) -#define mvinnstr(y,x,s,n) mvwinnstr(stdscr,y,x,s,n) -#define mvinsch(y,x,c) mvwinsch(stdscr,y,x,c) -#define mvinsnstr(y,x,s,n) mvwinsnstr(stdscr,y,x,s,n) -#define mvinsstr(y,x,s) mvwinsstr(stdscr,y,x,s) -#define mvinstr(y,x,s) mvwinstr(stdscr,y,x,s) -#define mvvline(y,x,c,n) mvwvline(stdscr,y,x,c,n) +#define mvwaddch(win,y,x,ch) (wmove((win),(y),(x)) == ERR ? ERR : waddch((win),(ch))) +#define mvwaddchnstr(win,y,x,str,n) (wmove((win),(y),(x)) == ERR ? ERR : waddchnstr((win),(str),(n))) +#define mvwaddchstr(win,y,x,str) (wmove((win),(y),(x)) == ERR ? ERR : waddchnstr((win),(str),-1)) +#define mvwaddnstr(win,y,x,str,n) (wmove((win),(y),(x)) == ERR ? ERR : waddnstr((win),(str),(n))) +#define mvwaddstr(win,y,x,str) (wmove((win),(y),(x)) == ERR ? ERR : waddnstr((win),(str),-1)) +#define mvwchgat(win,y,x,n,a,c,o) (wmove((win),(y),(x)) == ERR ? ERR : wchgat((win),(n),(a),(c),(o))) +#define mvwdelch(win,y,x) (wmove((win),(y),(x)) == ERR ? ERR : wdelch(win)) +#define mvwgetch(win,y,x) (wmove((win),(y),(x)) == ERR ? ERR : wgetch(win)) +#define mvwgetnstr(win,y,x,str,n) (wmove((win),(y),(x)) == ERR ? ERR : wgetnstr((win),(str),(n))) +#define mvwgetstr(win,y,x,str) (wmove((win),(y),(x)) == ERR ? ERR : wgetstr((win),(str))) +#define mvwhline(win,y,x,c,n) (wmove((win),(y),(x)) == ERR ? ERR : whline((win),(c),(n))) +#define mvwinch(win,y,x) (wmove((win),(y),(x)) == ERR ? NCURSES_CAST(chtype, ERR) : winch(win)) +#define mvwinchnstr(win,y,x,s,n) (wmove((win),(y),(x)) == ERR ? ERR : winchnstr((win),(s),(n))) +#define mvwinchstr(win,y,x,s) (wmove((win),(y),(x)) == ERR ? ERR : winchstr((win),(s))) +#define mvwinnstr(win,y,x,s,n) (wmove((win),(y),(x)) == ERR ? ERR : winnstr((win),(s),(n))) +#define mvwinsch(win,y,x,c) (wmove((win),(y),(x)) == ERR ? ERR : winsch((win),(c))) +#define mvwinsnstr(win,y,x,s,n) (wmove((win),(y),(x)) == ERR ? ERR : winsnstr((win),(s),(n))) +#define mvwinsstr(win,y,x,s) (wmove((win),(y),(x)) == ERR ? ERR : winsstr((win),(s))) +#define mvwinstr(win,y,x,s) (wmove((win),(y),(x)) == ERR ? ERR : winstr((win),(s))) +#define mvwvline(win,y,x,c,n) (wmove((win),(y),(x)) == ERR ? ERR : wvline((win),(c),(n))) + +#define mvaddch(y,x,ch) mvwaddch(stdscr,(y),(x),(ch)) +#define mvaddchnstr(y,x,str,n) mvwaddchnstr(stdscr,(y),(x),(str),(n)) +#define mvaddchstr(y,x,str) mvwaddchstr(stdscr,(y),(x),(str)) +#define mvaddnstr(y,x,str,n) mvwaddnstr(stdscr,(y),(x),(str),(n)) +#define mvaddstr(y,x,str) mvwaddstr(stdscr,(y),(x),(str)) +#define mvchgat(y,x,n,a,c,o) mvwchgat(stdscr,(y),(x),(n),(a),(c),(o)) +#define mvdelch(y,x) mvwdelch(stdscr,(y),(x)) +#define mvgetch(y,x) mvwgetch(stdscr,(y),(x)) +#define mvgetnstr(y,x,str,n) mvwgetnstr(stdscr,(y),(x),(str),(n)) +#define mvgetstr(y,x,str) mvwgetstr(stdscr,(y),(x),(str)) +#define mvhline(y,x,c,n) mvwhline(stdscr,(y),(x),(c),(n)) +#define mvinch(y,x) mvwinch(stdscr,(y),(x)) +#define mvinchnstr(y,x,s,n) mvwinchnstr(stdscr,(y),(x),(s),(n)) +#define mvinchstr(y,x,s) mvwinchstr(stdscr,(y),(x),(s)) +#define mvinnstr(y,x,s,n) mvwinnstr(stdscr,(y),(x),(s),(n)) +#define mvinsch(y,x,c) mvwinsch(stdscr,(y),(x),(c)) +#define mvinsnstr(y,x,s,n) mvwinsnstr(stdscr,(y),(x),(s),(n)) +#define mvinsstr(y,x,s) mvwinsstr(stdscr,(y),(x),(s)) +#define mvinstr(y,x,s) mvwinstr(stdscr,(y),(x),(s)) +#define mvvline(y,x,c,n) mvwvline(stdscr,(y),(x),(c),(n)) /* * Some wide-character functions can be implemented without the extensions. */ #if !NCURSES_OPAQUE -#define getbkgd(win) ((win)->_bkgd) +#define getbkgd(win) (NCURSES_OK_ADDR(win) ? ((win)->_bkgd) : 0) #endif /* NCURSES_OPAQUE */ #define slk_attr_off(a,v) ((v) ? ERR : slk_attroff(a)) #define slk_attr_on(a,v) ((v) ? ERR : slk_attron(a)) #if !NCURSES_OPAQUE -#if NCURSES_WIDECHAR && 0 -#define wattr_set(win,a,p,opts) ((win)->_attrs = ((a) & ~A_COLOR), \ - (win)->_color = (p), \ - OK) -#define wattr_get(win,a,p,opts) ((void)((a) != (void *)0 && (*(a) = (win)->_attrs)), \ - (void)((p) != (void *)0 && (*(p) = (win)->_color)), \ - OK) -#else -#define wattr_set(win,a,p,opts) ((win)->_attrs = (((a) & ~A_COLOR) | COLOR_PAIR(p)), OK) -#define wattr_get(win,a,p,opts) ((void)((a) != (void *)0 && (*(a) = (win)->_attrs)), \ - (void)((p) != (void *)0 && (*(p) = PAIR_NUMBER((win)->_attrs))), \ - OK) -#endif +#if NCURSES_WATTR_MACROS +#if NCURSES_WIDECHAR && 1 +#define wattr_set(win,a,p,opts) \ + (NCURSES_OK_ADDR(win) \ + ? ((void)((win)->_attrs = ((a) & ~A_COLOR), \ + (win)->_color = (opts) ? *(int *)(opts) : (p)), \ + OK) \ + : ERR) +#define wattr_get(win,a,p,opts) \ + (NCURSES_OK_ADDR(win) \ + ? ((void)(NCURSES_OK_ADDR(a) \ + ? (*(a) = (win)->_attrs) \ + : OK), \ + (void)(NCURSES_OK_ADDR(p) \ + ? (*(p) = (NCURSES_PAIRS_T) (win)->_color) \ + : OK), \ + (void)(NCURSES_OK_ADDR(opts) \ + ? (*(int *)(opts) = (win)->_color) \ + : OK), \ + OK) \ + : ERR) +#else /* !(NCURSES_WIDECHAR && NCURSES_EXE_COLORS) */ +#define wattr_set(win,a,p,opts) \ + (NCURSES_OK_ADDR(win) \ + ? ((void)((win)->_attrs = (((a) & ~A_COLOR) | \ + (attr_t)COLOR_PAIR(p))), \ + OK) \ + : ERR) +#define wattr_get(win,a,p,opts) \ + (NCURSES_OK_ADDR(win) \ + ? ((void)(NCURSES_OK_ADDR(a) \ + ? (*(a) = (win)->_attrs) \ + : OK), \ + (void)(NCURSES_OK_ADDR(p) \ + ? (*(p) = (NCURSES_PAIRS_T) PAIR_NUMBER((win)->_attrs)) \ + : OK), \ + OK) \ + : ERR) +#endif /* (NCURSES_WIDECHAR && NCURSES_EXE_COLORS) */ +#endif /* NCURSES_WATTR_MACROS */ #endif /* NCURSES_OPAQUE */ /* @@ -1158,8 +1415,8 @@ extern NCURSES_EXPORT(int) wgetscrreg (const WINDOW *, int *, int *); /* generat * use POSIX stdarg.h. The ncurses versions of vwprintw/vwscanw already * use stdarg.h, so... */ -#define vw_printw vwprintw -#define vw_scanw vwscanw +/* define vw_printw vwprintw */ +/* define vw_scanw vwscanw */ /* * Export fallback function for use in C++ binding. @@ -1174,21 +1431,30 @@ NCURSES_EXPORT(int) vsscanf(const char *, const char *, va_list); */ #if 1 #if !NCURSES_OPAQUE -#define is_cleared(win) ((win)->_clear) -#define is_idcok(win) ((win)->_idcok) -#define is_idlok(win) ((win)->_idlok) -#define is_immedok(win) ((win)->_immed) -#define is_keypad(win) ((win)->_use_keypad) -#define is_leaveok(win) ((win)->_leaveok) -#define is_nodelay(win) ((win)->_delay == 0) -#define is_notimeout(win) ((win)->_notimeout) -#define is_scrollok(win) ((win)->_scroll) -#define is_syncok(win) ((win)->_sync) -#define wgetparent(win) ((win) ? (win)->_parent : 0) -#define wgetscrreg(win,t,b) ((win) ? (*(t) = (win)->_regtop, *(b) = (win)->_regbottom, OK) : ERR) +#define is_cleared(win) (NCURSES_OK_ADDR(win) ? (win)->_clear : FALSE) +#define is_idcok(win) (NCURSES_OK_ADDR(win) ? (win)->_idcok : FALSE) +#define is_idlok(win) (NCURSES_OK_ADDR(win) ? (win)->_idlok : FALSE) +#define is_immedok(win) (NCURSES_OK_ADDR(win) ? (win)->_immed : FALSE) +#define is_keypad(win) (NCURSES_OK_ADDR(win) ? (win)->_use_keypad : FALSE) +#define is_leaveok(win) (NCURSES_OK_ADDR(win) ? (win)->_leaveok : FALSE) +#define is_nodelay(win) (NCURSES_OK_ADDR(win) ? ((win)->_delay == 0) : FALSE) +#define is_notimeout(win) (NCURSES_OK_ADDR(win) ? (win)->_notimeout : FALSE) +#define is_pad(win) (NCURSES_OK_ADDR(win) ? ((win)->_flags & _ISPAD) != 0 : FALSE) +#define is_scrollok(win) (NCURSES_OK_ADDR(win) ? (win)->_scroll : FALSE) +#define is_subwin(win) (NCURSES_OK_ADDR(win) ? ((win)->_flags & _SUBWIN) != 0 : FALSE) +#define is_syncok(win) (NCURSES_OK_ADDR(win) ? (win)->_sync : FALSE) +#define wgetdelay(win) (NCURSES_OK_ADDR(win) ? (win)->_delay : 0) +#define wgetparent(win) (NCURSES_OK_ADDR(win) ? (win)->_parent : 0) +#define wgetscrreg(win,t,b) (NCURSES_OK_ADDR(win) ? (*(t) = (win)->_regtop, *(b) = (win)->_regbottom, OK) : ERR) #endif #endif +/* + * X/Open says this returns a bool; SVr4 also checked for out-of-range line. + * The macro provides compatibility: + */ +#define is_linetouched(w,l) ((!(w) || ((l) > getmaxy(w)) || ((l) < 0)) ? ERR : (is_linetouched)((w),(l))) + #endif /* NCURSES_NOMACROS */ /* @@ -1199,7 +1465,7 @@ NCURSES_EXPORT(int) vsscanf(const char *, const char *, va_list); * It gives the ESC expire time in milliseconds. * b. ttytype is needed for backward compatibility */ -#if 0 +#if NCURSES_REENTRANT NCURSES_WRAPPED_VAR(WINDOW *, curscr); NCURSES_WRAPPED_VAR(WINDOW *, newscr); @@ -1256,7 +1522,7 @@ extern NCURSES_EXPORT_VAR(int) TABSIZE; #define KEY_SRESET 0530 /* Soft (partial) reset (unreliable) */ #define KEY_RESET 0531 /* Reset or hard reset (unreliable) */ /* - * These definitions were generated by ./MKkey_defs.sh ./Caps + * These definitions were generated by ./MKkey_defs.sh ./Caps ./Caps-ncurses */ #define KEY_DOWN 0402 /* down-arrow key */ #define KEY_UP 0403 /* up-arrow key */ @@ -1346,21 +1612,25 @@ extern NCURSES_EXPORT_VAR(int) TABSIZE; #define KEY_SUSPEND 0627 /* suspend key */ #define KEY_UNDO 0630 /* undo key */ #define KEY_MOUSE 0631 /* Mouse event has occurred */ + +#ifdef NCURSES_EXT_FUNCS #define KEY_RESIZE 0632 /* Terminal resize event */ -#define KEY_EVENT 0633 /* We were interrupted by an event */ +#endif -#define KEY_MAX 0777 /* Maximum key value is 0633 */ -/* $Id: curses.h,v 1.63 2022/10/10 09:03:08 nicm Exp $ */ +#define KEY_MAX 0777 /* Maximum key value is 0632 */ +/* $Id: curses.h,v 1.64 2023/10/17 09:52:08 nicm Exp $ */ /* * vile:cmode: * This file is part of ncurses, designed to be appended after curses.h.in * (see that file for the relevant copyright). */ +#define _XOPEN_CURSES 1 + #if NCURSES_WIDECHAR extern NCURSES_EXPORT_VAR(cchar_t *) _nc_wacs; -#define NCURSES_WACS(c) (&_nc_wacs[(unsigned char)c]) +#define NCURSES_WACS(c) (&_nc_wacs[NCURSES_CAST(unsigned char,(c))]) #define WACS_BSSB NCURSES_WACS('l') #define WACS_SSBB NCURSES_WACS('m') @@ -1412,6 +1682,56 @@ extern NCURSES_EXPORT_VAR(cchar_t *) _nc_wacs; #define WACS_NEQUAL NCURSES_WACS('|') /* not equal */ #define WACS_STERLING NCURSES_WACS('}') /* UK pound sign */ + /* double lines */ +#define WACS_BDDB NCURSES_WACS('C') +#define WACS_DDBB NCURSES_WACS('D') +#define WACS_BBDD NCURSES_WACS('B') +#define WACS_DBBD NCURSES_WACS('A') +#define WACS_DBDD NCURSES_WACS('G') +#define WACS_DDDB NCURSES_WACS('F') +#define WACS_DDBD NCURSES_WACS('H') +#define WACS_BDDD NCURSES_WACS('I') +#define WACS_BDBD NCURSES_WACS('R') +#define WACS_DBDB NCURSES_WACS('Y') +#define WACS_DDDD NCURSES_WACS('E') + +#define WACS_D_ULCORNER WACS_BDDB +#define WACS_D_LLCORNER WACS_DDBB +#define WACS_D_URCORNER WACS_BBDD +#define WACS_D_LRCORNER WACS_DBBD +#define WACS_D_RTEE WACS_DBDD +#define WACS_D_LTEE WACS_DDDB +#define WACS_D_BTEE WACS_DDBD +#define WACS_D_TTEE WACS_BDDD +#define WACS_D_HLINE WACS_BDBD +#define WACS_D_VLINE WACS_DBDB +#define WACS_D_PLUS WACS_DDDD + + /* thick lines */ +#define WACS_BTTB NCURSES_WACS('L') +#define WACS_TTBB NCURSES_WACS('M') +#define WACS_BBTT NCURSES_WACS('K') +#define WACS_TBBT NCURSES_WACS('J') +#define WACS_TBTT NCURSES_WACS('U') +#define WACS_TTTB NCURSES_WACS('T') +#define WACS_TTBT NCURSES_WACS('V') +#define WACS_BTTT NCURSES_WACS('W') +#define WACS_BTBT NCURSES_WACS('Q') +#define WACS_TBTB NCURSES_WACS('X') +#define WACS_TTTT NCURSES_WACS('N') + +#define WACS_T_ULCORNER WACS_BTTB +#define WACS_T_LLCORNER WACS_TTBB +#define WACS_T_URCORNER WACS_BBTT +#define WACS_T_LRCORNER WACS_TBBT +#define WACS_T_RTEE WACS_TBTT +#define WACS_T_LTEE WACS_TTTB +#define WACS_T_BTEE WACS_TTBT +#define WACS_T_TTEE WACS_BTTT +#define WACS_T_HLINE WACS_BTBT +#define WACS_T_VLINE WACS_TBTB +#define WACS_T_PLUS WACS_TTTT + /* * Function prototypes for wide-character operations. * @@ -1435,7 +1755,7 @@ extern NCURSES_EXPORT(int) erasewchar (wchar_t*); /* implemented */ extern NCURSES_EXPORT(int) get_wch (wint_t *); /* generated:WIDEC */ extern NCURSES_EXPORT(int) get_wstr (wint_t *); /* generated:WIDEC */ extern NCURSES_EXPORT(int) getbkgrnd (cchar_t *); /* generated:WIDEC */ -extern NCURSES_EXPORT(int) getcchar (const cchar_t *, wchar_t*, attr_t*, short*, void*); /* implemented */ +extern NCURSES_EXPORT(int) getcchar (const cchar_t *, wchar_t*, attr_t*, NCURSES_PAIRS_T*, void*); /* implemented */ extern NCURSES_EXPORT(int) getn_wstr (wint_t *, int); /* generated:WIDEC */ extern NCURSES_EXPORT(int) hline_set (const cchar_t *, int); /* generated:WIDEC */ extern NCURSES_EXPORT(int) in_wch (cchar_t *); /* generated:WIDEC */ @@ -1485,12 +1805,12 @@ extern NCURSES_EXPORT(int) mvwins_wstr (WINDOW *, int, int, const wchar_t *); /* extern NCURSES_EXPORT(int) mvwinwstr (WINDOW *, int, int, wchar_t *); /* generated:WIDEC */ extern NCURSES_EXPORT(int) mvwvline_set (WINDOW *, int,int, const cchar_t *,int); /* generated:WIDEC */ extern NCURSES_EXPORT(int) pecho_wchar (WINDOW *, const cchar_t *); /* implemented */ -extern NCURSES_EXPORT(int) setcchar (cchar_t *, const wchar_t *, const attr_t, short, const void *); /* implemented */ +extern NCURSES_EXPORT(int) setcchar (cchar_t *, const wchar_t *, const attr_t, NCURSES_PAIRS_T, const void *); /* implemented */ extern NCURSES_EXPORT(int) slk_wset (int, const wchar_t *, int); /* implemented */ extern NCURSES_EXPORT(attr_t) term_attrs (void); /* implemented */ extern NCURSES_EXPORT(int) unget_wch (const wchar_t); /* implemented */ -extern NCURSES_EXPORT(int) vid_attr (attr_t, short, void *); /* implemented */ -extern NCURSES_EXPORT(int) vid_puts (attr_t, short, void *, int (*)(int)); /* implemented */ +extern NCURSES_EXPORT(int) vid_attr (attr_t, NCURSES_PAIRS_T, void *); /* implemented */ +extern NCURSES_EXPORT(int) vid_puts (attr_t, NCURSES_PAIRS_T, void *, NCURSES_OUTC); /* implemented */ extern NCURSES_EXPORT(int) vline_set (const cchar_t *, int); /* generated:WIDEC */ extern NCURSES_EXPORT(int) wadd_wch (WINDOW *,const cchar_t *); /* implemented */ extern NCURSES_EXPORT(int) wadd_wchnstr (WINDOW *,const cchar_t *,int); /* implemented */ @@ -1504,7 +1824,7 @@ extern NCURSES_EXPORT(int) wecho_wchar (WINDOW *, const cchar_t *); /* implement extern NCURSES_EXPORT(int) wget_wch (WINDOW *, wint_t *); /* implemented */ extern NCURSES_EXPORT(int) wget_wstr (WINDOW *, wint_t *); /* generated:WIDEC */ extern NCURSES_EXPORT(int) wgetbkgrnd (WINDOW *, cchar_t *); /* generated:WIDEC */ -extern NCURSES_EXPORT(int) wgetn_wstr (WINDOW *,wint_t *, int); /* implemented */ +extern NCURSES_EXPORT(int) wgetn_wstr (WINDOW *, wint_t *, int); /* implemented */ extern NCURSES_EXPORT(int) whline_set (WINDOW *, const cchar_t *, int); /* implemented */ extern NCURSES_EXPORT(int) win_wch (WINDOW *, cchar_t *); /* implemented */ extern NCURSES_EXPORT(int) win_wchnstr (WINDOW *, cchar_t *, int); /* implemented */ @@ -1517,82 +1837,92 @@ extern NCURSES_EXPORT(int) winwstr (WINDOW *, wchar_t *); /* implemented */ extern NCURSES_EXPORT(wchar_t*) wunctrl (cchar_t *); /* implemented */ extern NCURSES_EXPORT(int) wvline_set (WINDOW *, const cchar_t *, int); /* implemented */ +#if NCURSES_SP_FUNCS +extern NCURSES_EXPORT(attr_t) NCURSES_SP_NAME(term_attrs) (SCREEN*); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(erasewchar) (SCREEN*, wchar_t *); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(killwchar) (SCREEN*, wchar_t *); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(unget_wch) (SCREEN*, const wchar_t); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(vid_attr) (SCREEN*, attr_t, NCURSES_PAIRS_T, void *); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(vid_puts) (SCREEN*, attr_t, NCURSES_PAIRS_T, void *, NCURSES_SP_OUTC); /* implemented:SP_FUNC */ +extern NCURSES_EXPORT(wchar_t*) NCURSES_SP_NAME(wunctrl) (SCREEN*, cchar_t *); /* implemented:SP_FUNC */ +#endif + #ifndef NCURSES_NOMACROS /* * XSI curses macros for XPG4 conformance. */ -#define add_wch(c) wadd_wch(stdscr,c) -#define add_wchnstr(str,n) wadd_wchnstr(stdscr,str,n) -#define add_wchstr(str) wadd_wchstr(stdscr,str) -#define addnwstr(wstr,n) waddnwstr(stdscr,wstr,n) -#define addwstr(wstr) waddwstr(stdscr,wstr) -#define bkgrnd(c) wbkgrnd(stdscr,c) -#define bkgrndset(c) wbkgrndset(stdscr,c) -#define border_set(l,r,t,b,tl,tr,bl,br) wborder_set(stdscr,l,r,t,b,tl,tr,bl,br) -#define box_set(w,v,h) wborder_set(w,v,v,h,h,0,0,0,0) -#define echo_wchar(c) wecho_wchar(stdscr,c) -#define get_wch(c) wget_wch(stdscr,c) -#define get_wstr(t) wget_wstr(stdscr,t) -#define getbkgrnd(wch) wgetbkgrnd(stdscr,wch) -#define getn_wstr(t,n) wgetn_wstr(stdscr,t,n) -#define hline_set(c,n) whline_set(stdscr,c,n) -#define in_wch(c) win_wch(stdscr,c) -#define in_wchnstr(c,n) win_wchnstr(stdscr,c,n) -#define in_wchstr(c) win_wchstr(stdscr,c) -#define innwstr(c,n) winnwstr(stdscr,c,n) -#define ins_nwstr(t,n) wins_nwstr(stdscr,t,n) -#define ins_wch(c) wins_wch(stdscr,c) -#define ins_wstr(t) wins_wstr(stdscr,t) -#define inwstr(c) winwstr(stdscr,c) -#define vline_set(c,n) wvline_set(stdscr,c,n) -#define wadd_wchstr(win,str) wadd_wchnstr(win,str,-1) -#define waddwstr(win,wstr) waddnwstr(win,wstr,-1) -#define wget_wstr(w,t) wgetn_wstr(w,t,-1) -#define win_wchstr(w,c) win_wchnstr(w,c,-1) -#define wins_wstr(w,t) wins_nwstr(w,t,-1) +#define add_wch(c) wadd_wch(stdscr,(c)) +#define add_wchnstr(str,n) wadd_wchnstr(stdscr,(str),(n)) +#define add_wchstr(str) wadd_wchstr(stdscr,(str)) +#define addnwstr(wstr,n) waddnwstr(stdscr,(wstr),(n)) +#define addwstr(wstr) waddwstr(stdscr,(wstr)) +#define bkgrnd(c) wbkgrnd(stdscr,(c)) +#define bkgrndset(c) wbkgrndset(stdscr,(c)) +#define border_set(l,r,t,b,tl,tr,bl,br) wborder_set(stdscr,(l),(r),(t),(b),tl,tr,bl,br) +#define box_set(w,v,h) wborder_set((w),(v),(v),(h),(h),0,0,0,0) +#define echo_wchar(c) wecho_wchar(stdscr,(c)) +#define get_wch(c) wget_wch(stdscr,(c)) +#define get_wstr(t) wget_wstr(stdscr,(t)) +#define getbkgrnd(wch) wgetbkgrnd(stdscr,(wch)) +#define getn_wstr(t,n) wgetn_wstr(stdscr,(t),(n)) +#define hline_set(c,n) whline_set(stdscr,(c),(n)) +#define in_wch(c) win_wch(stdscr,(c)) +#define in_wchnstr(c,n) win_wchnstr(stdscr,(c),(n)) +#define in_wchstr(c) win_wchstr(stdscr,(c)) +#define innwstr(c,n) winnwstr(stdscr,(c),(n)) +#define ins_nwstr(t,n) wins_nwstr(stdscr,(t),(n)) +#define ins_wch(c) wins_wch(stdscr,(c)) +#define ins_wstr(t) wins_wstr(stdscr,(t)) +#define inwstr(c) winwstr(stdscr,(c)) +#define vline_set(c,n) wvline_set(stdscr,(c),(n)) +#define wadd_wchstr(win,str) wadd_wchnstr((win),(str),-1) +#define waddwstr(win,wstr) waddnwstr((win),(wstr),-1) +#define wget_wstr(w,t) wgetn_wstr((w),(t),-1) +#define win_wchstr(w,c) win_wchnstr((w),(c),-1) +#define wins_wstr(w,t) wins_nwstr((w),(t),-1) #if !NCURSES_OPAQUE -#define wgetbkgrnd(win,wch) (*wch = win->_bkgrnd, OK) +#define wgetbkgrnd(win,wch) (NCURSES_OK_ADDR(wch) ? ((win) ? (*(wch) = (win)->_bkgrnd) : *(wch), OK) : ERR) #endif -#define mvadd_wch(y,x,c) mvwadd_wch(stdscr,y,x,c) -#define mvadd_wchnstr(y,x,s,n) mvwadd_wchnstr(stdscr,y,x,s,n) -#define mvadd_wchstr(y,x,s) mvwadd_wchstr(stdscr,y,x,s) -#define mvaddnwstr(y,x,wstr,n) mvwaddnwstr(stdscr,y,x,wstr,n) -#define mvaddwstr(y,x,wstr) mvwaddwstr(stdscr,y,x,wstr) -#define mvget_wch(y,x,c) mvwget_wch(stdscr,y,x,c) -#define mvget_wstr(y,x,t) mvwget_wstr(stdscr,y,x,t) -#define mvgetn_wstr(y,x,t,n) mvwgetn_wstr(stdscr,y,x,t,n) -#define mvhline_set(y,x,c,n) mvwhline_set(stdscr,y,x,c,n) -#define mvin_wch(y,x,c) mvwin_wch(stdscr,y,x,c) -#define mvin_wchnstr(y,x,c,n) mvwin_wchnstr(stdscr,y,x,c,n) -#define mvin_wchstr(y,x,c) mvwin_wchstr(stdscr,y,x,c) -#define mvinnwstr(y,x,c,n) mvwinnwstr(stdscr,y,x,c,n) -#define mvins_nwstr(y,x,t,n) mvwins_nwstr(stdscr,y,x,t,n) -#define mvins_wch(y,x,c) mvwins_wch(stdscr,y,x,c) -#define mvins_wstr(y,x,t) mvwins_wstr(stdscr,y,x,t) -#define mvinwstr(y,x,c) mvwinwstr(stdscr,y,x,c) -#define mvvline_set(y,x,c,n) mvwvline_set(stdscr,y,x,c,n) - -#define mvwadd_wch(win,y,x,c) (wmove(win,y,x) == ERR ? ERR : wadd_wch(win,c)) -#define mvwadd_wchnstr(win,y,x,s,n) (wmove(win,y,x) == ERR ? ERR : wadd_wchnstr(win,s,n)) -#define mvwadd_wchstr(win,y,x,s) (wmove(win,y,x) == ERR ? ERR : wadd_wchstr(win,s)) -#define mvwaddnwstr(win,y,x,wstr,n) (wmove(win,y,x) == ERR ? ERR : waddnwstr(win,wstr,n)) -#define mvwaddwstr(win,y,x,wstr) (wmove(win,y,x) == ERR ? ERR : waddwstr(win,wstr)) -#define mvwget_wch(win,y,x,c) (wmove(win,y,x) == ERR ? ERR : wget_wch(win,c)) -#define mvwget_wstr(win,y,x,t) (wmove(win,y,x) == ERR ? ERR : wget_wstr(win,t)) -#define mvwgetn_wstr(win,y,x,t,n) (wmove(win,y,x) == ERR ? ERR : wgetn_wstr(win,t,n)) -#define mvwhline_set(win,y,x,c,n) (wmove(win,y,x) == ERR ? ERR : whline_set(win,c,n)) -#define mvwin_wch(win,y,x,c) (wmove(win,y,x) == ERR ? ERR : win_wch(win,c)) -#define mvwin_wchnstr(win,y,x,c,n) (wmove(win,y,x) == ERR ? ERR : win_wchnstr(win,c,n)) -#define mvwin_wchstr(win,y,x,c) (wmove(win,y,x) == ERR ? ERR : win_wchstr(win,c)) -#define mvwinnwstr(win,y,x,c,n) (wmove(win,y,x) == ERR ? ERR : winnwstr(win,c,n)) -#define mvwins_nwstr(win,y,x,t,n) (wmove(win,y,x) == ERR ? ERR : wins_nwstr(win,t,n)) -#define mvwins_wch(win,y,x,c) (wmove(win,y,x) == ERR ? ERR : wins_wch(win,c)) -#define mvwins_wstr(win,y,x,t) (wmove(win,y,x) == ERR ? ERR : wins_wstr(win,t)) -#define mvwinwstr(win,y,x,c) (wmove(win,y,x) == ERR ? ERR : winwstr(win,c)) -#define mvwvline_set(win,y,x,c,n) (wmove(win,y,x) == ERR ? ERR : wvline_set(win,c,n)) +#define mvadd_wch(y,x,c) mvwadd_wch(stdscr,(y),(x),(c)) +#define mvadd_wchnstr(y,x,s,n) mvwadd_wchnstr(stdscr,(y),(x),(s),(n)) +#define mvadd_wchstr(y,x,s) mvwadd_wchstr(stdscr,(y),(x),(s)) +#define mvaddnwstr(y,x,wstr,n) mvwaddnwstr(stdscr,(y),(x),(wstr),(n)) +#define mvaddwstr(y,x,wstr) mvwaddwstr(stdscr,(y),(x),(wstr)) +#define mvget_wch(y,x,c) mvwget_wch(stdscr,(y),(x),(c)) +#define mvget_wstr(y,x,t) mvwget_wstr(stdscr,(y),(x),(t)) +#define mvgetn_wstr(y,x,t,n) mvwgetn_wstr(stdscr,(y),(x),(t),(n)) +#define mvhline_set(y,x,c,n) mvwhline_set(stdscr,(y),(x),(c),(n)) +#define mvin_wch(y,x,c) mvwin_wch(stdscr,(y),(x),(c)) +#define mvin_wchnstr(y,x,c,n) mvwin_wchnstr(stdscr,(y),(x),(c),(n)) +#define mvin_wchstr(y,x,c) mvwin_wchstr(stdscr,(y),(x),(c)) +#define mvinnwstr(y,x,c,n) mvwinnwstr(stdscr,(y),(x),(c),(n)) +#define mvins_nwstr(y,x,t,n) mvwins_nwstr(stdscr,(y),(x),(t),(n)) +#define mvins_wch(y,x,c) mvwins_wch(stdscr,(y),(x),(c)) +#define mvins_wstr(y,x,t) mvwins_wstr(stdscr,(y),(x),(t)) +#define mvinwstr(y,x,c) mvwinwstr(stdscr,(y),(x),(c)) +#define mvvline_set(y,x,c,n) mvwvline_set(stdscr,(y),(x),(c),(n)) + +#define mvwadd_wch(win,y,x,c) (wmove(win,(y),(x)) == ERR ? ERR : wadd_wch((win),(c))) +#define mvwadd_wchnstr(win,y,x,s,n) (wmove(win,(y),(x)) == ERR ? ERR : wadd_wchnstr((win),(s),(n))) +#define mvwadd_wchstr(win,y,x,s) (wmove(win,(y),(x)) == ERR ? ERR : wadd_wchstr((win),(s))) +#define mvwaddnwstr(win,y,x,wstr,n) (wmove(win,(y),(x)) == ERR ? ERR : waddnwstr((win),(wstr),(n))) +#define mvwaddwstr(win,y,x,wstr) (wmove(win,(y),(x)) == ERR ? ERR : waddwstr((win),(wstr))) +#define mvwget_wch(win,y,x,c) (wmove(win,(y),(x)) == ERR ? ERR : wget_wch((win),(c))) +#define mvwget_wstr(win,y,x,t) (wmove(win,(y),(x)) == ERR ? ERR : wget_wstr((win),(t))) +#define mvwgetn_wstr(win,y,x,t,n) (wmove(win,(y),(x)) == ERR ? ERR : wgetn_wstr((win),(t),(n))) +#define mvwhline_set(win,y,x,c,n) (wmove(win,(y),(x)) == ERR ? ERR : whline_set((win),(c),(n))) +#define mvwin_wch(win,y,x,c) (wmove(win,(y),(x)) == ERR ? ERR : win_wch((win),(c))) +#define mvwin_wchnstr(win,y,x,c,n) (wmove(win,(y),(x)) == ERR ? ERR : win_wchnstr((win),(c),(n))) +#define mvwin_wchstr(win,y,x,c) (wmove(win,(y),(x)) == ERR ? ERR : win_wchstr((win),(c))) +#define mvwinnwstr(win,y,x,c,n) (wmove(win,(y),(x)) == ERR ? ERR : winnwstr((win),(c),(n))) +#define mvwins_nwstr(win,y,x,t,n) (wmove(win,(y),(x)) == ERR ? ERR : wins_nwstr((win),(t),(n))) +#define mvwins_wch(win,y,x,c) (wmove(win,(y),(x)) == ERR ? ERR : wins_wch((win),(c))) +#define mvwins_wstr(win,y,x,t) (wmove(win,(y),(x)) == ERR ? ERR : wins_wstr((win),(t))) +#define mvwinwstr(win,y,x,c) (wmove(win,(y),(x)) == ERR ? ERR : winwstr((win),(c))) +#define mvwvline_set(win,y,x,c,n) (wmove(win,(y),(x)) == ERR ? ERR : wvline_set((win),(c),(n))) #endif /* NCURSES_NOMACROS */ @@ -1602,7 +1932,7 @@ extern NCURSES_EXPORT(const char *) _nc_viswibuf(const wint_t *); #endif #endif /* NCURSES_WIDECHAR */ -/* $Id: curses.h,v 1.63 2022/10/10 09:03:08 nicm Exp $ */ +/* $Id: curses.h,v 1.64 2023/10/17 09:52:08 nicm Exp $ */ /* * vile:cmode: * This file is part of ncurses, designed to be appended after curses.h.in @@ -1617,12 +1947,12 @@ extern NCURSES_EXPORT(const char *) _nc_viswibuf(const wint_t *); #define NCURSES_MOUSE_MASK(b,m) ((m) << (((b) - 1) * 6)) #endif -#define NCURSES_BUTTON_RELEASED 001L -#define NCURSES_BUTTON_PRESSED 002L -#define NCURSES_BUTTON_CLICKED 004L -#define NCURSES_DOUBLE_CLICKED 010L -#define NCURSES_TRIPLE_CLICKED 020L -#define NCURSES_RESERVED_EVENT 040L +#define NCURSES_BUTTON_RELEASED 001UL +#define NCURSES_BUTTON_PRESSED 002UL +#define NCURSES_BUTTON_CLICKED 004UL +#define NCURSES_DOUBLE_CLICKED 010UL +#define NCURSES_TRIPLE_CLICKED 020UL +#define NCURSES_RESERVED_EVENT 040UL /* event masks */ #define BUTTON1_RELEASED NCURSES_MOUSE_MASK(1, NCURSES_BUTTON_RELEASED) @@ -1698,28 +2028,42 @@ typedef struct } MEVENT; -extern NCURSES_EXPORT(int) getmouse (MEVENT *); -extern NCURSES_EXPORT(int) ungetmouse (MEVENT *); +extern NCURSES_EXPORT(bool) has_mouse(void); +extern NCURSES_EXPORT(int) getmouse (MEVENT *); +extern NCURSES_EXPORT(int) ungetmouse (MEVENT *); extern NCURSES_EXPORT(mmask_t) mousemask (mmask_t, mmask_t *); -extern NCURSES_EXPORT(bool) wenclose (const WINDOW *, int, int); -extern NCURSES_EXPORT(int) mouseinterval (int); -extern NCURSES_EXPORT(bool) wmouse_trafo (const WINDOW*, int*, int*, bool); -extern NCURSES_EXPORT(bool) mouse_trafo (int*, int*, bool); /* generated */ +extern NCURSES_EXPORT(bool) wenclose (const WINDOW *, int, int); +extern NCURSES_EXPORT(int) mouseinterval (int); +extern NCURSES_EXPORT(bool) wmouse_trafo (const WINDOW*, int*, int*, bool); +extern NCURSES_EXPORT(bool) mouse_trafo (int*, int*, bool); /* generated */ + +#if NCURSES_SP_FUNCS +extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(has_mouse) (SCREEN*); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(getmouse) (SCREEN*, MEVENT *); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(ungetmouse) (SCREEN*,MEVENT *); +extern NCURSES_EXPORT(mmask_t) NCURSES_SP_NAME(mousemask) (SCREEN*, mmask_t, mmask_t *); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(mouseinterval) (SCREEN*, int); +#endif +#ifndef NCURSES_NOMACROS #define mouse_trafo(y,x,to_screen) wmouse_trafo(stdscr,y,x,to_screen) +#endif /* other non-XSI functions */ extern NCURSES_EXPORT(int) mcprint (char *, int); /* direct data to printer */ extern NCURSES_EXPORT(int) has_key (int); /* do we have given key? */ +#if NCURSES_SP_FUNCS +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(has_key) (SCREEN*, int); /* do we have given key? */ +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(mcprint) (SCREEN*, char *, int); /* direct data to printer */ +#endif + /* Debugging : use with libncurses_g.a */ extern NCURSES_EXPORT(void) _tracef (const char *, ...) GCC_PRINTFLIKE(1,2); -extern NCURSES_EXPORT(void) _tracedump (const char *, WINDOW *); extern NCURSES_EXPORT(char *) _traceattr (attr_t); extern NCURSES_EXPORT(char *) _traceattr2 (int, chtype); -extern NCURSES_EXPORT(char *) _nc_tracebits (void); extern NCURSES_EXPORT(char *) _tracechar (int); extern NCURSES_EXPORT(char *) _tracechtype (chtype); extern NCURSES_EXPORT(char *) _tracechtype2 (int, chtype); @@ -1732,8 +2076,8 @@ extern NCURSES_EXPORT(char *) _tracecchar_t2 (int, const cchar_t *); #define _tracech_t _tracechtype #define _tracech_t2 _tracechtype2 #endif -extern NCURSES_EXPORT(char *) _tracemouse (const MEVENT *); -extern NCURSES_EXPORT(void) trace (const unsigned int); +extern NCURSES_EXPORT(void) trace (const unsigned) GCC_DEPRECATED("use curses_trace"); +extern NCURSES_EXPORT(unsigned) curses_trace (const unsigned); /* trace masks */ #define TRACE_DISABLE 0x0000 /* turn off tracing */ @@ -1764,6 +2108,10 @@ extern NCURSES_EXPORT(const char *) _nc_visbuf (const char *); #define OPTIMIZE_ALL 0xff /* enable all optimizations (dflt) */ #endif +extern GCC_NORETURN NCURSES_EXPORT(void) exit_curses (int); + +#include + #ifdef __cplusplus #ifndef NCURSES_NOMACROS diff --git a/lib/libcurses/curses.priv.h b/lib/libcurses/curses.priv.h index 95c1b9a8837..cbac9f67d79 100644 --- a/lib/libcurses/curses.priv.h +++ b/lib/libcurses/curses.priv.h @@ -1,7 +1,8 @@ -/* $OpenBSD: curses.priv.h,v 1.35 2021/03/10 20:16:08 millert Exp $ */ +/* $OpenBSD: curses.priv.h,v 1.36 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2017,2018 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,11 +33,11 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer * ****************************************************************************/ - /* - * $Id: curses.priv.h,v 1.35 2021/03/10 20:16:08 millert Exp $ + * $Id: curses.priv.h,v 1.36 2023/10/17 09:52:08 nicm Exp $ * * curses.priv.h * @@ -47,19 +48,9 @@ #ifndef CURSES_PRIV_H #define CURSES_PRIV_H 1 +/* *INDENT-OFF* */ -#if !defined(NCURSES_IMPEXP) -# define NCURSES_IMPEXP /* nothing */ -#endif -#if !defined(NCURSES_API) -# define NCURSES_API /* nothing */ -#endif -#if !defined(NCURSES_EXPORT) -# define NCURSES_EXPORT(type) NCURSES_IMPEXP type NCURSES_API -#endif -#if !defined(NCURSES_EXPORT_VAR) -# define NCURSES_EXPORT_VAR(type) NCURSES_IMPEXP type -#endif +#include #ifdef __cplusplus extern "C" { @@ -73,18 +64,16 @@ extern "C" { #define MODULE_ID(id) /*nothing*/ #endif +#include /* for offsetof */ #include #include #include +#include #if HAVE_UNISTD_H #include #endif -#if HAVE_SYS_BSDTYPES_H -#include /* needed for ISC */ -#endif - #if HAVE_LIMITS_H # include #elif HAVE_SYS_PARAM_H @@ -96,6 +85,12 @@ extern "C" { #include +#if defined __hpux +# ifndef EILSEQ +# define EILSEQ 47 +# endif +#endif + #ifndef PATH_MAX # if defined(_POSIX_PATH_MAX) # define PATH_MAX _POSIX_PATH_MAX @@ -110,7 +105,23 @@ extern "C" { extern int errno; #endif -#include +/* Some Windows related defines */ +#undef _NC_WINDOWS +#if (defined(_WIN32) || defined(_WIN64)) +#define _NC_WINDOWS +#else +#undef EXP_WIN32_DRIVER +#endif + +#undef _NC_MINGW +#if (defined(__MINGW32__) || defined(__MINGW64__)) +#define _NC_MINGW +#endif + +#undef _NC_MSC +#ifdef _MSC_VER +#define _NC_MSC +#endif /* Some systems have a broken 'select()', but workable 'poll()'. Use that */ #if HAVE_WORKING_POLL @@ -124,6 +135,27 @@ extern int errno; #define USE_FUNC_POLL 0 #endif +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif + +#if (defined(__USE_MINGW_ANSI_STDIO) && __USE_MINGW_ANSI_STDIO != 0) && (defined(__GNUC__) && (__GNUC__ < 12)) +# undef PRIxPTR /* gcc bug fixed in 12.x */ +# define PRIxPTR "lX" +# define CASTxPTR(n) (unsigned long)(intptr_t)(void*)(n) +#else +# define CASTxPTR(n) (intptr_t)(void*)(n) +#endif + +#ifndef PRIxPTR +# define PRIxPTR "lx" +# define CASTxPTR(n) (long)(void*)(n) +#endif + /* include signal.h before curses.h to work-around defect in glibc 2.1.3 */ #include @@ -148,6 +180,15 @@ extern int errno; #define USE_EMX_MOUSE 0 #endif +/* kLIBC keyboard/mouse support */ +#if defined(__OS2__) && defined(__KLIBC__) +#define USE_KLIBC_KBD 1 +#define USE_KLIBC_MOUSE 1 +#else +#define USE_KLIBC_KBD 0 +#define USE_KLIBC_MOUSE 0 +#endif + #define DEFAULT_MAXCLICK 166 #define EV_MAX 8 /* size of mouse circular event queue */ @@ -169,18 +210,33 @@ extern int errno; #endif /* - * If desired, one can configure this, disabling environment variables that - * point to custom terminfo/termcap locations. + * When building in the MSYS2 environment, the automatic discovery of + * the path separator in configure doesn't work properly. So, if building + * for MinGW, we enforce the correct Windows PATH separator */ -#ifdef USE_ROOT_ENVIRON -#ifdef __OpenBSD__ -#define use_terminfo_vars() (!issetugid()) -#else -#define use_terminfo_vars() 1 +#if defined(_NC_WINDOWS) +# ifdef NCURSES_PATHSEP +# undef NCURSES_PATHSEP +# endif +# define NCURSES_PATHSEP ';' #endif -#else -#define use_terminfo_vars() _nc_env_access() -extern NCURSES_EXPORT(int) _nc_env_access (void); + +/* + * When the standard handles have been redirected (such as inside a text editor + * or the less utility), keystrokes must be read from the console rather than + * the redirected handle. The standard output handle suffers from a similar + * problem. Both handles are not closed once opened. The console shall be + * considered reachable throughout the process. + */ +#if defined(_NC_WINDOWS) +#define GetDirectHandle(fileName, shareMode) \ + CreateFile(TEXT(fileName), \ + GENERIC_READ | GENERIC_WRITE, \ + shareMode, \ + 0, \ + OPEN_EXISTING, \ + 0, \ + 0) #endif /* @@ -194,6 +250,44 @@ extern NCURSES_EXPORT(int) _nc_env_access (void); extern NCURSES_EXPORT(void *) _nc_memmove (void *, const void *, size_t); #endif +/* + * If we have va_copy(), use it for assigning va_list's. + */ +#if defined(HAVE___VA_COPY) +#define begin_va_copy(dst,src) __va_copy(dst, src) +#define end_va_copy(dst) va_end(dst) +#elif defined(va_copy) || defined(HAVE_VA_COPY) +#define begin_va_copy(dst,src) va_copy(dst, src) +#define end_va_copy(dst) va_end(dst) +#else +#define begin_va_copy(dst,src) (dst) = (src) +#define end_va_copy(dst) /* nothing */ +#endif + +/* + * Either/both S_ISxxx and/or S_IFxxx are defined in sys/types.h; some systems + * lack one or the other. + */ +#ifndef S_ISDIR +#define S_ISDIR(mode) ((mode & S_IFMT) == S_IFDIR) +#endif + +#ifndef S_ISREG +#define S_ISREG(mode) ((mode & S_IFMT) == S_IFREG) +#endif + +/* + * POSIX ignores the "b", which c89 specified. Some very old systems do not + * accept it. + */ +#if USE_FOPEN_BIN_R +#define BIN_R "rb" +#define BIN_W "wb" +#else +#define BIN_R "r" +#define BIN_W "w" +#endif + /* * Scroll hints are useless when hashmap is used */ @@ -211,6 +305,26 @@ extern NCURSES_EXPORT(void *) _nc_memmove (void *, const void *, size_t); #define if_USE_SCROLL_HINTS(stmt) /*nothing*/ #endif +#include + +/* + * Options for terminal drivers, etc... + */ +#ifdef USE_TERM_DRIVER +#define NO_TERMINAL "unknown" +#define USE_SP_RIPOFF 1 +#define USE_SP_TERMTYPE 1 +#define USE_SP_WINDOWLIST 1 +#else +#define NO_TERMINAL 0 +#endif + +#define VALID_TERM_ENV(term_env, no_terminal) \ + (term_env = (NonEmpty(term_env) \ + ? term_env \ + : no_terminal), \ + NonEmpty(term_env)) + /* * Note: ht/cbt expansion flakes out randomly under Linux 1.1.47, but only * when we're throwing control codes at the screen at high volume. To see @@ -244,14 +358,6 @@ typedef TRIES { * Structure for palette tables */ -typedef struct -{ - short red, green, blue; /* what color_content() returns */ - short r, g, b; /* params to init_color() */ - int init; /* true if we called init_color() */ -} -color_t; - #define MAXCOLUMNS 135 #define MAXLINES 66 #define FIFO_SIZE MAXCOLUMNS+2 /* for nocbreak mode input */ @@ -262,11 +368,11 @@ color_t; #if USE_WIDEC_SUPPORT #define _nc_bkgd _bkgrnd -#define _XOPEN_SOURCE_EXTENDED 1 #else #undef _XOPEN_SOURCE_EXTENDED +#undef _XPG5 #define _nc_bkgd _bkgd -#define wgetbkgrnd(win, wch) *wch = win->_bkgd +#define wgetbkgrnd(win, wch) ((*wch = win->_bkgd) != 0 ? OK : ERR) #define wbkgrnd wbkgd #endif @@ -275,39 +381,189 @@ color_t; #define NCURSES_OPAQUE 0 #include /* we'll use -Ipath directive to get the right one! */ -#include + +#if !(defined(NCURSES_WGETCH_EVENTS) && defined(NEED_KEY_EVENT)) +#undef KEY_EVENT /* reduce compiler-warnings with Visual C++ */ +#endif + +typedef struct +{ + int red, green, blue; /* what color_content() returns */ + int r, g, b; /* params to init_color() */ + int init; /* true if we called init_color() */ +} +color_t; + +typedef union { + struct { + unsigned char red; + unsigned char green; + unsigned char blue; + } bits; /* bits per color-value in RGB */ + unsigned value; +} rgb_bits_t; + +/* + * If curses.h did not expose the SCREEN-functions, then we do not need the + * parameter in the corresponding unextended functions. + */ + +#define USE_SP_FUNC_SUPPORT NCURSES_SP_FUNCS +#define USE_EXT_SP_FUNC_SUPPORT (NCURSES_SP_FUNCS && NCURSES_EXT_FUNCS) + +#if NCURSES_SP_FUNCS +#define SP_PARM sp /* use parameter */ +#define NCURSES_SP_ARG SP_PARM +#define NCURSES_SP_DCL SCREEN *NCURSES_SP_ARG +#define NCURSES_SP_DCL0 NCURSES_SP_DCL +#define NCURSES_SP_ARGx NCURSES_SP_ARG, +#define NCURSES_SP_DCLx SCREEN *NCURSES_SP_ARGx +#else +#define SP_PARM SP /* use global variable */ +#define NCURSES_SP_ARG +#define NCURSES_SP_DCL +#define NCURSES_SP_DCL0 void +#define NCURSES_SP_ARGx +#define NCURSES_SP_DCLx +#endif + +#include + +#include +#include + +#define IsPreScreen(sp) (((sp) != 0) && sp->_prescreen) +#define HasTerminal(sp) (((sp) != 0) && (0 != ((sp)->_term))) +#define IsValidScreen(sp) (HasTerminal(sp) && !IsPreScreen(sp)) + +#if USE_REENTRANT +#define CurTerm _nc_prescreen._cur_term +#else +#define CurTerm cur_term +#endif + +#if NCURSES_SP_FUNCS +#define TerminalOf(sp) ((sp) ? ((sp)->_term ? (sp)->_term : CurTerm) : CurTerm) +#else +#define TerminalOf(sp) CurTerm +#endif + +/* + * The legacy layout for TERMTYPE uses "short" for all of the numbers. Moving + * past that, numeric capabilities can be "int" by using a TERMTYPE2 structure + * in TERMINAL, and doing most of the internal work using TERMTYPE2. There are + * a few places (mostly to expose the legacy layout) where the distinction + * needs attention. + */ +#if NCURSES_EXT_COLORS && HAVE_INIT_EXTENDED_COLOR +#define NCURSES_EXT_NUMBERS 1 +#define NCURSES_INT2 int +#define SIZEOF_INT2 4 +#define TerminalType(tp) (tp)->type2 +#else +#define NCURSES_EXT_NUMBERS 0 +#define NCURSES_INT2 short +#define SIZEOF_INT2 2 +#define TerminalType(tp) (tp)->type +#endif + +#define SIZEOF_SHORT 2 + +#ifdef CUR +#undef CUR +#define CUR TerminalType(cur_term). +#endif + +/* + * Reduce dependency on cur_term global by using terminfo data from SCREEN's + * pointer to this data. + */ +#ifdef USE_SP_TERMTYPE +#undef CUR +#endif + +#define SP_TERMTYPE TerminalType(TerminalOf(sp)). + #include + #include -#if NCURSES_EXT_COLORS && USE_WIDEC_SUPPORT +/* + * Simplify ifdef's for the "*_ATTR" macros in case italics are not configured. + */ +#if defined(A_ITALIC) && defined(exit_italics_mode) +#define USE_ITALIC 1 +#else +#define USE_ITALIC 0 +#undef A_ITALIC +#define A_ITALIC 0 +#endif + +/* + * Use these macros internally, to make tracing less verbose. But leave the + * option for compiling the tracing into the library. + */ +#if 1 +#define ColorPair(n) (NCURSES_BITS(n, 0) & A_COLOR) +#define PairNumber(a) (NCURSES_CAST(int,(((unsigned long)(a) & A_COLOR) >> NCURSES_ATTR_SHIFT))) +#else +#define ColorPair(pair) COLOR_PAIR(pair) +#define PairNumber(attr) PAIR_NUMBER(attr) +#endif + +#define unColor(n) unColor2(AttrOf(n)) +#define unColor2(a) ((a) & ALL_BUT_COLOR) + +/* + * Extended-colors stores the color pair in a separate struct-member than the + * attributes. But for compatibility, we handle most cases where a program + * written for non-extended colors stores the color in the attributes by + * checking for a color pair in both places. + */ +#if NCURSES_EXT_COLORS #define if_EXT_COLORS(stmt) stmt -#define NetPair(value,p) (value).ext_color = (p), \ - AttrOf(value) &= ALL_BUT_COLOR, \ - AttrOf(value) |= (A_COLOR & COLOR_PAIR((p > 255) ? 255 : p)) -#define SetPair(value,p) (value).ext_color = (p) -#define GetPair(value) (value).ext_color -#define unColor(n) (AttrOf(n) & ALL_BUT_COLOR) -#define GET_WINDOW_PAIR(w) (w)->_color +#define SetPair(value,p) SetPair2((value).ext_color, AttrOf(value), p) +#define SetPair2(c,a,p) c = (p), \ + a = (unColor2(a) | ColorPair(oldColor(c))) +#define GetPair(value) GetPair2((value).ext_color, AttrOf(value)) +#define GetPair2(c,a) ((c) ? (c) : PairNumber(a)) +#define oldColor(p) (((p) > 255) ? 255 : (p)) +#define GET_WINDOW_PAIR(w) GetPair2((w)->_color, (w)->_attrs) #define SET_WINDOW_PAIR(w,p) (w)->_color = (p) #define SameAttrOf(a,b) (AttrOf(a) == AttrOf(b) && GetPair(a) == GetPair(b)) -#define VIDATTR(attr, pair) vid_attr(attr, pair, 0) -#else + +#define VIDPUTS(sp,attr,pair) do { \ + int vid_pair = pair; \ + NCURSES_SP_NAME(vid_puts)( \ + NCURSES_SP_ARGx attr, \ + (NCURSES_PAIRS_T) pair, \ + &vid_pair, \ + NCURSES_OUTC_FUNC); \ + } while (0) + +#else /* !NCURSES_EXT_COLORS */ + #define if_EXT_COLORS(stmt) /* nothing */ #define SetPair(value,p) RemAttr(value, A_COLOR), \ - SetAttr(value, AttrOf(value) | (A_COLOR & COLOR_PAIR(p))) -#define GetPair(value) PAIR_NUMBER(AttrOf(value)) -#define unColor(n) (AttrOf(n) & ALL_BUT_COLOR) -#define GET_WINDOW_PAIR(w) PAIR_NUMBER(WINDOW_ATTRS(w)) + SetAttr(value, AttrOf(value) | ColorPair(p)) +#define GetPair(value) PairNumber(AttrOf(value)) +#define GET_WINDOW_PAIR(w) PairNumber(WINDOW_ATTRS(w)) #define SET_WINDOW_PAIR(w,p) WINDOW_ATTRS(w) &= ALL_BUT_COLOR, \ - WINDOW_ATTRS(w) |= (A_COLOR & COLOR_PAIR(p)) + WINDOW_ATTRS(w) |= ColorPair(p) #define SameAttrOf(a,b) (AttrOf(a) == AttrOf(b)) -#define VIDATTR(attr, pair) vidattr(attr) -#endif + +#define VIDPUTS(sp,attr,pair) NCURSES_SP_NAME(vidputs)(NCURSES_SP_ARGx attr, NCURSES_OUTC_FUNC) + +#endif /* NCURSES_EXT_COLORS */ + +#define NCURSES_OUTC_FUNC NCURSES_SP_NAME(_nc_outch) +#define NCURSES_PUTP2(name,value) NCURSES_SP_NAME(_nc_putp)(NCURSES_SP_ARGx name, value) +#define NCURSES_PUTP2_FLUSH(name,value) NCURSES_SP_NAME(_nc_putp_flush)(NCURSES_SP_ARGx name, value) #if NCURSES_NO_PADDING #define GetNoPadding(sp) ((sp) ? (sp)->_no_padding : _nc_prescreen._no_padding) #define SetNoPadding(sp) _nc_set_no_padding(sp) -extern NCURSES_EXPORT(void) _nc_set_no_padding(SCREEN *); +extern NCURSES_EXPORT(void) _nc_set_no_padding(SCREEN *); #else #define GetNoPadding(sp) FALSE #define SetNoPadding(sp) /*nothing*/ @@ -319,20 +575,45 @@ extern NCURSES_EXPORT(void) _nc_set_no_padding(SCREEN *); #define GET_SCREEN_PAIR(s) GetPair(SCREEN_ATTRS(s)) #define SET_SCREEN_PAIR(s,p) SetPair(SCREEN_ATTRS(s), p) +#if USE_REENTRANT || NCURSES_SP_FUNCS +extern NCURSES_EXPORT(int *) _nc_ptr_Lines (SCREEN *); +extern NCURSES_EXPORT(int *) _nc_ptr_Cols (SCREEN *); +extern NCURSES_EXPORT(int *) _nc_ptr_Tabsize (SCREEN *); +extern NCURSES_EXPORT(int *) _nc_ptr_Escdelay (SCREEN *); +#endif + #if USE_REENTRANT -NCURSES_EXPORT(int *) _nc_ptr_Lines (void); -NCURSES_EXPORT(int *) _nc_ptr_Cols (void); -#define ptrLines() (SP ? &(SP->_LINES) : &(_nc_prescreen._LINES)) -#define ptrCols() (SP ? &(SP->_COLS) : &(_nc_prescreen._COLS)) -#define SET_LINES(value) *_nc_ptr_Lines() = value -#define SET_COLS(value) *_nc_ptr_Cols() = value + +#define ptrLines(sp) (sp ? &(sp->_LINES) : &(_nc_prescreen._LINES)) +#define ptrCols(sp) (sp ? &(sp->_COLS) : &(_nc_prescreen._COLS)) +#define ptrTabsize(sp) (sp ? &(sp->_TABSIZE) : &(_nc_prescreen._TABSIZE)) +#define ptrEscdelay(sp) (sp ? &(sp->_ESCDELAY) : &(_nc_prescreen._ESCDELAY)) + +#define SET_LINES(value) *_nc_ptr_Lines(SP_PARM) = value +#define SET_COLS(value) *_nc_ptr_Cols(SP_PARM) = value +#define SET_TABSIZE(value) *_nc_ptr_Tabsize(SP_PARM) = value +#define SET_ESCDELAY(value) *_nc_ptr_Escdelay(SP_PARM) = value + #else -#define ptrLines() &LINES -#define ptrCols() &COLS -#define SET_LINES(value) LINES = value -#define SET_COLS(value) COLS = value + +#define ptrLines(sp) &LINES +#define ptrCols(sp) &COLS +#define ptrTabsize(sp) &TABSIZE +#define ptrEscdelay(sp) &ESCDELAY + +#define SET_LINES(value) LINES = value +#define SET_COLS(value) COLS = value +#define SET_TABSIZE(value) TABSIZE = value +#define SET_ESCDELAY(value) ESCDELAY = value + #endif +#define IS_SUBWIN(w) ((w)->_flags & _SUBWIN) +#define IS_PAD(w) ((w)->_flags & _ISPAD) +#define IS_WRAPPED(w) ((w)->_flags & _WRAPPED) + +#define HasHardTabs() (NonEmpty(clear_all_tabs) && NonEmpty(set_tab)) + #define TR_MUTEX(data) _tracef("%s@%d: me:%08lX COUNT:%2u/%2d/%6d/%2d/%s%9u: " #data, \ __FILE__, __LINE__, \ (unsigned long) (pthread_self()), \ @@ -344,6 +625,22 @@ NCURSES_EXPORT(int *) _nc_ptr_Cols (void); data.__data.__nusers) #define TR_GLOBAL_MUTEX(name) TR_MUTEX(_nc_globals.mutex_##name) +#if USE_WEAK_SYMBOLS +#if defined(__GNUC__) +# if defined __USE_ISOC99 +# define _cat_pragma(exp) _Pragma(#exp) +# define _weak_pragma(exp) _cat_pragma(weak name) +# else +# define _weak_pragma(exp) +# endif +# define _declare(name) __extension__ extern __typeof__(name) name +# define weak_symbol(name) _weak_pragma(name) _declare(name) __attribute__((weak)) +#else +# undef USE_WEAK_SYMBOLS +# define USE_WEAK_SYMBOLS 0 +#endif +#endif + #ifdef USE_PTHREADS #if USE_REENTRANT @@ -361,22 +658,10 @@ extern NCURSES_EXPORT(int) _nc_mutex_unlock(pthread_mutex_t *); #error POSIX threads requires --enable-reentrant option #endif -#if USE_WEAK_SYMBOLS -#if defined(__GNUC__) -# if defined __USE_ISOC99 -# define _cat_pragma(exp) _Pragma(#exp) -# define _weak_pragma(exp) _cat_pragma(weak name) -# else -# define _weak_pragma(exp) -# endif -# define _declare(name) __extension__ extern __typeof__(name) name -# define weak_symbol(name) _weak_pragma(name) _declare(name) __attribute__((weak)) -#endif -#endif - #ifdef USE_PTHREADS # if USE_WEAK_SYMBOLS weak_symbol(pthread_sigmask); +weak_symbol(pthread_kill); weak_symbol(pthread_self); weak_symbol(pthread_equal); weak_symbol(pthread_mutex_init); @@ -387,7 +672,10 @@ weak_symbol(pthread_mutexattr_settype); weak_symbol(pthread_mutexattr_init); extern NCURSES_EXPORT(int) _nc_sigprocmask(int, const sigset_t *, sigset_t *); # undef sigprocmask -# define sigprocmask _nc_sigprocmask +# define sigprocmask(a, b, c) _nc_sigprocmask(a, b, c) +# define GetThreadID() (((pthread_self)) ? pthread_self() : (pthread_t) getpid()) +# else +# define GetThreadID() pthread_self() # endif #endif @@ -398,18 +686,75 @@ extern NCURSES_EXPORT(int) _nc_sigprocmask(int, const sigset_t *, sigset_t *); #else /* !USE_PTHREADS */ +#if USE_PTHREADS_EINTR +# if USE_WEAK_SYMBOLS +#include +weak_symbol(pthread_sigmask); +weak_symbol(pthread_kill); +weak_symbol(pthread_self); +weak_symbol(pthread_equal); +extern NCURSES_EXPORT(int) _nc_sigprocmask(int, const sigset_t *, sigset_t *); +# undef sigprocmask +# define sigprocmask(a, b, c) _nc_sigprocmask(a, b, c) +# endif +#endif /* USE_PTHREADS_EINTR */ + #define _nc_init_pthreads() /* nothing */ #define _nc_mutex_init(obj) /* nothing */ #define _nc_lock_global(name) /* nothing */ #define _nc_try_global(name) 0 #define _nc_unlock_global(name) /* nothing */ - #endif /* USE_PTHREADS */ -#if HAVE_GETTIMEOFDAY +#if USE_PTHREADS_EINTR +extern NCURSES_EXPORT(void) _nc_set_read_thread(bool); +#else +#define _nc_set_read_thread(enable) /* nothing */ +#endif + +/* + * When using sp-funcs, locks are targeted to SCREEN-level granularity. + * So the locking is done in the non-sp-func (which calls the sp-func) rather + * than in the sp-func itself. + * + * Use the _nc_nonsp_XXX functions in the function using "NCURSES_SP_NAME()". + * Use the _nc_sp_XXX functions in the function using "#if NCURSES_SP_FUNCS". + */ +#if NCURSES_SP_FUNCS + +#define _nc_nonsp_lock_global(name) /* nothing */ +#define _nc_nonsp_try_global(name) 0 +#define _nc_nonsp_unlock_global(name) /* nothing */ + +#define _nc_sp_lock_global(name) _nc_lock_global(name) +#define _nc_sp_try_global(name) _nc_try_global(name) +#define _nc_sp_unlock_global(name) _nc_unlock_global(name) + +#else + +#define _nc_nonsp_lock_global(name) _nc_lock_global(name) +#define _nc_nonsp_try_global(name) _nc_try_global(name) +#define _nc_nonsp_unlock_global(name) _nc_unlock_global(name) + +#define _nc_sp_lock_global(name) /* nothing */ +#define _nc_sp_try_global(name) 0 +#define _nc_sp_unlock_global(name) /* nothing */ + +#endif + +#if HAVE_CLOCK_GETTIME +# define PRECISE_GETTIME 1 +# define GetClockTime(t) clock_gettime(CLOCK_REALTIME, t) +# define TimeType struct timespec +# define TimeScale 1000000000L /* 1e9 */ +# define sub_secs tv_nsec +#elif HAVE_GETTIMEOFDAY # define PRECISE_GETTIME 1 +# define GetClockTime(t) gettimeofday(t, 0) # define TimeType struct timeval +# define TimeScale 1000000L /* 1e6 */ +# define sub_secs tv_usec #else # define PRECISE_GETTIME 0 # define TimeType time_t @@ -418,15 +763,15 @@ extern NCURSES_EXPORT(int) _nc_sigprocmask(int, const sigset_t *, sigset_t *); /* * Definitions for color pairs */ -typedef unsigned colorpair_t; /* type big enough to store PAIR_OF() */ -#define C_SHIFT 9 /* we need more bits than there are colors */ -#define C_MASK ((1 << C_SHIFT) - 1) -#define PAIR_OF(fg, bg) ((((fg) & C_MASK) << C_SHIFT) | ((bg) & C_MASK)) -#define isDefaultColor(c) ((c) >= COLOR_DEFAULT || (c) < 0) -#define COLOR_DEFAULT C_MASK +#define MAX_OF_TYPE(t) (int)(((unsigned t)(~0))>>1) + +#include + +#define isDefaultColor(c) ((c) < 0) +#define COLOR_DEFAULT -1 -#if defined(USE_TERMLIB) && !defined(NEED_NCURSES_CH_T) +#if defined(USE_BUILD_CC) || (defined(USE_TERMLIB) && !defined(NEED_NCURSES_CH_T)) #undef NCURSES_CH_T /* this is not a termlib feature */ #define NCURSES_CH_T void /* ...but we need a pointer in SCREEN */ @@ -452,8 +797,19 @@ typedef enum { #if USE_SYSMOUSE ,M_SYSMOUSE /* FreeBSD sysmouse on console */ #endif +#ifdef USE_TERM_DRIVER + ,M_TERM_DRIVER /* Win32 console, etc */ +#endif } MouseType; +typedef enum { + MF_X10 = 0 /* conventional 3-byte format */ + , MF_SGR1006 /* xterm private mode 1006, SGR-style */ +#ifdef EXP_XTERM_1005 + , MF_XTERM_1005 /* xterm UTF-8 private mode 1005 */ +#endif +} MouseFormat; + /* * Structures for scrolling. */ @@ -470,7 +826,7 @@ typedef struct { struct _SLK; -#ifndef USE_TERMLIB +#if !(defined(USE_TERMLIB) || defined(USE_BUILD_CC)) typedef struct { @@ -482,27 +838,24 @@ typedef struct } slk_ent; typedef struct _SLK { - char dirty; /* all labels have changed */ - char hidden; /* soft labels are hidden */ - WINDOW *win; + bool dirty; /* all labels have changed */ + bool hidden; /* soft labels are hidden */ + WINDOW *win; slk_ent *ent; - short maxlab; /* number of available labels */ - short labcnt; /* number of allocated labels */ - short maxlen; /* length of labels */ + short maxlab; /* number of available labels */ + short labcnt; /* number of allocated labels */ + short maxlen; /* length of labels */ NCURSES_CH_T attr; /* soft label attribute */ } SLK; #endif /* USE_TERMLIB */ -typedef struct { - WINDOW *win; /* the window used in the hook */ - int line; /* lines to take, < 0 => from bottom*/ - int (*hook)(WINDOW *, int); /* callback for user */ -} ripoff_t; - #if USE_GPM_SUPPORT #undef buttons /* term.h defines this, and gpm uses it! */ #include +#if USE_WEAK_SYMBOLS +weak_symbol(Gpm_Wgetch); +#endif #ifdef HAVE_LIBDL /* link dynamically to GPM */ @@ -511,10 +864,10 @@ typedef int (*TYPE_Gpm_Open) (Gpm_Connect *, int); typedef int (*TYPE_Gpm_Close) (void); typedef int (*TYPE_Gpm_GetEvent) (Gpm_Event *); -#define my_gpm_fd SP->_mouse_gpm_fd -#define my_Gpm_Open SP->_mouse_Gpm_Open -#define my_Gpm_Close SP->_mouse_Gpm_Close -#define my_Gpm_GetEvent SP->_mouse_Gpm_GetEvent +#define my_gpm_fd SP_PARM->_mouse_gpm_fd +#define my_Gpm_Open SP_PARM->_mouse_Gpm_Open +#define my_Gpm_Close SP_PARM->_mouse_Gpm_Close +#define my_Gpm_GetEvent SP_PARM->_mouse_Gpm_GetEvent #else /* link statically to GPM */ #define my_gpm_fd &gpm_fd @@ -524,55 +877,15 @@ typedef int (*TYPE_Gpm_GetEvent) (Gpm_Event *); #endif /* HAVE_LIBDL */ #endif /* USE_GPM_SUPPORT */ -typedef struct { - long sequence; - bool last_used; - char *fix_sgr0; /* this holds the filtered sgr0 string */ - char *last_bufp; /* help with fix_sgr0 leak */ - TERMINAL *last_term; -} TGETENT_CACHE; - -#define TGETENT_MAX 4 - /* - * State of tparm(). + * When converting from terminfo to termcap, check for cases where we can trim + * octal escapes down to 2-character form. It is useful for terminfo format + * also, but not as important. */ -#define STACKSIZE 20 - -typedef struct { - union { - int num; - char *str; - } data; - bool num_type; -} STACK_FRAME; - -#define NUM_VARS 26 - -typedef struct { -#ifdef TRACE - const char *tname; -#endif - const char *tparam_base; - - STACK_FRAME stack[STACKSIZE]; - int stack_ptr; - - char *out_buff; - size_t out_size; - size_t out_used; - - char *fmt_buff; - size_t fmt_size; +#define MAX_TC_FIXUPS 10 +#define MIN_TC_FIXUPS 4 - int dynamic_var[NUM_VARS]; - int static_vars[NUM_VARS]; -} TPARM_STATE; - -typedef struct { - char *text; - size_t size; -} TRACEBUF; +#define isoctal(c) ((c) >= '0' && (c) <= '7') /* * The filesystem database normally uses a single-letter for the lower level @@ -581,8 +894,10 @@ typedef struct { */ #if MIXEDCASE_FILENAMES #define LEAF_FMT "%c" +#define LEAF_LEN 1 #else #define LEAF_FMT "%02x" +#define LEAF_LEN 2 #endif /* @@ -595,133 +910,69 @@ typedef struct { #define TRACEMSE_MAX (80 + (5 * 10) + (32 * 15)) #define TRACEMSE_FMT "id %2d at (%2d, %2d, %2d) state %4lx = {" /* } */ -/* - * Global data which is not specific to a screen. - */ -typedef struct { - SIG_ATOMIC_T have_sigwinch; - SIG_ATOMIC_T cleanup_nested; - - bool init_signals; - bool init_screen; - - const char *comp_sourcename; - char *comp_termtype; - - bool have_tic_directory; - bool keep_tic_directory; - const char *tic_directory; - - char *dbi_list; - int dbi_size; - - char *first_name; - char **keyname_table; - - int slk_format; - - char *safeprint_buf; - size_t safeprint_used; - - TGETENT_CACHE tgetent_cache[TGETENT_MAX]; - int tgetent_index; - long tgetent_sequence; - - WINDOWLIST *_nc_windowlist; -#define _nc_windows _nc_globals._nc_windowlist - -#if USE_HOME_TERMINFO - char *home_terminfo; -#endif - -#if !USE_SAFE_SPRINTF - int safeprint_cols; - int safeprint_rows; -#endif - -#ifdef TRACE - bool init_trace; - char trace_fname[PATH_MAX]; - int trace_level; - FILE *trace_fp; - - char *tracearg_buf; - size_t tracearg_used; - - TRACEBUF *tracebuf_ptr; - size_t tracebuf_used; - - char tracechr_buf[40]; - - char *tracedmp_buf; - size_t tracedmp_used; - - unsigned char *tracetry_buf; - size_t tracetry_used; - -#define _nc_globals_traceatr_color_buf_size 80 - char traceatr_color_buf[2][_nc_globals_traceatr_color_buf_size]; - int traceatr_color_sel; - int traceatr_color_last; - -#endif /* TRACE */ - -#ifdef USE_PTHREADS - pthread_mutex_t mutex_curses; - pthread_mutex_t mutex_tst_tracef; - pthread_mutex_t mutex_tracef; - int nested_tracef; - int use_pthreads; -#define _nc_use_pthreads _nc_globals.use_pthreads +#ifdef USE_TERM_DRIVER +struct DriverTCB; /* Terminal Control Block forward declaration */ +#define INIT_TERM_DRIVER() _nc_globals.term_driver = _nc_get_driver +#else +#define INIT_TERM_DRIVER() /* nothing */ #endif -} NCURSES_GLOBALS; extern NCURSES_EXPORT_VAR(NCURSES_GLOBALS) _nc_globals; -#define N_RIPS 5 +/* The limit reserves one byte for a terminating NUL */ +#define my_getstr_limit (_nc_globals.getstr_limit - 1) +#define _nc_getstr_limit(n) \ + (((n) < 0) \ + ? my_getstr_limit \ + : (((n) > my_getstr_limit) \ + ? my_getstr_limit \ + : (n))) /* - * Global data which can be swept up into a SCREEN when one is created. - * It may be modified before the next SCREEN is created. + * Use screen-specific ripoff data (for softkeys) rather than global. */ -typedef struct { - bool use_env; - bool filter_mode; - attr_t previous_attr; - ripoff_t rippedoff[N_RIPS]; - ripoff_t *rsp; - TPARM_STATE tparm_state; - TTY *saved_tty; /* savetty/resetty information */ -#if NCURSES_NO_PADDING - bool _no_padding; /* flag to set if padding disabled */ -#endif -#if BROKEN_LINKER || USE_REENTRANT - chtype *real_acs_map; - int _LINES; - int _COLS; - TERMINAL *_cur_term; -#ifdef TRACE - long _outchars; - const char *_tputs_trace; -#endif +#ifdef USE_SP_RIPOFF +#define safe_ripoff_sp (sp)->rsp +#define safe_ripoff_stack (sp)->rippedoff +#else +#define safe_ripoff_sp _nc_prescreen.rsp +#define safe_ripoff_stack _nc_prescreen.rippedoff #endif -} NCURSES_PRESCREEN; -#define ripoff_sp _nc_prescreen.rsp -#define ripoff_stack _nc_prescreen.rippedoff +extern NCURSES_EXPORT_VAR(NCURSES_PRESCREEN) _nc_prescreen; + +typedef enum { + ewInitial = 0, + ewRunning, + ewSuspend +} ENDWIN; + +typedef struct { + int _nl; /* True if NL -> CR/NL is on */ + int _raw; /* True if in raw mode */ + int _cbreak; /* 1 if in cbreak mode */ + /* > 1 if in halfdelay mode */ + int _echo; /* True if echo on */ +} TTY_FLAGS; -extern NCURSES_EXPORT_VAR(NCURSES_PRESCREEN) _nc_prescreen; +#define IsNl(sp) (sp)->_tty_flags._nl +#define IsRaw(sp) (sp)->_tty_flags._raw +#define IsCbreak(sp) (sp)->_tty_flags._cbreak +#define IsEcho(sp) (sp)->_tty_flags._echo /* * The SCREEN structure. */ - -struct screen { - int _ifd; /* input file ptr for screen */ +typedef struct screen { + int _ifd; /* input file descriptor for screen */ + int _ofd; /* output file descriptor for screen */ FILE *_ofp; /* output file ptr for screen */ - char *_setbuf; /* buffered I/O for output */ + char *out_buffer; /* output buffer */ + size_t out_limit; /* output buffer size */ + size_t out_inuse; /* output buffer current use */ bool _filtered; /* filter() was called */ - bool _buffered; /* setvbuf uses _setbuf data */ + bool _prescreen; /* is in prescreen phase */ + bool _use_env; /* LINES & COLS from environment? */ int _checkfd; /* filedesc for typeahead check */ TERMINAL *_term; /* terminal type information */ TTY _saved_tty; /* savetty/resetty information */ @@ -735,6 +986,10 @@ struct screen { WINDOW *_newscr; /* virtual screen to be updated to */ WINDOW *_stdscr; /* screen's full-window context */ +#define CurScreen(sp) (sp)->_curscr +#define NewScreen(sp) (sp)->_newscr +#define StdScreen(sp) (sp)->_stdscr + TRIES *_keytry; /* "Try" for use with keypad mode */ TRIES *_key_ok; /* Disabled keys via keyok(,FALSE) */ bool _tried; /* keypad mode was initialized */ @@ -755,27 +1010,16 @@ struct screen { int _cursrow; /* physical cursor row */ int _curscol; /* physical cursor column */ bool _notty; /* true if we cannot switch non-tty */ - int _nl; /* True if NL -> CR/NL is on */ - int _raw; /* True if in raw mode */ - int _cbreak; /* 1 if in cbreak mode */ - /* > 1 if in halfdelay mode */ - int _echo; /* True if echo on */ + TTY_FLAGS _tty_flags; int _use_meta; /* use the meta key? */ struct _SLK *_slk; /* ptr to soft key struct / NULL */ int slk_format; /* selected format for this screen */ /* cursor movement costs; units are 10ths of milliseconds */ -#if NCURSES_NO_PADDING - bool _no_padding; /* flag to set if padding disabled */ -#endif int _char_padding; /* cost of character put */ int _cr_cost; /* cost of (carriage_return) */ int _cup_cost; /* cost of (cursor_address) */ int _home_cost; /* cost of (cursor_home) */ int _ll_cost; /* cost of (cursor_to_ll) */ -#if USE_HARD_TABS - int _ht_cost; /* cost of (tab) */ - int _cbt_cost; /* cost of (backtab) */ -#endif /* USE_HARD_TABS */ int _cub1_cost; /* cost of (cursor_left) */ int _cuf1_cost; /* cost of (cursor_right) */ int _cud1_cost; /* cost of (cursor_down) */ @@ -809,16 +1053,13 @@ struct screen { int _scrolling; /* 1 if terminal's smart enough to */ /* used in lib_color.c */ + rgb_bits_t _direct_color; /* RGB overrides color-table */ color_t *_color_table; /* screen's color palette */ int _color_count; /* count of colors in palette */ colorpair_t *_color_pairs; /* screen's color pair list */ - int _pair_count; /* count of color pairs */ -#if NCURSES_EXT_FUNCS - bool _default_color; /* use default colors */ - bool _has_sgr_39_49; /* has ECMA default color support */ - int _default_fg; /* assumed default foreground */ - int _default_bg; /* assumed default background */ -#endif + int _pair_count; /* same as COLOR_PAIRS */ + int _pair_limit; /* actual limit of color-pairs */ + int _pair_alloc; /* current table-size of color-pairs */ chtype _ok_attributes; /* valid attributes for terminal */ chtype _xmc_suppress; /* attributes to suppress if xmc */ chtype _xmc_triggers; /* attributes to process if xmc */ @@ -839,8 +1080,6 @@ struct screen { */ bool _nc_sp_idlok; bool _nc_sp_idcok; -#define _nc_idlok SP->_nc_sp_idlok -#define _nc_idcok SP->_nc_sp_idcok /* * These are the data that support the mouse interface. @@ -855,11 +1094,68 @@ struct screen { void (*_mouse_wrap) (SCREEN *); int _mouse_fd; /* file-descriptor, if any */ bool _mouse_active; /* true if initialized */ - mmask_t _mouse_mask; + mmask_t _mouse_mask; /* set via mousemask() */ + mmask_t _mouse_mask2; /* OR's in press/release bits */ + mmask_t _mouse_bstate; + MouseFormat _mouse_format; /* type of xterm mouse protocol */ NCURSES_CONST char *_mouse_xtermcap; /* string to enable/disable mouse */ MEVENT _mouse_events[EV_MAX]; /* hold the last mouse event seen */ MEVENT *_mouse_eventp; /* next free slot in event queue */ + /* + * These are data that support the proper handling of the panel stack on an + * per screen basis. + */ + struct panelhook _panelHook; + + bool _sig_winch; + SCREEN *_next_screen; + + /* hashes for old and new lines */ + unsigned long *oldhash, *newhash; + HASHMAP *hashtab; + int hashtab_len; + int *_oldnum_list; + int _oldnum_size; + + NCURSES_SP_OUTC _outch; /* output handler if not putc */ + NCURSES_OUTC jump; + + ripoff_t rippedoff[N_RIPS]; + ripoff_t *rsp; + + int _legacy_coding; /* see use_legacy_coding() */ + +#if NCURSES_NO_PADDING + bool _no_padding; /* flag to set if padding disabled */ +#endif + +#if USE_HARD_TABS + int _ht_cost; /* cost of (tab) */ + int _cbt_cost; /* cost of (backtab) */ +#endif /* USE_HARD_TABS */ + + /* used in lib_vidattr.c */ +#if USE_ITALIC + bool _use_ritm; /* true if we may use 'ritm' */ +#endif + + /* used in getch/twait */ +#if USE_KLIBC_KBD + bool _extended_key; /* true if an extended key */ +#endif + + /* used in lib_color.c */ +#if NCURSES_EXT_FUNCS + bool _assumed_color; /* use assumed colors */ + bool _default_color; /* use default colors */ + bool _has_sgr_39_49; /* has ECMA default color support */ + int _default_fg; /* assumed default foreground */ + int _default_bg; /* assumed default background */ + int _default_pairs; /* count pairs using default color */ +#endif + + /* system-dependent mouse data */ #if USE_GPM_SUPPORT bool _mouse_gpm_loaded; bool _mouse_gpm_found; @@ -890,34 +1186,25 @@ struct screen { int _sysmouse_new_buttons; #endif +#if defined(USE_TERM_DRIVER) || defined(EXP_WIN32_DRIVER) + MEVENT _drv_mouse_fifo[FIFO_SIZE]; + int _drv_mouse_head; + int _drv_mouse_tail; + int _drv_mouse_old_buttons; + int _drv_mouse_new_buttons; +#endif /* * This supports automatic resizing */ #if USE_SIZECHANGE - int (*_resize)(int,int); + int (*_resize)(NCURSES_SP_DCLx int y, int x); int (*_ungetch)(SCREEN *, int); #endif - /* - * These are data that support the proper handling of the panel stack on an - * per screen basis. - */ - struct panelhook _panelHook; - - bool _sig_winch; - SCREEN *_next_screen; - - /* hashes for old and new lines */ - unsigned long *oldhash, *newhash; - HASHMAP *hashtab; - int hashtab_len; - int *_oldnum_list; - int _oldnum_size; - - bool _cleanup; /* cleanup after int/quit signal */ - int (*_outch)(int); /* output handler if not putc */ - - int _legacy_coding; /* see use_legacy_coding() */ +#ifdef USE_SP_WINDOWLIST + WINDOWLIST* _windowlist; +#define WindowList(sp) (sp)->_windowlist +#endif #if USE_REENTRANT char _ttytype[NAMESIZE]; @@ -925,17 +1212,12 @@ struct screen { int _TABSIZE; int _LINES; int _COLS; -#ifdef TRACE - long _outchars; - const char *_tputs_trace; -#endif #endif -#ifdef TRACE -#define _nc_screen_tracechr_buf_size 40 - char tracechr_buf[_nc_screen_tracechr_buf_size]; - char tracemse_buf[TRACEMSE_MAX]; +#if NCURSES_SP_FUNCS + bool use_tioctl; #endif + /* * ncurses/ncursesw are the same up to this point. */ @@ -944,17 +1226,34 @@ struct screen { * UTF-8, but do not permit ACS at the same time (see tty_update.c). */ bool _screen_acs_fix; + bool _screen_unicode; #endif -}; + +#if NCURSES_EXT_FUNCS && NCURSES_EXT_COLORS + void *_ordered_pairs; /* index used by alloc_pair() */ + int _pairs_used; /* actual number of color-pairs used */ + int _recent_pair; /* number for most recent free-pair */ +#endif + +#ifdef TRACE + char tracechr_buf[40]; + char tracemse_buf[TRACEMSE_MAX]; +#if USE_REENTRANT + long _outchars; + const char *_tputs_trace; +#endif +#endif +#undef SCREEN +} SCREEN; extern NCURSES_EXPORT_VAR(SCREEN *) _nc_screen_chain; extern NCURSES_EXPORT_VAR(SIG_ATOMIC_T) _nc_have_sigwinch; WINDOWLIST { - WINDOW win; /* first, so WINDOW_EXT() works */ WINDOWLIST *next; SCREEN *screen; /* screen containing the window */ -#ifdef _XOPEN_SOURCE_EXTENDED + WINDOW win; /* WINDOW_EXT() needs to account for offset */ +#if NCURSES_WIDECHAR char addch_work[(MB_LEN_MAX * 9) + 1]; unsigned addch_used; /* number of bytes in addch_work[] */ int addch_x; /* x-position for addch_work[] */ @@ -962,7 +1261,27 @@ extern NCURSES_EXPORT_VAR(SIG_ATOMIC_T) _nc_have_sigwinch; #endif }; -#define WINDOW_EXT(win,field) (((WINDOWLIST *)(win))->field) +#define WINDOW_EXT(w,m) (((WINDOWLIST *)((void *)((char *)(w) - offsetof(WINDOWLIST, win))))->m) + +#ifdef USE_SP_WINDOWLIST +#define SP_INIT_WINDOWLIST(sp) WindowList(sp) = 0 +#else +#define SP_INIT_WINDOWLIST(sp) /* nothing */ +#endif + +#define SP_PRE_INIT(sp) \ + sp->_cursrow = -1; \ + sp->_curscol = -1; \ + IsNl(sp) = TRUE; \ + IsRaw(sp) = FALSE; \ + IsCbreak(sp) = 0; \ + IsEcho(sp) = TRUE; \ + sp->_fifohead = -1; \ + sp->_endwin = ewSuspend; \ + sp->_cursor = -1; \ + SP_INIT_WINDOWLIST(sp); \ + sp->_outch = NCURSES_OUTC_FUNC; \ + sp->jump = 0 \ /* usually in */ #ifndef UCHAR_MAX @@ -1038,17 +1357,21 @@ extern NCURSES_EXPORT_VAR(SIG_ATOMIC_T) _nc_have_sigwinch; #define RESET_OUTCHARS() COUNT_OUTCHARS(-_nc_outchars) #define UChar(c) ((unsigned char)(c)) -#define ChCharOf(c) ((c) & (chtype)A_CHARTEXT) -#define ChAttrOf(c) ((c) & (chtype)A_ATTRIBUTES) +#define UShort(c) ((unsigned short)(c)) +#define ChCharOf(c) ((chtype)(c) & (chtype)A_CHARTEXT) +#define ChAttrOf(c) ((chtype)(c) & (chtype)A_ATTRIBUTES) + +#define TR_PUTC(c) TR(TRACE_CHARPUT, ("PUTC %#x", UChar(c))) #ifndef MB_LEN_MAX -#define MB_LEN_MAX 8 /* should be >= MB_CUR_MAX, but that may be a function */ +#define MB_LEN_MAX 16 /* should be >= MB_CUR_MAX, but that may be a function */ #endif #if USE_WIDEC_SUPPORT /* { */ +/* true if the status/errno indicate an illegal multibyte sequence */ #define isEILSEQ(status) (((size_t)status == (size_t)-1) && (errno == EILSEQ)) -#define init_mb(state) memset(&state, 0, sizeof(state)) +#define init_mb(state) memset(&(state), 0, sizeof(state)) #if NCURSES_EXT_COLORS #define NulColor , 0 @@ -1075,42 +1398,52 @@ extern NCURSES_EXPORT_VAR(SIG_ATOMIC_T) _nc_have_sigwinch; && (a).chars[3] == (b).chars[3] \ && (a).chars[4] == (b).chars[4] \ if_EXT_COLORS(&& (a).ext_color == (b).ext_color)) +#elif CCHARW_MAX > 0 +#error Inconsistent values for CCHARW_MAX #else #define CharEq(a,b) (!memcmp(&(a), &(b), sizeof(a))) #endif #define SetChar(ch,c,a) do { \ - NCURSES_CH_T *_cp = &ch; \ + NCURSES_CH_T *_cp = &(ch); \ memset(_cp, 0, sizeof(ch)); \ - _cp->chars[0] = (c); \ + _cp->chars[0] = (wchar_t) (c); \ _cp->attr = (a); \ - if_EXT_COLORS(SetPair(ch, PAIR_NUMBER(a))); \ + if_EXT_COLORS(SetPair(ch, PairNumber(a))); \ } while (0) -#define CHREF(wch) (&wch) -#define CHDEREF(wch) (*wch) +#define CHREF(wch) (&(wch)) +#define CHDEREF(wch) (*(wch)) #define ARG_CH_T NCURSES_CH_T * #define CARG_CH_T const NCURSES_CH_T * #define PUTC_DATA char PUTC_buf[MB_LEN_MAX]; int PUTC_i, PUTC_n; \ mbstate_t PUT_st; wchar_t PUTC_ch #define PUTC_INIT init_mb (PUT_st) -#define PUTC(ch,b) do { if(!isWidecExt(ch)) { \ +#define PUTC(ch) do { if(!isWidecExt(ch)) { \ if (Charable(ch)) { \ - fputc(CharOf(ch), b); \ + TR_PUTC(CharOf(ch)); \ + NCURSES_OUTC_FUNC (NCURSES_SP_ARGx CharOf(ch)); \ COUNT_OUTCHARS(1); \ } else { \ - PUTC_INIT; \ for (PUTC_i = 0; PUTC_i < CCHARW_MAX; ++PUTC_i) { \ PUTC_ch = (ch).chars[PUTC_i]; \ if (PUTC_ch == L'\0') \ break; \ - PUTC_n = wcrtomb(PUTC_buf, \ - (ch).chars[PUTC_i], &PUT_st); \ + PUTC_INIT; \ + PUTC_n = (int) wcrtomb(PUTC_buf, \ + (ch).chars[PUTC_i], &PUT_st); \ if (PUTC_n <= 0) { \ - if (PUTC_ch && is8bits(PUTC_ch) && PUTC_i == 0) \ - putc(PUTC_ch,b); \ + if (PUTC_ch && is8bits(PUTC_ch) && PUTC_i == 0) { \ + TR_PUTC(CharOf(ch)); \ + NCURSES_OUTC_FUNC (NCURSES_SP_ARGx CharOf(ch)); \ + } \ break; \ + } else { \ + int PUTC_j; \ + for (PUTC_j = 0; PUTC_j < PUTC_n; ++PUTC_j) { \ + TR_PUTC(PUTC_buf[PUTC_j]); \ + NCURSES_OUTC_FUNC (NCURSES_SP_ARGx PUTC_buf[PUTC_j]); \ + } \ } \ - fwrite(PUTC_buf, (unsigned) PUTC_n, 1, b); \ } \ COUNT_OUTCHARS(PUTC_i); \ } } } while (0) @@ -1126,18 +1459,18 @@ extern NCURSES_EXPORT_VAR(SIG_ATOMIC_T) _nc_have_sigwinch; * zero. Otherwise we can use those bits to tell if a cell is the * first or extension part of a wide character. */ -#define WidecExt(ch) (AttrOf(ch) & A_CHARTEXT) +#define WidecExt(ch) (int) (AttrOf(ch) & A_CHARTEXT) #define isWidecBase(ch) (WidecExt(ch) == 1) #define isWidecExt(ch) (WidecExt(ch) > 1 && WidecExt(ch) < 32) #define SetWidecExt(dst, ext) AttrOf(dst) &= ~A_CHARTEXT, \ - AttrOf(dst) |= (ext + 1) + AttrOf(dst) |= (attr_t) (ext + 1) #define if_WIDEC(code) code -#define Charable(ch) ((SP != 0 && SP->_legacy_coding) \ +#define Charable(ch) (((SP_PARM->_legacy_coding) \ || (AttrOf(ch) & A_ALTCHARSET) \ - || (!isWidecExt(ch) && \ + || (!isWidecExt(ch))) && \ (ch).chars[1] == L'\0' && \ - _nc_is_charable(CharOf(ch)))) + _nc_is_charable(CharOf(ch))) #define L(ch) L ## ch #else /* }{ */ @@ -1154,8 +1487,11 @@ extern NCURSES_EXPORT_VAR(SIG_ATOMIC_T) _nc_have_sigwinch; #define CHDEREF(wch) wch #define ARG_CH_T NCURSES_CH_T #define CARG_CH_T NCURSES_CH_T -#define PUTC_DATA int data = 0 -#define PUTC(ch,b) do { data = CharOf(ch); putc(data,b); } while (0) +#define PUTC_DATA /* nothing */ +#define PUTC(ch) { \ + TR_PUTC(ch); \ + NCURSES_OUTC_FUNC (NCURSES_SP_ARGx (int) ch); \ + } #define BLANK (' '|A_NORMAL) #define ZEROS ('\0'|A_NORMAL) @@ -1164,6 +1500,7 @@ extern NCURSES_EXPORT_VAR(SIG_ATOMIC_T) _nc_have_sigwinch; #define isWidecExt(ch) (0) #define if_WIDEC(code) /* nothing */ +#define Charable(ch) (CharOf(ch) >= ' ' && CharOf(ch) <= '~') #define L(ch) ch #endif /* } */ @@ -1183,36 +1520,75 @@ extern NCURSES_EXPORT_VAR(SIG_ATOMIC_T) _nc_have_sigwinch; #define CHANGED_CELL(line,col) \ if (line->firstchar == _NOCHANGE) \ - line->firstchar = line->lastchar = col; \ + line->firstchar = line->lastchar = (NCURSES_SIZE_T) (col); \ else if ((col) < line->firstchar) \ - line->firstchar = col; \ + line->firstchar = (NCURSES_SIZE_T) (col); \ else if ((col) > line->lastchar) \ - line->lastchar = col + line->lastchar = (NCURSES_SIZE_T) (col) #define CHANGED_RANGE(line,start,end) \ if (line->firstchar == _NOCHANGE \ || line->firstchar > (start)) \ - line->firstchar = start; \ + line->firstchar = (NCURSES_SIZE_T) (start); \ if (line->lastchar == _NOCHANGE \ || line->lastchar < (end)) \ - line->lastchar = end + line->lastchar = (NCURSES_SIZE_T) (end) #define CHANGED_TO_EOL(line,start,end) \ if (line->firstchar == _NOCHANGE \ || line->firstchar > (start)) \ - line->firstchar = start; \ - line->lastchar = end + line->firstchar = (NCURSES_SIZE_T) (start); \ + line->lastchar = (NCURSES_SIZE_T) (end) #define SIZEOF(v) (sizeof(v)/sizeof(v[0])) +#include +#include + #define FreeIfNeeded(p) if ((p) != 0) free(p) /* FreeAndNull() is not a comma-separated expression because some compilers * do not accept a mixture of void with values. */ -#define FreeAndNull(p) free(p); p = 0 +#define FreeAndNull(p) do { free(p); p = 0; } while (0) -#include +#ifdef EXP_OOM_TESTING +extern NCURSES_EXPORT(void *) _nc_oom_malloc(size_t size); +extern NCURSES_EXPORT(void *) _nc_oom_calloc(size_t nmemb, size_t size); +extern NCURSES_EXPORT(void *) _nc_oom_realloc(void *ptr, size_t size); +extern NCURSES_EXPORT(void) _nc_oom_free(void *ptr); +extern NCURSES_EXPORT(char *) _nc_oom_strdup(const char *ptr); +#define malloc(size) _nc_oom_malloc(size) +#define calloc(nmemb, size) _nc_oom_calloc(nmemb, size) +#define realloc(ptr, size) _nc_oom_realloc(ptr, size) +#define free(ptr) _nc_oom_free(ptr) +#define strdup(ptr) _nc_oom_strdup(ptr) +#endif + +/* + * Use these for tic/infocmp malloc failures. Generally the ncurses library + * tries to limp along after a failure. + */ +#define TYPE_MALLOC(type, size, name) \ + do { \ + name = typeMalloc(type, size); \ + if (name == 0) \ + _nc_err_abort(MSG_NO_MEMORY); \ + } while (0) + +#define TYPE_CALLOC(type, size, name) \ + do { \ + name = typeCalloc(type, size); \ + if (name == 0) \ + _nc_err_abort(MSG_NO_MEMORY); \ + } while (0) + +#define TYPE_REALLOC(type, size, name) \ + do { \ + name = typeRealloc(type, size, name); \ + if (name == 0) \ + _nc_err_abort(MSG_NO_MEMORY); \ + } while (0) /* * TTY bit definition for converting tabs to spaces. @@ -1231,12 +1607,20 @@ extern NCURSES_EXPORT_VAR(SIG_ATOMIC_T) _nc_have_sigwinch; # endif #endif +#ifdef __TANDEM +#define ROOT_UID 65535 +#endif + +#ifndef ROOT_UID +#define ROOT_UID 0 +#endif + /* * Standardize/simplify common loops */ #define each_screen(p) p = _nc_screen_chain; p != 0; p = (p)->_next_screen -#define each_window(p) p = _nc_windows; p != 0; p = (p)->next -#define each_ripoff(p) p = ripoff_stack; (p - ripoff_stack) < N_RIPS; ++p +#define each_window(sp,p) p = WindowList(sp); p != 0; p = (p)->next +#define each_ripoff(p) p = safe_ripoff_stack; (p - safe_ripoff_stack) < N_RIPS; ++p /* * Prefixes for call/return points of library function traces. We use these to @@ -1247,6 +1631,9 @@ extern NCURSES_EXPORT_VAR(SIG_ATOMIC_T) _nc_have_sigwinch; #define T_CREATE(fmt) "create :" fmt #define T_RETURN(fmt) "return }" fmt +#define NonNull(s) ((s) != 0 ? s : "") +#define NonEmpty(s) ((s) != 0 && *(s) != '\0') + #ifdef TRACE #if USE_REENTRANT @@ -1255,12 +1642,16 @@ extern NCURSES_EXPORT_VAR(SIG_ATOMIC_T) _nc_have_sigwinch; #define TPUTS_TRACE(s) _nc_tputs_trace = s; #endif +#ifdef HAVE_CONSISTENT_GETENV #define START_TRACE() \ if ((_nc_tracing & TRACE_MAXIMUM) == 0) { \ int t = _nc_getenv_num("NCURSES_TRACE"); \ if (t >= 0) \ - trace((unsigned) t); \ + curses_trace((unsigned) t); \ } +#else +#define START_TRACE() /* nothing */ +#endif /* * Many of the _tracef() calls use static buffers; lock the trace state before @@ -1277,37 +1668,58 @@ extern NCURSES_EXPORT(void) _nc_locked_tracef (const char *, ...) GCC_PRINTFLIKE #define TR(n, a) if (USE_TRACEF(n)) _nc_locked_tracef a #define T(a) TR(TRACE_CALLS, a) -#define TRACE_RETURN(value,type) return _nc_retrace_##type(value) +#define TRACE_RETURN(value,type) return _nc_retrace_##type((type)(value)) +#define TRACE_RETURN1(value,dst) return _nc_retrace_##dst(value) +#define TRACE_RETURN2(value,dst,src) return _nc_retrace_##dst##_##src(value) +#define TRACE_RETURN_SP(value,type) return _nc_retrace_##type(SP_PARM, value) + +typedef void VoidFunc(void); + +#define TR_FUNC_LEN ((sizeof(void *) + sizeof(void (*)(void))) * 2 + 4) +#define TR_FUNC_BFR(max) char tr_func_data[max][TR_FUNC_LEN] +#define TR_FUNC_ARG(num,func) _nc_fmt_funcptr(&tr_func_data[num][0], (const char *)&(func), sizeof((func))) #define returnAttr(code) TRACE_RETURN(code,attr_t) #define returnBits(code) TRACE_RETURN(code,unsigned) #define returnBool(code) TRACE_RETURN(code,bool) -#define returnCPtr(code) TRACE_RETURN(code,cptr) -#define returnCVoidPtr(code) TRACE_RETURN(code,cvoid_ptr) -#define returnChar(code) TRACE_RETURN(code,chtype) +#define returnCPtr(code) TRACE_RETURN1(code,cptr) +#define returnCVoidPtr(code) TRACE_RETURN1(code,cvoid_ptr) +#define returnChar(code) TRACE_RETURN(code,char) +#define returnChtype(code) TRACE_RETURN(code,chtype) #define returnCode(code) TRACE_RETURN(code,int) -#define returnPtr(code) TRACE_RETURN(code,ptr) -#define returnSP(code) TRACE_RETURN(code,sp) -#define returnVoid T((T_RETURN(""))); return -#define returnVoidPtr(code) TRACE_RETURN(code,void_ptr) -#define returnWin(code) TRACE_RETURN(code,win) - -extern NCURSES_EXPORT(NCURSES_BOOL) _nc_retrace_bool (NCURSES_BOOL); +#define returnIntAttr(code) TRACE_RETURN2(code,int,attr_t) +#define returnMMask(code) TRACE_RETURN_SP(code,mmask_t) +#define returnPtr(code) TRACE_RETURN1(code,ptr) +#define returnSP(code) TRACE_RETURN1(code,sp) +#define returnVoid { T((T_RETURN(""))); return; } +#define returnVoidPtr(code) TRACE_RETURN1(code,void_ptr) +#define returnWin(code) TRACE_RETURN1(code,win) + +#define returnDB(rc) do { TR(TRACE_DATABASE,(T_RETURN("code %d"), (rc))); return (rc); } while (0) +#define returnPtrDB(rc) do { TR(TRACE_DATABASE,(T_RETURN("%p"), (rc))); return (rc); } while (0) +#define returnVoidDB do { TR(TRACE_DATABASE,(T_RETURN(""))); return; } while (0) + +extern NCURSES_EXPORT(NCURSES_BOOL) _nc_retrace_bool (int); extern NCURSES_EXPORT(NCURSES_CONST void *) _nc_retrace_cvoid_ptr (NCURSES_CONST void *); extern NCURSES_EXPORT(SCREEN *) _nc_retrace_sp (SCREEN *); extern NCURSES_EXPORT(WINDOW *) _nc_retrace_win (WINDOW *); extern NCURSES_EXPORT(attr_t) _nc_retrace_attr_t (attr_t); extern NCURSES_EXPORT(char *) _nc_retrace_ptr (char *); -extern NCURSES_EXPORT(char *) _nc_trace_ttymode(TTY *tty); +extern NCURSES_EXPORT(char *) _nc_trace_ttymode(const TTY *tty); extern NCURSES_EXPORT(char *) _nc_varargs (const char *, va_list); extern NCURSES_EXPORT(chtype) _nc_retrace_chtype (chtype); extern NCURSES_EXPORT(const char *) _nc_altcharset_name(attr_t, chtype); extern NCURSES_EXPORT(const char *) _nc_retrace_cptr (const char *); +extern NCURSES_EXPORT(char) _nc_retrace_char (int); extern NCURSES_EXPORT(int) _nc_retrace_int (int); +extern NCURSES_EXPORT(int) _nc_retrace_int_attr_t (attr_t); +extern NCURSES_EXPORT(mmask_t) _nc_retrace_mmask_t (SCREEN *, mmask_t); extern NCURSES_EXPORT(unsigned) _nc_retrace_unsigned (unsigned); extern NCURSES_EXPORT(void *) _nc_retrace_void_ptr (void *); extern NCURSES_EXPORT(void) _nc_fifo_dump (SCREEN *); +extern NCURSES_EXPORT(char *) _nc_fmt_funcptr(char *, const char *, size_t); + #if USE_REENTRANT NCURSES_WRAPPED_VAR(long, _nc_outchars); NCURSES_WRAPPED_VAR(const char *, _nc_tputs_trace); @@ -1322,6 +1734,10 @@ extern NCURSES_EXPORT_VAR(long) _nc_outchars; extern NCURSES_EXPORT_VAR(unsigned) _nc_tracing; +extern NCURSES_EXPORT(char *) _nc_tracebits (void); +extern NCURSES_EXPORT(char *) _tracemouse (const MEVENT *); +extern NCURSES_EXPORT(void) _tracedump (const char *, WINDOW *); + #if USE_WIDEC_SUPPORT extern NCURSES_EXPORT(const char *) _nc_viswbuf2 (int, const wchar_t *); extern NCURSES_EXPORT(const char *) _nc_viswbufn (const wchar_t *, int); @@ -1337,22 +1753,39 @@ extern NCURSES_EXPORT(const char *) _nc_viscbuf (const NCURSES_CH_T *, int); #define T(a) #define TR(n, a) #define TPUTS_TRACE(s) +#define TR_FUNC_BFR(max) #define returnAttr(code) return code #define returnBits(code) return code #define returnBool(code) return code #define returnCPtr(code) return code #define returnCVoidPtr(code) return code -#define returnChar(code) return code +#define returnChar(code) return ((char) code) +#define returnChtype(code) return code #define returnCode(code) return code +#define returnIntAttr(code) return code +#define returnMMask(code) return code #define returnPtr(code) return code #define returnSP(code) return code #define returnVoid return #define returnVoidPtr(code) return code #define returnWin(code) return code +#define returnDB(code) return code +#define returnPtrDB(rc) return rc +#define returnVoidDB return + #endif /* TRACE/!TRACE */ +/* + * Workaround for defective implementation of gcc attribute warn_unused_result + */ +#if defined(__GNUC__) && defined(_FORTIFY_SOURCE) +#define IGNORE_RC(func) errno = (int) func +#else +#define IGNORE_RC(func) (void) func +#endif /* gcc workarounds */ + /* * Return-codes for tgetent() and friends. */ @@ -1368,58 +1801,61 @@ extern NCURSES_EXPORT(void) name (void); \ NCURSES_EXPORT(void) name (void) { } #define ALL_BUT_COLOR ((chtype)~(A_COLOR)) -#define NONBLANK_ATTR (A_NORMAL|A_BOLD|A_DIM|A_BLINK) -#define XMC_CHANGES(c) ((c) & SP->_xmc_suppress) +#define NONBLANK_ATTR (A_BOLD | A_DIM | A_BLINK | A_ITALIC) +#define TPARM_ATTR (A_STANDOUT | A_UNDERLINE | A_REVERSE | A_BLINK | A_DIM | A_BOLD | A_ALTCHARSET | A_INVIS | A_PROTECT) +#define XMC_CONFLICT (A_STANDOUT | A_UNDERLINE | A_REVERSE | A_BLINK | A_DIM | A_BOLD | A_INVIS | A_PROTECT | A_ITALIC) +#define XMC_CHANGES(c) ((c) & SP_PARM->_xmc_suppress) #define toggle_attr_on(S,at) {\ - if (PAIR_NUMBER(at) > 0) {\ - (S) = ((S) & ALL_BUT_COLOR) | (at);\ + if (PairNumber(at) > 0) {\ + (S) = ((S) & ALL_BUT_COLOR) | (attr_t) (at);\ } else {\ - (S) |= (at);\ + (S) |= (attr_t) (at);\ }\ TR(TRACE_ATTRS, ("new attribute is %s", _traceattr((S))));} #define toggle_attr_off(S,at) {\ - if (PAIR_NUMBER(at) > 0) {\ + if (PairNumber(at) > 0) {\ (S) &= ~(at|A_COLOR);\ } else {\ (S) &= ~(at);\ }\ TR(TRACE_ATTRS, ("new attribute is %s", _traceattr((S))));} -#define DelCharCost(count) \ +#define DelCharCost(sp,count) \ ((parm_dch != 0) \ - ? SP->_dch_cost \ + ? sp->_dch_cost \ : ((delete_character != 0) \ - ? (SP->_dch1_cost * count) \ + ? (sp->_dch1_cost * count) \ : INFINITY)) -#define InsCharCost(count) \ +#define InsCharCost(sp,count) \ ((parm_ich != 0) \ - ? SP->_ich_cost \ + ? sp->_ich_cost \ : ((enter_insert_mode && exit_insert_mode) \ - ? SP->_smir_cost + SP->_rmir_cost + (SP->_ip_cost * count) \ + ? sp->_smir_cost + sp->_rmir_cost + (sp->_ip_cost * count) \ : ((insert_character != 0) \ - ? ((SP->_ich1_cost + SP->_ip_cost) * count) \ + ? ((sp->_ich1_cost + sp->_ip_cost) * count) \ : INFINITY))) #if USE_XMC_SUPPORT -#define UpdateAttrs(c) if (!SameAttrOf(SCREEN_ATTRS(SP), c)) { \ - attr_t chg = AttrOf(SCREEN_ATTRS(SP)); \ - VIDATTR(AttrOf(c), GetPair(c)); \ +#define UpdateAttrs(sp,c) if (!SameAttrOf(SCREEN_ATTRS(sp), c)) { \ + attr_t chg = AttrOf(SCREEN_ATTRS(sp)); \ + VIDPUTS(sp, AttrOf(c), GetPair(c)); \ if (magic_cookie_glitch > 0 \ - && XMC_CHANGES((chg ^ AttrOf(SCREEN_ATTRS(SP))))) { \ + && XMC_CHANGES((chg ^ AttrOf(SCREEN_ATTRS(sp))))) { \ T(("%s @%d before glitch %d,%d", \ __FILE__, __LINE__, \ - SP->_cursrow, \ - SP->_curscol)); \ - _nc_do_xmc_glitch(chg); \ + sp->_cursrow, \ + sp->_curscol)); \ + NCURSES_SP_NAME(_nc_do_xmc_glitch)(NCURSES_SP_ARGx chg); \ } \ } #else -#define UpdateAttrs(c) if (!SameAttrOf(SCREEN_ATTRS(SP), c)) \ - VIDATTR(AttrOf(c), GetPair(c)); +#define UpdateAttrs(sp,c) if (!SameAttrOf(SCREEN_ATTRS(sp), c)) { \ + VIDPUTS(sp, AttrOf(c), GetPair(c)); \ + } #endif /* @@ -1429,10 +1865,12 @@ extern NCURSES_EXPORT(void) name (void); \ #define EVENTLIST_0th(param) param #define EVENTLIST_1st(param) param #define EVENTLIST_2nd(param) , param +#define TWAIT_MASK (TW_ANY | TW_EVENT) #else #define EVENTLIST_0th(param) void #define EVENTLIST_1st(param) /* nothing */ #define EVENTLIST_2nd(param) /* nothing */ +#define TWAIT_MASK TW_ANY #endif #if NCURSES_EXPANDED && NCURSES_EXT_FUNCS @@ -1446,16 +1884,28 @@ extern NCURSES_EXPORT(void) _nc_toggle_attr_on (attr_t *, attr_t); extern NCURSES_EXPORT(void) _nc_toggle_attr_off (attr_t *, attr_t); #undef DelCharCost -#define DelCharCost(count) _nc_DelCharCost(count) -extern NCURSES_EXPORT(int) _nc_DelCharCost (int); +#define DelCharCost(sp, count) NCURSES_SP_NAME(_nc_DelCharCost)(NCURSES_SP_ARGx count) #undef InsCharCost -#define InsCharCost(count) _nc_InsCharCost(count) -extern NCURSES_EXPORT(int) _nc_InsCharCost (int); +#define InsCharCost(sp, count) NCURSES_SP_NAME(_nc_InsCharCost)(NCURSES_SP_ARGx count) + +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(_nc_DelCharCost) (NCURSES_SP_DCLx int _c); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(_nc_InsCharCost) (NCURSES_SP_DCLx int _c); #undef UpdateAttrs -#define UpdateAttrs(c) _nc_UpdateAttrs(c) -extern NCURSES_EXPORT(void) _nc_UpdateAttrs (NCURSES_CH_T); +#define UpdateAttrs(sp,c) NCURSES_SP_NAME(_nc_UpdateAttrs)(NCURSES_SP_ARGx CHREF(c)) + +#if USE_WIDEC_SUPPORT || defined(NEED_NCURSES_CH_T) +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_UpdateAttrs) (NCURSES_SP_DCLx CARG_CH_T _c); +#else +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_UpdateAttrs) (NCURSES_SP_DCLx chtype c); +#endif + +#if NCURSES_SP_FUNCS +extern NCURSES_EXPORT(int) _nc_DelCharCost (int); +extern NCURSES_EXPORT(int) _nc_InsCharCost (int); +extern NCURSES_EXPORT(void) _nc_UpdateAttrs (CARG_CH_T); +#endif /* NCURSES_SP_FUNCS */ #else @@ -1471,6 +1921,20 @@ extern NCURSES_EXPORT(void) _nc_expanded (void); #define getcwd(buf,len) getwd(buf) #endif +#define save_ttytype(termp) \ + if (TerminalType(termp).term_names != 0) { \ + _nc_STRNCPY(ttytype, \ + TerminalType(termp).term_names, \ + NAMESIZE - 1); \ + ttytype[NAMESIZE - 1] = '\0'; \ + } + +#if !NCURSES_WCWIDTH_GRAPHICS +extern NCURSES_EXPORT(int) _nc_wacs_width(unsigned); +#else +#define _nc_wacs_width(ch) wcwidth(ch) +#endif + /* charable.c */ #if USE_WIDEC_SUPPORT extern NCURSES_EXPORT(bool) _nc_is_charable(wchar_t); @@ -1493,6 +1957,16 @@ typedef struct short source; } alias_table_data; +/* comp_userdefs.c */ +typedef struct { + short ute_name; /* offset of name to hash on */ + unsigned ute_type; /* mask (BOOLEAN, NUMBER, STRING) */ + unsigned ute_argc; /* number of parameters */ + unsigned ute_args; /* bit-mask for string parameters */ + short ute_index; /* index of associated variable in its array */ + short ute_link; /* index in table of next hash, or -1 */ +} user_table_data; + /* doupdate.c */ #if USE_XMC_SUPPORT extern NCURSES_EXPORT(void) _nc_do_xmc_glitch (attr_t); @@ -1504,31 +1978,42 @@ extern NCURSES_EXPORT(void) _nc_linedump (void); #endif /* lib_acs.c */ -extern NCURSES_EXPORT(void) _nc_init_acs (void); /* corresponds to traditional 'init_acs()' */ -extern NCURSES_EXPORT(int) _nc_msec_cost (const char *const, int); /* used by 'tack' program */ +extern NCURSES_EXPORT(void) _nc_init_acs (void); /* corresponds to traditional 'init_acs()' */ +extern NCURSES_EXPORT(int) _nc_msec_cost (const char *const, int); /* lib_addch.c */ #if USE_WIDEC_SUPPORT -NCURSES_EXPORT(int) _nc_build_wch(WINDOW *win, ARG_CH_T ch); +extern NCURSES_EXPORT(int) _nc_build_wch(WINDOW *win, ARG_CH_T ch); #endif /* lib_addstr.c */ -#if USE_WIDEC_SUPPORT && !defined(USE_TERMLIB) +#if USE_WIDEC_SUPPORT && !(defined(USE_TERMLIB) || defined(USE_BUILD_CC)) extern NCURSES_EXPORT(int) _nc_wchstrlen(const cchar_t *); #endif /* lib_color.c */ +extern NCURSES_EXPORT(int) _nc_init_color(SCREEN *, int, int, int, int); +extern NCURSES_EXPORT(int) _nc_init_pair(SCREEN *, int, int, int); +extern NCURSES_EXPORT(int) _nc_pair_content(SCREEN *, int, int *, int *); extern NCURSES_EXPORT(bool) _nc_reset_colors(void); +extern NCURSES_EXPORT(void) _nc_reserve_pairs(SCREEN *, int); +extern NCURSES_EXPORT(void) _nc_change_pair(SCREEN *, int); + +#define ReservePairs(sp,want) \ + if ((sp->_color_pairs == 0) || (want >= sp->_pair_alloc)) \ + _nc_reserve_pairs(sp, want) /* lib_getch.c */ -extern NCURSES_EXPORT(int) _nc_wgetch(WINDOW *, unsigned long *, int EVENTLIST_2nd(_nc_eventlist *)); +extern NCURSES_EXPORT(int) _nc_wgetch(WINDOW *, int *, int EVENTLIST_2nd(_nc_eventlist *)); /* lib_insch.c */ -extern NCURSES_EXPORT(int) _nc_insert_ch(WINDOW *, chtype); +extern NCURSES_EXPORT(int) _nc_insert_ch(SCREEN *, WINDOW *, chtype); /* lib_mvcur.c */ #define INFINITY 1000000 /* cost: too high to use */ +extern NCURSES_EXPORT(int) _nc_mvcur(int yold, int xold, int ynew, int xnew); + extern NCURSES_EXPORT(void) _nc_mvcur_init (void); extern NCURSES_EXPORT(void) _nc_mvcur_resume (void); extern NCURSES_EXPORT(void) _nc_mvcur_wrap (void); @@ -1540,7 +2025,7 @@ extern NCURSES_EXPORT(void) _nc_screen_resume (void); extern NCURSES_EXPORT(void) _nc_screen_wrap (void); /* lib_mouse.c */ -extern NCURSES_EXPORT(int) _nc_has_mouse (void); +extern NCURSES_EXPORT(bool) _nc_has_mouse (SCREEN *); /* lib_mvcur.c */ #define INFINITY 1000000 /* cost: too high to use */ @@ -1548,10 +2033,46 @@ extern NCURSES_EXPORT(int) _nc_has_mouse (void); /* lib_setup.c */ extern NCURSES_EXPORT(char *) _nc_get_locale(void); -extern NCURSES_EXPORT(int) _nc_unicode_locale(void); -extern NCURSES_EXPORT(int) _nc_locale_breaks_acs(TERMINAL *); -extern NCURSES_EXPORT(int) _nc_setupterm(NCURSES_CONST char *, int, int *, bool); -extern NCURSES_EXPORT(void) _nc_get_screensize(SCREEN *, int *, int *); +extern NCURSES_EXPORT(int) _nc_unicode_locale(void); +extern NCURSES_EXPORT(int) _nc_locale_breaks_acs(TERMINAL *); +extern NCURSES_EXPORT(int) _nc_setupterm(const char *, int, int *, int); +extern NCURSES_EXPORT(void) _nc_tinfo_cmdch(TERMINAL *, int); + +#ifdef USE_PTHREADS +extern NCURSES_EXPORT(SCREEN *) _nc_find_prescr(void); +extern NCURSES_EXPORT(void) _nc_forget_prescr(void); +#else +#define _nc_find_prescr() _nc_prescreen.allocated +#define _nc_forget_prescr() _nc_prescreen.allocated = 0 +#endif + +/* lib_set_term.c */ +extern NCURSES_EXPORT(int) _nc_ripoffline(int, int(*)(WINDOW*, int)); + +/* lib_setup.c */ +#define ExitTerminfo(code) exit_terminfo(code) + +#define SETUP_FAIL ERR + +#define ret_error(rc, fmt, p, q) if (errret) {\ + *errret = rc;\ + q;\ + returnCode(SETUP_FAIL);\ + } else {\ + fprintf(stderr, fmt, p);\ + q;\ + ExitTerminfo(EXIT_FAILURE);\ + } + +#define ret_error1(rc, fmt, p, q) ret_error(rc, "'%s': " fmt, p, q) + +#define ret_error0(rc, msg) if (errret) {\ + *errret = rc;\ + returnCode(SETUP_FAIL);\ + } else {\ + fprintf(stderr, msg);\ + ExitTerminfo(EXIT_FAILURE);\ + } /* lib_tstp.c */ #if USE_SIGWINCH @@ -1560,9 +2081,6 @@ extern NCURSES_EXPORT(int) _nc_handle_sigwinch(SCREEN *); #define _nc_handle_sigwinch(a) /* nothing */ #endif -/* lib_ungetch.c */ -extern NCURSES_EXPORT(int) _nc_ungetch (SCREEN *, int); - /* lib_wacs.c */ #if USE_WIDEC_SUPPORT extern NCURSES_EXPORT(void) _nc_init_wacs(void); @@ -1578,7 +2096,7 @@ typedef struct { /* strings.c */ extern NCURSES_EXPORT(string_desc *) _nc_str_init (string_desc *, char *, size_t); extern NCURSES_EXPORT(string_desc *) _nc_str_null (string_desc *, size_t); -extern NCURSES_EXPORT(string_desc *) _nc_str_copy (string_desc *, string_desc *); +extern NCURSES_EXPORT(string_desc *) _nc_str_copy (string_desc *, const string_desc *); extern NCURSES_EXPORT(bool) _nc_safe_strcat (string_desc *, const char *); extern NCURSES_EXPORT(bool) _nc_safe_strcpy (string_desc *, const char *); @@ -1597,59 +2115,92 @@ extern NCURSES_EXPORT(int) _nc_remove_key (TRIES **, unsigned); extern NCURSES_EXPORT(int) _nc_remove_string (TRIES **, const char *); /* elsewhere ... */ -extern NCURSES_EXPORT(ENTRY *) _nc_delink_entry (ENTRY *, TERMTYPE *); -extern NCURSES_EXPORT(NCURSES_CONST char *) _nc_keyname (SCREEN *, int); -extern NCURSES_EXPORT(NCURSES_CONST char *) _nc_unctrl (SCREEN *, chtype); extern NCURSES_EXPORT(SCREEN *) _nc_screen_of (WINDOW *); +extern NCURSES_EXPORT(TERMINAL*) _nc_get_cur_term (void); extern NCURSES_EXPORT(WINDOW *) _nc_makenew (int, int, int, int, int); extern NCURSES_EXPORT(char *) _nc_trace_buf (int, size_t); extern NCURSES_EXPORT(char *) _nc_trace_bufcat (int, const char *); extern NCURSES_EXPORT(char *) _nc_tracechar (SCREEN *, int); extern NCURSES_EXPORT(char *) _nc_tracemouse (SCREEN *, MEVENT const *); +extern NCURSES_EXPORT(char *) _nc_trace_mmask_t (SCREEN *, mmask_t); extern NCURSES_EXPORT(int) _nc_access (const char *, int); extern NCURSES_EXPORT(int) _nc_baudrate (int); extern NCURSES_EXPORT(int) _nc_freewin (WINDOW *); extern NCURSES_EXPORT(int) _nc_getenv_num (const char *); -extern NCURSES_EXPORT(int) _nc_keypad (SCREEN *, bool); +extern NCURSES_EXPORT(int) _nc_keypad (SCREEN *, int); extern NCURSES_EXPORT(int) _nc_ospeed (int); extern NCURSES_EXPORT(int) _nc_outch (int); -extern NCURSES_EXPORT(int) _nc_read_termcap_entry (const char *const, TERMTYPE *const); -extern NCURSES_EXPORT(int) _nc_setupscreen (int, int, FILE *, bool, int); +extern NCURSES_EXPORT(int) _nc_putchar (int); +extern NCURSES_EXPORT(int) _nc_putp(const char *, const char *); +extern NCURSES_EXPORT(int) _nc_putp_flush(const char *, const char *); +extern NCURSES_EXPORT(int) _nc_read_termcap_entry (const char *const, TERMTYPE2 *const); +extern NCURSES_EXPORT(int) _nc_setup_tinfo(const char *, TERMTYPE2 *); +extern NCURSES_EXPORT(int) _nc_setupscreen (int, int, FILE *, int, int); extern NCURSES_EXPORT(int) _nc_timed_wait (SCREEN *, int, int, int * EVENTLIST_2nd(_nc_eventlist *)); -extern NCURSES_EXPORT(void) _nc_do_color (short, short, bool, int (*)(int)); +extern NCURSES_EXPORT(int) _nc_trans_string (char *, const char *); +extern NCURSES_EXPORT(void) _nc_init_termtype (TERMTYPE2 *const); +extern NCURSES_EXPORT(void) _nc_do_color (int, int, int, NCURSES_OUTC); extern NCURSES_EXPORT(void) _nc_flush (void); -extern NCURSES_EXPORT(void) _nc_free_and_exit (int); -extern NCURSES_EXPORT(void) _nc_free_entry (ENTRY *, TERMTYPE *); +extern NCURSES_EXPORT(void) _nc_free_entry (ENTRY *, TERMTYPE2 *); extern NCURSES_EXPORT(void) _nc_freeall (void); extern NCURSES_EXPORT(void) _nc_hash_map (void); extern NCURSES_EXPORT(void) _nc_init_keytry (SCREEN *); extern NCURSES_EXPORT(void) _nc_keep_tic_dir (const char *); extern NCURSES_EXPORT(void) _nc_make_oldhash (int i); +extern NCURSES_EXPORT(void) _nc_reset_input (FILE *, char *); extern NCURSES_EXPORT(void) _nc_scroll_oldhash (int n, int top, int bot); extern NCURSES_EXPORT(void) _nc_scroll_optimize (void); -extern NCURSES_EXPORT(void) _nc_set_buffer (FILE *, bool); -extern NCURSES_EXPORT(void) _nc_signal_handler (bool); +extern NCURSES_EXPORT(void) _nc_set_buffer (FILE *, int); +extern NCURSES_EXPORT(void) _nc_setenv_num (const char *, int); +extern NCURSES_EXPORT(void) _nc_signal_handler (int); extern NCURSES_EXPORT(void) _nc_synchook (WINDOW *); extern NCURSES_EXPORT(void) _nc_trace_tries (TRIES *); +#if NCURSES_EXT_NUMBERS +extern NCURSES_EXPORT(const TERMTYPE2 *) _nc_fallback2 (const char *); +#else +#define _nc_fallback2(tp) _nc_fallback(tp) +#endif + +extern NCURSES_EXPORT(void) _nc_copy_termtype(TERMTYPE *, const TERMTYPE *); + +#if NCURSES_EXT_NUMBERS +extern NCURSES_EXPORT(void) _nc_copy_termtype2 (TERMTYPE2 *, const TERMTYPE2 *); +extern NCURSES_EXPORT(void) _nc_export_termtype2(TERMTYPE *, const TERMTYPE2 *); +#else +#define _nc_copy_termtype2(dst,src) _nc_copy_termtype((dst),(src)) +#define _nc_export_termtype2(dst,src) /* nothing */ +#define _nc_free_termtype2(t) _nc_free_termtype(t) +/* also... */ +#define _nc_read_entry2 _nc_read_entry +#endif + #if NO_LEAKS extern NCURSES_EXPORT(void) _nc_alloc_entry_leaks(void); extern NCURSES_EXPORT(void) _nc_captoinfo_leaks(void); extern NCURSES_EXPORT(void) _nc_codes_leaks(void); extern NCURSES_EXPORT(void) _nc_comp_captab_leaks(void); +extern NCURSES_EXPORT(void) _nc_comp_error_leaks(void); extern NCURSES_EXPORT(void) _nc_comp_scan_leaks(void); +extern NCURSES_EXPORT(void) _nc_comp_userdefs_leaks(void); +extern NCURSES_EXPORT(void) _nc_db_iterator_leaks(void); extern NCURSES_EXPORT(void) _nc_keyname_leaks(void); extern NCURSES_EXPORT(void) _nc_names_leaks(void); +extern NCURSES_EXPORT(void) _nc_tgetent_leak(const TERMINAL *); extern NCURSES_EXPORT(void) _nc_tgetent_leaks(void); #endif -#ifndef USE_TERMLIB +#if !(defined(USE_TERMLIB) || defined(USE_BUILD_CC)) extern NCURSES_EXPORT(NCURSES_CH_T) _nc_render (WINDOW *, NCURSES_CH_T); extern NCURSES_EXPORT(int) _nc_waddch_nosync (WINDOW *, const NCURSES_CH_T); -extern NCURSES_EXPORT(void) _nc_scroll_window (WINDOW *, int const, NCURSES_SIZE_T const, NCURSES_SIZE_T const, NCURSES_CH_T); +extern NCURSES_EXPORT(void) _nc_scroll_window (WINDOW *, int const, int const, int const, NCURSES_CH_T); +#endif + +#if USE_WIDEC_SUPPORT +extern NCURSES_EXPORT(int) _nc_insert_wch(WINDOW *, const cchar_t *); #endif -#if USE_WIDEC_SUPPORT && !defined(USE_TERMLIB) +#if USE_WIDEC_SUPPORT && !(defined(USE_TERMLIB) || defined(USE_BUILD_CC)) extern NCURSES_EXPORT(size_t) _nc_wcrtomb (char *, wchar_t, mbstate_t *); #endif @@ -1670,6 +2221,50 @@ extern NCURSES_EXPORT(int) _nc_eventlist_timeout(_nc_eventlist *); #define wgetnstr_events(win, str, maxlen, evl) wgetnstr(win, str, maxlen) #endif +/* + * Wide-character macros to hide some platform-differences. + */ +#if USE_WIDEC_SUPPORT + +#if defined(_NC_WINDOWS) && !defined(_NC_MSC) && !defined(EXP_WIN32_DRIVER) +/* + * MinGW has wide-character functions, but they do not work correctly. + */ +extern int __MINGW_NOTHROW _nc_wctomb(char *, wchar_t); +#define wctomb(s,wc) _nc_wctomb(s,wc) +#define wcrtomb(s,wc,n) _nc_wctomb(s,wc) + +extern int __MINGW_NOTHROW _nc_mbtowc(wchar_t *, const char *, size_t); +#define mbtowc(pwc,s,n) _nc_mbtowc(pwc,s,n) + +extern int __MINGW_NOTHROW _nc_mblen(const char *, size_t); +#define mblen(s,n) _nc_mblen(s, n) + +#endif /* _NC_WINDOWS && !_NC_MSC */ + +#if defined(_NC_WINDOWS) || defined(_NC_MINGW) +/* see wcwidth.c */ +extern NCURSES_EXPORT(int) mk_wcwidth(wchar_t); +#define wcwidth(ucs) _nc_wcwidth(ucs) +#endif + +#if HAVE_MBTOWC && HAVE_MBLEN +#define reset_mbytes(state) IGNORE_RC(mblen(NULL, (size_t) 0)), IGNORE_RC(mbtowc(NULL, NULL, (size_t) 0)) +#define count_mbytes(buffer,length,state) mblen(buffer,length) +#define check_mbytes(wch,buffer,length,state) \ + (int) mbtowc(&(wch), buffer, length) +#define state_unused +#elif HAVE_MBRTOWC && HAVE_MBRLEN +#define reset_mbytes(state) init_mb(state) +#define count_mbytes(buffer,length,state) mbrlen(buffer,length,&(state)) +#define check_mbytes(wch,buffer,length,state) \ + (int) mbrtowc(&(wch), buffer, length, &(state)) +#else +make an error +#endif + +#endif /* USE_WIDEC_SUPPORT */ + /* * Not everyone has vsscanf(), but we'd like to use it for scanw(). */ @@ -1682,35 +2277,44 @@ extern NCURSES_EXPORT_VAR(int *) _nc_oldnums; #define USE_SETBUF_0 0 -#define NC_BUFFERED(flag) _nc_set_buffer(SP->_ofp, flag) - -#define NC_OUTPUT ((SP != 0) ? SP->_ofp : stdout) +#define NC_OUTPUT(sp) ((sp != 0 && sp->_ofp != 0) ? sp->_ofp : stdout) /* * On systems with a broken linker, define 'SP' as a function to force the * linker to pull in the data-only module with 'SP'. */ +#define _nc_alloc_screen_sp() typeCalloc(SCREEN, 1) + #if BROKEN_LINKER #define SP _nc_screen() extern NCURSES_EXPORT(SCREEN *) _nc_screen (void); -extern NCURSES_EXPORT(int) _nc_alloc_screen (void); -extern NCURSES_EXPORT(void) _nc_set_screen (SCREEN *); +extern NCURSES_EXPORT(int) _nc_alloc_screen (void); +extern NCURSES_EXPORT(void) _nc_set_screen (SCREEN *); +#define CURRENT_SCREEN _nc_screen() #else /* current screen is private data; avoid possible linking conflicts too */ extern NCURSES_EXPORT_VAR(SCREEN *) SP; -#define _nc_alloc_screen() ((SP = typeCalloc(SCREEN, 1)) != 0) -#define _nc_set_screen(sp) SP = sp +#define CURRENT_SCREEN SP +#define _nc_alloc_screen() ((SP = _nc_alloc_screen_sp()) != 0) +#define _nc_set_screen(sp) SP = sp +#endif + +#if NCURSES_SP_FUNCS +#define CURRENT_SCREEN_PRE (IsPreScreen(CURRENT_SCREEN) ? CURRENT_SCREEN : new_prescr()) +#else +#define CURRENT_SCREEN_PRE CURRENT_SCREEN #endif /* * We don't want to use the lines or columns capabilities internally, because - * if the application is running multiple screens under X, it's quite possible + * if the application is running multiple screens under X, it is quite possible * they could all have type xterm but have different sizes! So... */ -#define screen_lines SP->_lines -#define screen_columns SP->_columns +#define screen_lines(sp) (sp)->_lines +#define screen_columns(sp) (sp)->_columns extern NCURSES_EXPORT(int) _nc_slk_initialize (WINDOW *, int); +extern NCURSES_EXPORT(int) _nc_format_slks (NCURSES_SP_DCLx int _c); /* * Some constants related to SLK's @@ -1728,16 +2332,318 @@ extern NCURSES_EXPORT(int) _nc_slk_initialize (WINDOW *, int); #define MAX_SKEY(fmt) (SLK_STDFMT(fmt)? MAX_SKEY_OLD : MAX_SKEY_PC) #define MAX_SKEY_LEN(fmt) (SLK_STDFMT(fmt)? MAX_SKEY_LEN_OLD : MAX_SKEY_LEN_PC) -extern NCURSES_EXPORT(int) _nc_ripoffline (int line, int (*init)(WINDOW *,int)); - /* * Common error messages */ #define MSG_NO_MEMORY "Out of memory" #define MSG_NO_INPUTS "Premature EOF" +extern NCURSES_EXPORT(int) _nc_set_tty_mode(TTY *); +extern NCURSES_EXPORT(int) _nc_get_tty_mode(TTY *); + +/* timed_wait flag definitions */ +#define TW_NONE 0 +#define TW_INPUT 1 +#define TW_MOUSE 2 +#define TW_ANY (TW_INPUT | TW_MOUSE) +#define TW_EVENT 4 + +#define SetSafeOutcWrapper(outc) \ + SCREEN* sp = CURRENT_SCREEN; \ + struct screen outc_wrapper; \ + if (sp==0) { \ + sp = &outc_wrapper; \ + memset(sp,0,sizeof(struct screen)); \ + sp->_outch = _nc_outc_wrapper; \ + }\ + sp->jump = outc + +#ifdef USE_TERM_DRIVER + +typedef struct _termInfo +{ + bool caninit; + + bool hascolor; + bool initcolor; + bool canchange; + + int tabsize; + + int maxcolors; + int maxpairs; + int nocolorvideo; + + int numbuttons; + int numlabels; + int labelwidth; + int labelheight; + + const color_t* defaultPalette; +} TerminalInfo; + +typedef struct term_driver { + bool isTerminfo; + const char* (*td_name)(struct DriverTCB*); + bool (*td_CanHandle)(struct DriverTCB*, const char*, int*); + void (*td_init)(struct DriverTCB*); + void (*td_release)(struct DriverTCB*); + int (*td_size)(struct DriverTCB*, int* Line, int *Cols); + int (*td_sgmode)(struct DriverTCB*, int setFlag, TTY*); + chtype (*td_conattr)(struct DriverTCB*); + int (*td_hwcur)(struct DriverTCB*, int yold, int xold, int y, int x); + int (*td_mode)(struct DriverTCB*, int progFlag, int defFlag); + bool (*td_rescol)(struct DriverTCB*); + bool (*td_rescolors)(struct DriverTCB*); + void (*td_color)(struct DriverTCB*, int fore, int color, int(*)(SCREEN*, int)); + int (*td_doBeepOrFlash)(struct DriverTCB*, int); + void (*td_initpair)(struct DriverTCB*, int, int, int); + void (*td_initcolor)(struct DriverTCB*, int, int, int, int); + void (*td_docolor)(struct DriverTCB*, int, int, int, int(*)(SCREEN*, int)); + void (*td_initmouse)(struct DriverTCB*); + int (*td_testmouse)(struct DriverTCB*, int EVENTLIST_2nd(_nc_eventlist*)); + void (*td_setfilter)(struct DriverTCB*); + void (*td_hwlabel)(struct DriverTCB*, int, char*); + void (*td_hwlabelOnOff)(struct DriverTCB*, int); + int (*td_update)(struct DriverTCB*); + int (*td_defaultcolors)(struct DriverTCB*, int, int); + int (*td_print)(struct DriverTCB*, char*, int); + int (*td_getsize)(struct DriverTCB*, int*, int*); + int (*td_setsize)(struct DriverTCB*, int, int); + void (*td_initacs)(struct DriverTCB*, chtype*, chtype*); + void (*td_scinit)(SCREEN *); + void (*td_scexit)(SCREEN *); + int (*td_twait)(struct DriverTCB*, int, int, int* EVENTLIST_2nd(_nc_eventlist*)); + int (*td_read)(struct DriverTCB*, int*); + int (*td_nap)(struct DriverTCB*, int); + int (*td_kpad)(struct DriverTCB*, int); + int (*td_kyOk)(struct DriverTCB*, int, int); + bool (*td_kyExist)(struct DriverTCB*, int); + int (*td_cursorSet)(struct DriverTCB*, int); +} TERM_DRIVER; + +typedef struct DriverTCB +{ + TERMINAL term; /* needs to be the first Element !!! */ + TERM_DRIVER* drv; /* The driver for that Terminal */ + SCREEN* csp; /* The screen that owns that Terminal */ + TerminalInfo info; /* Driver independent core capabilities of the Terminal */ + void* prop; /* Driver dependent property storage to be used by the Driver */ + long magic; +} TERMINAL_CONTROL_BLOCK; + +#define NCDRV_MAGIC(id) (0x47110000 | (id&0xffff)) +#define NCDRV_TINFO 0x01 +#define NCDRV_WINCONSOLE 0x02 + +#define TCBOf(sp) ((TERMINAL_CONTROL_BLOCK*)(TerminalOf(sp))) +#define InfoOf(sp) TCBOf(sp)->info +#define CallDriver(sp,method) TCBOf(sp)->drv->method(TCBOf(sp)) +#define CallDriver_1(sp,method,arg1) TCBOf(sp)->drv->method(TCBOf(sp),arg1) +#define CallDriver_2(sp,method,arg1,arg2) TCBOf(sp)->drv->method(TCBOf(sp),arg1,arg2) +#define CallDriver_3(sp,method,arg1,arg2,arg3) TCBOf(sp)->drv->method(TCBOf(sp),arg1,arg2,arg3) +#define CallDriver_4(sp,method,arg1,arg2,arg3,arg4) TCBOf(sp)->drv->method(TCBOf(sp),arg1,arg2,arg3,arg4) + +extern NCURSES_EXPORT_VAR(const color_t*) _nc_cga_palette; +extern NCURSES_EXPORT_VAR(const color_t*) _nc_hls_palette; + +extern NCURSES_EXPORT(int) _nc_get_driver(TERMINAL_CONTROL_BLOCK*, const char*, int*); +extern NCURSES_EXPORT(void) _nc_get_screensize_ex(SCREEN *, TERMINAL *, int *, int *); +#endif /* USE_TERM_DRIVER */ + +/* + * Entrypoints which are actually provided in the terminal driver, which would + * be an sp-name otherwise. + */ +#ifdef USE_TERM_DRIVER +#define TINFO_HAS_KEY _nc_tinfo_has_key +#define TINFO_DOUPDATE _nc_tinfo_doupdate +#define TINFO_MVCUR _nc_tinfo_mvcur +extern NCURSES_EXPORT(int) TINFO_HAS_KEY(SCREEN*, int); +extern NCURSES_EXPORT(int) TINFO_DOUPDATE(SCREEN *); +extern NCURSES_EXPORT(int) TINFO_MVCUR(SCREEN*, int, int, int, int); +#else +#define TINFO_HAS_KEY NCURSES_SP_NAME(has_key) +#define TINFO_DOUPDATE NCURSES_SP_NAME(doupdate) +#define TINFO_MVCUR NCURSES_SP_NAME(_nc_mvcur) +#endif + +#if defined(EXP_WIN32_DRIVER) +#include +#endif + +/* + * Entrypoints using an extra parameter with the terminal driver. + */ +#ifdef USE_TERM_DRIVER +extern NCURSES_EXPORT(void) _nc_get_screensize(SCREEN *, TERMINAL *, int *, int *); +extern NCURSES_EXPORT(int) _nc_setupterm_ex(TERMINAL **, const char *, int , int *, int); +#define TINFO_GET_SIZE(sp, tp, lp, cp) \ + _nc_get_screensize(sp, tp, lp, cp) +#define TINFO_SET_CURTERM(sp, tp) \ + NCURSES_SP_NAME(set_curterm)(sp, tp) +#define TINFO_SETUP_TERM(tpp, name, fd, err, reuse) \ + _nc_setupterm_ex(tpp, name, fd, err, reuse) +#else /* !USE_TERM_DRIVER */ +extern NCURSES_EXPORT(void) _nc_get_screensize(SCREEN *, int *, int *); +#define TINFO_GET_SIZE(sp, tp, lp, cp) \ + _nc_get_screensize(sp, lp, cp) +#define TINFO_SET_CURTERM(sp, tp) \ + set_curterm(tp) +#define TINFO_SETUP_TERM(tpp, name, fd, err, reuse) \ + _nc_setupterm(name, fd, err, reuse) +#endif /* !USE_TERM_DRIVER */ + +#ifdef EXP_WIN32_DRIVER +extern NCURSES_EXPORT_VAR(TERM_DRIVER) _nc_TINFO_DRIVER; +#else +#ifdef USE_TERM_DRIVER +#if defined(USE_WIN32CON_DRIVER) +#include +extern NCURSES_EXPORT_VAR(TERM_DRIVER) _nc_WIN_DRIVER; +extern NCURSES_EXPORT(int) _nc_mingw_isatty(int fd); +extern NCURSES_EXPORT(int) _nc_mingw_isconsole(int fd); +extern NCURSES_EXPORT(int) _nc_mingw_console_read( + SCREEN *sp, + HANDLE fd, + int *buf); +extern NCURSES_EXPORT(int) _nc_mingw_testmouse( + SCREEN * sp, + HANDLE fd, + int delay EVENTLIST_2nd(_nc_eventlist*)); +#else +#endif +extern NCURSES_EXPORT_VAR(TERM_DRIVER) _nc_TINFO_DRIVER; +#endif /* USE_TERM_DRIVER */ +#endif /* EXP_WIN32_DRIVER */ + +#if defined(USE_TERM_DRIVER) && defined(EXP_WIN32_DRIVER) +#define NC_ISATTY(fd) (0 != _nc_console_isatty(fd)) +#elif defined(USE_TERM_DRIVER) && defined(USE_WIN32CON_DRIVER) +#define NC_ISATTY(fd) _nc_mingw_isatty(fd) +#else +#define NC_ISATTY(fd) isatty(fd) +#endif + +#ifdef USE_TERM_DRIVER +# define IsTermInfo(sp) ((TCBOf(sp) != 0) && ((TCBOf(sp)->drv->isTerminfo))) +# define HasTInfoTerminal(sp) ((0 != TerminalOf(sp)) && IsTermInfo(sp)) +# if defined(EXP_WIN32_DRIVER) +# define IsTermInfoOnConsole(sp) (IsTermInfo(sp) && _nc_console_test(TerminalOf(sp)->Filedes)) +# elif defined(USE_WIN32CON_DRIVER) +# define IsTermInfoOnConsole(sp) (IsTermInfo(sp) && _nc_mingw_isconsole(TerminalOf(sp)->Filedes)) +# else +# define IsTermInfoOnConsole(sp) FALSE +# endif +#else +# define IsTermInfo(sp) TRUE +# define HasTInfoTerminal(sp) (0 != TerminalOf(sp)) +# if defined(EXP_WIN32_DRIVER) +# define IsTermInfoOnConsole(sp) _nc_console_test(TerminalOf(sp)->Filedes) +# else +# define IsTermInfoOnConsole(sp) FALSE +# endif +#endif + +#define IsValidTIScreen(sp) (HasTInfoTerminal(sp)) + +/* + * Exported entrypoints beyond the published API + */ +#if NCURSES_SP_FUNCS +extern NCURSES_EXPORT(WINDOW *) _nc_curscr_of(SCREEN*); +extern NCURSES_EXPORT(WINDOW *) _nc_newscr_of(SCREEN*); +extern NCURSES_EXPORT(WINDOW *) _nc_stdscr_of(SCREEN*); +extern NCURSES_EXPORT(int) _nc_outc_wrapper(SCREEN*,int); + +#if USE_REENTRANT +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(_nc_TABSIZE)(SCREEN*); +extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(longname)(SCREEN*); +#endif + +#if NCURSES_EXT_FUNCS +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(_nc_set_tabsize)(SCREEN*, int); +#endif + +/* + * We put the safe versions of various calls here as they are not published + * part of the API up to now + */ +extern NCURSES_EXPORT(TERMINAL*) NCURSES_SP_NAME(_nc_get_cur_term) (SCREEN *sp); +extern NCURSES_EXPORT(WINDOW *) NCURSES_SP_NAME(_nc_makenew) (SCREEN*, int, int, int, int, int); +extern NCURSES_EXPORT(bool) NCURSES_SP_NAME(_nc_reset_colors)(SCREEN*); +extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(_nc_printf_string)(SCREEN*, const char *, va_list); +extern NCURSES_EXPORT(chtype) NCURSES_SP_NAME(_nc_acs_char)(SCREEN*,int); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(_nc_get_tty_mode)(SCREEN*,TTY*); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(_nc_mcprint)(SCREEN*,char*, int); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(_nc_msec_cost)(SCREEN*, const char *, int); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(_nc_mvcur)(SCREEN*, int, int, int, int); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(_nc_outch)(SCREEN*, int); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(_nc_putchar)(SCREEN*, int); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(_nc_putp)(SCREEN*, const char *, const char*); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(_nc_putp_flush)(SCREEN*, const char *, const char *); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(_nc_ripoffline)(SCREEN*, int, int (*)(WINDOW *,int)); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(_nc_scrolln)(SCREEN*, int, int, int, int); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(_nc_set_tty_mode)(SCREEN*, TTY*); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(_nc_setupscreen)(SCREEN**, int, int, FILE *, int, int); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(_nc_tgetent)(SCREEN*,char*,const char *); +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_do_color)(SCREEN*, int, int, int, NCURSES_SP_OUTC); +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_do_xmc_glitch)(SCREEN*, attr_t); +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_flush)(SCREEN*); +extern GCC_NORETURN NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_free_and_exit)(SCREEN*, int); +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_freeall)(SCREEN*); +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_hash_map)(SCREEN*); +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_init_acs)(SCREEN*); +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_make_oldhash)(SCREEN*, int i); +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_mvcur_init)(SCREEN*); +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_mvcur_resume)(SCREEN*); +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_mvcur_wrap)(SCREEN*); +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_screen_init)(SCREEN*); +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_screen_resume)(SCREEN*); +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_screen_wrap)(SCREEN*); +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_scroll_oldhash)(SCREEN*, int n, int top, int bot); +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_scroll_optimize)(SCREEN*); +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_set_buffer)(SCREEN*, FILE *, int); + +extern NCURSES_EXPORT(void) _nc_cookie_init(SCREEN *sp); + +#if defined(TRACE) || defined(SCROLLDEBUG) || defined(HASHDEBUG) +extern NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_linedump)(SCREEN*); +#endif + +#if USE_WIDEC_SUPPORT +extern NCURSES_EXPORT(wchar_t *) NCURSES_SP_NAME(_nc_wunctrl)(SCREEN*, cchar_t *); +#endif + +#endif /* NCURSES_SP_FUNCS */ + +#if NCURSES_SP_FUNCS + +#define safe_keyname NCURSES_SP_NAME(keyname) +#define safe_unctrl NCURSES_SP_NAME(unctrl) +#define safe_ungetch NCURSES_SP_NAME(ungetch) + +#else + +#define safe_keyname _nc_keyname +#define safe_unctrl _nc_unctrl +#define safe_ungetch _nc_ungetch + +extern NCURSES_EXPORT(NCURSES_CONST char *) _nc_keyname (SCREEN *, int); +extern NCURSES_EXPORT(int) _nc_ungetch (SCREEN *, int); +extern NCURSES_EXPORT(NCURSES_CONST char *) _nc_unctrl (SCREEN *, chtype); + +#endif + +#ifdef EXP_XTERM_1005 +extern NCURSES_EXPORT(int) _nc_conv_to_utf8(unsigned char *, unsigned, unsigned); +extern NCURSES_EXPORT(int) _nc_conv_to_utf32(unsigned *, const char *, unsigned); +#endif + #ifdef __cplusplus } #endif +/* *INDENT-ON* */ + #endif /* CURSES_PRIV_H */ diff --git a/lib/libcurses/default_colors.3 b/lib/libcurses/default_colors.3 index e0848a8e824..c657ac29168 100644 --- a/lib/libcurses/default_colors.3 +++ b/lib/libcurses/default_colors.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: default_colors.3,v 1.2 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: default_colors.3,v 1.3 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2021,2022 Thomas E. Dickey * +.\" Copyright 2000-2011,2016 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -30,22 +31,23 @@ .\" .\" Author: Thomas E. Dickey 1997,1999,2000,2005 .\" -.\" $Id: default_colors.3,v 1.2 2010/01/12 23:21:59 nicm Exp $ -.TH default_colors 3 "" +.\" $Id: default_colors.3,v 1.3 2023/10/17 09:52:08 nicm Exp $ +.TH default_colors 3 2023-08-19 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .SH NAME -\fBuse_default_colors\fR, -\fBassume_default_colors\fR \- use terminal's default colors +\fBuse_default_colors\fP, +\fBassume_default_colors\fP \- use terminal's default colors .SH SYNOPSIS \fB#include \fP .sp \fBint use_default_colors(void);\fP .br -\fBint assume_default_colors(int fg, int bg);\fP +\fBint assume_default_colors(int \fIfg\fB, int \fIbg\fB);\fR .SH DESCRIPTION -The -.I use_default_colors() -and -.I assume_default_colors() +The \fBuse_default_colors\fP and \fBassume_default_colors\fP functions are extensions to the curses library. They are used with terminals that support ISO 6429 color, or equivalent. These terminals allow the application to reset color to an unspecified @@ -57,23 +59,24 @@ Some applications are designed to work with the default background, using colors only for text. For example, there are several implementations of the \fBls\fP program which use colors to denote different file types or permissions. -These "color ls" programs do not necessarily modify the background color, -typically using only the \fIsetaf\fP terminfo capability to set the +These \*(``color ls\*('' programs do not necessarily +modify the background color, +typically using only the \fBsetaf\fP terminfo capability to set the foreground color. Full-screen applications that use default colors can achieve similar visual effects. .PP -The first function, -.I use_default_colors() +The first function, \fBuse_default_colors\fP tells the curses library to assign terminal default -foreground/background colors to color number -1. So init_pair(x,COLOR_RED,-1) -will initialize pair x as red on default background and init_pair(x,-1,COLOR_BLUE) will +foreground/background colors to color number \-1. +So init_pair(x,COLOR_RED,\-1) +will initialize pair x as red on default background +and init_pair(x,\-1,COLOR_BLUE) will initialize pair x as default foreground on blue. .PP -The other, -.I assume_default_colors() +The other, \fBassume_default_colors\fP is a refinement which tells which colors to paint for color pair 0. -This function recognizes a special color number -1, +This function recognizes a special color number \-1, which denotes the default terminal color. .PP The following are equivalent: @@ -81,40 +84,42 @@ The following are equivalent: .br .I use_default_colors(); .br -.I assume_default_colors(-1,-1); +.I assume_default_colors(\-1,\-1); .RE .PP These are ncurses extensions. For other curses implementations, color -number -1 does not mean anything, just as for ncurses before a -successful call of \fIuse_default_colors()\fP or \fIassume_default_colors()\fP. +number \-1 does not mean anything, just as for ncurses before a +successful call of \fBuse_default_colors\fP or \fBassume_default_colors\fP. .PP Other curses implementations do not allow an application to modify color pair 0. They assume that the background is COLOR_BLACK, but do not ensure that the color pair 0 is painted to match the assumption. If your application does not use either -.I use_default_colors() +.B use_default_colors or -.I assume_default_colors() +.B assume_default_colors ncurses will paint a white foreground (text) with black background for color pair 0. .SH RETURN VALUE -These functions return the integer \fBERR\fP upon failure and \fBOK\fP on success. +These functions return the integer \fBERR\fP upon failure +and \fBOK\fP on success. They will fail if either the terminal does not support -the \fIorig_pair\fP or \fIorig_colors\fP capability. -If the \fIinitialize_pair\fP capability is found, this causes an +the \fBorig_pair\fP or \fBorig_colors\fP capability. +If the \fBinitialize_pair\fP capability is not found, this causes an error as well. .SH NOTES -Associated with this extension, the \fBinit_pair\fR function accepts +Associated with this extension, the \fBinit_pair\fP function accepts negative arguments to specify default foreground or background colors. .PP -The \fIuse_default_colors()\fP function was added to support \fIded\fP. +The \fBuse_default_colors\fP function was added to support \fBded\fP. This is a full-screen application which uses curses to manage only part -of the screen. The bottom portion of the screen, which is of adjustable +of the screen. +The bottom portion of the screen, which is of adjustable size, is left uncolored to display the results from shell commands. The top portion of the screen colors filenames using a scheme like the -"color ls" programs. +\*(``color ls\*('' programs. Attempting to manage the background color of the screen for this application would give unsatisfactory results for a variety of reasons. This extension was devised after @@ -122,25 +127,21 @@ noting that color xterm (and similar programs) provides a background color which does not necessarily correspond to any of the ANSI colors. While a special terminfo entry could be constructed using nine colors, there was no mechanism provided within curses to account for the related -\fIorig_pair\fP and \fIback_color_erase\fP capabilities. +\fBorig_pair\fP and \fBback_color_erase\fP capabilities. .PP -The \fIassume_default_colors()\fP function was added to solve +The \fBassume_default_colors\fP function was added to solve a different problem: support for applications which would use environment variables and other configuration to bypass curses' notion of the terminal's default colors, setting specific values. .SH PORTABILITY -These routines are specific to ncurses. They were not supported on -Version 7, BSD or System V implementations. It is recommended that +These routines are specific to ncurses. +They were not supported on +Version 7, BSD or System V implementations. +It is recommended that any code depending on them be conditioned using NCURSES_VERSION. .SH SEE ALSO -\fBcurs_color\fR(3), -\fBded\fP(1). +\fBded\fP(1), +\fBcurs_color\fP(3). .SH AUTHOR Thomas Dickey (from an analysis of the requirements for color xterm for XFree86 3.1.2C, February 1996). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: diff --git a/lib/libcurses/define_key.3 b/lib/libcurses/define_key.3 index 9104ca26fd7..00f5ae04806 100644 --- a/lib/libcurses/define_key.3 +++ b/lib/libcurses/define_key.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: define_key.3,v 1.5 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: define_key.3,v 1.6 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2004,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2021,2022 Thomas E. Dickey * +.\" Copyright 1998-2010,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -30,14 +31,14 @@ .\" .\" Author: Thomas E. Dickey 1997 .\" -.\" $Id: define_key.3,v 1.5 2010/01/12 23:21:59 nicm Exp $ -.TH define_key 3 "" +.\" $Id: define_key.3,v 1.6 2023/10/17 09:52:08 nicm Exp $ +.TH define_key 3 2022-02-12 "ncurses 6.4" "Library calls" .SH NAME \fBdefine_key\fP \- define a keycode .SH SYNOPSIS \fB#include \fP .sp -\fBint define_key(const char *definition, int keycode);\fP +\fBint define_key(const char *\fIdefinition\fB, int \fIkeycode\fB);\fR .SH DESCRIPTION This is an extension to the curses library. It permits an application to define keycodes with their corresponding control @@ -49,19 +50,19 @@ removed. Similarly, if the given keycode is negative or zero, any existing string for the given definition is removed. .SH RETURN VALUE -The keycode must be greater than zero, else ERR is returned. +The keycode must be greater than zero, and the string non-null, +otherwise \fBERR\fP is returned. +\fBERR\fP may also be returned if there is insufficient memory to allocate the +data to store the definition. +If no error is detected, \fBOK\fP is returned. .SH PORTABILITY -These routines are specific to ncurses. They were not supported on -Version 7, BSD or System V implementations. It is recommended that +These routines are specific to ncurses. +They were not supported on +Version 7, BSD or System V implementations. +It is recommended that any code depending on them be conditioned using NCURSES_VERSION. .SH SEE ALSO -\fBkeyok\fR(3), -\fBkey_defined\fR(3). +\fBkeyok\fP(3), +\fBkey_defined\fP(3). .SH AUTHOR Thomas Dickey. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: diff --git a/lib/libcurses/fifo_defs.h b/lib/libcurses/fifo_defs.h index babc3c05ad7..1dc3a959bb1 100644 --- a/lib/libcurses/fifo_defs.h +++ b/lib/libcurses/fifo_defs.h @@ -1,7 +1,8 @@ -/* $OpenBSD: fifo_defs.h,v 1.3 2010/01/12 23:21:59 nicm Exp $ */ +/* $OpenBSD: fifo_defs.h,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2002,2008 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2012,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -36,7 +37,7 @@ /* * Common macros for lib_getch.c, lib_ungetch.c * - * $Id: fifo_defs.h,v 1.3 2010/01/12 23:21:59 nicm Exp $ + * $Id: fifo_defs.h,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ #ifndef FIFO_DEFS_H @@ -47,15 +48,41 @@ /* peek points to next uninterpreted character */ #define peek sp->_fifopeek -#define h_inc() { head == FIFO_SIZE-1 ? head = 0 : head++; if (head == tail) head = -1, tail = 0;} -#define h_dec() { head == 0 ? head = FIFO_SIZE-1 : head--; if (head == tail) tail = -1;} -#define t_inc() { tail == FIFO_SIZE-1 ? tail = 0 : tail++; if (tail == head) tail = -1;} -#define t_dec() { tail == 0 ? tail = FIFO_SIZE-1 : tail--; if (head == tail) fifo_clear(sp);} -#define p_inc() { peek == FIFO_SIZE-1 ? peek = 0 : peek++;} +#define h_inc() { \ + (head >= FIFO_SIZE-1) \ + ? head = 0 \ + : head++; \ + if (head == tail) \ + head = -1, tail = 0; \ + } +#define h_dec() { \ + (head <= 0) \ + ? head = FIFO_SIZE-1 \ + : head--; \ + if (head == tail) \ + tail = -1; \ + } +#define t_inc() { \ + (tail >= FIFO_SIZE-1) \ + ? tail = 0 \ + : tail++; \ + if (tail == head) \ + tail = -1; \ + } +#define t_dec() { \ + (tail <= 0) \ + ? tail = FIFO_SIZE-1 \ + : tail--; \ + if (head == tail) \ + fifo_clear(sp); \ + } +#define p_inc() { \ + (peek >= FIFO_SIZE-1) \ + ? peek = 0 \ + : peek++; \ + } -#define cooked_key_in_fifo() ((head != -1) && (peek != head)) -#define raw_key_in_fifo() ((head != -1) && (peek != tail)) - -#undef HIDE_EINTR +#define cooked_key_in_fifo() ((head >= 0) && (peek != head)) +#define raw_key_in_fifo() ((head >= 0) && (peek != tail)) #endif /* FIFO_DEFS_H */ diff --git a/lib/libcurses/hashed_db.h b/lib/libcurses/hashed_db.h index c8557e5c9c2..f56c2b38832 100644 --- a/lib/libcurses/hashed_db.h +++ b/lib/libcurses/hashed_db.h @@ -1,7 +1,8 @@ -/* $OpenBSD: hashed_db.h,v 1.1 2010/01/12 23:21:59 nicm Exp $ */ +/* $OpenBSD: hashed_db.h,v 1.2 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2006 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 2006-2014,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,19 +34,23 @@ ****************************************************************************/ /* - * $Id: hashed_db.h,v 1.1 2010/01/12 23:21:59 nicm Exp $ + * $Id: hashed_db.h,v 1.2 2023/10/17 09:52:08 nicm Exp $ */ #ifndef HASHED_DB_H #define HASHED_DB_H 1 +#include + #include #if USE_HASHED_DB +#define DB_DBM_HSEARCH 0 /* quiet gcc -Wundef with db6 */ + #include -#ifndef DBN_SUFFIX +#ifndef DBM_SUFFIX #define DBM_SUFFIX ".db" #endif diff --git a/lib/libcurses/key_defined.3 b/lib/libcurses/key_defined.3 index 1ca4ddac1a7..765bd10bfff 100644 --- a/lib/libcurses/key_defined.3 +++ b/lib/libcurses/key_defined.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: key_defined.3,v 1.1 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: key_defined.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 2003-2004,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2021,2022 Thomas E. Dickey * +.\" Copyright 2003-2006,2010 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -30,14 +31,14 @@ .\" .\" Author: Thomas E. Dickey 2003 .\" -.\" $Id: key_defined.3,v 1.1 2010/01/12 23:21:59 nicm Exp $ -.TH key_defined 3 "" +.\" $Id: key_defined.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ +.TH key_defined 3 2022-02-12 "ncurses 6.4" "Library calls" .SH NAME \fBkey_defined\fP \- check if a keycode is defined .SH SYNOPSIS \fB#include \fP .sp -\fBint key_defined(const char *definition);\fP +\fBint key_defined(const char *\fIdefinition\fB);\fR .SH DESCRIPTION This is an extension to the curses library. It permits an application to determine if a string is currently bound @@ -45,18 +46,15 @@ to any keycode. .SH RETURN VALUE If the string is bound to a keycode, its value (greater than zero) is returned. If no keycode is bound, zero is returned. -If the string conflicts with longer strings which are bound to keys, -1 is returned. +If the string conflicts with longer strings +which are bound to keys, \-1 is returned. .SH PORTABILITY -These routines are specific to ncurses. They were not supported on -Version 7, BSD or System V implementations. It is recommended that +These routines are specific to ncurses. +They were not supported on +Version 7, BSD or System V implementations. +It is recommended that any code depending on them be conditioned using NCURSES_VERSION. .SH SEE ALSO -\fBdefine_key\fR(3). +\fBdefine_key\fP(3). .SH AUTHOR Thomas Dickey. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: diff --git a/lib/libcurses/keybound.3 b/lib/libcurses/keybound.3 index bd586434234..278d351b5da 100644 --- a/lib/libcurses/keybound.3 +++ b/lib/libcurses/keybound.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: keybound.3,v 1.3 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: keybound.3,v 1.4 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1999-2003,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2021,2022 Thomas E. Dickey * +.\" Copyright 1999-2008,2010 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -30,14 +31,14 @@ .\" .\" Author: Thomas E. Dickey 1999 .\" -.\" $Id: keybound.3,v 1.3 2010/01/12 23:21:59 nicm Exp $ -.TH keybound 3 "" +.\" $Id: keybound.3,v 1.4 2023/10/17 09:52:08 nicm Exp $ +.TH keybound 3 2022-02-12 "ncurses 6.4" "Library calls" .SH NAME \fBkeybound\fP \- return definition of keycode .SH SYNOPSIS \fB#include \fP .sp -\fBchar * keybound(int keycode, int count);\fP +\fBchar * keybound(int \fIkeycode\fB, int \fIcount);\fR .SH DESCRIPTION This is an extension to the curses library. It permits an application to determine the string which is defined @@ -50,17 +51,13 @@ through multiple definitions, counting from zero. When successful, the function returns a string which must be freed by the caller. .SH PORTABILITY -These routines are specific to ncurses. They were not supported on -Version 7, BSD or System V implementations. It is recommended that +These routines are specific to ncurses. +They were not supported on +Version 7, BSD or System V implementations. +It is recommended that any code depending on them be conditioned using NCURSES_VERSION. .SH SEE ALSO -\fBdefine_key\fR(3), -\fBkeyok\fR(3). +\fBdefine_key\fP(3), +\fBkeyok\fP(3). .SH AUTHOR Thomas Dickey. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: diff --git a/lib/libcurses/keyok.3 b/lib/libcurses/keyok.3 index 4168f9d246b..26a41aad649 100644 --- a/lib/libcurses/keyok.3 +++ b/lib/libcurses/keyok.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: keyok.3,v 1.4 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: keyok.3,v 1.5 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2003,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2021,2022 Thomas E. Dickey * +.\" Copyright 1998-2010,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -30,36 +31,32 @@ .\" .\" Author: Thomas E. Dickey 1997 .\" -.\" $Id: keyok.3,v 1.4 2010/01/12 23:21:59 nicm Exp $ -.TH keyok 3 "" +.\" $Id: keyok.3,v 1.5 2023/10/17 09:52:08 nicm Exp $ +.TH keyok 3 2022-02-12 "ncurses 6.4" "Library calls" .SH NAME \fBkeyok\fP \- enable or disable a keycode .SH SYNOPSIS \fB#include \fP .sp -\fBint keyok(int keycode, bool enable);\fP +\fBint keyok(int \fIkeycode\fB, bool \fIenable\fB);\fR .SH DESCRIPTION This is an extension to the curses library. It permits an application to disable specific keycodes, rather than -use the \fIkeypad\fP function to disable all keycodes. -Keys that have been disabled can be reenabled. +use the \fBkeypad\fP function to disable all keycodes. +Keys that have been disabled can be re-enabled. .SH RETURN VALUE -The keycode must be greater than zero, else ERR is returned. -If it does not correspond to a defined key, then ERR is returned. +The keycode must be greater than zero, else \fBERR\fP is returned. +If it does not correspond to a defined key, then \fBERR\fP is returned. If the \fIenable\fP parameter is true, then the key must have been disabled, and vice versa. -Otherwise, the function returns OK. +Otherwise, the function returns \fBOK\fP. .SH PORTABILITY -These routines are specific to ncurses. They were not supported on -Version 7, BSD or System V implementations. It is recommended that +These routines are specific to ncurses. +They were not supported on +Version 7, BSD or System V implementations. +It is recommended that any code depending on them be conditioned using NCURSES_VERSION. .SH SEE ALSO -\fBdefine_key\fR(3). +\fBdefine_key\fP(3). .SH AUTHOR Thomas Dickey. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: diff --git a/lib/libcurses/legacy_coding.3 b/lib/libcurses/legacy_coding.3 index fe490540fdb..0c8f84b9dd4 100644 --- a/lib/libcurses/legacy_coding.3 +++ b/lib/libcurses/legacy_coding.3 @@ -1,5 +1,6 @@ .\"*************************************************************************** -.\" Copyright (c) 2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2020-2021,2022 Thomas E. Dickey * +.\" Copyright 2005-2016,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,18 +29,16 @@ .\" .\" Author: Thomas E. Dickey .\" -.\" $Id: legacy_coding.3,v 1.1 2016/09/16 17:24:20 nicm Exp $ -.TH legacy_coding 3 "" +.\" $Id: legacy_coding.3,v 1.2 2023/10/17 09:52:08 nicm Exp $ +.TH legacy_coding 3 2022-02-12 "ncurses 6.4" "Library calls" .SH NAME -\fBuse_legacy_coding\fR \- use terminal's default colors +\fBuse_legacy_coding\fP \- override locale-encoding checks .SH SYNOPSIS \fB#include \fP .sp -\fBint use_legacy_coding(int level);\fP +\fBint use_legacy_coding(int \fIlevel\fB);\fR .SH DESCRIPTION -The -.I use_legacy_coding() -function is an extension to the curses library. +The \fBuse_legacy_coding\fP function is an extension to the curses library. It allows the caller to change the result of \fBunctrl\fP, and suppress related checks within the library that would normally cause nonprinting characters to be rendered in visible form. @@ -71,12 +70,6 @@ It was not supported on Version 7, BSD or System V implementations. It is recommended that any code depending on ncurses extensions be conditioned using NCURSES_VERSION. .SH SEE ALSO -\fBunctrl\fR(3). +\fBunctrl\fP(3). .SH AUTHOR Thomas Dickey (to support lynx's font-switching feature). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: diff --git a/lib/libcurses/manhtml.aliases b/lib/libcurses/manhtml.aliases new file mode 100644 index 00000000000..0310e971c64 --- /dev/null +++ b/lib/libcurses/manhtml.aliases @@ -0,0 +1,80 @@ +# $Id: manhtml.aliases,v 1.1 2023/10/17 09:52:08 nicm Exp $ +#*************************************************************************** +# Copyright 2019-2022,2023 Thomas E. Dickey * +# Copyright 2013,2017 Free Software Foundation, Inc. * +# * +# Permission is hereby granted, free of charge, to any person obtaining a * +# copy of this software and associated documentation files (the * +# "Software"), to deal in the Software without restriction, including * +# without limitation the rights to use, copy, modify, merge, publish, * +# distribute, distribute with modifications, sublicense, and/or sell * +# copies of the Software, and to permit persons to whom the Software is * +# furnished to do so, subject to the following conditions: * +# * +# The above copyright notice and this permission notice shall be included * +# in all copies or substantial portions of the Software. * +# * +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * +# IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * +# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * +# THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +# * +# Except as contained in this notice, the name(s) of the above copyright * +# holders shall not be used in advertising or otherwise to promote the * +# sale, use or other dealings in this Software without prior written * +# authorization. * +#*************************************************************************** +# Items in this list will be linked to the corresponding manpages by man2html +addch(3) curs_addch(3) +assume_default_colors(3) default_colors(3) +baudrate(3) curs_termattrs(3) +clearok(3) curs_outopts(3) +curs_set(3) curs_kernel(3) +def_prog_mode(3) curs_kernel(3) +def_shell_mode(3) curs_kernel(3) +delscreen(3) curs_initscr(3) +doupdate(3) curs_refresh(3) +endwin(3) curs_initscr(3) +filter(3) curs_util(3) +get_wch(3) curs_get_wch(3) +getcchar(3) curs_getcchar(3) +getch(3) curs_getch(3) +immedok(3) curs_outopts(3) +inch(3) curs_inch(3) +infocmp(1) infocmp(1) +initscr(3) curs_initscr(3) +is_scrollok(3) curs_opaque(3) +keypad(3) curs_inopts(3) +longname(3) curs_termattrs(3) +meta(3) curs_inopts(3) +mvcur(3) curs_terminfo(3) +mvwin(3) curs_window(3) +newterm(3) curs_initscr(3) +refresh(3) curs_refresh(3) +reset_shell_mode(3) curs_kernel(3) +restartterm(3) curs_terminfo(3) +set_curterm(3) curs_terminfo(3) +set_term(3) curs_initscr(3) +setcchar(3) curs_getcchar(3) +setupterm(3) curs_terminfo(3) +slk_init(3) curs_slk(3) +slk_touch(3) curs_slk(3) +tic(1) tic(1) +tigetstr(3) curs_terminfo(3) +tparm(3) curs_terminfo(3) +tputs(3) curs_terminfo(3) +use_default_colors(3) default_colors(3) +use_env(3) curs_util(3) +use_extended_names(3) curs_extend(3) +use_legacy_coding(3) legacy_coding(3) +vidputs(3) curs_terminfo(3) +wadd_wch(3) curs_add_wch(3) +waddch(3) curs_addch(3) +wbkgdset(3) curs_bkgd(3) +wget_wch(3) curs_get_wch(3) +wgetch(3) curs_getch(3) +wnoutrefresh(3) curs_refresh(3) +wrefresh(3) curs_refresh(3) diff --git a/lib/libcurses/manhtml.externs b/lib/libcurses/manhtml.externs new file mode 100644 index 00000000000..4d31412ab53 --- /dev/null +++ b/lib/libcurses/manhtml.externs @@ -0,0 +1,75 @@ +# $Id: manhtml.externs,v 1.1 2023/10/17 09:52:08 nicm Exp $ +# Items in this list will not be linked by man2html +#*************************************************************************** +# Copyright 2019-2020,2021 Thomas E. Dickey * +# Copyright 2013,2017 Free Software Foundation, Inc. * +# * +# Permission is hereby granted, free of charge, to any person obtaining a * +# copy of this software and associated documentation files (the * +# "Software"), to deal in the Software without restriction, including * +# without limitation the rights to use, copy, modify, merge, publish, * +# distribute, distribute with modifications, sublicense, and/or sell * +# copies of the Software, and to permit persons to whom the Software is * +# furnished to do so, subject to the following conditions: * +# * +# The above copyright notice and this permission notice shall be included * +# in all copies or substantial portions of the Software. * +# * +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * +# IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * +# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * +# THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +# * +# Except as contained in this notice, the name(s) of the above copyright * +# holders shall not be used in advertising or otherwise to promote the * +# sale, use or other dealings in this Software without prior written * +# authorization. * +#*************************************************************************** +ADACURSES(1) +COLOR_PAIR(1) +COLOR_PAIR(2) +COLOR_PAIR(3) +atoi(3) +conflict(1) +cron(1) +csh(1) +ded(1) +emacs(1) +environ(7) +errno(3) +file(1) +getty(1) +jove(1) +lynx(1) +nvi(1) +mutt(1) +od(1) +printf(3) +profile(5) +putc(3) +putchar(3) +putwc(3) +read(2) +readline(3) +resize(1) +scanf(3) +screen(1) +setlocale(3) +sh(1) +sscanf(3) +stdio(3) +stty(1) +system(3) +termios(3) +tmux(1) +tty(4) +ttys(5) +vi(1) +vprintf(3) +vscanf(3) +wcwidth(3) +write(2) +xterm(1) diff --git a/lib/libcurses/nc_access.h b/lib/libcurses/nc_access.h new file mode 100644 index 00000000000..7fb3aff8455 --- /dev/null +++ b/lib/libcurses/nc_access.h @@ -0,0 +1,80 @@ +/**************************************************************************** + * Copyright 2021,2023 Thomas E. Dickey * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/* $Id: nc_access.h,v 1.1 2023/10/17 09:52:08 nicm Exp $ */ + +#ifndef NC_ACCESS_included +#define NC_ACCESS_included 1 +/* *INDENT-OFF* */ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Turn off the 'use_terminfo_vars()' symbol to limit access to environment + * variables when running with privileges. + */ +#if defined(USE_ROOT_ENVIRON) && defined(USE_SETUID_ENVIRON) +#define use_terminfo_vars() 1 +#else +#define use_terminfo_vars() _nc_env_access() +#endif + +extern NCURSES_EXPORT(int) _nc_env_access (void); + +/* + * Turn off this symbol to limit access to files when running setuid. + */ +#ifdef USE_ROOT_ACCESS + +#define safe_fopen(name,mode) fopen(name,mode) +#define safe_open2(name,flags) open(name,flags) +#define safe_open3(name,flags,mode) open(name,flags,mode) + +#else + +#define safe_fopen(name,mode) _nc_safe_fopen(name,mode) +#define safe_open2(name,flags) _nc_safe_open3(name,flags,0) +#define safe_open3(name,flags,mode) _nc_safe_open3(name,flags,mode) +extern NCURSES_EXPORT(FILE *) _nc_safe_fopen (const char *, const char *); +extern NCURSES_EXPORT(int) _nc_safe_open3 (const char *, int, mode_t); + +#endif + +#ifdef __cplusplus +} +#endif + +/* *INDENT-ON* */ + +#endif /* NC_ACCESS_included */ diff --git a/lib/libcurses/nc_alloc.h b/lib/libcurses/nc_alloc.h index 93a12b3cdf6..77fade59ec8 100644 --- a/lib/libcurses/nc_alloc.h +++ b/lib/libcurses/nc_alloc.h @@ -1,7 +1,8 @@ -/* $OpenBSD: nc_alloc.h,v 1.7 2010/01/12 23:21:59 nicm Exp $ */ +/* $OpenBSD: nc_alloc.h,v 1.8 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2019-2020,2021 Thomas E. Dickey * + * Copyright 1998-2013,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,16 +32,20 @@ /**************************************************************************** * Author: Thomas E. Dickey 1996-on * ****************************************************************************/ -/* $Id: nc_alloc.h,v 1.7 2010/01/12 23:21:59 nicm Exp $ */ +/* $Id: nc_alloc.h,v 1.8 2023/10/17 09:52:08 nicm Exp $ */ #ifndef NC_ALLOC_included #define NC_ALLOC_included 1 +/* *INDENT-OFF* */ + +#include +#include #ifdef __cplusplus extern "C" { #endif -#if HAVE_LIBDMALLOC +#if defined(HAVE_LIBDMALLOC) && HAVE_LIBDMALLOC #include #undef strndup /* workaround for #define in GLIBC 2.7 */ #include /* Gray Watson's library */ @@ -49,14 +54,14 @@ extern "C" { #define HAVE_LIBDMALLOC 0 #endif -#if HAVE_LIBDBMALLOC +#if defined(HAVE_LIBDBMALLOC) && HAVE_LIBDBMALLOC #include /* Conor Cahill's library */ #else #undef HAVE_LIBDBMALLOC #define HAVE_LIBDBMALLOC 0 #endif -#if HAVE_LIBMPATROL +#if defined(HAVE_LIBMPATROL) && HAVE_LIBMPATROL #include /* Memory-Patrol library */ #else #undef HAVE_LIBMPATROL @@ -70,15 +75,28 @@ extern "C" { #if HAVE_LIBDBMALLOC || HAVE_LIBDMALLOC || NO_LEAKS #define HAVE_NC_FREEALL 1 struct termtype; -extern NCURSES_EXPORT(void) _nc_free_and_exit(int) GCC_NORETURN; -extern NCURSES_EXPORT(void) _nc_free_tinfo(int) GCC_NORETURN; -extern NCURSES_EXPORT(void) _nc_free_tic(int) GCC_NORETURN; -extern NCURSES_EXPORT(void) _nc_free_tparm(void); -extern NCURSES_EXPORT(void) _nc_leaks_dump_entry(void); +extern GCC_NORETURN NCURSES_EXPORT(void) _nc_free_tinfo(int) GCC_DEPRECATED("use exit_terminfo"); + +#ifdef NCURSES_INTERNALS +extern GCC_NORETURN NCURSES_EXPORT(void) _nc_free_tic(int); +extern void _nc_leaks_dump_entry(void); extern NCURSES_EXPORT(void) _nc_leaks_tic(void); -#define ExitProgram(code) _nc_free_and_exit(code) + +#if NCURSES_SP_FUNCS +extern GCC_NORETURN NCURSES_EXPORT(void) NCURSES_SP_NAME(_nc_free_and_exit)(SCREEN*, int); +#endif +extern GCC_NORETURN NCURSES_EXPORT(void) _nc_free_and_exit(int); + +#else /* !NCURSES_INTERNALS */ +extern GCC_NORETURN NCURSES_EXPORT(void) _nc_free_and_exit(int) GCC_DEPRECATED("use exit_curses"); #endif +#define ExitProgram(code) exit_curses(code) + +#else +extern GCC_NORETURN NCURSES_EXPORT(void) _nc_free_and_exit(int) GCC_DEPRECATED("use exit_curses"); +#endif /* NO_LEAKS, etc */ + #ifndef HAVE_NC_FREEALL #define HAVE_NC_FREEALL 0 #endif @@ -90,6 +108,7 @@ extern NCURSES_EXPORT(void) _nc_leaks_tic(void); /* doalloc.c */ extern NCURSES_EXPORT(void *) _nc_doalloc(void *, size_t); #if !HAVE_STRDUP +#undef strdup #define strdup _nc_strdup extern NCURSES_EXPORT(char *) _nc_strdup(const char *); #endif @@ -97,12 +116,14 @@ extern NCURSES_EXPORT(char *) _nc_strdup(const char *); /* entries.c */ extern NCURSES_EXPORT(void) _nc_leaks_tinfo(void); -#define typeMalloc(type,elts) (type *)malloc((elts)*sizeof(type)) -#define typeCalloc(type,elts) (type *)calloc((elts),sizeof(type)) -#define typeRealloc(type,elts,ptr) (type *)_nc_doalloc(ptr, (elts)*sizeof(type)) +#define typeMalloc(type,elts) (type *)malloc((size_t)(elts)*sizeof(type)) +#define typeCalloc(type,elts) (type *)calloc((size_t)(elts),sizeof(type)) +#define typeRealloc(type,elts,ptr) (type *)_nc_doalloc(ptr, (size_t)(elts)*sizeof(type)) #ifdef __cplusplus } #endif +/* *INDENT-ON* */ + #endif /* NC_ALLOC_included */ diff --git a/lib/libcurses/nc_panel.h b/lib/libcurses/nc_panel.h index 83c4e3a8ece..4ecfb5570cb 100644 --- a/lib/libcurses/nc_panel.h +++ b/lib/libcurses/nc_panel.h @@ -1,7 +1,8 @@ -/* $OpenBSD: nc_panel.h,v 1.4 2010/01/12 23:21:59 nicm Exp $ */ +/* $OpenBSD: nc_panel.h,v 1.5 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2008 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2009,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,9 +34,8 @@ * and: Thomas E. Dickey * ****************************************************************************/ - /* - * $Id: nc_panel.h,v 1.4 2010/01/12 23:21:59 nicm Exp $ + * $Id: nc_panel.h,v 1.5 2023/10/17 09:52:08 nicm Exp $ * * nc_panel.h * @@ -46,26 +46,37 @@ #ifndef NC_PANEL_H #define NC_PANEL_H 1 +#include +#include + #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -struct panel; /* Forward Declaration */ + struct panel; /* Forward Declaration */ -struct panelhook { - struct panel* top_panel; - struct panel* bottom_panel; - struct panel* stdscr_pseudo_panel; + struct panelhook + { + struct panel *top_panel; + struct panel *bottom_panel; + struct panel *stdscr_pseudo_panel; #if NO_LEAKS - int (*destroy)(struct panel *); + int (*destroy) (struct panel *); #endif -}; + }; -/* Retrieve the panelhook of the current screen */ -extern NCURSES_EXPORT(struct panelhook*) _nc_panelhook (void); + struct screen; /* Forward declaration */ +/* Retrieve the panelhook of the specified screen */ + extern NCURSES_EXPORT(struct panelhook *) + _nc_panelhook (void); +#if NCURSES_SP_FUNCS + extern NCURSES_EXPORT(struct panelhook *) + NCURSES_SP_NAME(_nc_panelhook) (SCREEN *); +#endif #ifdef __cplusplus } #endif -#endif /* NC_PANEL_H */ +#endif /* NC_PANEL_H */ diff --git a/lib/libcurses/nc_string.h b/lib/libcurses/nc_string.h new file mode 100644 index 00000000000..db8caf48ffe --- /dev/null +++ b/lib/libcurses/nc_string.h @@ -0,0 +1,90 @@ +/**************************************************************************** + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 2012-2013,2016 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey 2012 * + ****************************************************************************/ + +#ifndef STRING_HACKS_H +#define STRING_HACKS_H 1 + +#include + +#if HAVE_BSD_STRING_H +#include +#endif + +/* + * $Id: nc_string.h,v 1.1 2023/10/17 09:52:08 nicm Exp $ + * + * String-hacks. Use these macros to stifle warnings on (presumably) correct + * uses of strcat, strcpy and sprintf. + * + * By the way - + * A fundamental limitation of the interfaces (and frequent issue in bug + * reports using these functions) is that sizes are passed as unsigned values + * (with associated sign-extension problems), limiting their effectiveness + * when checking for buffer overflow. + */ + +#ifdef __cplusplus +#define NCURSES_VOID /* nothing */ +#else +#define NCURSES_VOID (void) +#endif + +#if USE_STRING_HACKS && HAVE_STRLCAT +#define _nc_STRCAT(d,s,n) NCURSES_VOID strlcat((d),(s),NCURSES_CAST(size_t,n)) +#define _nc_STRNCAT(d,s,m,n) NCURSES_VOID strlcat((d),(s),NCURSES_CAST(size_t,m)) +#else +#define _nc_STRCAT(d,s,n) NCURSES_VOID strcat((d),(s)) +#define _nc_STRNCAT(d,s,m,n) NCURSES_VOID strncat((d),(s),(n)) +#endif + +#if USE_STRING_HACKS && HAVE_STRLCPY +#define _nc_STRCPY(d,s,n) NCURSES_VOID strlcpy((d),(s),NCURSES_CAST(size_t,n)) +#define _nc_STRNCPY(d,s,n) NCURSES_VOID strlcpy((d),(s),NCURSES_CAST(size_t,n)) +#else +#define _nc_STRCPY(d,s,n) NCURSES_VOID strcpy((d),(s)) +#define _nc_STRNCPY(d,s,n) NCURSES_VOID strncpy((d),(s),(n)) +#endif + +#if USE_STRING_HACKS && HAVE_SNPRINTF +#ifdef __cplusplus +#define _nc_SPRINTF NCURSES_VOID snprintf +#else +#define _nc_SPRINTF NCURSES_VOID (snprintf) +#endif +#define _nc_SLIMIT(n) NCURSES_CAST(size_t,n), +#else +#define _nc_SPRINTF NCURSES_VOID sprintf +#define _nc_SLIMIT(n) /* nothing */ +#endif + +#endif /* STRING_HACKS_H */ diff --git a/lib/libcurses/nc_termios.h b/lib/libcurses/nc_termios.h new file mode 100644 index 00000000000..0b337d31d7e --- /dev/null +++ b/lib/libcurses/nc_termios.h @@ -0,0 +1,168 @@ +/**************************************************************************** + * Copyright 2018,2020 Thomas E. Dickey * + * Copyright 2011-2014,2017 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey 2011 * + ****************************************************************************/ + +/* $Id: nc_termios.h,v 1.1 2023/10/17 09:52:08 nicm Exp $ */ + +#ifndef NC_TERMIOS_included +#define NC_TERMIOS_included 1 + +#include + +#if HAVE_TERMIOS_H && HAVE_TCGETATTR + +#else /* !HAVE_TERMIOS_H */ + +#if HAVE_TERMIO_H + +/* Add definitions to make termio look like termios. + * But ifdef it, since there are some implementations + * that try to do this for us in a fake . + */ +#ifndef TCSADRAIN +#define TCSADRAIN TCSETAW +#endif +#ifndef TCSAFLUSH +#define TCSAFLUSH TCSETAF +#endif +#ifndef tcsetattr +#define tcsetattr(fd, cmd, arg) ioctl(fd, cmd, arg) +#endif +#ifndef tcgetattr +#define tcgetattr(fd, arg) ioctl(fd, TCGETA, arg) +#endif +#ifndef cfgetospeed +#define cfgetospeed(t) ((t)->c_cflag & CBAUD) +#endif +#ifndef TCIFLUSH +#define TCIFLUSH 0 +#endif +#ifndef tcflush +#define tcflush(fd, arg) ioctl(fd, TCFLSH, arg) +#endif + +#if defined(EXP_WIN32_DRIVER) +#undef TERMIOS +#endif + +#else /* !HAVE_TERMIO_H */ + +#if defined(_WIN32) && !defined(EXP_WIN32_DRIVER) + +/* lflag bits */ +#define ISIG 0x0001 +#define ICANON 0x0002 +#define ECHO 0x0004 +#define ECHOE 0x0008 +#define ECHOK 0x0010 +#define ECHONL 0x0020 +#define NOFLSH 0x0040 +#define IEXTEN 0x0100 + +#define VEOF 4 +#define VERASE 5 +#define VINTR 6 +#define VKILL 7 +#define VMIN 9 +#define VQUIT 10 +#define VTIME 16 + +/* iflag bits */ +#define IGNBRK 0x00001 +#define BRKINT 0x00002 +#define IGNPAR 0x00004 +#define INPCK 0x00010 +#define ISTRIP 0x00020 +#define INLCR 0x00040 +#define IGNCR 0x00080 +#define ICRNL 0x00100 +#define IXON 0x00400 +#define IXOFF 0x01000 +#define PARMRK 0x10000 + +/* oflag bits */ +#define OPOST 0x00001 + +/* cflag bits */ +#define CBAUD 0x0100f +#define B0 0x00000 +#define B50 0x00001 +#define B75 0x00002 +#define B110 0x00003 +#define B134 0x00004 +#define B150 0x00005 +#define B200 0x00006 +#define B300 0x00007 +#define B600 0x00008 +#define B1200 0x00009 +#define B1800 0x0000a +#define B2400 0x0000b +#define B4800 0x0000c +#define B9600 0x0000d + +#define CSIZE 0x00030 +#define CS8 0x00030 +#define CSTOPB 0x00040 +#define CREAD 0x00080 +#define PARENB 0x00100 +#define PARODD 0x00200 +#define HUPCL 0x00400 +#define CLOCAL 0x00800 + +#define TCIFLUSH 0 +#define TCSADRAIN 3 + +#ifndef cfgetospeed +#define cfgetospeed(t) ((t)->c_cflag & CBAUD) +#endif + +#ifndef tcsetattr +#define tcsetattr(fd, opt, arg) _nc_mingw_tcsetattr(fd, opt, arg) +#endif + +#ifndef tcgetattr +#define tcgetattr(fd, arg) _nc_mingw_tcgetattr(fd, arg) +#endif + +#ifndef tcflush +#define tcflush(fd, queue) _nc_mingw_tcflush(fd, queue) +#endif + +#undef ttyname +#define ttyname(fd) NULL + +#endif /* _WIN32 */ +#endif /* HAVE_TERMIO_H */ + +#endif /* HAVE_TERMIOS_H */ + +#endif /* NC_TERMIOS_included */ diff --git a/lib/libcurses/nc_tparm.h b/lib/libcurses/nc_tparm.h index 5b6d063128f..7ba9299f409 100644 --- a/lib/libcurses/nc_tparm.h +++ b/lib/libcurses/nc_tparm.h @@ -1,7 +1,8 @@ -/* $OpenBSD: nc_tparm.h,v 1.2 2020/06/05 19:50:59 denis Exp $ */ +/* $OpenBSD: nc_tparm.h,v 1.3 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2006 Free Software Foundation, Inc. * + * Copyright 2018-2020,2023 Thomas E. Dickey * + * Copyright 2006-2012,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,13 +33,26 @@ * Author: Thomas E. Dickey 2006 * ****************************************************************************/ -/* $Id: nc_tparm.h,v 1.2 2020/06/05 19:50:59 denis Exp $ */ +/* $Id: nc_tparm.h,v 1.3 2023/10/17 09:52:08 nicm Exp $ */ + +#ifndef NC_TPARM_included +#define NC_TPARM_included 1 + +#include +#include /* * Cast parameters past the formatting-string for tparm() to match the * assumption of the varargs code. */ +#ifndef TPARM_ARG +#ifdef NCURSES_TPARM_ARG +#define TPARM_ARG NCURSES_TPARM_ARG +#else #define TPARM_ARG long +#endif +#endif /* TPARAM_ARG */ + #define TPARM_N(n) (TPARM_ARG)(n) #define TPARM_9(a,b,c,d,e,f,g,h,i,j) tparm(a,TPARM_N(b),TPARM_N(c),TPARM_N(d),TPARM_N(e),TPARM_N(f),TPARM_N(g),TPARM_N(h),TPARM_N(i),TPARM_N(j)) @@ -64,3 +78,18 @@ #define TPARM_1(a,b) TPARM_2(a,b,0) #define TPARM_0(a) TPARM_1(a,0) #endif + +#ifdef NCURSES_INTERNALS +#define TIPARM_0(s) _nc_tiparm(0,s) +#define TIPARM_1(s,a) _nc_tiparm(1,s,a) +#define TIPARM_2(s,a,b) _nc_tiparm(2,s,a,b) +#define TIPARM_3(s,a,b,c) _nc_tiparm(3,s,a,b,c) +#define TIPARM_4(s,a,b,c,d) _nc_tiparm(4,s,a,b,c,d) +#define TIPARM_5(s,a,b,c,d,e) _nc_tiparm(5,s,a,b,c,d,e) +#define TIPARM_6(s,a,b,c,d,e,f) _nc_tiparm(6,s,a,b,c,d,e,f) +#define TIPARM_7(s,a,b,c,d,e,f,g) _nc_tiparm(7,s,a,b,c,d,e,f,g) +#define TIPARM_8(s,a,b,c,d,e,f,g,h) _nc_tiparm(8,s,a,b,c,d,e,f,g,h) +#define TIPARM_9(s,a,b,c,d,e,f,g,h,i) _nc_tiparm(9,s,a,b,c,d,e,f,g,h,i) +#endif + +#endif /* NC_TPARM_included */ diff --git a/lib/libcurses/ncurses_cfg.h b/lib/libcurses/ncurses_cfg.h index dfd0604b7c1..5216167765c 100644 --- a/lib/libcurses/ncurses_cfg.h +++ b/lib/libcurses/ncurses_cfg.h @@ -1,8 +1,9 @@ -/* $OpenBSD: ncurses_cfg.h,v 1.27 2011/09/21 06:26:51 nicm Exp $ */ +/* $OpenBSD: ncurses_cfg.h,v 1.28 2023/10/17 09:52:08 nicm Exp $ */ /* include/ncurses_cfg.h. Generated automatically by configure. */ /**************************************************************************** - * Copyright (c) 1998-2004,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -30,10 +31,13 @@ ****************************************************************************/ /**************************************************************************** - * Author: Thomas E. Dickey 1997 * + * Author: Thomas E. Dickey 1997-on * ****************************************************************************/ /* - * $Id: ncurses_cfg.h,v 1.27 2011/09/21 06:26:51 nicm Exp $ + * $Id: ncurses_cfg.h,v 1.28 2023/10/17 09:52:08 nicm Exp $ + * + * Both ncurses_cfg.h and ncurses_def.h are internal header-files used when + * building ncurses. * * This is a template-file used to generate the "ncurses_cfg.h" file. * @@ -42,141 +46,198 @@ * 971222) to autoconf 2.12 or 2.13 to do this. * * See: - * http://invisible-island.net/autoconf/ - * ftp://invisible-island.net/autoconf/ + * https://invisible-island.net/autoconf/ + * ftp://ftp.invisible-island.net/autoconf/ */ #ifndef NC_CONFIG_H #define NC_CONFIG_H -#define BSD_TPUTS 1 -#define CC_HAS_PROTOS 1 -#define CPP_HAS_STATIC_CAST 1 -#define ETIP_NEEDS_MATH_H 1 -#define GCC_NORETURN __attribute__((__noreturn__)) -#define GCC_PRINTF 1 -#define GCC_SCANF 1 -#define GCC_UNUSED __attribute__((__unused__)) -#define HAVE_BIG_CORE 1 -#define HAVE_BSD_CGETENT 1 -#define HAVE_BTOWC 1 -#define HAVE_CURSES_VERSION 1 -#define HAVE_DIRENT_H 1 -#define HAVE_ERRNO 1 -#define HAVE_FCNTL_H 1 -#define HAVE_FORM_H 1 -#define HAVE_FSEEKO 1 -#define HAVE_GETCWD 1 -#define HAVE_GETEGID 1 -#define HAVE_GETEUID 1 -#define HAVE_GETOPT_H 1 -#define HAVE_GETTIMEOFDAY 1 -#define HAVE_GETTTYNAM 1 -#define HAVE_HAS_KEY 1 +#define PACKAGE "ncurses" +#define NCURSES_VERSION "6.4" +#define NCURSES_PATCHDATE 20230826 +#define SYSTEM_NAME "openbsd" +#if 0 +#include +#endif +#define HAVE_LONG_FILE_NAMES 1 +#define MIXEDCASE_FILENAMES 1 +#define STDC_HEADERS 1 +#define HAVE_SYS_TYPES_H 1 +#define HAVE_SYS_STAT_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STRING_H 1 +#define HAVE_MEMORY_H 1 +#define HAVE_STRINGS_H 1 #define HAVE_INTTYPES_H 1 -#define HAVE_IOSTREAM 1 -#define HAVE_ISASCII 1 -#define HAVE_ISSETUGID 1 -#define HAVE_LANGINFO_CODESET 1 -#define HAVE_LIMITS_H 1 +#define HAVE_STDINT_H 1 +#define HAVE_UNISTD_H 1 +#define HAVE_DIRENT_H 1 +#define TERMINFO_DIRS "/usr/share/terminfo:/usr/local/share/terminfo" +#define TERMINFO "/usr/share/terminfo" +#define HAVE_BIG_CORE 1 +#define PURE_TERMINFO 0 +#define USE_GETCAP 1 +#define USE_HOME_TERMINFO 1 +#define USE_ROOT_ENVIRON 1 +#define USE_ROOT_ACCESS 1 +#define HAVE_UNISTD_H 1 +#define HAVE_REMOVE 1 +#define HAVE_UNLINK 1 #define HAVE_LINK 1 -#define HAVE_LOCALE_H 1 -#define HAVE_LONG_FILE_NAMES 1 +#define HAVE_SYMLINK 1 +#define USE_LINKS 1 +#define BSD_TPUTS 1 +#define HAVE_LANGINFO_CODESET 1 +#define USE_WIDEC_SUPPORT 1 +#define NCURSES_WIDECHAR 1 +#define HAVE_WCHAR_H 1 +#define HAVE_WCTYPE_H 1 +#define HAVE_PUTWC 1 +#define HAVE_BTOWC 1 +#define HAVE_WCTOB 1 +#define HAVE_WMEMCHR 1 +#define HAVE_MBTOWC 1 +#define HAVE_WCTOMB 1 #define HAVE_MBLEN 1 #define HAVE_MBRLEN 1 #define HAVE_MBRTOWC 1 +#define HAVE_WCSRTOMBS 1 #define HAVE_MBSRTOWCS 1 +#define HAVE_WCSTOMBS 1 #define HAVE_MBSTOWCS 1 -#define HAVE_MBTOWC 1 -#define HAVE_MEMORY_H 1 -#define HAVE_MENU_H 1 -#define HAVE_MKSTEMP 1 -#define HAVE_NANOSLEEP 1 +#define NEED_WCHAR_H 1 +#define HAVE_FSEEKO 1 +#define RGB_PATH "/usr/lib64/X11/rgb.txt" +#define SIZEOF_SIGNED_CHAR 1 +#define NCURSES_EXT_FUNCS 1 +#define HAVE_ASSUME_DEFAULT_COLORS 1 +#define HAVE_CURSES_VERSION 1 +#define HAVE_HAS_KEY 1 +#define HAVE_RESIZETERM 1 +#define HAVE_RESIZE_TERM 1 +#define HAVE_TERM_ENTRY_H 1 +#define HAVE_USE_DEFAULT_COLORS 1 +#define HAVE_USE_SCREEN 1 +#define HAVE_USE_WINDOW 1 +#define HAVE_WRESIZE 1 +#define NCURSES_SP_FUNCS 1 +#define HAVE_TPUTS_SP 1 +#define NCURSES_EXT_COLORS 1 +#define HAVE_ALLOC_PAIR 1 +#define HAVE_INIT_EXTENDED_COLOR 1 +#define HAVE_RESET_COLOR_PAIRS 1 +#define NCURSES_EXT_PUTWIN 1 +#define NCURSES_NO_PADDING 1 +#define USE_SIGWINCH 1 +#define NCURSES_XNAMES 1 +#define NCURSES_WRAP_PREFIX "_nc_" +#define USE_ASSUMED_COLOR 1 +#define USE_HASHMAP 1 +#define GCC_SCANF 1 +#define GCC_SCANFLIKE(fmt,var) __attribute__((format(scanf,fmt,var))) +#define GCC_PRINTF 1 +#define GCC_PRINTFLIKE(fmt,var) __attribute__((format(printf,fmt,var))) +#define GCC_UNUSED __attribute__((unused)) +#define GCC_NORETURN __attribute__((noreturn)) +#define USE_STRING_HACKS 1 +#define HAVE_STRLCAT 1 +#define HAVE_STRLCPY 1 +#define HAVE_SNPRINTF 1 #define HAVE_NC_ALLOC_H 1 -#define HAVE_PANEL_H 1 -#define HAVE_POLL 1 -#define HAVE_POLL_H 1 -#define HAVE_PUTWC 1 +#define HAVE_MATH_FUNCS 1 +#define TIME_WITH_SYS_TIME 1 #define HAVE_REGEX_H_FUNCS 1 +#define HAVE_FCNTL_H 1 +#define HAVE_GETOPT_H 1 +#define HAVE_LIMITS_H 1 +#define HAVE_LOCALE_H 1 +#define HAVE_MATH_H 1 +#define HAVE_POLL_H 1 +#define HAVE_SYS_IOCTL_H 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_SYS_POLL_H 1 +#define HAVE_SYS_SELECT_H 1 +#define HAVE_SYS_TIME_H 1 +#define HAVE_SYS_TIMES_H 1 +#define HAVE_UNISTD_H 1 +#define HAVE_WCTYPE_H 1 +#define HAVE_UNISTD_H 1 +#define HAVE_GETOPT_H 1 +#define HAVE_GETOPT_HEADER 1 +#define DECL_ENVIRON 1 +#define HAVE_ENVIRON 1 +#define HAVE_PUTENV 1 +#define HAVE_SETENV 1 +#define HAVE_STRDUP 1 +#define HAVE_SYS_TIME_SELECT 1 +#define SIG_ATOMIC_T volatile sig_atomic_t +#define HAVE_CLOCK_GETTIME 1 +#define HAVE_FPATHCONF 1 +#define HAVE_GETCWD 1 +#define HAVE_GETEGID 1 +#define HAVE_GETEUID 1 +#define HAVE_GETOPT 1 +#define HAVE_GETUID 1 +#define HAVE_ISSETUGID 1 +#define HAVE_LOCALECONV 1 +#define HAVE_POLL 1 +#define HAVE_PUTENV 1 #define HAVE_REMOVE 1 -#define HAVE_REMOVE 1 -#define HAVE_RESIZETERM 1 -#define HAVE_RESIZE_TERM 1 #define HAVE_SELECT 1 #define HAVE_SETBUF 1 #define HAVE_SETBUFFER 1 +#define HAVE_SETENV 1 #define HAVE_SETVBUF 1 #define HAVE_SIGACTION 1 #define HAVE_SIGVEC 1 -#define HAVE_SIZECHANGE 1 -#define HAVE_SLK_COLOR 1 -#define HAVE_STDINT_H 1 -#define HAVE_STDLIB_H 1 +#define HAVE_SNPRINTF 1 #define HAVE_STRDUP 1 -#define HAVE_STRINGS_H 1 -#define HAVE_STRING_H 1 #define HAVE_STRSTR 1 -#define HAVE_SYMLINK 1 -#define HAVE_SYS_IOCTL_H 1 -#define HAVE_SYS_PARAM_H 1 -#define HAVE_SYS_POLL_H 1 -#define HAVE_SYS_SELECT_H 1 -#define HAVE_SYS_STAT_H 1 -#define HAVE_SYS_TIMES_H 1 -#define HAVE_SYS_TIME_H 1 -#define HAVE_SYS_TIME_SELECT 1 -#define HAVE_SYS_TYPES_H 1 -#define HAVE_TCGETATTR 1 +#define HAVE_SYSCONF 1 #define HAVE_TCGETPGRP 1 -#define HAVE_TERMIOS_H 1 #define HAVE_TIMES 1 -#define HAVE_TTYENT_H 1 -#define HAVE_TYPEINFO 1 -#define HAVE_UNISTD_H 1 -#define HAVE_UNISTD_H 1 -#define HAVE_UNISTD_H 1 -#define HAVE_UNLINK 1 -#define HAVE_USE_DEFAULT_COLORS 1 +#define HAVE_TSEARCH 1 #define HAVE_VSNPRINTF 1 +#define HAVE_PATH_TTYS 1 +#define HAVE_GETTTYNAM 1 +#define HAVE_BSD_CGETENT 1 +#define HAVE_ISASCII 1 +#define HAVE_NANOSLEEP 1 +#define HAVE_TERMIOS_H 1 +#define HAVE_UNISTD_H 1 +#define HAVE_SYS_IOCTL_H 1 +#define HAVE_TCGETATTR 1 #define HAVE_VSSCANF 1 -#define HAVE_WCSRTOMBS 1 -#define HAVE_WCSTOMBS 1 -#define HAVE_WCTOB 1 -#define HAVE_WCTOMB 1 -#define HAVE_WCTYPE_H 1 +#define HAVE_UNISTD_H 1 +#define HAVE_MKSTEMP 1 +#define HAVE_SIZECHANGE 1 #define HAVE_WORKING_POLL 1 -#define HAVE_WRESIZE 1 -#define IOSTREAM_NAMESPACE 1 -#define MIXEDCASE_FILENAMES 1 -#define NCURSES_EXT_FUNCS 1 -#define NCURSES_NO_PADDING 1 -#define NCURSES_PATHSEP ':' -#define NCURSES_VERSION_STRING "5.7.20081102" -#define NDEBUG 1 -#define NEED_WCHAR_H 1 -#define PURE_TERMINFO 0 -#define RETSIGTYPE void -#define SIG_ATOMIC_T volatile sig_atomic_t -#define SIZEOF_SIGNED_CHAR 1 -#define STDC_HEADERS 1 -#define SYSTEM_NAME "openbsd" -#define TERMINFO "/usr/share/terminfo" -#define TERMINFO_DIRS "/usr/share/terminfo:/usr/local/share/terminfo" -#define TIME_WITH_SYS_TIME 1 -#define TYPEOF_CHTYPE long -#define USE_ASSUMED_COLOR 1 -#define USE_DATABASE 1 -#define USE_GETCAP 1 -#define USE_HASHMAP 1 -#define USE_HOME_TERMINFO 1 -#define USE_LINKS 1 +#define HAVE_VA_COPY 1 +#define HAVE_UNISTD_H 1 +#define HAVE_FORK 1 +#define HAVE_VFORK 1 +#define HAVE_WORKING_VFORK 1 +#define HAVE_WORKING_FORK 1 +#define USE_FOPEN_BIN_R 1 #define USE_OPENPTY_HEADER -#define USE_ROOT_ENVIRON 1 -#define USE_SIGWINCH 1 -#define USE_WIDEC_SUPPORT 1 #define USE_XTERM_PTY 1 -/* #define HAVE_LIBFORM 1 */ -/* #define HAVE_LIBMENU 1 */ +#define HAVE_TYPEINFO 1 +#define HAVE_IOSTREAM 1 +#define IOSTREAM_NAMESPACE 1 +#define SIZEOF_BOOL 1 +#define CPP_HAS_OVERRIDE 1 +#define CPP_HAS_STATIC_CAST 1 +#define SIZEOF_WCHAR_T 4 +#define HAVE_SLK_COLOR 1 +#define HAVE_PANEL_H 1 /* #define HAVE_LIBPANEL 1 */ +#define HAVE_MENU_H 1 +/* #define HAVE_LIBMENU 1 */ +#define HAVE_FORM_H 1 +/* #define HAVE_LIBFORM 1 */ +#define NCURSES_PATHSEP ':' +#define NCURSES_VERSION_STRING "6.4.20230826" +#define NCURSES_OSPEED_COMPAT 0 #include @@ -184,11 +245,6 @@ #ifdef __cplusplus #undef const #undef inline -#else -#if defined(lint) || defined(TRACE) -#undef inline -#define inline /* nothing */ -#endif #endif /* On HP-UX, the C compiler doesn't grok mbstate_t without @@ -201,4 +257,7 @@ #endif #endif +/* + * vile:cmode + */ #endif /* NC_CONFIG_H */ diff --git a/lib/libcurses/ncurses_def.h b/lib/libcurses/ncurses_def.h index 87ff0cc7393..11010def021 100644 --- a/lib/libcurses/ncurses_def.h +++ b/lib/libcurses/ncurses_def.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ncurses_def.h,v 1.2 2010/01/12 23:21:59 nicm Exp $ */ +/* $OpenBSD: ncurses_def.h,v 1.3 2023/10/17 09:52:08 nicm Exp $ */ /* * This file is generated by ./MKncurses_def.sh @@ -15,8 +15,8 @@ #define BSD_TPUTS 0 #endif -#ifndef CC_HAS_PROTOS -#define CC_HAS_PROTOS 0 +#ifndef CGETENT_CONST +#define CGETENT_CONST /* nothing */ #endif #ifndef CPP_HAS_PARAM_INIT @@ -47,6 +47,14 @@ #define GCC_UNUSED /* nothing */ #endif +#ifndef HAVE_ALLOC_PAIR +#define HAVE_ALLOC_PAIR 0 +#endif + +#ifndef HAVE_ASSUME_DEFAULT_COLORS +#define HAVE_ASSUME_DEFAULT_COLORS 0 +#endif + #ifndef HAVE_BIG_CORE #define HAVE_BIG_CORE 0 #endif @@ -59,6 +67,10 @@ #define HAVE_BSD_SIGNAL_H 0 #endif +#ifndef HAVE_BSD_STRING_H +#define HAVE_BSD_STRING_H 0 +#endif + #ifndef HAVE_BTOWC #define HAVE_BTOWC 0 #endif @@ -71,18 +83,70 @@ #define HAVE_CHGAT 1 #endif +#ifndef HAVE_CLOCK_GETTIME +#define HAVE_CLOCK_GETTIME 0 +#endif + +#ifndef HAVE_COLOR_CONTENT +#define HAVE_COLOR_CONTENT 1 +#endif + #ifndef HAVE_COLOR_SET #define HAVE_COLOR_SET 1 #endif +#ifndef HAVE_CONSISTENT_GETENV +#define HAVE_CONSISTENT_GETENV 0 +#endif + +#ifndef HAVE_COPYWIN +#define HAVE_COPYWIN 1 +#endif + +#ifndef HAVE_CURSCR +#define HAVE_CURSCR 1 +#endif + +#ifndef HAVE_CURSES_DATA_TABSIZE +#define HAVE_CURSES_DATA_TABSIZE 1 +#endif + +#ifndef HAVE_CURSES_DATA_TTYTYPE +#define HAVE_CURSES_DATA_TTYTYPE 1 +#endif + +#ifndef HAVE_CURSES_TRACE +#define HAVE_CURSES_TRACE 1 +#endif + +#ifndef HAVE_DELSCREEN +#define HAVE_DELSCREEN 1 +#endif + +#ifndef HAVE_DERWIN +#define HAVE_DERWIN 1 +#endif + #ifndef HAVE_DIRENT_H #define HAVE_DIRENT_H 0 #endif +#ifndef HAVE_DUPWIN +#define HAVE_DUPWIN 1 +#endif + #ifndef HAVE_ERRNO #define HAVE_ERRNO 0 #endif +#ifndef HAVE_EXIT_CURSES +#define HAVE_EXIT_CURSES 1 +#endif + +#ifndef HAVE_EXIT_TERMINFO +#define HAVE_EXIT_TERMINFO 1 +#endif + #ifndef HAVE_FCNTL_H #define HAVE_FCNTL_H 0 #endif @@ -95,6 +159,14 @@ #define HAVE_FORM_H 0 #endif +#ifndef HAVE_FPATHCONF +#define HAVE_FPATHCONF 0 +#endif + +#ifndef HAVE_GETAUXVAL +#define HAVE_GETAUXVAL 0 +#endif + #ifndef HAVE_GETBEGX #define HAVE_GETBEGX 1 #endif @@ -139,6 +211,10 @@ #define HAVE_GETTTYNAM 0 #endif +#ifndef HAVE_GETUID +#define HAVE_GETUID 0 +#endif + #ifndef HAVE_GETWIN #define HAVE_GETWIN 1 #endif @@ -155,10 +231,22 @@ #define HAVE_GXX_BUILTIN_H 0 #endif +#ifndef HAVE_HALFDELAY +#define HAVE_HALFDELAY 1 +#endif + #ifndef HAVE_HAS_KEY #define HAVE_HAS_KEY 0 #endif +#ifndef HAVE_INIT_EXTENDED_COLOR +#define HAVE_INIT_EXTENDED_COLOR 0 +#endif + +#ifndef HAVE_INTTYPES_H +#define HAVE_INTTYPES_H 0 +#endif + #ifndef HAVE_IOSTREAM #define HAVE_IOSTREAM 0 #endif @@ -207,6 +295,10 @@ #define HAVE_LIBPANEL 0 #endif +#ifndef HAVE_LIB_PCRE2 +#define HAVE_LIB_PCRE2 0 +#endif + #ifndef HAVE_LIMITS_H #define HAVE_LIMITS_H 0 #endif @@ -215,6 +307,10 @@ #define HAVE_LINK 0 #endif +#ifndef HAVE_LOCALECONV +#define HAVE_LOCALECONV 0 +#endif + #ifndef HAVE_LOCALE_H #define HAVE_LOCALE_H 0 #endif @@ -223,6 +319,14 @@ #define HAVE_LONG_FILE_NAMES 0 #endif +#ifndef HAVE_MATH_FUNCS +#define HAVE_MATH_FUNCS 0 +#endif + +#ifndef HAVE_MATH_H +#define HAVE_MATH_H 0 +#endif + #ifndef HAVE_MBLEN #define HAVE_MBLEN 0 #endif @@ -255,10 +359,18 @@ #define HAVE_MKSTEMP 0 #endif +#ifndef HAVE_MVDERWIN +#define HAVE_MVDERWIN 1 +#endif + #ifndef HAVE_MVVLINE #define HAVE_MVVLINE 1 #endif +#ifndef HAVE_MVWIN +#define HAVE_MVWIN 1 +#endif + #ifndef HAVE_MVWVLINE #define HAVE_MVWVLINE 1 #endif @@ -267,14 +379,34 @@ #define HAVE_NANOSLEEP 0 #endif +#ifndef HAVE_NAPMS +#define HAVE_NAPMS 1 +#endif + #ifndef HAVE_NC_ALLOC_H #define HAVE_NC_ALLOC_H 0 #endif +#ifndef HAVE_NEWPAD +#define HAVE_NEWPAD 1 +#endif + #ifndef HAVE_PANEL_H #define HAVE_PANEL_H 0 #endif +#ifndef HAVE_PATH_TTYS +#define HAVE_PATH_TTYS 0 +#endif + +#ifndef HAVE_PCRE2POSIX_H +#define HAVE_PCRE2POSIX_H 0 +#endif + +#ifndef HAVE_PCREPOSIX_H +#define HAVE_PCREPOSIX_H 0 +#endif + #ifndef HAVE_POLL #define HAVE_POLL 0 #endif @@ -287,6 +419,10 @@ #define HAVE_PURIFY 0 #endif +#ifndef HAVE_PUTENV +#define HAVE_PUTENV 0 +#endif + #ifndef HAVE_PUTWC #define HAVE_PUTWC 0 #endif @@ -311,6 +447,10 @@ #define HAVE_REMOVE 0 #endif +#ifndef HAVE_RESET_COLOR_PAIRS +#define HAVE_RESET_COLOR_PAIRS 0 +#endif + #ifndef HAVE_RESIZETERM #define HAVE_RESIZETERM 0 #endif @@ -319,10 +459,18 @@ #define HAVE_RESIZE_TERM 0 #endif +#ifndef HAVE_RESTARTTERM +#define HAVE_RESTARTTERM 1 +#endif + #ifndef HAVE_RIPOFFLINE #define HAVE_RIPOFFLINE 1 #endif +#ifndef HAVE_SCR_DUMP +#define HAVE_SCR_DUMP 1 +#endif + #ifndef HAVE_SELECT #define HAVE_SELECT 0 #endif @@ -335,6 +483,14 @@ #define HAVE_SETBUFFER 0 #endif +#ifndef HAVE_SETENV +#define HAVE_SETENV 0 +#endif + +#ifndef HAVE_SETFSUID +#define HAVE_SETFSUID 0 +#endif + #ifndef HAVE_SETUPTERM #define HAVE_SETUPTERM 1 #endif @@ -343,6 +499,10 @@ #define HAVE_SETVBUF 0 #endif +#ifndef HAVE_SGTTY_H +#define HAVE_SGTTY_H 0 +#endif + #ifndef HAVE_SIGACTION #define HAVE_SIGACTION 0 #endif @@ -363,10 +523,26 @@ #define HAVE_SLK_INIT 1 #endif +#ifndef HAVE_SNPRINTF +#define HAVE_SNPRINTF 0 +#endif + +#ifndef HAVE_STDINT_H +#define HAVE_STDINT_H 0 +#endif + #ifndef HAVE_STRDUP #define HAVE_STRDUP 0 #endif +#ifndef HAVE_STRLCAT +#define HAVE_STRLCAT 0 +#endif + +#ifndef HAVE_STRLCPY +#define HAVE_STRLCPY 0 +#endif + #ifndef HAVE_STRSTR #define HAVE_STRSTR 0 #endif @@ -375,10 +551,18 @@ #define HAVE_SYMLINK 0 #endif +#ifndef HAVE_SYSCONF +#define HAVE_SYSCONF 0 +#endif + #ifndef HAVE_SYS_BSDTYPES_H #define HAVE_SYS_BSDTYPES_H 0 #endif +#ifndef HAVE_SYS_AUXV_H +#define HAVE_SYS_AUXV_H 0 +#endif + #ifndef HAVE_SYS_IOCTL_H #define HAVE_SYS_IOCTL_H 0 #endif @@ -427,6 +611,10 @@ #define HAVE_TERMATTRS 1 #endif +#ifndef HAVE_TERMCAP_H +#define HAVE_TERMCAP_H 1 +#endif + #ifndef HAVE_TERMIOS_H #define HAVE_TERMIOS_H 0 #endif @@ -439,6 +627,10 @@ #define HAVE_TERMNAME 1 #endif +#ifndef HAVE_TERM_ENTRY_H +#define HAVE_TERM_ENTRY_H 1 +#endif + #ifndef HAVE_TERM_H #define HAVE_TERM_H 1 #endif @@ -455,12 +647,28 @@ #define HAVE_TIGETSTR 1 #endif +#ifndef HAVE_TIPARM +#define HAVE_TIPARM 1 +#endif + +#ifndef HAVE_TIPARM_S +#define HAVE_TIPARM_S 1 +#endif + +#ifndef HAVE_TISCAN_S +#define HAVE_TISCAN_S 1 +#endif + #ifndef HAVE_TIMES #define HAVE_TIMES 0 #endif -#ifndef HAVE_TTYENT_H -#define HAVE_TTYENT_H 0 +#ifndef HAVE_TPUTS_SP +#define HAVE_TPUTS_SP 0 +#endif + +#ifndef HAVE_TSEARCH +#define HAVE_TSEARCH 0 #endif #ifndef HAVE_TYPEAHEAD @@ -479,6 +687,14 @@ #define HAVE_TYPE_SIGACTION 0 #endif +#ifndef HAVE_UNCTRL_H +#define HAVE_UNCTRL_H 1 +#endif + +#ifndef HAVE_UNGET_WCH +#define HAVE_UNGET_WCH 1 +#endif + #ifndef HAVE_UNISTD_H #define HAVE_UNISTD_H 0 #endif @@ -491,10 +707,34 @@ #define HAVE_USE_DEFAULT_COLORS 0 #endif +#ifndef HAVE_USE_ENV +#define HAVE_USE_ENV 1 +#endif + +#ifndef HAVE_USE_EXTENDED_NAMES +#define HAVE_USE_EXTENDED_NAMES NCURSES_XNAMES +#endif + +#ifndef HAVE_USE_SCREEN +#define HAVE_USE_SCREEN 0 +#endif + +#ifndef HAVE_USE_WINDOW +#define HAVE_USE_WINDOW 0 +#endif + #ifndef HAVE_VFSCANF #define HAVE_VFSCANF 0 #endif +#ifndef HAVE_VIDPUTS +#define HAVE_VIDPUTS 1 +#endif + +#ifndef HAVE_VID_PUTS +#define HAVE_VID_PUTS 1 +#endif + #ifndef HAVE_VSNPRINTF #define HAVE_VSNPRINTF 0 #endif @@ -503,6 +743,14 @@ #define HAVE_VSSCANF 0 #endif +#ifndef HAVE_VW_PRINTW +#define HAVE_VW_PRINTW 1 +#endif + +#ifndef HAVE_WCHGAT +#define HAVE_WCHGAT 1 +#endif + #ifndef HAVE_WCSRTOMBS #define HAVE_WCSRTOMBS 0 #endif @@ -523,10 +771,18 @@ #define HAVE_WCTYPE_H 0 #endif +#ifndef HAVE_WINSDELLN +#define HAVE_WINSDELLN 1 +#endif + #ifndef HAVE_WINSSTR #define HAVE_WINSSTR 1 #endif +#ifndef HAVE_WMEMCHR +#define HAVE_WMEMCHR 0 +#endif + #ifndef HAVE_WORKING_POLL #define HAVE_WORKING_POLL 0 #endif @@ -535,10 +791,22 @@ #define HAVE_WRESIZE 0 #endif +#ifndef HAVE_WSYNCDOWN +#define HAVE_WSYNCDOWN 1 +#endif + #ifndef HAVE__DOSCAN #define HAVE__DOSCAN 0 #endif +#ifndef HAVE__TRACEF +#define HAVE__TRACEF 0 +#endif + +#ifndef HAVE__NC_TPARM_ANALYZE +#define HAVE__NC_TPARM_ANALYZE 1 +#endif + #ifndef MIXEDCASE_FILENAMES #define MIXEDCASE_FILENAMES 0 #endif @@ -559,16 +827,24 @@ #define NCURSES_EXT_FUNCS 0 #endif +#ifndef NCURSES_EXT_PUTWIN +#define NCURSES_EXT_PUTWIN 0 +#endif + #ifndef NCURSES_NO_PADDING #define NCURSES_NO_PADDING 0 #endif +#ifndef NCURSES_OSPEED_COMPAT +#define NCURSES_OSPEED_COMPAT 0 +#endif + #ifndef NCURSES_PATHSEP #define NCURSES_PATHSEP ':' #endif -#ifndef NDEBUG -#define NDEBUG 0 +#ifndef NCURSES_WIDECHAR +#define NCURSES_WIDECHAR 0 #endif #ifndef NEED_PTEM_H @@ -583,10 +859,6 @@ #define PURE_TERMINFO 0 #endif -#ifndef RETSIGTYPE -#define RETSIGTYPE 0 -#endif - #ifndef STDC_HEADERS #define STDC_HEADERS 0 #endif @@ -623,8 +895,8 @@ #define USE_COLORFGBG 0 #endif -#ifndef USE_DATABASE -#define USE_DATABASE 0 +#ifndef USE_FOPEN_BIN_R +#define USE_FOPEN_BIN_R 0 #endif #ifndef USE_GETCAP @@ -663,6 +935,10 @@ #define USE_OK_BCOPY 0 #endif +#ifndef USE_PTHREADS_EINTR +#define USE_PTHREADS_EINTR 0 +#endif + #ifndef USE_RCS_IDS #define USE_RCS_IDS 0 #endif @@ -683,6 +959,10 @@ #define USE_SIGWINCH 0 #endif +#ifndef USE_STRING_HACKS +#define USE_STRING_HACKS 0 +#endif + #ifndef USE_SYMLINKS #define USE_SYMLINKS 0 #endif @@ -691,10 +971,6 @@ #define USE_SYSMOUSE 0 #endif -#ifndef USE_TERMCAP -#define USE_TERMCAP 0 -#endif - #ifndef USE_WEAK_SYMBOLS #define USE_WEAK_SYMBOLS 0 #endif diff --git a/lib/libcurses/ncurses_dll.h b/lib/libcurses/ncurses_dll.h new file mode 100644 index 00000000000..97c72fbaaae --- /dev/null +++ b/lib/libcurses/ncurses_dll.h @@ -0,0 +1,103 @@ +/**************************************************************************** + * Copyright 2018-2020,2023 Thomas E. Dickey * + * Copyright 2009,2014 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ +/* $Id: ncurses_dll.h,v 1.1 2023/10/17 09:52:08 nicm Exp $ */ + +#ifndef NCURSES_DLL_H_incl +#define NCURSES_DLL_H_incl 1 + +/* + * MinGW gcc (unlike MSYS2 and Cygwin) should define _WIN32 and possibly _WIN64. + */ +#if defined(__MINGW64__) + +#ifndef _WIN64 +#define _WIN64 1 +#endif + +#elif defined(__MINGW32__) + +#ifndef _WIN32 +#define _WIN32 1 +#endif + +/* 2014-08-02 workaround for broken MinGW compiler. + * Oddly, only TRACE is mapped to trace - the other -D's are okay. + * suggest TDM as an alternative. + */ +#if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) + +#ifdef trace +#undef trace +#define TRACE +#endif + +#endif /* broken compiler */ + +#endif /* MingW */ + +/* + * For reentrant code, we map the various global variables into SCREEN by + * using functions to access them. + */ +#define NCURSES_PUBLIC_VAR(name) _nc_##name + +#if defined(BUILDING_NCURSES) +# define NCURSES_IMPEXP NCURSES_EXPORT_GENERAL_EXPORT +#else +# define NCURSES_IMPEXP NCURSES_EXPORT_GENERAL_IMPORT +#endif + +#define NCURSES_WRAPPED_VAR(type,name) extern NCURSES_IMPEXP type NCURSES_PUBLIC_VAR(name)(void) + +#define NCURSES_EXPORT(type) NCURSES_IMPEXP type NCURSES_API +#define NCURSES_EXPORT_VAR(type) NCURSES_IMPEXP type + +/* + * These symbols hide dllimport/dllexport, for compilers which care about it. + */ +#if defined(__CYGWIN__) || (defined(_WIN32) || defined(_WIN64)) +# if defined(NCURSES_STATIC) /* "static" here only implies "not-a-DLL" */ +# define NCURSES_EXPORT_GENERAL_IMPORT +# define NCURSES_EXPORT_GENERAL_EXPORT +# else +# define NCURSES_EXPORT_GENERAL_IMPORT __declspec(dllimport) +# define NCURSES_EXPORT_GENERAL_EXPORT __declspec(dllexport) +# endif +# define NCURSES_API __cdecl +#else +# define NCURSES_EXPORT_GENERAL_IMPORT +# if (__GNUC__ >= 4) && !defined(__cplusplus) +# define NCURSES_EXPORT_GENERAL_EXPORT __attribute__((visibility ("default"))) +# else +# define NCURSES_EXPORT_GENERAL_EXPORT +# endif +# define NCURSES_API /* FIXME: __attribute__ ((cdecl)) is only available on x86 */ +#endif + +#endif /* NCURSES_DLL_H_incl */ diff --git a/lib/libcurses/new_pair.3 b/lib/libcurses/new_pair.3 new file mode 100644 index 00000000000..ab8ab4624bd --- /dev/null +++ b/lib/libcurses/new_pair.3 @@ -0,0 +1,165 @@ +.\"*************************************************************************** +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 2017 Free Software Foundation, Inc. * +.\" * +.\" Permission is hereby granted, free of charge, to any person obtaining a * +.\" copy of this software and associated documentation files (the * +.\" "Software"), to deal in the Software without restriction, including * +.\" without limitation the rights to use, copy, modify, merge, publish, * +.\" distribute, distribute with modifications, sublicense, and/or sell * +.\" copies of the Software, and to permit persons to whom the Software is * +.\" furnished to do so, subject to the following conditions: * +.\" * +.\" The above copyright notice and this permission notice shall be included * +.\" in all copies or substantial portions of the Software. * +.\" * +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * +.\" IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * +.\" DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * +.\" OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * +.\" THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +.\" * +.\" Except as contained in this notice, the name(s) of the above copyright * +.\" holders shall not be used in advertising or otherwise to promote the * +.\" sale, use or other dealings in this Software without prior written * +.\" authorization. * +.\"*************************************************************************** +.\" +.\" Author: Thomas E. Dickey +.\" +.\" $Id: new_pair.3,v 1.1 2023/10/17 09:52:08 nicm Exp $ +.TH new_pair 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.de NS +.ie n .sp +.el .sp .5 +.ie n .in +4 +.el .in +2 +.nf +.ft CR \" Courier +.. +.de NE +.fi +.ft R +.ie n .in -4 +.el .in -2 +.. +.SH NAME +\fBalloc_pair\fP, +\fBfind_pair\fP, +\fBfree_pair\fP \- new curses color-pair functions +.SH SYNOPSIS +\fB#include \fP +.sp +\fBint alloc_pair(int \fIfg\fB, int \fIbg\fB);\fR +.br +\fBint find_pair(int \fIfg\fB, int \fIbg\fB);\fR +.br +\fBint free_pair(int \fIpair\fB);\fR +.SH DESCRIPTION +These functions are an extension to the curses library. +They permit an application to dynamically allocate a color pair using +the foreground/background colors rather than assign a fixed color pair number, +and return an unused pair to the pool. +.PP +The number of colors may be related to the number of possible color +pairs for a given terminal, or it may not: +.bP +While almost all terminals allow setting the color \fIattributes\fP +independently, +it is unlikely that your terminal allows you to modify the attributes +of a given character cell without rewriting it. +That is, the foreground and background colors are applied as a pair. +.bP +Color pairs are the curses library's way of managing a color palette +on a terminal. +If the library does not keep track of the \fIcombinations\fP of +colors which are displayed, it will be inefficient. +.bP +For simple terminal emulators +with only a few dozen color combinations, +it is convenient to use the maximum number of combinations +as the limit on color pairs: +.NS +\fBCOLORS\fI * \fBCOLORS\fR +.NE +.bP +Terminals which support \fIdefault colors\fP distinct +from \*(``ANSI colors\*('' +add to the possible combinations, producing this total: +.NS +\fI( \fBCOLORS\fI + 1 ) * ( \fBCOLORS\fI + 1 )\fR +.NE +.bP +An application might use up to a few dozen color pairs to +implement a predefined color scheme. +.IP +Beyond that lies in the realm of programs using the foreground +and background colors for \*(``ASCII art\*('' +(or some other non-textual application). +.IP +Also beyond those few dozen pairs, the required size for a table +to represent the combinations grows rapidly with an increasing number of colors. +.IP +These functions allow a developer to let the screen library +manage color pairs. +.SS alloc_pair +The \fBalloc_pair\fP function accepts parameters for +foreground and background color, and +checks if that color combination is already associated with a color pair. +.bP +If the combination already exists, +\fBalloc_pair\fP returns the existing pair. +.bP +If the combination does not exist, +\fBalloc_pair\fP allocates a new color pair and returns that. +.bP +If the table fills up, \fBalloc_pair\fP discards the least-recently +allocated entry using \fBfree_pair\fP and allocates a new color pair. +.PP +All of the color pairs are allocated from a table of possible color pairs. +The size of the table is determined by the terminfo \fBpairs\fP capability. +The table is shared with \fBinit_pair\fP; +in fact \fBalloc_pair\fP calls \fBinit_pair\fP after +updating the ncurses library's fast index to the colors versus color pairs. +.SS find_pair +The \fBfind_pair\fP function accepts parameters for +foreground and background color, and +checks if that color combination is already associated with a color pair, +returning the pair number if it has been allocated. +Otherwise it returns \-1. +.SS free_pair +Marks the given color pair as unused, +i.e., like color pair 0. +.SH RETURN VALUE +The \fBalloc_pair\fP function returns a color pair number in the range +1 through \fBCOLOR_PAIRS\fP\-1, unless it encounters an error updating +its fast index to the color pair values, preventing it from allocating +a color pair. +In that case, it returns \-1. +.PP +The \fBfind_pair\fP function returns a color pair number if the +given color combination has been associated with a color pair, +or \-1 if not. +.PP +Likewise, \fBfree_pair\fP returns \fBOK\fP unless it encounters an +error updating the fast index or if no such color pair is in use. +.SH PORTABILITY +These routines are specific to ncurses. +They were not supported on +Version 7, BSD or System V implementations. +It is recommended that +any code depending on them be conditioned using NCURSES_VERSION. +.SH SEE ALSO +\fBcurs_color\fP(3). +.SH AUTHOR +Thomas Dickey. diff --git a/lib/libcurses/new_pair.h b/lib/libcurses/new_pair.h new file mode 100644 index 00000000000..e43c48950f1 --- /dev/null +++ b/lib/libcurses/new_pair.h @@ -0,0 +1,139 @@ +/**************************************************************************** + * Copyright 2018-2020,2021 Thomas E. Dickey * + * Copyright 2017 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey * + ****************************************************************************/ + +/* + * Common type definitions and macros for new_pair.c, lib_color.c + * + * $Id: new_pair.h,v 1.1 2023/10/17 09:52:08 nicm Exp $ + */ + +#ifndef NEW_PAIR_H +#define NEW_PAIR_H 1 +/* *INDENT-OFF* */ + +#include +#include + +#include + +#undef SCREEN +#define SCREEN struct screen +SCREEN; + +#define LIMIT_TYPED(n,t) \ + (t)(((n) > MAX_OF_TYPE(t)) \ + ? MAX_OF_TYPE(t) \ + : ((n) < -MAX_OF_TYPE(t)) \ + ? -MAX_OF_TYPE(t) \ + : (n)) + +#define limit_COLOR(n) LIMIT_TYPED(n,NCURSES_COLOR_T) +#define limit_PAIRS(n) LIMIT_TYPED(n,NCURSES_PAIRS_T) + +#define MAX_XCURSES_PAIR MAX_OF_TYPE(NCURSES_PAIRS_T) + +#if NCURSES_EXT_COLORS +#define OPTIONAL_PAIR GCC_UNUSED +#define get_extended_pair(opts, color_pair) \ + if ((opts) != NULL) { \ + *(int*)(opts) = color_pair; \ + } +#define set_extended_pair(opts, color_pair) \ + if ((opts) != NULL) { \ + color_pair = *(const int*)(opts); \ + } +#else +#define OPTIONAL_PAIR /* nothing */ +#define get_extended_pair(opts, color_pair) /* nothing */ +#define set_extended_pair(opts, color_pair) \ + if ((opts) != NULL) { \ + color_pair = -1; \ + } +#endif + +#ifdef NEW_PAIR_INTERNAL + +typedef enum { + cpKEEP = -1, /* color pair 0 */ + cpFREE = 0, /* free for use */ + cpINIT = 1 /* initialized */ +} CPMODE; + +typedef struct _color_pairs +{ + int fg; + int bg; +#if NCURSES_EXT_COLORS + int mode; /* tells if the entry is allocated or free */ + int prev; /* index of previous item */ + int next; /* index of next item */ +#endif +} +colorpair_t; + +#define MakeColorPair(target,f,b) target.fg = f, target.bg = b +#define isSamePair(a,b) ((a).fg == (b).fg && (a).bg == (b).bg) +#define FORE_OF(c) (c).fg +#define BACK_OF(c) (c).bg + +/* + * Ensure that we use color pairs only when colors have been started, and also + * that the index is within the limits of the table which we allocated. + */ +#define ValidPair(sp,pair) \ + ((sp != 0) && (pair >= 0) && (pair < sp->_pair_limit) && sp->_coloron) + +#if NCURSES_EXT_COLORS +extern NCURSES_EXPORT(void) _nc_copy_pairs(SCREEN*, colorpair_t*, colorpair_t*, int); +extern NCURSES_EXPORT(void) _nc_free_ordered_pairs(SCREEN*); +extern NCURSES_EXPORT(void) _nc_reset_color_pair(SCREEN*, int, colorpair_t*); +extern NCURSES_EXPORT(void) _nc_set_color_pair(SCREEN*, int, int); +#else +#define _nc_free_ordered_pairs(sp) /* nothing */ +#define _nc_reset_color_pair(sp, pair, data) /* nothing */ +#define _nc_set_color_pair(sp, pair, mode) /* nothing */ +#endif + +#else + +typedef struct _color_pairs colorpair_t; + +#endif /* NEW_PAIR_INTERNAL */ + +#if NO_LEAKS +extern NCURSES_EXPORT(void) _nc_new_pair_leaks(SCREEN*); +#endif + +/* *INDENT-ON* */ + +#endif /* NEW_PAIR_H */ diff --git a/lib/libcurses/parametrized.h b/lib/libcurses/parametrized.h index 9d40a537a1b..8a435eae276 100644 --- a/lib/libcurses/parametrized.h +++ b/lib/libcurses/parametrized.h @@ -1,5 +1,7 @@ -/* $OpenBSD: parametrized.h,v 1.3 2010/01/12 23:21:59 nicm Exp $ */ +/* $OpenBSD: parametrized.h,v 1.4 2023/10/17 09:52:08 nicm Exp $ */ +#ifndef PARAMETRIZED_H +#define PARAMETRIZED_H 1 /* * parametrized.h --- is a termcap capability parametrized? * @@ -283,7 +285,7 @@ static short const parametrized[] = { 0, /* mgc */ 0, /* smgl */ 0, /* smgr */ -0, /* fln */ +-1, /* fln */ 1, /* sclk */ 0, /* dclk */ 0, /* rmclk */ @@ -423,140 +425,7 @@ static short const parametrized[] = { -1, /* OTGC */ 0, /* meml */ 0, /* memu */ -1, /* pln */ -0, /* smln */ -0, /* rmln */ -0, /* kf11 */ -0, /* kf12 */ -0, /* kf13 */ -0, /* kf14 */ -0, /* kf15 */ -0, /* kf16 */ -0, /* kf17 */ -0, /* kf18 */ -0, /* kf19 */ -0, /* kf20 */ -0, /* kf21 */ -0, /* kf22 */ -0, /* kf23 */ -0, /* kf24 */ -0, /* kf25 */ -0, /* kf26 */ -0, /* kf27 */ -0, /* kf28 */ -0, /* kf29 */ -0, /* kf30 */ -0, /* kf31 */ -0, /* kf32 */ -0, /* kf33 */ -0, /* kf34 */ -0, /* kf35 */ -0, /* kf36 */ -0, /* kf37 */ -0, /* kf38 */ -0, /* kf39 */ -0, /* kf40 */ -0, /* kf41 */ -0, /* kf42 */ -0, /* kf43 */ -0, /* kf44 */ -0, /* kf45 */ -0, /* kf46 */ -0, /* kf47 */ -0, /* kf48 */ -0, /* kf49 */ -0, /* kf50 */ -0, /* kf51 */ -0, /* kf52 */ -0, /* kf53 */ -0, /* kf54 */ -0, /* kf55 */ -0, /* kf56 */ -0, /* kf57 */ -0, /* kf58 */ -0, /* kf59 */ -0, /* kf60 */ -0, /* kf61 */ -0, /* kf62 */ -0, /* kf63 */ 0, /* box1 */ -0, /* box2 */ -0, /* batt1 */ -0, /* batt2 */ -0, /* colb0 */ -0, /* colb1 */ -0, /* colb2 */ -0, /* colb3 */ -0, /* colb4 */ -0, /* colb5 */ -0, /* colb6 */ -0, /* colb7 */ -0, /* colf0 */ -0, /* colf1 */ -0, /* colf2 */ -0, /* colf3 */ -0, /* colf4 */ -0, /* colf5 */ -0, /* colf6 */ -0, /* colf7 */ -0, /* font0 */ -0, /* font1 */ -0, /* font2 */ -0, /* font3 */ -0, /* font4 */ -0, /* font5 */ -0, /* font6 */ -0, /* font7 */ -0, /* kbtab */ -0, /* kdo */ -0, /* kcmd */ -0, /* kcpn */ -0, /* kend */ -0, /* khlp */ -0, /* knl */ -0, /* knpn */ -0, /* kppn */ -0, /* kppn */ -0, /* kquit */ -0, /* ksel */ -0, /* kscl */ -0, /* kscr */ -0, /* ktab */ -0, /* kmpf1 */ -0, /* kmpt1 */ -0, /* kmpf2 */ -0, /* kmpt2 */ -0, /* kmpf3 */ -0, /* kmpt3 */ -0, /* kmpf4 */ -0, /* kmpt4 */ -0, /* kmpf5 */ -0, /* kmpt5 */ -0, /* apstr */ -0, /* kmpf6 */ -0, /* kmpt6 */ -0, /* kmpf7 */ -0, /* kmpt7 */ -0, /* kmpf8 */ -0, /* kmpt8 */ -0, /* kmpf9 */ -0, /* kmpt9 */ -0, /* ksf1 */ -0, /* ksf2 */ -0, /* ksf3 */ -0, /* ksf4 */ -0, /* ksf5 */ -0, /* ksf6 */ -0, /* ksf7 */ -0, /* ksf8 */ -0, /* ksf9 */ -0, /* ksf10 */ -0, /* kf11 */ -0, /* kf12 */ -0, /* kact */ -0, /* topl */ -0, /* btml */ -0, /* rvert */ -0, /* lvert */ -} /* 548 entries */; +} /* 414 entries */; +#endif /* PARAMETRIZED_H */ diff --git a/lib/libcurses/report_hashing.c b/lib/libcurses/report_hashing.c new file mode 100644 index 00000000000..f01ccbc1d1a --- /dev/null +++ b/lib/libcurses/report_hashing.c @@ -0,0 +1,73 @@ +/**************************************************************************** + * Copyright 2020 Thomas E. Dickey * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey * + ****************************************************************************/ + +#include +#include + +MODULE_ID("$Id: report_hashing.c,v 1.1 2023/10/17 09:52:08 nicm Exp $") + +static void +check_names(const char *name, NCURSES_CONST char *const *table, int termcap) +{ + int errs = 0; + int n; + struct name_table_entry const *entry_ptr; + const HashValue *hash_table = _nc_get_hash_table(termcap); + + printf("%s:\n", name); + for (n = 0; table[n] != NULL; ++n) { + entry_ptr = _nc_find_entry(table[n], hash_table); + if (entry_ptr == 0) { + printf(" %s\n", table[n]); + errs++; + } + } + if (errs) + printf("%d errors\n", errs); +} + +int +main(void) +{ +#define CHECK_TI(name) check_names(#name, name, 0) +#define CHECK_TC(name) check_names(#name, name, 1) + + CHECK_TI(boolnames); + CHECK_TI(numnames); + CHECK_TI(strnames); + + CHECK_TC(boolcodes); + CHECK_TC(numcodes); + CHECK_TC(strcodes); + + return EXIT_SUCCESS; +} diff --git a/lib/libcurses/report_offsets.c b/lib/libcurses/report_offsets.c new file mode 100644 index 00000000000..9560893a1e0 --- /dev/null +++ b/lib/libcurses/report_offsets.c @@ -0,0 +1,250 @@ +/**************************************************************************** + * Copyright 2018-2020,2021 Thomas E. Dickey * + * Copyright 2017 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey * + ****************************************************************************/ + +#include + +MODULE_ID("$Id: report_offsets.c,v 1.1 2023/10/17 09:52:08 nicm Exp $") + +#define show_size(type) \ + flag = 0; \ + last = 0; \ + printf("%5lu " #type "\n", (unsigned long)sizeof(type)) +#define show_offset(type,member) \ + next = (unsigned long)offsetof(type,member); \ + if (last > next) \ + printf("?? incorrect order for " #type "." #member "\n"); \ + printf("%5lu %c " #type "." #member "\n", next, flag ? *flag : ' '); \ + last = next; \ + flag = 0 + +#if NCURSES_WIDECHAR && NCURSES_EXT_COLORS +#define show_COLORS(type,member) { flag = "c"; show_offset(type,member); } +#else +#define show_COLORS(type,member) /* nothing */ +#endif + +#ifdef USE_TERM_DRIVER +#define show_DRIVER(type,member) { flag = "d"; show_offset(type,member); } +#else +#define show_DRIVER(type,member) /* nothing */ +#endif + +#if NO_LEAKS +#define show_MLEAKS(type,member) { flag = "L"; show_offset(type,member); } +#else +#define show_MLEAKS(type,member) /* nothing */ +#endif + +#ifdef USE_TERM_DRIVER +#define show_NORMAL(type,member) /* nothing */ +#else +#define show_NORMAL(type,member) { flag = "n"; show_offset(type,member); } +#endif + +#define show_OPTION(type,member) { flag = "+"; show_offset(type,member); } + +#if USE_REENTRANT +#define show_REENTR(type,member) { flag = "r"; show_offset(type,member); } +#else +#define show_REENTR(type,member) /* nothing */ +#endif + +#if NCURSES_SP_FUNCS +#define show_SPFUNC(type,member) { flag = "s"; show_offset(type,member); } +#else +#define show_SPFUNC(type,member) /* nothing */ +#endif + +#ifdef USE_PTHREADS +#define show_THREAD(type,member) { flag = "t"; show_offset(type,member); } +#else +#define show_THREAD(type,member) /* nothing */ +#endif + +#ifdef TRACE +#define show_TRACES(type,member) { flag = "T"; show_offset(type,member); } +#else +#define show_TRACES(type,member) /* nothing */ +#endif + +#if USE_WIDEC_SUPPORT +#define show_WIDECH(type,member) { flag = "w"; show_offset(type,member); } +#else +#define show_WIDECH(type,member) /* nothing */ +#endif + +int +main(void) +{ + const char *flag = 0; + unsigned long last, next; + + printf("Size/offsets of data structures:\n"); + + show_size(attr_t); + show_size(chtype); +#if USE_WIDEC_SUPPORT + show_size(cchar_t); +#endif + show_size(mmask_t); + show_size(MEVENT); + show_size(NCURSES_BOOL); + + printf("\n"); + show_size(SCREEN); + show_offset(SCREEN, _ifd); + show_offset(SCREEN, _fifo); + show_offset(SCREEN, _fifohead); + show_offset(SCREEN, _direct_color); + show_offset(SCREEN, _panelHook); + show_offset(SCREEN, jump); + show_offset(SCREEN, rsp); +#if NCURSES_NO_PADDING + show_OPTION(SCREEN, _no_padding); +#endif +#if USE_HARD_TABS + show_OPTION(SCREEN, _ht_cost); +#endif +#if USE_ITALIC + show_OPTION(SCREEN, _use_ritm); +#endif +#if USE_KLIBC_KBD + show_OPTION(SCREEN, _extended_key); +#endif +#if NCURSES_EXT_FUNCS + show_OPTION(SCREEN, _assumed_color); +#endif +#if USE_GPM_SUPPORT + show_OPTION(SCREEN, _mouse_gpm_loaded); +#ifdef HAVE_LIBDL + show_OPTION(SCREEN, _dlopen_gpm); +#endif +#endif +#if USE_EMX_MOUSE + show_OPTION(SCREEN, _emxmouse_wfd); +#endif +#if USE_SYSMOUSE + show_OPTION(SCREEN, _sysmouse_fifo); +#endif + show_DRIVER(SCREEN, _drv_mouse_fifo); +#if USE_SIZECHANGE + show_OPTION(SCREEN, _resize); +#endif + show_DRIVER(SCREEN, _windowlist); + show_REENTR(SCREEN, _ttytype); + show_SPFUNC(SCREEN, use_tioctl); + show_WIDECH(SCREEN, _screen_acs_fix); + show_COLORS(SCREEN, _ordered_pairs); + show_TRACES(SCREEN, tracechr_buf); + + printf("\n"); + show_size(TERMINAL); + show_offset(TERMINAL, type); + show_offset(TERMINAL, Filedes); + show_offset(TERMINAL, Ottyb); + show_offset(TERMINAL, Nttyb); + show_offset(TERMINAL, _baudrate); + show_offset(TERMINAL, _termname); + show_offset(TERMINAL, tparm_state); +#if HAVE_INIT_EXTENDED_COLOR + show_COLORS(TERMINAL, type2); +#endif + + printf("\n"); + show_size(TERMTYPE); +#if NCURSES_XNAMES + show_OPTION(TERMTYPE, ext_str_table); + show_OPTION(TERMTYPE, ext_Strings); +#endif + + printf("\n"); + show_size(TPARM_STATE); + show_offset(TPARM_STATE, stack); + show_offset(TPARM_STATE, stack_ptr); + show_offset(TPARM_STATE, out_buff); + show_offset(TPARM_STATE, fmt_buff); + show_offset(TPARM_STATE, static_vars); + show_TRACES(TPARM_STATE, tname); + + printf("\n"); + show_size(WINDOW); + show_WIDECH(WINDOW, _bkgrnd); + show_COLORS(WINDOW, _color); + + printf("\n"); + show_size(NCURSES_GLOBALS); + show_offset(NCURSES_GLOBALS, init_signals); + show_offset(NCURSES_GLOBALS, tgetent_cache); + show_offset(NCURSES_GLOBALS, dbd_vars); +#if HAVE_TSEARCH + show_offset(NCURSES_GLOBALS, cached_tparm); +#endif + show_DRIVER(NCURSES_GLOBALS, term_driver); + show_NORMAL(NCURSES_GLOBALS, _nc_windowlist); +#if USE_HOME_TERMINFO + show_OPTION(NCURSES_GLOBALS, home_terminfo); +#endif +#if !USE_SAFE_SPRINTF + show_OPTION(NCURSES_GLOBALS, safeprint_rows); +#endif + show_THREAD(NCURSES_GLOBALS, mutex_curses); +#if USE_PTHREADS_EINTR + show_THREAD(NCURSES_GLOBALS, read_thread); +#endif + show_WIDECH(NCURSES_GLOBALS, key_name); + show_TRACES(NCURSES_GLOBALS, trace_opened); + show_MLEAKS(NCURSES_GLOBALS, leak_checking); + + printf("\n"); + show_size(NCURSES_PRESCREEN); + show_offset(NCURSES_PRESCREEN, tparm_state); + show_offset(NCURSES_PRESCREEN, saved_tty); + show_offset(NCURSES_PRESCREEN, use_tioctl); + show_offset(NCURSES_PRESCREEN, _outch); +#ifndef USE_SP_RIPOFF + show_NORMAL(NCURSES_PRESCREEN, rippedoff); +#endif +#if NCURSES_NO_PADDING + show_OPTION(NCURSES_PRESCREEN, _no_padding); +#endif +#if BROKEN_LINKER + show_offset(NCURSES_PRESCREEN, real_acs_map); +#else + show_REENTR(NCURSES_PRESCREEN, real_acs_map); +#endif +#if BROKEN_LINKER || USE_REENTRANT + show_TRACES(NCURSES_PRESCREEN, _outchars); +#endif + + return EXIT_SUCCESS; +} diff --git a/lib/libcurses/resizeterm.3 b/lib/libcurses/resizeterm.3 index 6d2bd228694..b40a2ecafea 100644 --- a/lib/libcurses/resizeterm.3 +++ b/lib/libcurses/resizeterm.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: resizeterm.3,v 1.6 2021/03/10 20:16:08 millert Exp $ +.\" $OpenBSD: resizeterm.3,v 1.7 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2003,2005 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2015,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,73 +29,150 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" Author: Thomas E. Dickey 1996-2005 +.\" Author: Thomas E. Dickey 1996-on .\" -.\" $Id: resizeterm.3,v 1.6 2021/03/10 20:16:08 millert Exp $ -.TH resizeterm 3 "" +.\" $Id: resizeterm.3,v 1.7 2023/10/17 09:52:08 nicm Exp $ +.TH resizeterm 3 2023-07-01 "ncurses 6.4" "Library calls" +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .SH NAME -\fBis_term_resized\fR, -\fBresize_term\fR, -\fBresizeterm\fR - change the curses terminal size +\fBis_term_resized\fP, +\fBresize_term\fP, +\fBresizeterm\fP \- change the curses terminal size .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBbool is_term_resized(int lines, int columns);\fR +\fBbool is_term_resized(int \fIlines\fB, int \fIcolumns\fB);\fR .br -\fBint resize_term(int lines, int columns);\fR +\fBint resize_term(int \fIlines\fB, int \fIcolumns\fB);\fR .br -\fBint resizeterm(int lines, int columns);\fR +\fBint resizeterm(int \fIlines\fB, int \fIcolumns\fB);\fR .SH DESCRIPTION This is an extension to the curses library. -It provides callers with a hook into the \fBncurses\fR data to resize windows, -primarily for use by programs running in an X Window terminal (e.g., xterm). -The function \fBresizeterm\fR resizes the standard and current windows +It provides callers with a hook into the \fBncurses\fP data to resize windows, +primarily for use by programs running in an X Window terminal (e.g., xterm) +when the terminal's screen size is changed by the user: +.bP +Curses windows cannot extend outside the screen. +If the terminal is shrunk, curses windows must be shrunk to fit. +.bP +If the terminal is stretched, +rows and/or columns can be added to existing windows. +The added cells should match the current attributes of the windows. +.PP +If the calling program has not set up a handler for \fBSIGWINCH\fP +when it initializes \fBncurses\fP +(e.g., using \fBinitscr\fP(3) or \fBnewterm\fP(3)), +then \fBncurses\fP sets a handler for \fBSIGWINCH\fP which notifies +the library when a window-size event has occurred. +The library checks for this notification +.bP +when reading input data, +.bP +when implicitly resuming program mode +(e.g., between \fBendwin\fP(3) and \fBwrefresh\fP(3)), +and +.bP +when explicitly resuming program mode in \fBrestartterm\fP(3). +.PP +When the library has found that the terminal's window-size has +changed, it calls \fBresizeterm\fP to update its data structures. +.PP +An application which establishes its own \fBSIGWINCH\fP handler +can call \fBresizeterm\fP, but in that case, the library will not +see \fBSIGWINCH\fP, and proper layout will rely upon the application. +.SH FUNCTIONS +.SS resizeterm +The function \fBresizeterm\fP resizes the standard and current windows +(i.e., \fBstdscr\fP and \fBcurscr\fP) to the specified dimensions, and adjusts other bookkeeping data used by -the \fBncurses\fR library that record the window dimensions. -.LP -Most of the work is done by the inner function \fBresize_term\fR. -The outer function \fBresizeterm\fR adds bookkeeping for the SIGWINCH handler. -When resizing the windows, -\fBresize_term\fR blank-fills the areas that are extended. -The calling application should fill in these areas with appropriate data. -The \fBresize_term\fR function attempts to resize all windows. -However, due to the calling convention of pads, -it is not possible to resize these -without additional interaction with the application. -.LP -A support function \fBis_term_resized\fR is provided so that applications -can check if the \fBresize_term\fR function would modify the window structures. -It returns TRUE if the windows would be modified, and FALSE otherwise. +the \fBncurses\fP library that record the window dimensions +such as the \fBLINES\fP and \fBCOLS\fP variables. +.SS resize_term +Most of the work for \fBresizeterm\fP is +done by the inner function \fBresize_term\fP. +The outer function \fBresizeterm\fP adds bookkeeping +for the \fBSIGWINCH\fP handler, +as well as repainting the soft-key area (see \fBslk_touch\fP(3)). +.PP +The \fBresize_term\fP function attempts to resize all windows. +This helps with simple applications. +However: +.bP +It is not possible to automatically resize pads. +.bP +Applications which have complicated layouts should check for +\fBKEY_RESIZE\fP returned from \fBwgetch\fP, +and adjust their layout, e.g., using \fBwresize\fP and \fBmvwin\fP, +or by recreating the windows. +.PP +When resizing windows, \fBresize_term\fP recursively adjusts subwindows, +keeping them within the updated parent window's limits. +If a top-level window happens to extend to the screen's limits, +then on resizing the window, \fBresize_term\fP will keep the window +extending to the corresponding limit, regardless of whether the +screen has shrunk or grown. +.SS is_term_resized +A support function \fBis_term_resized\fP is provided so that applications +can check if the \fBresize_term\fP function would modify the window structures. +It returns \fBTRUE\fP if the windows would be modified, +and \fBFALSE\fP otherwise. .SH RETURN VALUE -Except as notes, these function return -the integer \fBERR\fR upon failure and \fBOK\fR on success. +Except as noted, these functions return +the integer \fBERR\fP upon failure and \fBOK\fP on success. They will fail if either of the dimensions are less than or equal to zero, or if an error occurs while (re)allocating memory for the windows. .SH NOTES While these functions are intended to be used to support a signal handler -(i.e., for SIGWINCH), care should be taken to avoid invoking them in a -context where \fBmalloc\fR or \fBrealloc\fR may have been interrupted, +(i.e., for \fBSIGWINCH\fP), care should be taken to avoid invoking them in a +context where \fBmalloc\fP or \fBrealloc\fP may have been interrupted, since it uses those functions. .PP -If ncurses is configured to supply its own SIGWINCH handler, -the \fBresizeterm\fR function ungetch's a \fBKEY_RESIZE\fR which -will be read on the next call to \fBgetch\fR. -This is used to alert an application that the screen size has changed, +If ncurses is configured to supply its own \fBSIGWINCH\fP handler, +.bP +on receipt of a \fBSIGWINCH\fP, the handler sets a flag +.bP +which is tested in +\fBwgetch\fP(3), +\fBdoupdate\fP(3) and +\fBrestartterm\fP(3), +.bP +in turn, calling the \fBresizeterm\fP function, +.bP +which \fBungetch\fP's a \fBKEY_RESIZE\fP which +will be read on the next call to \fBwgetch\fP. +.IP +The \fBKEY_RESIZE\fP alerts an application that the screen size has changed, and that it should repaint special features such as pads that cannot be done automatically. +.IP +Calling \fBresizeterm\fP or \fBresize_term\fP +directly from a signal handler is unsafe. +This indirect method is used to provide a safe way to resize the ncurses +data structures. .PP If the environment variables \fBLINES\fP or \fBCOLUMNS\fP are set, this overrides the library's use of the window size obtained from the operating system. -Thus, even if a SIGWINCH is received, +Thus, even if a \fBSIGWINCH\fP is received, no screen size change may be recorded. +.SH PORTABILITY +It is possible to resize the screen with SVr4 curses, +by +.bP +exiting curses with \fBendwin\fP(3) and +.bP +resuming using \fBrefresh\fP(3). +.PP +Doing that clears the screen and is visually distracting. +.PP +This extension of ncurses was introduced in mid-1995. +It was adopted in NetBSD curses (2001) and PDCurses (2003). .SH SEE ALSO -\fBwresize\fR(3). +\fBcurs_getch\fP(3), +\fBcurs_variables\fP(3), +\fBwresize\fP(3). .SH AUTHOR Thomas Dickey (from an equivalent function written in 1988 for BSD curses). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: diff --git a/lib/libcurses/scr_dump.5 b/lib/libcurses/scr_dump.5 new file mode 100644 index 00000000000..f55c70e8d22 --- /dev/null +++ b/lib/libcurses/scr_dump.5 @@ -0,0 +1,417 @@ +.\"*************************************************************************** +.\" Copyright 2018-2021,2023 Thomas E. Dickey * +.\" Copyright 2017 Free Software Foundation, Inc. * +.\" * +.\" Permission is hereby granted, free of charge, to any person obtaining a * +.\" copy of this software and associated documentation files (the * +.\" "Software"), to deal in the Software without restriction, including * +.\" without limitation the rights to use, copy, modify, merge, publish, * +.\" distribute, distribute with modifications, sublicense, and/or sell * +.\" copies of the Software, and to permit persons to whom the Software is * +.\" furnished to do so, subject to the following conditions: * +.\" * +.\" The above copyright notice and this permission notice shall be included * +.\" in all copies or substantial portions of the Software. * +.\" * +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * +.\" IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * +.\" DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * +.\" OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * +.\" THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +.\" * +.\" Except as contained in this notice, the name(s) of the above copyright * +.\" holders shall not be used in advertising or otherwise to promote the * +.\" sale, use or other dealings in this Software without prior written * +.\" authorization. * +.\"*************************************************************************** +.\" +.\" $Id: scr_dump.5,v 1.1 2023/10/17 09:52:08 nicm Exp $ +.TH scr_dump 5 2023-07-01 "ncurses 6.4" "File formats" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de NS +.ie n .sp +.el .sp .5 +.ie n .in +4 +.el .in +2 +.nf +.ft CR \" Courier +.. +.de NE +.fi +.ft R +.ie n .in -4 +.el .in -2 +.. +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.SH NAME +scr_dump \- format of curses screen-dumps. +.SH SYNOPSIS +.B scr_dump +.SH DESCRIPTION +The curses library provides applications with the ability to write the +contents of a window to an external file using \fBscr_dump\fP or \fBputwin\fP, +and read it back using \fBscr_restore\fP or \fBgetwin\fP. +.PP +The \fBputwin\fP and \fBgetwin\fP functions do the work; +while \fBscr_dump\fP and \fBscr_restore\fP conveniently save and restore +the whole screen, i.e., \fBstdscr\fP. +.SS ncurses6 +A longstanding implementation of screen-dump was +revised with ncurses6 to remedy problems with the earlier approach: +.bP +A \*(``magic number\*('' is written to the beginning of the dump file, +allowing applications (such as \fBfile\fP(1)) to recognize curses dump files. +.IP +Because ncurses6 uses a new format, +that requires a new magic number +was unused by other applications. +This 16-bit number was unused: +.NS +0x8888 (octal \*(``\\210\\210\*('') +.NE +.IP +but to be more certain, this 32-bit number was chosen: +.NS +0x88888888 (octal \*(``\\210\\210\\210\\210\*('') +.NE +.IP +This is the pattern submitted to the maintainers of the \fBfile\fP program: +.NS +# +# ncurses5 (and before) did not use a magic number, +# making screen dumps "data". +# +# ncurses6 (2015) uses this format, ignoring byte-order +0 string \\210\\210\\210\\210ncurses ncurses6 screen image +# +.NE +.bP +The screen dumps are written in textual form, +so that internal data sizes are not directly related to the dump-format, and +enabling the library to read dumps from either narrow- or wide-character- +configurations. +.IP +The \fInarrow\fP library configuration holds characters and video attributes +in a 32-bit \fBchtype\fP, while the \fIwide-character\fP library stores +this information in the \fBcchar_t\fP structure, which is much larger than +32-bits. +.bP +It is possible to read a screen dump into a terminal with a different +screen-size, +because the library truncates or fills the screen as necessary. +.bP +The ncurses6 \fBgetwin\fP reads the legacy screen dumps from ncurses5. +.SS ncurses5 (legacy) +The screen-dump feature was added to ncurses in June 1995. +While there were fixes and improvements in succeeding years, +the basic scheme was unchanged: +.bP +The \fBWINDOW\fP structure was written in binary form. +.bP +The \fBWINDOW\fP structure refers to lines of data, +which were written as an array of binary data following the \fBWINDOW\fP. +.bP +When \fBgetwin\fP restored the window, +it would keep track of offsets into the array of line-data +and adjust the \fBWINDOW\fP structure which was read back into memory. +.PP +This is similar to Unix SystemV, +but does not write a \*(``magic number\*('' to identify the file format. +.SH PORTABILITY +There is no standard format for \fBputwin\fP. +This section gives a brief description of the existing formats. +.SS X/Open Curses +Refer to \fIX/Open Curses, Issue 7\fP (2009). +.PP +X/Open's documentation for \fIenhanced curses\fP says only: +.RS 3 +.PP +The \fBgetwin(\ ) \fPfunction reads window-related data +stored in the file by \fIputwin(\ )\fP. +The function +then creates and initializes a new window using that data. +.PP +The \fBputwin(\ )\fP function writes all data associated +with \fIwin\fP into the \fBstdio\fP(3) stream to which \fIfilep\fP +points, using an \fBunspecified format\fP. +This information can be retrieved later using \fBgetwin(\ )\fP. +.RE +.PP +In the mid-1990s when the X/Open Curses document was written, +there were still systems using older, less capable curses libraries +(aside from the BSD curses library which was not relevant to X/Open +because it did not meet the criteria for \fIbase curses\fP). +The document explained the term \*(``enhanced\*('' as follows: +.RS 3 +.bP +Shading is used to identify \fIX/Open Enhanced Curses\fP material, +relating to interfaces included to provide enhanced capabilities +for applications originally written to be compiled on systems +based on the UNIX operating system. +Therefore, the features described may not be present on systems +that conform to \fBXPG4 or to earlier XPG releases\fP. +The relevant reference pages may provide additional +or more specific portability warnings about use of the material. +.RE +.PP +In the foregoing, emphasis was added to \fBunspecified format\fP +and to \fBXPG4 or to earlier XPG releases\fP, +for clarity. +.SS Unix SystemV +Unix SystemV curses identified the file format by writing a +\*(``magic number\*('' at the beginning of the dump. +The \fBWINDOW\fP data and the lines of text follow, all in binary form. +.PP +The Solaris curses source has these definitions: +.NS +/* terminfo magic number */ +#define MAGNUM 0432 + +/* curses screen dump magic number */ +#define SVR2_DUMP_MAGIC_NUMBER 0433 +#define SVR3_DUMP_MAGIC_NUMBER 0434 +.NE +.PP +That is, the feature was likely introduced in SVr2 (1984), +and improved in SVr3 (1987). +The Solaris curses source has no magic number for SVr4 (1989). +Other operating systems (AIX and HPUX) use a magic number which would +correspond to this definition: +.NS +/* curses screen dump magic number */ +#define SVR4_DUMP_MAGIC_NUMBER 0435 +.NE +.PP +That octal number in bytes is 001, 035. +Because most Unix vendors use big-endian hardware, +the magic number is written with the high-order byte first, e.g., +.NS +\001\035 +.NE +.PP +After the magic number, the \fBWINDOW\fP structure and line-data are +written in binary format. +While the magic number used by the Unix systems can be seen using \fBod\fP(1), +none of the Unix systems documents the format used for screen-dumps. +.PP +The Unix systems do not use identical formats. +While collecting information for for this manual page, +the \fIsavescreen\fP test-program +produced dumps of different size +(all on 64-bit hardware, on 40x80 screens): +.bP +AIX (51817 bytes) +.bP +HPUX (90093 bytes) +.bP +Solaris 10 (13273 bytes) +.bP +ncurses5 (12888 bytes) +.SS Solaris +As noted above, Solaris curses has no magic number corresponding +to SVr4 curses. +This is odd since Solaris was the first operating system +to pass the SVr4 guidelines. +Solaris has two versions of curses: +.bP +The default curses library uses the SVr3 magic number. +.bP +There is an alternate curses library in \fB/usr/xpg4\fP. +This uses a textual format with no magic number. +.IP +According to the copyright notice, the \fIxpg4\fP Solaris curses library was +developed by MKS (Mortice Kern Systems) from 1990 to 1995. +.IP +Like ncurses6, there is a file-header with parameters. +Unlike ncurses6, the contents of the window are written piecemeal, +with coordinates and attributes for each chunk of text rather +than writing the whole window from top to bottom. +.SS PDCurses +PDCurses added support for screen dumps in version 2.7 (2005). +Like Unix SystemV and ncurses5, +it writes the \fBWINDOW\fP structure in binary, +but begins the file with its three-byte identifier \*(``PDC\*('', +followed by a one-byte version, +e.g., +.NS + \*(``PDC\\001\*('' +.NE +.SS NetBSD +As of April 2017, NetBSD curses does +not support \fBscr_dump\fP and \fBscr_restore\fP +(or \fBscr_init\fP, \fBscr_set\fP), +although it has \fBputwin\fP and \fBgetwin\fP. +.PP +Like ncurses5, NetBSD \fBputwin\fP does not identify its dumps with a +useful magic number. +It writes +.bP +the curses shared library major and minor versions +as the first two bytes (e.g., 7 and 1), +.bP +followed by a binary dump of the \fBWINDOW\fP, +.bP +some data for wide-characters referenced by the \fBWINDOW\fP structure, and +.bP +finally, lines as done by other implementations. +.SH EXAMPLE +Given a simple program which writes text to the screen +(and for the sake of example, limiting the screen-size to 10x20): +.NS +#include + +int +main(void) +{ + putenv("LINES=10"); + putenv("COLUMNS=20"); + initscr(); + start_color(); + init_pair(1, COLOR_WHITE, COLOR_BLUE); + init_pair(2, COLOR_RED, COLOR_BLACK); + bkgd(COLOR_PAIR(1)); + move(4, 5); + attron(A_BOLD); + addstr("Hello"); + move(5, 5); + attroff(A_BOLD); + attrset(A_REVERSE | COLOR_PAIR(2)); + addstr("World!"); + refresh(); + scr_dump("foo.out"); + endwin(); + return 0; +} +.NE +.PP +When run using ncurses6, the output looks like this: +.NS +\\210\\210\\210\\210ncurses 6.0.20170415 +_cury=5 +_curx=11 +_maxy=9 +_maxx=19 +_flags=14 +_attrs=\\{REVERSE|C2} +flag=_idcok +_delay=-1 +_regbottom=9 +_bkgrnd=\\{NORMAL|C1}\\s +rows: +1:\\{NORMAL|C1}\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s +2:\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s +3:\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s +4:\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s +5:\\s\\s\\s\\s\\s\\{BOLD}Hello\\{NORMAL}\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s +6:\\s\\s\\s\\s\\s\\{REVERSE|C2}World!\\{NORMAL|C1}\\s\\s\\s\\s\\s\\s\\s\\s\\s +7:\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s +8:\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s +9:\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s +10:\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s\\s +.NE +.PP +The first four octal escapes are actually nonprinting characters, +while the remainder of the file is printable text. +You may notice: +.bP +The actual color pair values are not written to the file. +.bP +All characters are shown in printable form; spaces are \*(``\\s\*('' to +ensure they are not overlooked. +.bP +Attributes are written in escaped curly braces, e.g., \*(``\\{BOLD}\*('', +and may include a color-pair (C1 or C2 in this example). +.bP +The parameters in the header are written out only if they are nonzero. +When reading back, order does not matter. +.ne 10 +.PP +Running the same program with Solaris \fIxpg4\fP curses gives this dump: +.NS +MAX=10,20 +BEG=0,0 +SCROLL=0,10 +VMIN=1 +VTIME=0 +FLAGS=0x1000 +FG=0,0 +BG=0,0, +0,0,0,1, +0,19,0,0, +1,0,0,1, +1,19,0,0, +2,0,0,1, +2,19,0,0, +3,0,0,1, +3,19,0,0, +4,0,0,1, +4,5,0x20,0,Hello +4,10,0,1, +4,19,0,0, +5,0,0,1, +5,5,0x4,2,World! +5,11,0,1, +5,19,0,0, +6,0,0,1, +6,19,0,0, +7,0,0,1, +7,19,0,0, +8,0,0,1, +8,19,0,0, +9,0,0,1, +9,19,0,0, +CUR=11,5 +.NE +.PP +Solaris \fBgetwin\fP requires that all parameters are present, and +in the same order. +The \fIxpg4\fP curses library does not know about the \fBbce\fP +(back color erase) capability, and does not color the window background. +.ne 10 +.PP +On the other hand, the SVr4 curses library does know about the background color. +However, its screen dumps are in binary. +Here is the corresponding dump (using \*(``od -t x1\*(''): +.NS +0000000 1c 01 c3 d6 f3 58 05 00 0b 00 0a 00 14 00 00 00 +0000020 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 +0000040 00 00 b8 1a 06 08 cc 1a 06 08 00 00 09 00 10 00 +0000060 00 00 00 80 00 00 20 00 00 00 ff ff ff ff 00 00 +0000100 ff ff ff ff 00 00 00 00 20 80 00 00 20 80 00 00 +0000120 20 80 00 00 20 80 00 00 20 80 00 00 20 80 00 00 +* +0000620 20 80 00 00 20 80 00 00 20 80 00 00 48 80 00 04 +0000640 65 80 00 04 6c 80 00 04 6c 80 00 04 6f 80 00 04 +0000660 20 80 00 00 20 80 00 00 20 80 00 00 20 80 00 00 +* +0000740 20 80 00 00 20 80 00 00 20 80 00 00 57 00 81 00 +0000760 6f 00 81 00 72 00 81 00 6c 00 81 00 64 00 81 00 +0001000 21 00 81 00 20 80 00 00 20 80 00 00 20 80 00 00 +0001020 20 80 00 00 20 80 00 00 20 80 00 00 20 80 00 00 +* +0001540 20 80 00 00 20 80 00 00 00 00 f6 d1 01 00 f6 d1 +0001560 08 00 00 00 40 00 00 00 00 00 00 00 00 00 00 07 +0001600 00 04 00 01 00 01 00 00 00 01 00 00 00 00 00 00 +0001620 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +* +0002371 +.NE +.SH SEE ALSO +\fBcurs_scr_dump\fP(3), +\fBcurs_util\fP(3). +.SH AUTHORS +Thomas E. Dickey +.br +extended screen-dump format for ncurses 6.0 (2015) +.sp +Eric S. Raymond +.br +screen dump feature in ncurses 1.9.2d (1995) diff --git a/lib/libcurses/shlib_version b/lib/libcurses/shlib_version index 2b806bd3e47..9c0249765d4 100644 --- a/lib/libcurses/shlib_version +++ b/lib/libcurses/shlib_version @@ -1,3 +1,3 @@ # Don't forget to give libedit and gnu/lib/libreadline the same type of bump! -major=14 +major=15 minor=0 diff --git a/lib/libcurses/term.5 b/lib/libcurses/term.5 index 554d921b10f..91a8a942c09 100644 --- a/lib/libcurses/term.5 +++ b/lib/libcurses/term.5 @@ -1,5 +1,6 @@ .\"*************************************************************************** -.\" Copyright (c) 1998-2004,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2021,2023 Thomas E. Dickey * +.\" Copyright 1998-2016,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -26,8 +27,30 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: term.5,v 1.1 2019/02/13 07:18:57 nicm Exp $ -.TH term 5 +.\" $Id: term.5,v 1.2 2023/10/17 09:52:08 nicm Exp $ +.TH term 5 2023-07-01 "ncurses 6.4" "File formats" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de NS +.ie n .sp +.el .sp .5 +.ie n .in +4 +.el .in +2 +.nf +.ft CR \" Courier +.. +.de NE +.fi +.ft R +.ie n .in -4 +.el .in -2 +.. +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .ds n 5 .ds d /usr/share/terminfo .SH NAME @@ -37,7 +60,7 @@ term \- format of compiled term file. .SH DESCRIPTION .SS STORAGE LOCATION Compiled terminfo descriptions are placed under the directory \fB\*d\fP. -Two configurations are supported (when building the ncurses libraries): +Two configurations are supported (when building the \fBncurses\fP libraries): .TP 5 .B directory tree A two-level scheme is used to avoid a linear search @@ -60,112 +83,147 @@ the terminfo's primary name as a key, and records containing only aliases pointing to the primary name. .IP If built to write hashed databases, -ncurses can still read terminfo databases organized as a directory tree, +\fBncurses\fP can still read terminfo databases organized as a directory tree, but cannot write entries into the directory tree. It can write (or rewrite) entries in the hashed database. .IP -ncurses distinguishes the two cases in the TERMINFO and TERMINFO_DIRS +\fBncurses\fP distinguishes the two cases in the TERMINFO and TERMINFO_DIRS environment variable by assuming a directory tree for entries that correspond to an existing directory, and hashed database otherwise. -.SS STORAGE FORMAT +.SS LEGACY STORAGE FORMAT The format has been chosen so that it will be the same on all hardware. An 8 or more bit byte is assumed, but no assumptions about byte ordering or sign extension are made. .PP -The compiled file is created with the -.I tic -program, and read by the routine -.IR setupterm . +The compiled file is created with the \fBtic\fP program, +and read by the routine \fBsetupterm\fP(3). The file is divided into six parts: -the header, -terminal names, -boolean flags, -numbers, -strings, -and -string table. +.RS 5 +.TP 3 +a) \fIheader\fP, +.TP 3 +b) \fIterminal names\fP, +.TP 3 +c) \fIboolean flags\fP, +.TP 3 +d) \fInumbers\fP, +.TP 3 +e) \fIstrings\fP, and +.TP 3 +f) \fIstring table\fP. +.RE .PP -The header section begins the file. +The \fIheader\fP section begins the file. This section contains six short integers in the format described below. These integers are .RS 5 .TP 5 -(1) the magic number (octal 0432); +(1) the \fImagic number\fP (octal 0432); .TP 5 -(2) the size, in bytes, of the names section; +(2) the size, in bytes, of the \fIterminal names\fP section; .TP 5 -(3) the number of bytes in the boolean section; +(3) the number of bytes in the \fIboolean flags\fP section; .TP 5 -(4) the number of short integers in the numbers section; +(4) the number of short integers in the \fInumbers\fP section; .TP 5 -(5) the number of offsets (short integers) in the strings section; +(5) the number of offsets (short integers) in the \fIstrings\fP section; .TP 5 -(6) the size, in bytes, of the string table. +(6) the size, in bytes, of the \fIstring table\fP. .RE .PP -Short integers are stored in two 8-bit bytes. +The capabilities in the +\fIboolean flags\fP, +\fInumbers\fP, and +\fIstrings\fP +sections are in the same order as the file . +.PP +Short integers are signed, in the range \-32768 to 32767. +They are stored as two 8-bit bytes. The first byte contains the least significant 8 bits of the value, and the second byte contains the most significant 8 bits. (Thus, the value represented is 256*second+first.) -The value -1 is represented by the two bytes 0377, 0377; other negative -values are illegal. This value generally -means that the corresponding capability is missing from this terminal. -Note that this format corresponds to the hardware of the \s-1VAX\s+1 +This format corresponds to the hardware of the \s-1VAX\s+1 and \s-1PDP\s+1-11 (that is, little-endian machines). Machines where this does not correspond to the hardware must read the integers as two bytes and compute the little-endian value. .PP -The terminal names section comes next. +Numbers in a terminal description, +whether they are entries in the \fInumbers\fP or \fIstrings\fP table, +are positive integers. +Boolean flags are treated as positive one-byte integers. +In each case, those positive integers represent a terminal capability. +The terminal compiler tic uses negative integers to handle the cases where +a capability is not available: +.bP +If a capability is absent from this terminal, +tic stores a \-1 in the corresponding table. +.IP +The integer value \-1 is represented by two bytes 0377, 0377. +.br +Absent boolean values are represented by the byte 0 (false). +.bP +If a capability has been canceled from this terminal, +tic stores a \-2 in the corresponding table. +.IP +The integer value \-2 is represented by two bytes 0377, 0376. +.br +The boolean value \-2 is represented by the byte 0376. +.br +.bP +Other negative values are illegal. +.PP +The \fIterminal names\fP section comes after the \fIheader\fP. It contains the first line of the terminfo description, listing the various names for the terminal, -separated by the `|' character. -The section is terminated with an \s-1ASCII NUL\s+1 character. +separated by the \*(``|\*('' character. +The \fIterminal names\fP section is terminated +with an \s-1ASCII NUL\s+1 character. .PP -The boolean flags have one byte for each flag. -This byte is either 0 or 1 if the flag is present or absent. -The capabilities are in the same order as the file . +The \fIboolean flags\fP section has one byte for each flag. +Boolean capabilities are either 1 or 0 (true or false) +according to whether the terminal supports the given capability or not. .PP -Between the boolean section and the number section, +Between the \fIboolean flags\fP section and the \fInumber\fP section, a null byte will be inserted, if necessary, -to ensure that the number section begins on an even byte (this is a -relic of the PDP-11's word-addressed architecture, originally -designed in to avoid IOT traps induced by addressing a word on an -odd byte boundary). +to ensure that the \fInumber\fP section begins on an even byte +This is a relic of the PDP\-11's word-addressed architecture, +originally designed to avoid traps induced +by addressing a word on an odd byte boundary. All short integers are aligned on a short word boundary. .PP -The numbers section is similar to the flags section. +The \fInumbers\fP section is similar to the \fIboolean flags\fP section. Each capability takes up two bytes, and is stored as a little-endian short integer. -If the value represented is -1, the capability is taken to be missing. .PP -The strings section is also similar. -Each capability is stored as a short integer, in the format above. -A value of -1 means the capability is missing. -Otherwise, the value is taken as an offset from the beginning -of the string table. +The \fIstrings\fP section is also similar. +Each capability is stored as a short integer. +The capability value is an index into the \fIstring table\fP. +.PP +The \fIstring table\fP is the last section. +It contains all of the values of string capabilities referenced in +the \fIstrings\fP section. +Each string is null-terminated. Special characters in ^X or \ec notation are stored in their interpreted form, not the printing representation. Padding information $ and parameter information %x are stored intact in uninterpreted form. -.PP -The final section is the string table. -It contains all the values of string capabilities referenced in -the string section. -Each string is null terminated. .SS EXTENDED STORAGE FORMAT The previous section describes the conventional terminfo binary format. With some minor variations of the offsets (see PORTABILITY), the same binary format is used in all modern UNIX systems. Each system uses a predefined set of boolean, number or string capabilities. .PP -The ncurses libraries and applications support extended terminfo binary format, -allowing users to define capabilities which are loaded at runtime. This +The \fBncurses\fP libraries and applications support +extended terminfo binary format, +allowing users to define capabilities which are loaded at runtime. +This extension is made possible by using the fact that the other implementations stop reading the terminfo data when they have reached the end of the size given in the header. -ncurses checks the size, and if it exceeds that due to the predefined data, +\fBncurses\fP checks the size, +and if it exceeds that due to the predefined data, continues to parse according to its own scheme. .PP First, it reads the extended header (5 short integers): @@ -181,59 +239,121 @@ count of extended numeric capabilities count of extended string capabilities .TP 5 (4) -size of the extended string table in bytes. +count of the items in extended string table .TP 5 (5) -last offset of the extended string table in bytes. +size of the extended string table in bytes .RE .PP -Using the counts and sizes, ncurses allocates arrays and reads data -for the extended capabilties in the same order as the header information. +The count- and size-values for the extended string table +include the extended capability \fInames\fP as well as +extended capability \fIvalues\fP. +.PP +Using the counts and sizes, \fBncurses\fP allocates arrays and reads data +for the extended capabilities in the same order as the header information. .PP The extended string table contains values for string capabilities. After the end of these values, it contains the names for each of the extended capabilities in order, e.g., booleans, then numbers and finally strings. +.PP +Applications which manipulate terminal data can use the definitions +described in \fBterm_variables\fP(3) which associate the long capability +names with members of a \fBTERMTYPE\fP structure. . +.SS EXTENDED NUMBER FORMAT +On occasion, 16-bit signed integers are not large enough. +With \fBncurses\fP 6.1, a new format was introduced by making a few changes +to the legacy format: +.bP +a different magic number (octal 01036) +.bP +changing the type for the \fInumber\fP array from signed 16-bit integers +to signed 32-bit integers. +.PP +To maintain compatibility, the library presents the same data structures +to direct users of the \fBTERMTYPE\fP structure as in previous formats. +However, that cannot provide callers with the extended numbers. +The library uses a similar but hidden data structure \fBTERMTYPE2\fP +to provide data for the terminfo functions. .SH PORTABILITY +.SS setupterm Note that it is possible for -.I setupterm +.B setupterm to expect a different set of capabilities than are actually present in the file. Either the database may have been updated since -.I setupterm +.B setupterm was recompiled (resulting in extra unrecognized entries in the file) or the program may have been recompiled more recently than the database was updated (resulting in missing entries). The routine -.I setupterm +.B setupterm must be prepared for both possibilities \- this is why the numbers and sizes are included. Also, new capabilities must always be added at the end of the lists of boolean, number, and string capabilities. +.SS Binary format +X/Open Curses does not specify a format for the terminfo database. +UNIX System V curses used a directory-tree of binary files, +one per terminal description. .PP Despite the consistent use of little-endian for numbers and the otherwise self-describing format, it is not wise to count on portability of binary -terminfo entries between commercial UNIX versions. The problem is that there -are at least three versions of terminfo (under HP-UX, AIX, and OSF/1) which +terminfo entries between commercial UNIX versions. +The problem is that there +are at least three versions of terminfo (under HP\-UX, AIX, and OSF/1) which diverged from System V terminfo after SVr1, and have added extension capabilities to the string table that (in the binary format) collide with -System V and XSI Curses extensions. See \fBterminfo\fR(\*n) for detailed +System V and XSI Curses extensions. +See \fBterminfo\fP(\*n) for detailed discussion of terminfo source compatibility issues. +.PP +This implementation is by default compatible with the binary +terminfo format used by Solaris curses, +except in a few less-used details +where it was found that the latter did not match X/Open Curses. +The format used by the other Unix versions +can be matched by building ncurses +with different configuration options. +.SS Magic codes +The magic number in a binary terminfo file is the first 16-bits (two bytes). +Besides making it more reliable for the library to check that a file +is terminfo, +utilities such as \fBfile\fP(1) also use that to tell what the file-format is. +System V defined more than one magic number, +with 0433, 0435 as screen-dumps (see \fBscr_dump\fP(5)). +This implementation uses 01036 as a continuation of that sequence, +but with a different high-order byte to avoid confusion. +.SS The TERMTYPE structure +Direct access to the \fBTERMTYPE\fP structure is provided for legacy +applications. +Portable applications should use the \fBtigetflag\fP and related functions +described in \fBterminfo\fP(3) for reading terminal capabilities. +.SS Mixed-case terminal names +A small number of terminal descriptions use uppercase characters in +their names. +If the underlying filesystem ignores the difference between +uppercase and lowercase, +\fBncurses\fP represents the \*(``first character\*('' +of the terminal name used as +the intermediate level of a directory tree in (two-character) hexadecimal form. .SH EXAMPLE -As an example, here is a hex dump of the description for the Lear-Siegler -ADM-3, a popular though rather stupid early terminal: -.nf -.sp +As an example, here is a description for the Lear-Siegler +ADM\-3, a popular though rather stupid early terminal: +.NS adm3a|lsi adm3a, am, cols#80, lines#24, bel=^G, clear=\032$<1>, cr=^M, cub1=^H, cud1=^J, cuf1=^L, cup=\\E=%p1%{32}%+%c%p2%{32}%+%c, cuu1=^K, home=^^, ind=^J, -.sp +.NE +.PP +and a hexadecimal dump of the compiled terminal description: +.NS .ft CW \s-20000 1a 01 10 00 02 00 03 00 82 00 31 00 61 64 6d 33 ........ ..1.adm3 0010 61 7c 6c 73 69 20 61 64 6d 33 61 00 00 01 50 00 a|lsi ad m3a...P. @@ -258,26 +378,34 @@ adm3a|lsi adm3a, 0140 25 70 32 25 7b 33 32 7d 25 2b 25 63 00 0a 00 1e %p2%{32} %+%c.... 0150 00 08 00 0c 00 0b 00 0a 00 ........ .\s+2 .ft R -.fi +.NE .sp .SH LIMITS -Some limitations: total compiled entries cannot exceed 4096 bytes. -The name field cannot exceed 128 bytes. +Some limitations: +.bP +total compiled entries cannot exceed 4096 bytes in the legacy format. +.bP +total compiled entries cannot exceed 32768 bytes in the extended format. +.bP +the name field cannot exceed 128 bytes. +.PP +Compiled entries are limited to 32768 bytes because offsets into the +\fIstrings table\fP use two-byte integers. +The legacy format could have supported 32768-byte entries, +but was limited a virtual memory page's 4096 bytes. .SH FILES -\*d/?/* compiled terminal capability database +\*d/*/* compiled terminal capability database .SH SEE ALSO -\fBcurses\fR(3), \fBterminfo\fR(\*n). +\fBcurses\fP(3), \fBterminfo\fP(\*n). .SH AUTHORS Thomas E. Dickey .br extended terminfo format for ncurses 5.0 .br hashed database support for ncurses 5.6 +.br +extended number support for ncurses 6.1 .sp Eric S. Raymond -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +.br +documented legacy terminfo format, e.g., from \fIpcurses\fP. diff --git a/lib/libcurses/term.7 b/lib/libcurses/term.7 index 68fd127a7b1..99d627949c3 100644 --- a/lib/libcurses/term.7 +++ b/lib/libcurses/term.7 @@ -1,7 +1,8 @@ -.\" $OpenBSD: term.7,v 1.9 2015/12/03 11:29:55 nicm Exp $ +.\" $OpenBSD: term.7,v 1.10 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * +.\" Copyright 2018-2021,2023 Thomas E. Dickey * +.\" Copyright 1998-2011,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,161 +29,185 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: term.7,v 1.9 2015/12/03 11:29:55 nicm Exp $ -.TH term 7 +.\" $Id: term.7,v 1.10 2023/10/17 09:52:08 nicm Exp $ +.TH term 7 2023-07-01 "ncurses 6.4" Miscellaneous +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .ds n 5 .ds d /usr/share/terminfo .SH NAME term \- conventions for naming terminal types .SH DESCRIPTION -.PP -The environment variable \fBTERM\fR should normally contain the type name of -the terminal, console or display-device type you are using. This information +The environment variable \fBTERM\fP should normally contain the type name of +the terminal, console or display-device type you are using. +This information is critical for all screen-oriented programs, including your editor and mailer. .PP -A default \fBTERM\fR value will be set on a per-line basis by either -\fB/etc/inittab\fR (Linux and System-V-like UNIXes) or \fB/etc/ttys\fR (BSD -UNIXes). This will nearly always suffice for workstation and microcomputer -consoles. +A default \fBTERM\fP value will be set on a per-line basis by either +\fB/etc/inittab\fP (e.g., System\-V-like UNIXes) +or \fB/etc/ttys\fP (BSD UNIXes). +This will nearly always suffice for workstation and microcomputer consoles. .PP -If you use a dialup line, the type of device attached to it may vary. Older -UNIX systems pre-set a very dumb terminal type like `dumb' or `dialup' on -dialup lines. Newer ones may pre-set `vt100', reflecting the prevalence of DEC +If you use a dialup line, the type of device attached to it may vary. +Older UNIX systems pre-set a very dumb terminal type +like \*(``dumb\*('' or \*(``dialup\*('' on dialup lines. +Newer ones may pre-set \*(``vt100\*('', reflecting the prevalence of DEC VT100-compatible terminals and personal-computer emulators. .PP -Modern telnets pass your \fBTERM\fR environment variable from the local side to -the remote one. There can be problems if the remote terminfo or termcap entry +Modern telnets pass your \fBTERM\fP environment variable from the local side to +the remote one. +There can be problems if the remote terminfo or termcap entry for your type is not compatible with yours, but this situation is rare and -can almost always be avoided by explicitly exporting `vt100' (assuming you -are in fact using a VT100-superset console, terminal, or terminal emulator). +can almost always be avoided by explicitly exporting \*(``vt100\*('' +(assuming you are in fact using a VT100-superset console, +terminal, or terminal emulator). .PP -In any case, you are free to override the system \fBTERM\fR setting to your -taste in your shell profile. The \fBtset\fP(1) utility may be of assistance; +In any case, you are free to override the system \fBTERM\fP setting to your +taste in your shell profile. +The \fBtset\fP(1) utility may be of assistance; you can give it a set of rules for deducing or requesting a terminal type based on the tty device and baud rate. .PP -Setting your own \fBTERM\fR value may also be useful if you have created a +Setting your own \fBTERM\fP value may also be useful if you have created a custom entry incorporating options (such as visual bell or reverse-video) which you wish to override the system default type for your line. .PP Terminal type descriptions are stored as files of capability data underneath -\*d. To browse a list of all terminal names recognized by the system, do +\*d. +To browse a list of all terminal names recognized by the system, do .sp - toe | more + toe | more .sp -from your shell. These capability files are in a binary format optimized for -retrieval speed (unlike the old text-based \fBtermcap\fR format they replace); -to examine an entry, you must use the \fBinfocmp\fR(1) command. +from your shell. +These capability files are in a binary format optimized for +retrieval speed (unlike the old text-based \fBtermcap\fP format they replace); +to examine an entry, you must use the \fBinfocmp\fP(1) command. Invoke it as follows: .sp - infocmp \fIentry-name\fR + infocmp \fIentry_name\fP .sp -where \fIentry-name\fR is the name of the type you wish to examine (and the +where \fIentry_name\fP is the name of the type you wish to examine (and the name of its capability file the subdirectory of \*d named for its first -letter). This command dumps a capability file in the text format described by -\fBterminfo\fR(\*n). -.PP -The first line of a \fBterminfo\fR(\*n) description gives the names by which -terminfo knows a terminal, separated by `|' (pipe-bar) characters with the last -name field terminated by a comma. The first name field is the type's -\fIprimary name\fR, and is the one to use when setting \fBTERM\fR. The last +letter). +This command dumps a capability file in the text format described by +\fBterminfo\fP(\*n). +.PP +The first line of a \fBterminfo\fP(\*n) description gives the names by which +terminfo knows a terminal, +separated by \*(``|\*('' (pipe-bar) characters with the last +name field terminated by a comma. +The first name field is the type's +\fIprimary name\fP, and is the one to use when setting \fBTERM\fP. The last name field (if distinct from the first) is actually a description of the -terminal type (it may contain blanks; the others must be single words). Name +terminal type (it may contain blanks; the others must be single words). +Name fields between the first and last (if present) are aliases for the terminal, usually historical names retained for compatibility. .PP There are some conventions for how to choose terminal primary names that help -keep them informative and unique. Here is a step-by-step guide to naming +keep them informative and unique. +Here is a step-by-step guide to naming terminals that also explains how to parse them: .PP -First, choose a root name. The root will consist of a lower-case letter -followed by up to seven lower-case letters or digits. You need to avoid using +First, choose a root name. +The root will consist of a lower-case letter +followed by up to seven lower-case letters or digits. +You need to avoid using punctuation characters in root names, because they are used and interpreted as filenames and shell meta-characters (such as !, $, *, ?, etc.) embedded in them -may cause odd and unhelpful behavior. The slash (/), or any other character +may cause odd and unhelpful behavior. +The slash (/), or any other character that may be interpreted by anyone's file system (\e, $, [, ]), is especially dangerous (terminfo is platform-independent, and choosing names with special -characters could someday make life difficult for users of a future port). The +characters could someday make life difficult for users of a future port). +The dot (.) character is relatively safe as long as there is at most one per root name; some historical terminfo names use it. .PP The root name for a terminal or workstation console type should almost always -begin with a vendor prefix (such as \fBhp\fR for Hewlett-Packard, \fBwy\fR for -Wyse, or \fBatt\fR for AT&T terminals), or a common name of the terminal line -(\fBvt\fR for the VT series of terminals from DEC, or \fBsun\fR for Sun -Microsystems workstation consoles, or \fBregent\fR for the ADDS Regent series. +begin with a vendor prefix (such as \fBhp\fP for Hewlett-Packard, \fBwy\fP for +Wyse, or \fBatt\fP for AT&T terminals), or a common name of the terminal line +(\fBvt\fP for the VT series of terminals from DEC, or \fBsun\fP for Sun +Microsystems workstation consoles, or \fBregent\fP for the ADDS Regent series. You can list the terminfo tree to see what prefixes are already in common use. The root name prefix should be followed when appropriate by a model number; -thus \fBvt100\fR, \fBhp2621\fR, \fBwy50\fR. +thus \fBvt100\fP, \fBhp2621\fP, \fBwy50\fP. .PP The root name for a PC-Unix console type should be the OS name, -i.e. \fBlinux\fR, \fBbsdos\fR, \fBfreebsd\fR, \fBnetbsd\fR. It should -\fInot\fR be \fBconsole\fR or any other generic that might cause confusion in a +i.e., \fBlinux\fP, \fBbsdos\fP, \fBfreebsd\fP, \fBnetbsd\fP. It should +\fInot\fP be \fBconsole\fP or any other generic that might cause confusion in a multi-platform environment! If a model number follows, it should indicate either the OS release level or the console driver release level. .PP The root name for a terminal emulator (assuming it does not fit one of the standard ANSI or vt100 types) should be the program name or a readily -recognizable abbreviation of it (i.e. \fBversaterm\fR, \fBctrm\fR). +recognizable abbreviation of it (i.e., \fBversaterm\fP, \fBctrm\fP). .PP Following the root name, you may add any reasonable number of hyphen-separated feature suffixes. .TP 5 2p -Has two pages of memory. Likewise 4p, 8p, etc. +Has two pages of memory. +Likewise 4p, 8p, etc. .TP 5 mc -Magic-cookie. Some terminals (notably older Wyses) can only support one -attribute without magic-cookie lossage. Their base entry is usually paired +Magic-cookie. +Some terminals (notably older Wyses) can only support one +attribute without magic-cookie lossage. +Their base entry is usually paired with another that has this suffix and uses magic cookies to support multiple attributes. .TP 5 --am +\-am Enable auto-margin (right-margin wraparound). .TP 5 --m -Mono mode - suppress color support. +\-m +Mono mode \- suppress color support. .TP 5 --na -No arrow keys - termcap ignores arrow keys which are actually there on the +\-na +No arrow keys \- termcap ignores arrow keys which are actually there on the terminal, so the user can use the arrow keys locally. .TP 5 --nam -No auto-margin - suppress am capability. +\-nam +No auto-margin \- suppress am capability. .TP 5 --nl -No labels - suppress soft labels. +\-nl +No labels \- suppress soft labels. .TP 5 --nsl -No status line - suppress status line. +\-nsl +No status line \- suppress status line. .TP 5 --pp +\-pp Has a printer port which is used. .TP 5 --rv +\-rv Terminal in reverse video mode (black on white). .TP 5 --s +\-s Enable status line. .TP 5 --vb +\-vb Use visible bell (flash) rather than beep. .TP 5 --w -Wide; terminal is in 132 column mode. +\-w +Wide; terminal is in 132-column mode. .PP Conventionally, if your terminal type is a variant intended to specify a -line height, that suffix should go first. So, for a hypothetical FuBarCo +line height, that suffix should go first. +So, for a hypothetical FuBarCo model 2317 terminal in 30-line mode with reverse video, best form would be -\fBfubar-30-rv\fR (rather than, say, `fubar-rv-30'). +\fBfubar\-30\-rv\fP (rather than, say, \*(``fubar\-rv\-30\*(''). .PP -Terminal types that are written not as stand-alone entries, but rather as +Terminal types that are written not as standalone entries, but rather as components to be plugged into other entries via \fBuse\fP capabilities, are distinguished by using embedded plus signs rather than dashes. .PP -Commands which use a terminal type to control display often accept a -T -option that accepts a terminal name argument. Such programs should fall back -on the \fBTERM\fR environment variable when no -T option is specified. +Commands which use a terminal type to control display often accept a \-T +option that accepts a terminal name argument. +Such programs should fall back +on the \fBTERM\fP environment variable when no \-T option is specified. .SH PORTABILITY For maximum compatibility with older System V UNIXes, names and aliases should be unique within the first 14 characters. @@ -197,10 +222,4 @@ tty line initialization (AT&T-like UNIXes) /etc/ttys tty line initialization (BSD-like UNIXes) .SH SEE ALSO -\fBcurses\fR(3), \fBterminfo\fR(\*n), \fBterm\fR(\*n). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), \fBterminfo\fP(\*n), \fBterm\fP(\*n). diff --git a/lib/libcurses/term.h b/lib/libcurses/term.h index 119bcec494b..4682059d7c1 100644 --- a/lib/libcurses/term.h +++ b/lib/libcurses/term.h @@ -1,7 +1,8 @@ -/* $OpenBSD: term.h,v 1.16 2020/12/14 22:05:31 naddy Exp $ */ +/* $OpenBSD: term.h,v 1.17 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2021,2023 Thomas E. Dickey * + * Copyright 1998-2013,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -34,7 +35,7 @@ /* and: Thomas E. Dickey 1995-on */ /****************************************************************************/ -/* $Id: term.h,v 1.16 2020/12/14 22:05:31 naddy Exp $ */ +/* $Id: term.h,v 1.17 2023/10/17 09:52:08 nicm Exp $ */ /* ** term.h -- Definition of struct term @@ -44,20 +45,9 @@ #define NCURSES_TERM_H_incl 1 #undef NCURSES_VERSION -#define NCURSES_VERSION "5.7" +#define NCURSES_VERSION "6.4" -#if !defined(NCURSES_IMPEXP) -# define NCURSES_IMPEXP /* nothing */ -#endif -#if !defined(NCURSES_API) -# define NCURSES_API /* nothing */ -#endif -#if !defined(NCURSES_EXPORT) -# define NCURSES_EXPORT(type) NCURSES_IMPEXP type NCURSES_API -#endif -#if !defined(NCURSES_EXPORT_VAR) -# define NCURSES_EXPORT_VAR(type) NCURSES_IMPEXP type -#endif +#include #ifdef __cplusplus extern "C" { @@ -67,12 +57,36 @@ extern "C" { * definition (based on the system for which this was configured). */ +#ifndef __NCURSES_H + +typedef struct screen SCREEN; + +#if 1 +#undef NCURSES_SP_FUNCS +#define NCURSES_SP_FUNCS 20230826 +#undef NCURSES_SP_NAME +#define NCURSES_SP_NAME(name) name##_sp + +/* Define the sp-funcs helper function */ +#undef NCURSES_SP_OUTC +#define NCURSES_SP_OUTC NCURSES_SP_NAME(NCURSES_OUTC) +typedef int (*NCURSES_SP_OUTC)(SCREEN*, int); +#endif + +#endif /* __NCURSES_H */ + #undef NCURSES_CONST #define NCURSES_CONST const #undef NCURSES_SBOOL #define NCURSES_SBOOL signed char +#undef NCURSES_USE_DATABASE +#define NCURSES_USE_DATABASE 1 + +#undef NCURSES_USE_TERMCAP +#define NCURSES_USE_TERMCAP 1 + #undef NCURSES_XNAMES #define NCURSES_XNAMES 1 @@ -104,48 +118,22 @@ extern "C" { #include #define TTY struct termio -/* Add definitions to make termio look like termios. - * But ifdef it, since there are some implementations - * that try to do this for us in a fake . - */ -#ifndef TCSANOW -#define TCSANOW TCSETA -#endif -#ifndef TCSADRAIN -#define TCSADRAIN TCSETAW -#endif -#ifndef TCSAFLUSH -#define TCSAFLUSH TCSETAF -#endif -#ifndef tcsetattr -#define tcsetattr(fd, cmd, arg) ioctl(fd, cmd, arg) -#endif -#ifndef tcgetattr -#define tcgetattr(fd, arg) ioctl(fd, TCGETA, arg) -#endif -#ifndef cfgetospeed -#define cfgetospeed(t) ((t)->c_cflag & CBAUD) -#endif -#ifndef TCIFLUSH -#define TCIFLUSH 0 -#endif -#ifndef TCOFLUSH -#define TCOFLUSH 1 -#endif -#ifndef TCIOFLUSH -#define TCIOFLUSH 2 -#endif -#ifndef tcflush -#define tcflush(fd, arg) ioctl(fd, TCFLSH, arg) -#endif - #else /* !HAVE_TERMIO_H */ +#if (defined(_WIN32) || defined(_WIN64)) +#if 0 +#include +#define TTY struct winconmode +#else +#include +#define TTY struct termios +#endif +#else #undef TERMIOS #include #include #define TTY struct sgttyb - +#endif /* MINGW32 */ #endif /* HAVE_TERMIO_H */ #endif /* HAVE_TERMIOS_H */ @@ -153,14 +141,22 @@ extern "C" { #ifdef TERMIOS #define GET_TTY(fd, buf) tcgetattr(fd, buf) #define SET_TTY(fd, buf) tcsetattr(fd, TCSADRAIN, buf) +#elif 0 && (defined(_WIN32) || defined(_WIN64)) +#define GET_TTY(fd, buf) _nc_console_getmode(_nc_console_fd2handle(fd),buf) +#define SET_TTY(fd, buf) _nc_console_setmode(_nc_console_fd2handle(fd),buf) #else #define GET_TTY(fd, buf) gtty(fd, buf) #define SET_TTY(fd, buf) stty(fd, buf) #endif +#ifndef GCC_NORETURN +#define GCC_NORETURN /* nothing */ +#endif + #define NAMESIZE 256 -#define CUR cur_term->type. +/* The cast works because TERMTYPE is the first data in TERMINAL */ +#define CUR ((TERMTYPE *)(cur_term))-> #define auto_left_margin CUR Booleans[0] #define auto_right_margin CUR Booleans[1] @@ -634,7 +630,11 @@ extern "C" { /* older synonyms for some capabilities */ #define beehive_glitch no_esc_ctlc #define teleray_glitch dest_tabs_magic_smso + +/* HPUX-11 uses this name rather than the standard one */ +#ifndef micro_char_size #define micro_char_size micro_col_size +#endif #ifdef __INTERNAL_CAPS_VISIBLE #define termcap_init2 CUR Strings[394] @@ -705,17 +705,60 @@ typedef struct termtype { /* in-core form of terminfo data */ } TERMTYPE; +/* + * The only reason these structures are visible is for read-only use. + * Programs which modify the data are not, never were, portable across + * curses implementations. + * + * The first field in TERMINAL is used in macros. + * The remaining fields are private. + */ +#ifdef NCURSES_INTERNALS + +#undef TERMINAL +#define TERMINAL struct term +TERMINAL; + +typedef struct termtype2 { /* in-core form of terminfo data */ + char *term_names; /* str_table offset of term names */ + char *str_table; /* pointer to string table */ + NCURSES_SBOOL *Booleans; /* array of boolean values */ + int *Numbers; /* array of integer values */ + char **Strings; /* array of string offsets */ + +#if NCURSES_XNAMES + char *ext_str_table; /* pointer to extended string table */ + char **ext_Names; /* corresponding names */ + + unsigned short num_Booleans;/* count total Booleans */ + unsigned short num_Numbers; /* count total Numbers */ + unsigned short num_Strings; /* count total Strings */ + + unsigned short ext_Booleans;/* count extensions to Booleans */ + unsigned short ext_Numbers; /* count extensions to Numbers */ + unsigned short ext_Strings; /* count extensions to Strings */ +#endif /* NCURSES_XNAMES */ + +} TERMTYPE2; +#else + typedef struct term { /* describe an actual terminal */ TERMTYPE type; /* terminal type description */ - short Filedes; /* file description being written to */ - TTY Ottyb, /* original state of the terminal */ - Nttyb; /* current state of the terminal */ - int _baudrate; /* used to compute padding */ - char * _termname; /* used for termname() */ } TERMINAL; -#if 0 || 0 +#endif /* NCURSES_INTERNALS */ + + +#if 0 && !0 +extern NCURSES_EXPORT_VAR(TERMINAL *) cur_term; +#elif 0 NCURSES_WRAPPED_VAR(TERMINAL *, cur_term); +#define cur_term NCURSES_PUBLIC_VAR(cur_term()) +#else +extern NCURSES_EXPORT_VAR(TERMINAL *) cur_term; +#endif + +#if 0 || 0 NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, boolnames); NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, boolcodes); NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, boolfnames); @@ -726,7 +769,6 @@ NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, strnames); NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, strcodes); NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, strfnames); -#define cur_term NCURSES_PUBLIC_VAR(cur_term()) #define boolnames NCURSES_PUBLIC_VAR(boolnames()) #define boolcodes NCURSES_PUBLIC_VAR(boolcodes()) #define boolfnames NCURSES_PUBLIC_VAR(boolfnames()) @@ -739,8 +781,6 @@ NCURSES_WRAPPED_VAR(NCURSES_CONST char * const *, strfnames); #else -extern NCURSES_EXPORT_VAR(TERMINAL *) cur_term; - extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) boolnames[]; extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) boolcodes[]; extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) boolfnames[]; @@ -753,51 +793,98 @@ extern NCURSES_EXPORT_VAR(NCURSES_CONST char * const ) strfnames[]; #endif -/* internals */ +/* + * These entrypoints are used only by the ncurses utilities such as tic. + */ +#ifdef NCURSES_INTERNALS + extern NCURSES_EXPORT(int) _nc_set_tty_mode (TTY *buf); -extern NCURSES_EXPORT(int) _nc_get_tty_mode (TTY *buf); -extern NCURSES_EXPORT(int) _nc_read_entry (const char * const, char * const, TERMTYPE *const); -extern NCURSES_EXPORT(int) _nc_read_file_entry (const char *const, TERMTYPE *); -extern NCURSES_EXPORT(int) _nc_read_termtype (TERMTYPE *, char *, int); +extern NCURSES_EXPORT(int) _nc_read_entry2 (const char * const, char * const, TERMTYPE2 *const); +extern NCURSES_EXPORT(int) _nc_read_file_entry (const char *const, TERMTYPE2 *); +extern NCURSES_EXPORT(int) _nc_read_termtype (TERMTYPE2 *, char *, int); extern NCURSES_EXPORT(char *) _nc_first_name (const char *const); extern NCURSES_EXPORT(int) _nc_name_match (const char *const, const char *const, const char *const); +extern NCURSES_EXPORT(char *) _nc_tiparm(int, const char *, ...); extern NCURSES_EXPORT(const TERMTYPE *) _nc_fallback (const char *); +extern NCURSES_EXPORT(int) _nc_read_entry (const char * const, char * const, TERMTYPE *const); + +#endif /* NCURSES_INTERNALS */ -/* entry points */ +/* + * Normal entry points + */ extern NCURSES_EXPORT(TERMINAL *) set_curterm (TERMINAL *); extern NCURSES_EXPORT(int) del_curterm (TERMINAL *); /* miscellaneous entry points */ extern NCURSES_EXPORT(int) restartterm (NCURSES_CONST char *, int, int *); -extern NCURSES_EXPORT(int) setupterm (NCURSES_CONST char *,int,int *); +extern NCURSES_EXPORT(int) setupterm (const char *,int,int *); /* terminfo entry points, also declared in curses.h */ #if !defined(__NCURSES_H) -extern NCURSES_EXPORT(char *) tigetstr (NCURSES_CONST char *); +extern NCURSES_EXPORT(char *) tigetstr (const char *); extern NCURSES_EXPORT_VAR(char) ttytype[]; extern NCURSES_EXPORT(int) putp (const char *); -extern NCURSES_EXPORT(int) tigetflag (NCURSES_CONST char *); -extern NCURSES_EXPORT(int) tigetnum (NCURSES_CONST char *); +extern NCURSES_EXPORT(int) tigetflag (const char *); +extern NCURSES_EXPORT(int) tigetnum (const char *); #if 1 /* NCURSES_TPARM_VARARGS */ -extern NCURSES_EXPORT(char *) tparm (NCURSES_CONST char *, ...); /* special */ +extern NCURSES_EXPORT(char *) tparm (const char *, ...); /* special */ #else -extern NCURSES_EXPORT(char *) tparm (NCURSES_CONST char *, long,long,long,long,long,long,long,long,long); /* special */ -extern NCURSES_EXPORT(char *) tparm_varargs (NCURSES_CONST char *, ...); /* special */ +extern NCURSES_EXPORT(char *) tparm (const char *, long,long,long,long,long,long,long,long,long); /* special */ #endif +extern NCURSES_EXPORT(char *) tiparm (const char *, ...); /* special */ +extern NCURSES_EXPORT(char *) tiparm_s (int, int, const char *, ...); /* special */ +extern NCURSES_EXPORT(int) tiscan_s (int *, int *, const char *); /* special */ + #endif /* __NCURSES_H */ /* termcap database emulation (XPG4 uses const only for 2nd param of tgetent) */ #if !defined(NCURSES_TERMCAP_H_incl) -extern NCURSES_EXPORT(char *) tgetstr (NCURSES_CONST char *, char **); +extern NCURSES_EXPORT(char *) tgetstr (const char *, char **); extern NCURSES_EXPORT(char *) tgoto (const char *, int, int); extern NCURSES_EXPORT(int) tgetent (char *, const char *); -extern NCURSES_EXPORT(int) tgetflag (NCURSES_CONST char *); -extern NCURSES_EXPORT(int) tgetnum (NCURSES_CONST char *); +extern NCURSES_EXPORT(int) tgetflag (const char *); +extern NCURSES_EXPORT(int) tgetnum (const char *); extern NCURSES_EXPORT(int) tputs (const char *, int, int (*)(int)); #endif /* NCURSES_TERMCAP_H_incl */ +/* + * Include curses.h before term.h to enable these extensions. + */ +#if defined(NCURSES_SP_FUNCS) && (NCURSES_SP_FUNCS != 0) + +extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(tigetstr) (SCREEN*, const char *); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(putp) (SCREEN*, const char *); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(tigetflag) (SCREEN*, const char *); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(tigetnum) (SCREEN*, const char *); + +#if 1 /* NCURSES_TPARM_VARARGS */ +extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(tparm) (SCREEN*, const char *, ...); /* special */ +#else +extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(tparm) (SCREEN*, const char *, long,long,long,long,long,long,long,long,long); /* special */ +#endif + +/* termcap database emulation (XPG4 uses const only for 2nd param of tgetent) */ +extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(tgetstr) (SCREEN*, const char *, char **); +extern NCURSES_EXPORT(char *) NCURSES_SP_NAME(tgoto) (SCREEN*, const char *, int, int); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(tgetent) (SCREEN*, char *, const char *); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(tgetflag) (SCREEN*, const char *); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(tgetnum) (SCREEN*, const char *); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(tputs) (SCREEN*, const char *, int, NCURSES_SP_OUTC); + +extern NCURSES_EXPORT(TERMINAL *) NCURSES_SP_NAME(set_curterm) (SCREEN*, TERMINAL *); +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(del_curterm) (SCREEN*, TERMINAL *); + +extern NCURSES_EXPORT(int) NCURSES_SP_NAME(restartterm) (SCREEN*, NCURSES_CONST char *, int, int *); +#endif /* NCURSES_SP_FUNCS */ + +/* + * Debugging features. + */ +extern GCC_NORETURN NCURSES_EXPORT(void) exit_terminfo(int); + #ifdef __cplusplus } #endif diff --git a/lib/libcurses/term.priv.h b/lib/libcurses/term.priv.h new file mode 100644 index 00000000000..0a1e1682702 --- /dev/null +++ b/lib/libcurses/term.priv.h @@ -0,0 +1,335 @@ +/**************************************************************************** + * Copyright 2021 Thomas E. Dickey * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/* + * $Id: term.priv.h,v 1.1 2023/10/17 09:52:08 nicm Exp $ + * + * term.priv.h + * + * Header file for terminfo library objects which are private to + * the library. + * + */ + +#ifndef _TERM_PRIV_H +#define _TERM_PRIV_H 1 +/* *INDENT-OFF* */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#undef NCURSES_OPAQUE +#define NCURSES_INTERNALS 1 +#define NCURSES_OPAQUE 0 + +#include /* PATH_MAX */ +#include /* sig_atomic_t */ +#include /* time_t */ +#include /* time_t */ + +#ifdef USE_PTHREADS +#if USE_REENTRANT +#include +#endif +#endif + +/* + * State of tparm(). + */ +#define STACKSIZE 20 + +typedef struct { + union { + int num; + char * str; + } data; + bool num_type; +} STACK_FRAME; + +#define NUM_VARS 26 + +typedef struct { + const char * tparam_base; + + STACK_FRAME stack[STACKSIZE]; + int stack_ptr; + + char * out_buff; + size_t out_size; + size_t out_used; + + char * fmt_buff; + size_t fmt_size; + + int static_vars[NUM_VARS]; +#ifdef TRACE + const char * tname; +#endif +} TPARM_STATE; + +typedef struct { + char * text; + size_t size; +} TRACEBUF; + +typedef struct { + const char * name; + char * value; +} ITERATOR_VARS; + +/* + * Internals for term.h + */ +typedef struct term { /* describe an actual terminal */ + TERMTYPE type; /* terminal type description */ + short Filedes; /* file description being written to */ + TTY Ottyb; /* original state of the terminal */ + TTY Nttyb; /* current state of the terminal */ + int _baudrate; /* used to compute padding */ + char * _termname; /* used for termname() */ + TPARM_STATE tparm_state; +#if NCURSES_EXT_COLORS + TERMTYPE2 type2; /* extended terminal type description */ +#endif +#undef TERMINAL +} TERMINAL; + +/* + * Internals for soft-keys + */ +typedef struct { + WINDOW * win; /* the window used in the hook */ + int line; /* lines to take, < 0 => from bottom*/ + int (*hook)(WINDOW *, int); /* callback for user */ +} ripoff_t; + +/* + * Internals for tgetent + */ +typedef struct { + long sequence; + bool last_used; + char * fix_sgr0; /* this holds the filtered sgr0 string */ + char * last_bufp; /* help with fix_sgr0 leak */ + TERMINAL * last_term; +} TGETENT_CACHE; + +#define TGETENT_MAX 4 + +#include /* dbdLAST */ + +#ifdef USE_TERM_DRIVER +struct DriverTCB; /* Terminal Control Block forward declaration */ +#endif + +/* + * Global data which is not specific to a screen. + */ +typedef struct { + SIG_ATOMIC_T have_sigtstp; + SIG_ATOMIC_T have_sigwinch; + SIG_ATOMIC_T cleanup_nested; + + bool init_signals; + bool init_screen; + + char * comp_sourcename; + char * comp_termtype; + + bool have_tic_directory; + bool keep_tic_directory; + const char * tic_directory; + + char * dbi_list; + int dbi_size; + + char * first_name; + char ** keyname_table; + int init_keyname; + + int slk_format; + + int getstr_limit; /* getstr_limit based on POSIX LINE_MAX */ + + char * safeprint_buf; + size_t safeprint_used; + + TGETENT_CACHE tgetent_cache[TGETENT_MAX]; + int tgetent_index; + long tgetent_sequence; + int terminal_count; + + char * dbd_blob; /* string-heap for dbd_list[] */ + char ** dbd_list; /* distinct places to look for data */ + int dbd_size; /* length of dbd_list[] */ + time_t dbd_time; /* cache last updated */ + ITERATOR_VARS dbd_vars[dbdLAST]; + +#if HAVE_TSEARCH + void * cached_tparm; + int count_tparm; +#endif /* HAVE_TSEARCH */ + +#ifdef USE_TERM_DRIVER + int (*term_driver)(struct DriverTCB*, const char*, int*); +#endif + +#define WINDOWLIST struct _win_list + +#ifndef USE_SP_WINDOWLIST + WINDOWLIST * _nc_windowlist; +#define WindowList(sp) _nc_globals._nc_windowlist +#endif + +#if USE_HOME_TERMINFO + char * home_terminfo; +#endif + +#if !USE_SAFE_SPRINTF + int safeprint_cols; + int safeprint_rows; +#endif + +#ifdef USE_PTHREADS + pthread_mutex_t mutex_curses; + pthread_mutex_t mutex_prescreen; + pthread_mutex_t mutex_screen; + pthread_mutex_t mutex_update; + pthread_mutex_t mutex_tst_tracef; + pthread_mutex_t mutex_tracef; + int nested_tracef; + int use_pthreads; +#define _nc_use_pthreads _nc_globals.use_pthreads +#if USE_PTHREADS_EINTR + pthread_t read_thread; /* The reading thread */ +#endif +#endif +#if USE_WIDEC_SUPPORT + char key_name[MB_LEN_MAX + 1]; +#endif + +#ifdef TRACE + bool trace_opened; + char trace_fname[PATH_MAX]; + int trace_level; + FILE * trace_fp; + int trace_fd; + + char * tracearg_buf; + size_t tracearg_used; + + TRACEBUF * tracebuf_ptr; + size_t tracebuf_used; + + char tracechr_buf[40]; + + char * tracedmp_buf; + size_t tracedmp_used; + + unsigned char * tracetry_buf; + size_t tracetry_used; + + char traceatr_color_buf[2][80]; + int traceatr_color_sel; + int traceatr_color_last; +#if !defined(USE_PTHREADS) && USE_REENTRANT + int nested_tracef; +#endif +#endif /* TRACE */ + +#if NO_LEAKS + bool leak_checking; +#endif +} NCURSES_GLOBALS; + +extern NCURSES_EXPORT_VAR(NCURSES_GLOBALS) _nc_globals; + +#define N_RIPS 5 + +#ifdef USE_PTHREADS +typedef struct _prescreen_list { + struct _prescreen_list *next; + pthread_t id; + struct screen * sp; +} PRESCREEN_LIST; +#endif + +/* + * Global data which can be swept up into a SCREEN when one is created. + * It may be modified before the next SCREEN is created. + */ +typedef struct { +#ifdef USE_PTHREADS + PRESCREEN_LIST *allocated; +#else + struct screen * allocated; +#endif + bool use_env; + bool filter_mode; + attr_t previous_attr; + TPARM_STATE tparm_state; + TTY * saved_tty; /* savetty/resetty information */ + bool use_tioctl; + NCURSES_SP_OUTC _outch; /* output handler if not putc */ +#ifndef USE_SP_RIPOFF + ripoff_t rippedoff[N_RIPS]; + ripoff_t * rsp; +#endif +#if NCURSES_NO_PADDING + bool _no_padding; /* flag to set if padding disabled */ +#endif +#if BROKEN_LINKER || USE_REENTRANT + chtype * real_acs_map; + int _LINES; + int _COLS; + int _TABSIZE; + int _ESCDELAY; + TERMINAL * _cur_term; +#endif +#ifdef TRACE +#if BROKEN_LINKER || USE_REENTRANT + long _outchars; + const char * _tputs_trace; +#endif +#endif +} NCURSES_PRESCREEN; + +extern NCURSES_EXPORT_VAR(NCURSES_PRESCREEN) _nc_prescreen; + +extern NCURSES_EXPORT(void) _nc_free_tparm(TERMINAL*); + +#ifdef __cplusplus +} +#endif + +/* *INDENT-ON* */ + +#endif /* _TERM_PRIV_H */ diff --git a/lib/libcurses/term_entry.h b/lib/libcurses/term_entry.h index 3cd0a59aa1c..f112021a5cc 100644 --- a/lib/libcurses/term_entry.h +++ b/lib/libcurses/term_entry.h @@ -1,7 +1,8 @@ -/* $OpenBSD: term_entry.h,v 1.12 2010/01/12 23:21:59 nicm Exp $ */ +/* $OpenBSD: term_entry.h,v 1.13 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2008 Free Software Foundation, Inc. * + * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2015,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -34,7 +35,7 @@ * and: Thomas E. Dickey 1998-on * ****************************************************************************/ -/* $Id: term_entry.h,v 1.12 2010/01/12 23:21:59 nicm Exp $ */ +/* $Id: term_entry.h,v 1.13 2023/10/17 09:52:08 nicm Exp $ */ /* * term_entry.h -- interface to entry-manipulation code @@ -42,35 +43,18 @@ #ifndef NCURSES_TERM_ENTRY_H_incl #define NCURSES_TERM_ENTRY_H_incl 1 +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif +#include #include -#define MAX_USES 32 -#define MAX_CROSSLINKS 16 - -typedef struct entry { - TERMTYPE tterm; - unsigned nuses; - struct - { - char *name; - struct entry *link; - long line; - } - uses[MAX_USES]; - int ncrosslinks; - struct entry *crosslinks[MAX_CROSSLINKS]; - long cstart, cend; - long startline; - struct entry *next; - struct entry *last; -} -ENTRY; - +/* + * These macros may be used by programs that know about TERMTYPE: + */ #if NCURSES_XNAMES #define NUM_BOOLEANS(tp) (tp)->num_Booleans #define NUM_NUMBERS(tp) (tp)->num_Numbers @@ -83,19 +67,77 @@ ENTRY; #define EXT_NAMES(tp,i,limit,index,table) table[i] #endif -#define NUM_EXT_NAMES(tp) ((tp)->ext_Booleans + (tp)->ext_Numbers + (tp)->ext_Strings) +#define NUM_EXT_NAMES(tp) (unsigned) ((tp)->ext_Booleans + (tp)->ext_Numbers + (tp)->ext_Strings) #define for_each_boolean(n,tp) for(n = 0; n < NUM_BOOLEANS(tp); n++) #define for_each_number(n,tp) for(n = 0; n < NUM_NUMBERS(tp); n++) #define for_each_string(n,tp) for(n = 0; n < NUM_STRINGS(tp); n++) +#if NCURSES_XNAMES +#define for_each_ext_boolean(n,tp) for(n = BOOLCOUNT; (int) n < (int) NUM_BOOLEANS(tp); n++) +#define for_each_ext_number(n,tp) for(n = NUMCOUNT; (int) n < (int) NUM_NUMBERS(tp); n++) +#define for_each_ext_string(n,tp) for(n = STRCOUNT; (int) n < (int) NUM_STRINGS(tp); n++) +#endif + #define ExtBoolname(tp,i,names) EXT_NAMES(tp, i, BOOLCOUNT, (i - (tp->num_Booleans - tp->ext_Booleans)), names) #define ExtNumname(tp,i,names) EXT_NAMES(tp, i, NUMCOUNT, (i - (tp->num_Numbers - tp->ext_Numbers)) + tp->ext_Booleans, names) #define ExtStrname(tp,i,names) EXT_NAMES(tp, i, STRCOUNT, (i - (tp->num_Strings - tp->ext_Strings)) + (tp->ext_Numbers + tp->ext_Booleans), names) +/* + * The remaining type-definitions and macros are used only internally by the + * ncurses utilities. + */ +#ifdef NCURSES_INTERNALS + +/* + * see db_iterator.c - this enumeration lists the places searched for a + * terminal description and defines the order in which they are searched. + */ +typedef enum { + dbdTIC = 0, /* special, used by tic when writing entry */ +#if NCURSES_USE_DATABASE + dbdEnvOnce, /* the $TERMINFO environment variable */ + dbdHome, /* $HOME/.terminfo */ + dbdEnvList, /* the $TERMINFO_DIRS environment variable */ + dbdCfgList, /* the compiled-in TERMINFO_DIRS value */ + dbdCfgOnce, /* the compiled-in TERMINFO value */ +#endif +#if NCURSES_USE_TERMCAP + dbdEnvOnce2, /* the $TERMCAP environment variable */ + dbdEnvList2, /* the $TERMPATH environment variable */ + dbdCfgList2, /* the compiled-in TERMPATH */ +#endif + dbdLAST +} DBDIRS; + +#define MAX_USES 32 +#define MAX_CROSSLINKS 16 + +typedef struct entry ENTRY; + +typedef struct { + char *name; + ENTRY *link; + long line; +} ENTRY_USES; + +struct entry { + TERMTYPE2 tterm; + unsigned nuses; + ENTRY_USES uses[MAX_USES]; + int ncrosslinks; + ENTRY *crosslinks[MAX_CROSSLINKS]; + long cstart; + long cend; + long startline; + ENTRY *next; + ENTRY *last; +}; + extern NCURSES_EXPORT_VAR(ENTRY *) _nc_head; extern NCURSES_EXPORT_VAR(ENTRY *) _nc_tail; #define for_entry_list(qp) for (qp = _nc_head; qp; qp = qp->next) +#define for_entry_list2(qp,q0) for (qp = q0; qp; qp = qp->next) #define MAX_LINE 132 @@ -103,13 +145,16 @@ extern NCURSES_EXPORT_VAR(ENTRY *) _nc_tail; /* * Note that WANTED and PRESENT are not simple inverses! If a capability - * has been explicitly cancelled, it's not considered WANTED. + * has been explicitly cancelled, it is not considered WANTED. */ #define WANTED(s) ((s) == ABSENT_STRING) #define PRESENT(s) (((s) != ABSENT_STRING) && ((s) != CANCELLED_STRING)) #define ANDMISSING(p,q) \ - {if (PRESENT(p) && !PRESENT(q)) _nc_warning(#p " but no " #q);} + { \ + if (PRESENT(p) && !PRESENT(q)) \ + _nc_warning(#p " but no " #q); \ + } #define PAIRED(p,q) \ { \ @@ -119,25 +164,27 @@ extern NCURSES_EXPORT_VAR(ENTRY *) _nc_tail; _nc_warning(#p " but no " #q); \ } +/* + * These entrypoints are used only by the ncurses utilities such as tic. + */ + /* alloc_entry.c: elementary allocation code */ extern NCURSES_EXPORT(ENTRY *) _nc_copy_entry (ENTRY *oldp); extern NCURSES_EXPORT(char *) _nc_save_str (const char *const); -extern NCURSES_EXPORT(void) _nc_init_entry (TERMTYPE *const); -extern NCURSES_EXPORT(void) _nc_merge_entry (TERMTYPE *const, TERMTYPE *const); +extern NCURSES_EXPORT(void) _nc_init_entry (ENTRY *const); +extern NCURSES_EXPORT(void) _nc_merge_entry (ENTRY *const, ENTRY *const); extern NCURSES_EXPORT(void) _nc_wrap_entry (ENTRY *const, bool); /* alloc_ttype.c: elementary allocation code */ -extern NCURSES_EXPORT(void) _nc_align_termtype (TERMTYPE *, TERMTYPE *); -extern NCURSES_EXPORT(void) _nc_copy_termtype (TERMTYPE *, TERMTYPE *); +extern NCURSES_EXPORT(void) _nc_align_termtype (TERMTYPE2 *, TERMTYPE2 *); /* free_ttype.c: elementary allocation code */ extern NCURSES_EXPORT(void) _nc_free_termtype (TERMTYPE *); - -/* lib_acs.c */ -extern NCURSES_EXPORT(void) _nc_init_acs (void); /* corresponds to traditional 'init_acs()' */ +extern NCURSES_EXPORT(void) _nc_free_termtype1 (TERMTYPE *); +extern NCURSES_EXPORT(void) _nc_free_termtype2 (TERMTYPE2 *); /* lib_termcap.c: trim sgr0 string for termcap users */ -extern NCURSES_EXPORT(char *) _nc_trim_sgr0 (TERMTYPE *); +extern NCURSES_EXPORT(char *) _nc_trim_sgr0 (TERMTYPE2 *); /* parse_entry.c: entry-parsing code */ #if NCURSES_XNAMES @@ -148,8 +195,9 @@ extern NCURSES_EXPORT(int) _nc_parse_entry (ENTRY *, int, bool); extern NCURSES_EXPORT(int) _nc_capcmp (const char *, const char *); /* write_entry.c: writing an entry to the file system */ -extern NCURSES_EXPORT(void) _nc_set_writedir (char *); -extern NCURSES_EXPORT(void) _nc_write_entry (TERMTYPE *const); +extern NCURSES_EXPORT(void) _nc_set_writedir (const char *); +extern NCURSES_EXPORT(void) _nc_write_entry (TERMTYPE2 *const); +extern NCURSES_EXPORT(int) _nc_write_object (TERMTYPE2 *, char *, unsigned *, unsigned); /* comp_parse.c: entry list handling */ extern NCURSES_EXPORT(void) _nc_read_entry_source (FILE*, char*, int, bool, bool (*)(ENTRY*)); @@ -157,20 +205,18 @@ extern NCURSES_EXPORT(bool) _nc_entry_match (char *, char *); extern NCURSES_EXPORT(int) _nc_resolve_uses (bool); /* obs 20040705 */ extern NCURSES_EXPORT(int) _nc_resolve_uses2 (bool, bool); extern NCURSES_EXPORT(void) _nc_free_entries (ENTRY *); -extern NCURSES_IMPEXP void NCURSES_API (*_nc_check_termtype)(TERMTYPE *); /* obs 20040705 */ -extern NCURSES_IMPEXP void NCURSES_API (*_nc_check_termtype2)(TERMTYPE *, bool); +extern NCURSES_IMPEXP void (NCURSES_API *_nc_check_termtype)(TERMTYPE *); /* obs 20040705 */ +extern NCURSES_IMPEXP void (NCURSES_API *_nc_check_termtype2)(TERMTYPE2 *, bool); /* trace_xnames.c */ extern NCURSES_EXPORT(void) _nc_trace_xnames (TERMTYPE *); -#ifdef __OpenBSD__ -/* read_bsd_terminfo.c: terminfo.db reading */ -extern int _nc_read_bsd_terminfo_entry(const char * const, char * const, TERMTYPE *const); -extern int _nc_read_bsd_terminfo_file(const char * const, TERMTYPE *const); -#endif /* __OpenBSD__ */ +#endif /* NCURSES_INTERNALS */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ + #endif /* NCURSES_TERM_ENTRY_H_incl */ diff --git a/lib/libcurses/term_variables.3 b/lib/libcurses/term_variables.3 new file mode 100644 index 00000000000..49ae267d513 --- /dev/null +++ b/lib/libcurses/term_variables.3 @@ -0,0 +1,193 @@ +.\"*************************************************************************** +.\" Copyright 2019-2022,2023 Thomas E. Dickey * +.\" Copyright 2010-2015,2017 Free Software Foundation, Inc. * +.\" * +.\" Permission is hereby granted, free of charge, to any person obtaining a * +.\" copy of this software and associated documentation files (the * +.\" "Software"), to deal in the Software without restriction, including * +.\" without limitation the rights to use, copy, modify, merge, publish, * +.\" distribute, distribute with modifications, sublicense, and/or sell * +.\" copies of the Software, and to permit persons to whom the Software is * +.\" furnished to do so, subject to the following conditions: * +.\" * +.\" The above copyright notice and this permission notice shall be included * +.\" in all copies or substantial portions of the Software. * +.\" * +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * +.\" IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * +.\" DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * +.\" OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * +.\" THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +.\" * +.\" Except as contained in this notice, the name(s) of the above copyright * +.\" holders shall not be used in advertising or otherwise to promote the * +.\" sale, use or other dealings in this Software without prior written * +.\" authorization. * +.\"*************************************************************************** +.\" +.\" $Id: term_variables.3,v 1.1 2023/10/17 09:52:08 nicm Exp $ +.TH term_variables 3 2023-07-01 "ncurses 6.4" "Library calls" +.ds n 5 +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.na +.hy 0 +.SH NAME +\fBSP\fP, +\fBacs_map\fP, +\fBboolcodes\fP, +\fBboolfnames\fP, +\fBboolnames\fP, +\fBcur_term\fP, +\fBnumcodes\fP, +\fBnumfnames\fP, +\fBnumnames\fP, +\fBstrcodes\fP, +\fBstrfnames\fP, +\fBstrnames\fP, +\fBttytype\fP +\- \fBcurses\fP terminfo global variables +.ad +.hy +.SH SYNOPSIS +.nf +\fB#include \fP +.br +\fB#include \fP +.PP +\fBchtype acs_map[];\fP +.sp +\fBSCREEN * SP;\fP +.sp +\fBTERMINAL * cur_term;\fP +.sp +\fBchar ttytype[];\fP +.sp +\fBNCURSES_CONST char * const boolcodes[];\fP +.br +\fBNCURSES_CONST char * const boolfnames[];\fP +.br +\fBNCURSES_CONST char * const boolnames[];\fP +.sp +\fBNCURSES_CONST char * const numcodes[];\fP +.br +\fBNCURSES_CONST char * const numfnames[];\fP +.br +\fBNCURSES_CONST char * const numnames[];\fP +.sp +\fBNCURSES_CONST char * const strcodes[];\fP +.br +\fBNCURSES_CONST char * const strfnames[];\fP +.br +\fBNCURSES_CONST char * const strnames[];\fP +.br +.fi +.SH DESCRIPTION +This page summarizes variables provided by the \fBcurses\fP library's +low-level terminfo interface. +A more complete description is given in the \fBterminfo\fP(3) manual page. +.PP +Depending on the configuration, these may be actual variables, +or macros (see \fBcurs_threads\fP(3)) +which provide read-only access to \fIcurses\fP's state. +In either case, applications should treat them as read-only to avoid +confusing the library. +.SS Alternate Character Set Mapping +After initializing the curses or terminfo interfaces, +the \fBacs_map\fP array holds information used to translate cells +with the \fBA_ALTCHARSET\fP video attribute into line-drawing characters. +.PP +The encoding of the information in this array has changed periodically. +Application developers need only know that it is used for the \*(``ACS_\*('' +constants in . +.PP +The comparable data for the wide-character library is a private variable. +.SS Current Terminal Data +After initializing the curses or terminfo interfaces, +the \fBcur_term\fP contains data describing the current terminal. +This variable is also set as a side-effect of \fBset_term\fP(3) +and \fBdelscreen\fP(3). +.PP +It is possible to save a value of \fBcur_term\fP for subsequent +use as a parameter to \fBset_term\fP, for switching between screens. +Alternatively, one can save the return value from \fBnewterm\fP +or \fBsetupterm\fP(3) to reuse in \fBset_term\fP. +.SS Terminfo Lookup Tables +The \fBtic\fP(1) and \fBinfocmp\fP(1) programs use lookup tables for +the long and short names of terminfo capabilities, +as well as the corresponding names for termcap capabilities. +These are available to other applications, +although the hash-tables used by +the terminfo and termcap functions are not available. +.PP +The long terminfo capability names use a \*(``f\*('' (eff) in their names: +\fBboolfnames\fP, +\fBnumfnames\fP, and +\fBstrfnames\fP. +.PP +These are the short names for terminfo capabilities: +\fBboolnames\fP, +\fBnumnames\fP, and +\fBstrnames\fP. +.PP +These are the corresponding names used for termcap descriptions: +\fBboolcodes\fP, +\fBnumcodes\fP, and +\fBstrcodes\fP. +.\" +.SS Terminal Type +A terminal description begins with one or more terminal names +separated by \*(``|\*('' (vertical bars). +On initialization of the curses or terminfo interfaces, +\fBsetupterm\fP(3) copies the terminal names to the array \fBttytype\fP. +.\" +.SS Terminfo Names +In addition to the variables, \fB\fP also defines a symbol for each +terminfo capability \fIlong name\fP. +These are in terms of the symbol \fBCUR\fP, +which is defined +.PP +.nf +.ft CW +#define CUR ((TERMTYPE *)(cur_term))-> +.fi +.ft R +.PP +These symbols provide a faster method of accessing terminfo capabilities +than using \fBtigetstr\fP(3), etc. +.PP +The actual definition of \fBCUR\fP depends upon the implementation, +but each terminfo library provides these long names defined to point +into the current terminal description loaded into memory. +.\" +.SH NOTES +The low-level terminfo interface is initialized using +.hy 0 +\fBsetupterm\fP(3). +.hy +The upper-level curses interface uses the low-level terminfo interface, +internally. +.\" +.SH PORTABILITY +X/Open Curses does not describe any of these except for \fBcur_term\fP. +(The inclusion of \fBcur_term\fP appears to be an oversight, +since other comparable low-level information is omitted by X/Open). +.PP +Other implementations may have comparable variables. +Some implementations provide the variables in their libraries, +but omit them from the header files. +.PP +All implementations which provide terminfo interfaces add definitions +as described in the \fBTerminfo Names\fP section. +Most, but not all, base the definition upon the \fBcur_term\fP variable. +.SH SEE ALSO +.hy 0 +\fBcurses\fP(3), +\fBterminfo\fP(3), +\fBcurs_threads\fP(3), +\fBterminfo\fP(\*n). +.hy diff --git a/lib/libcurses/termcap.3 b/lib/libcurses/termcap.3 index 7bdab28b4a1..1486bdc9ae2 100644 --- a/lib/libcurses/termcap.3 +++ b/lib/libcurses/termcap.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: termcap.3,v 1.9 2013/12/10 20:33:51 naddy Exp $ +.\" $OpenBSD: termcap.3,v 1.10 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2017,2018 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,142 +29,361 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: termcap.3,v 1.9 2013/12/10 20:33:51 naddy Exp $ -.TH termcap 3 "" +.\" $Id: termcap.3,v 1.10 2023/10/17 09:52:08 nicm Exp $ +.TH termcap 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.na +.hy 0 .ds n 5 .SH NAME -\fBtgetent\fR, -\fBtgetflag\fR, -\fBtgetnum\fR, -\fBtgetstr\fR, -\fBtgoto\fR, -\fBtputs\fR - direct \fBcurses\fR interface to the terminfo capability database +\fBPC\fP, +\fBUP\fP, +\fBBC\fP, +\fBospeed\fP, +\fBtgetent\fP, +\fBtgetflag\fP, +\fBtgetnum\fP, +\fBtgetstr\fP, +\fBtgoto\fP, +\fBtputs\fP \- \fBcurses\fP emulation of termcap +.ad +.hy .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .br -\fB#include \fR +\fB#include \fP .sp -\fBextern char PC;\fR +\fBextern char PC;\fP .br -\fBextern char * UP;\fR +\fBextern char * UP;\fP .br -\fBextern char * BC;\fR +\fBextern char * BC;\fP .br -\fBextern int ospeed;\fR +\fBextern int ospeed;\fP .sp -\fBint tgetent(char *bp, const char *name);\fR +\fBint tgetent(char *\fIbp\fB, const char *\fIname\fB);\fR .br -\fBint tgetflag(char *id);\fR +\fBint tgetflag(const char *\fIid\fB);\fR .br -\fBint tgetnum(char *id);\fR +\fBint tgetnum(const char *\fIid\fB);\fR .br -\fBchar *tgetstr(char *id, char **area);\fR +\fBchar *tgetstr(const char *\fIid\fB, char **\fIarea\fB);\fR .br -\fBchar *tgoto(const char *cap, int col, int row);\fR -.br -\fBint tputs(const char *str, int affcnt, int (*putc)(int));\fR +\fBchar *tgoto(const char *\fIcap\fB, int \fIcol\fB, int \fIrow\fB);\fR .br +\fBint tputs(const char *\fIstr\fB, int \fIaffcnt\fB, int (*\fIputc\fB)(int));\fR .SH DESCRIPTION These routines are included as a conversion aid for programs that use -the \fItermcap\fR library. Their parameters are the same and the -routines are emulated using the \fIterminfo\fR database. Thus, they +the \fItermcap\fP library. +Their parameters are the same, but the +routines are emulated using the \fIterminfo\fP database. +Thus, they can only be used to query the capabilities of entries for which a terminfo entry has been compiled. +.SS Initialization +The \fBtgetent\fP routine loads the entry for \fIname\fP. +It returns: +.RS 3 +.TP 3 +1 +on success, +.TP 3 +0 +if there is no such entry +(or that it is a generic type, having too little information for curses +applications to run), and +.TP 3 +\-1 +if the terminfo database could not be found. +.RE .PP -The \fBtgetent\fR routine loads the entry for \fIname\fR. -It returns 1 on success, 0 if there is no such entry, and -1 if the -terminfo database could not be found. -The emulation ignores the buffer pointer \fIbp\fR. -.PP -The \fBtgetflag\fR routine gets the boolean entry for \fIid\fR, +This differs from the \fItermcap\fP library in two ways: +.RS 3 +.bP +The emulation ignores the buffer pointer \fIbp\fP. +The \fItermcap\fP library would store a copy of the terminal +description in the area referenced by this pointer. +However, ncurses stores its terminal descriptions in compiled +binary form, which is not the same thing. +.bP +There is a difference in return codes. +The \fItermcap\fP library does not check if the terminal +description is marked with the \fIgeneric\fP capability, +or if the terminal description has cursor-addressing. +.RE +.SS Capability Values +The \fBtgetflag\fP routine gets the boolean entry for \fIid\fP, or zero if it is not available. .PP -The \fBtgetnum\fR routine gets the numeric entry for \fIid\fR, -or -1 if it is not available. +The \fBtgetnum\fP routine gets the numeric entry for \fIid\fP, +or \-1 if it is not available. .PP -The \fBtgetstr\fR routine returns the string entry for \fIid\fR, +The \fBtgetstr\fP routine returns the string entry for \fIid\fP, or zero if it is not available. -Use \fBtputs\fR to output the returned string. -The return value will also be copied to the buffer pointed to by \fIarea\fR, -and the \fIarea\fR value will be updated to point past the null ending +Use \fBtputs\fP to output the returned string. +The \fIarea\fP parameter is used as follows: +.RS 3 +.bP +It is assumed to be the address of a pointer to a buffer managed by the +calling application. +.bP +However, ncurses checks to ensure that \fBarea\fP is not NULL, +and also that the resulting buffer pointer is not NULL. +If either check fails, the \fIarea\fP parameter is ignored. +.bP +If the checks succeed, ncurses also copies the return value to +the buffer pointed to by \fIarea\fP, +and the \fIarea\fP value will be updated to point past the null ending this value. +.bP +The return value itself is an address in the terminal description which +is loaded into memory. +.RE .PP -Only the first two characters of the \fBid\fR parameter of -\fBtgetflag\fR, -\fBtgetnum\fR and -\fBtgetstr\fR are compared in lookups. -.PP -The \fBtgoto\fR routine instantiates the parameters into the given capability. -The output from this routine is to be passed to \fBtputs\fR. -.PP -The \fBtputs\fR routine is described on the \fBterminfo\fR(3) manual -page. It can retrieve capabilities by either termcap or terminfo name. +Only the first two characters of the \fBid\fP parameter of +\fBtgetflag\fP, +\fBtgetnum\fP and +\fBtgetstr\fP are compared in lookups. +.SS Formatting Capabilities +The \fBtgoto\fP routine expands the given capability using the parameters. +.bP +Because the capability may have padding characters, +the output of \fBtgoto\fP should be passed to \fBtputs\fP +rather than some other output function such as \fBprintf\fP(3). +.bP +While \fBtgoto\fP is assumed to be used for the two-parameter +cursor positioning capability, +termcap applications also use it for single-parameter capabilities. +.IP +Doing this shows a quirk in \fBtgoto\fP: most hardware +terminals use cursor addressing with \fIrow\fP first, +but the original developers of the termcap interface chose to +put the \fIcolumn\fP parameter first. +The \fBtgoto\fP function swaps the order of parameters. +It does this also for calls requiring only a single parameter. +In that case, the first parameter is merely a placeholder. +.bP +Normally the ncurses library is compiled with terminfo support. +In that case, \fBtgoto\fP uses an internal version of +\fBtparm\fP(3) (a more capable formatter). +.IP +With terminfo support, \fBtgoto\fP is able to use some of the terminfo +features, but not all. +In particular, it allows only numeric parameters; +\fBtparm\fP supports string parameters. +.IP +However, \fBtparm\fP is not a \fItermcap\fP feature, +and portable \fItermcap\fP applications should not rely upon its availability. .PP +The \fBtputs\fP routine is described on the \fBterminfo\fP(3) manual +page. +It can retrieve capabilities by either termcap or terminfo name. +.SS Global Variables The variables -\fBPC\fR, -\fBUP\fR and -\fBBC\fR -are set by \fBtgetent\fR to the terminfo entry's data for -\fBpad_char\fR, -\fBcursor_up\fR and -\fBbackspace_if_not_bs\fR, +\fBPC\fP, +\fBUP\fP and +\fBBC\fP +are set by \fBtgetent\fP to the terminfo entry's data for +\fBpad_char\fP, +\fBcursor_up\fP and +\fBbackspace_if_not_bs\fP, respectively. -\fBUP\fR is not used by ncurses. -\fBPC\fR is used in the \fBtdelay_output\fR function. -\fBBC\fR is used in the \fBtgoto\fR emulation. -The variable \fBospeed\fR is set by ncurses in a system-specific coding +\fBUP\fP is not used by ncurses. +\fBPC\fP is used in the \fBtdelay_output\fP function. +\fBBC\fP is used in the \fBtgoto\fP emulation. +The variable \fBospeed\fP is set by ncurses in a system-specific coding to reflect the terminal speed. +.SS Releasing Memory +The termcap functions provide no means for freeing memory, +because legacy termcap implementations used only the buffer +areas provided by the caller via \fBtgetent\fP and \fBtgetstr\fP. +Those buffers are unused in terminfo. +.PP +On the other hand, terminfo allocates memory. +It uses \fBsetupterm\fP to retrieve the data used by \fBtgetent\fP +and the functions which return capability values such as \fBtgetstr\fP. +One could use +.sp + \fBdel_curterm(cur_term);\fP +.sp +.PP +to free this memory, but there is an additional complication with ncurses. +It uses a fixed-size \fIpool\fP of storage locations, +one per setting of the \fBTERM\fP variable when \fBtgetent\fP is called. +The \fBscreen\fP(1) program relies upon this arrangement, +to improve its performance. +.PP +An application which uses only the low-level termcap functions could +free the memory using \fBdel_curterm\fP, +because the pool is freed using other functions +(see \fBcurs_memleaks\fP(3)). . .SH RETURN VALUE Except where explicitly noted, -routines that return an integer return \fBERR\fR upon failure and \fBOK\fR -(SVr4 only specifies "an integer value other than \fBERR\fR") upon successful +routines that return an integer return \fBERR\fP upon failure and \fBOK\fP +(SVr4 only specifies "an integer value other than \fBERR\fP") upon successful completion. .PP -Routines that return pointers return \fBNULL\fR on error. +Routines that return pointers return \fBNULL\fP on error. +.PP +A few special cases apply: +.bP +If the terminal database has not been initialized, +these return an error. +.bP +The calls with a string parameter (\fBtgoto\fP, \fBtputs\fP) +check if the string is null, or cancelled. +Those return an error. +.bP +A call to \fBtgoto\fP using a capability with string parameters is an error. +.bP +A call to \fBtgoto\fP using a capability with more than two parameters +is an error. .SH BUGS -If you call \fBtgetstr\fR to fetch \fBca\fR or any other parameterized string, +If you call \fBtgetstr\fP to fetch \fBca\fP or any other parameterized string, be aware that it will be returned in terminfo notation, not the older and -not-quite-compatible termcap notation. This will not cause problems if all -you do with it is call \fBtgoto\fR or \fBtparm\fR, which both expand +not-quite-compatible termcap notation. +This will not cause problems if all +you do with it is call \fBtgoto\fP or \fBtparm\fP, which both expand terminfo-style strings as terminfo. -(The \fBtgoto\fR function, if configured to support termcap, will check +(The \fBtgoto\fP function, if configured to support termcap, will check if the string is indeed terminfo-style by looking for "%p" parameters or "$<..>" delays, and invoke a termcap-style parser if the string does not appear to be terminfo). .PP Because terminfo conventions for representing padding in string capabilities -differ from termcap's, \fBtputs("50");\fR will put out a literal "50" rather -than busy-waiting for 50 milliseconds. Cope with it. +differ from termcap's, +users can be surprised: +.bP +\fBtputs("50")\fP in a terminfo system will put out a literal \*(``50\*('' +rather than busy-waiting for 50 milliseconds. +.bP +However, if ncurses is configured to support termcap, +it may also have been configured to support the BSD-style padding. +.IP +In that case, \fBtputs\fP inspects strings passed to it, +looking for digits at the beginning of the string. +.IP +\fBtputs("50")\fP in a termcap system may wait for 50 milliseconds +rather than put out a literal \*(``50\*('' .PP -Note that termcap has nothing analogous to terminfo's \fBsgr\fR string. -One consequence of this is that termcap applications assume \fRme\fR -(terminfo \fBsgr0\fR) does not reset the alternate character set. +Note that termcap has nothing analogous to terminfo's \fBsgr\fP string. +One consequence of this is that termcap applications assume \fBme\fP +(terminfo \fBsgr0\fP) does not reset the alternate character set. This implementation checks for, and modifies the data shown to the termcap interface to accommodate termcap's limitation in this respect. .SH PORTABILITY -The XSI Curses standard, Issue 4 describes these functions. However, they +.SS Standards +These functions are provided for supporting legacy applications, +and should not be used in new programs: +.bP +The XSI Curses standard, Issue 4 describes these functions. +However, they are marked TO BE WITHDRAWN and may be removed in future versions. +.bP +X/Open Curses, Issue 5 (December 2007) marked the termcap interface +(along with \fBvwprintw\fP and \fBvwscanw\fP) as withdrawn. .PP Neither the XSI Curses standard nor the SVr4 man pages documented the return -values of \fBtgetent\fR correctly, though all three were in fact returned ever +values of \fBtgetent\fP correctly, though all three were in fact returned ever since SVr1. In particular, an omission in the XSI Curses documentation has been -misinterpreted to mean that \fBtgetent\fR returns \fBOK\fR or \fBERR\fR. +misinterpreted to mean that \fBtgetent\fP returns \fBOK\fP or \fBERR\fP. Because the purpose of these functions is to provide compatibility with -the \fItermcap\fR library, that is a defect in XCurses, Issue 4, Version 2 +the \fItermcap\fP library, that is a defect in XCurses, Issue 4, Version 2 rather than in ncurses. -.PP +.SS Compatibility with BSD Termcap External variables are provided for support of certain termcap applications. However, termcap applications' use of those variables is poorly documented, e.g., not distinguishing between input and output. In particular, some applications are reported to declare and/or -modify \fBospeed\fR. +modify \fBospeed\fP. +.PP +The comment that only the first two characters of the \fBid\fP parameter +are used escapes many application developers. +The original BSD 4.2 termcap library (and historical relics thereof) +did not require a trailing null NUL on the parameter name passed +to \fBtgetstr\fP, \fBtgetnum\fP and \fBtgetflag\fP. +Some applications assume that the termcap interface does not require +the trailing NUL for the parameter name. +Taking into account these issues: +.bP +As a special case, +\fBtgetflag\fP matched against a single-character identifier +provided that was at the end of the terminal description. +You should not rely upon this behavior in portable programs. +This implementation disallows matches against single-character capability names. +.bP +This implementation disallows matches by the termcap interface against +extended capability names which are longer than two characters. +.PP +The BSD termcap function \fBtgetent\fP returns the text of a termcap +entry in the buffer passed as an argument. +This library (like other terminfo implementations) does not store +terminal descriptions as text. +It sets the buffer contents to a null-terminated string. +.SS Other Compatibility +This library includes a termcap.h header, +for compatibility with other implementations. +But the header is rarely used because the other implementations +are not strictly compatible. +.PP +The original BSD termcap (through 4.3BSD) had no header file which +gave function prototypes, because that was a feature of ANSI C. +BSD termcap was written several years before C was standardized. +However, there were two different termcap.h header files in the BSD +sources: +.bP +One was used internally by the \fBjove\fP editor in 2BSD through 4.4BSD. +It defined global symbols for the termcap variables which it used. +.bP +The other appeared in 4.4BSD Lite Release 2 (mid-1993) +as part of \fIlibedit\fP (also known as the \fIeditline\fP library). +The CSRG source history shows that this was added in mid-1992. +The \fIlibedit\fP header file was used internally, +as a convenience for compiling the \fIeditline\fP library. +It declared function prototypes, but no global variables. +.PP +The header file from \fIlibedit\fP was added to NetBSD's termcap +library in mid-1994. +.PP +Meanwhile, GNU termcap was under development, starting in 1990. +The first release (termcap 1.0) in 1991 included a termcap.h header. +The second release (termcap 1.1) in September 1992 modified the +header to use \fBconst\fP for the function prototypes in the header +where one would expect the parameters to be read-only. +This was a difference versus the original BSD termcap. +The prototype for \fBtputs\fP also differed, +but in that instance, it was \fIlibedit\fP which differed from BSD termcap. +.PP +A copy of GNU termcap 1.3 was bundled with \fIbash\fP in mid-1993, +to support the \fBreadline\fP(3) library. +.PP +A termcap.h file was provided in ncurses 1.8.1 (November 1993). +That reflected influence by \fBemacs\fP(1) (rather than \fBjove\fP(1)) +and GNU termcap: +.bP +it provided declarations for a few global symbols used by \fBemacs\fP +.bP +it provided function prototypes (using \fBconst\fP). +.bP +a prototype for \fBtparam\fP (a GNU termcap feature) was provided. +.PP +Later (in mid-1996) the \fBtparam\fP function was removed from ncurses. +As a result, there are differences between any of the four implementations, +which must be taken into account by programs which can work with all +termcap library interfaces. .SH SEE ALSO -\fBcurses\fR(3), \fBterminfo\fR(\*n), \fBputc\fR(3). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBputc\fP(3), +\fBterm_variables\fP(3), +\fBterminfo\fP(\*n). +.sp +https://invisible-island.net/ncurses/tctest.html diff --git a/lib/libcurses/termcap.h b/lib/libcurses/termcap.h index 648763d758c..944d8b15680 100644 --- a/lib/libcurses/termcap.h +++ b/lib/libcurses/termcap.h @@ -1,7 +1,8 @@ -/* $OpenBSD: termcap.h,v 1.11 2020/12/14 22:05:31 naddy Exp $ */ +/* $OpenBSD: termcap.h,v 1.12 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright 2018-2020,2021 Thomas E. Dickey * + * Copyright 1998-2000,2001 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,26 +34,15 @@ * and: Eric S. Raymond * ****************************************************************************/ -/* $Id: termcap.h,v 1.11 2020/12/14 22:05:31 naddy Exp $ */ +/* $Id: termcap.h,v 1.12 2023/10/17 09:52:08 nicm Exp $ */ #ifndef NCURSES_TERMCAP_H_incl #define NCURSES_TERMCAP_H_incl 1 #undef NCURSES_VERSION -#define NCURSES_VERSION "5.7" +#define NCURSES_VERSION "6.4" -#if !defined(NCURSES_IMPEXP) -# define NCURSES_IMPEXP /* nothing */ -#endif -#if !defined(NCURSES_API) -# define NCURSES_API /* nothing */ -#endif -#if !defined(NCURSES_EXPORT) -# define NCURSES_EXPORT(type) NCURSES_IMPEXP type NCURSES_API -#endif -#if !defined(NCURSES_EXPORT_VAR) -# define NCURSES_EXPORT_VAR(type) NCURSES_IMPEXP type -#endif +#include #ifdef __cplusplus extern "C" @@ -61,23 +51,20 @@ extern "C" #include -#undef NCURSES_CONST -#define NCURSES_CONST const - -#undef NCURSES_OSPEED -#define NCURSES_OSPEED int +#undef NCURSES_OSPEED +#define NCURSES_OSPEED int extern NCURSES_EXPORT_VAR(char) PC; extern NCURSES_EXPORT_VAR(char *) UP; extern NCURSES_EXPORT_VAR(char *) BC; -extern NCURSES_EXPORT_VAR(NCURSES_OSPEED) ospeed; +extern NCURSES_EXPORT_VAR(NCURSES_OSPEED) ospeed; #if !defined(NCURSES_TERM_H_incl) -extern NCURSES_EXPORT(char *) tgetstr (NCURSES_CONST char *, char **); +extern NCURSES_EXPORT(char *) tgetstr (const char *, char **); extern NCURSES_EXPORT(char *) tgoto (const char *, int, int); extern NCURSES_EXPORT(int) tgetent (char *, const char *); -extern NCURSES_EXPORT(int) tgetflag (NCURSES_CONST char *); -extern NCURSES_EXPORT(int) tgetnum (NCURSES_CONST char *); +extern NCURSES_EXPORT(int) tgetflag (const char *); +extern NCURSES_EXPORT(int) tgetnum (const char *); extern NCURSES_EXPORT(int) tputs (const char *, int, int (*)(int)); #endif diff --git a/lib/libcurses/terminfo.3 b/lib/libcurses/terminfo.3 index c2471742827..257f0a3ddbc 100644 --- a/lib/libcurses/terminfo.3 +++ b/lib/libcurses/terminfo.3 @@ -1,7 +1,9 @@ -.\" $OpenBSD: terminfo.3,v 1.10 2010/01/12 23:21:59 nicm Exp $ +'\" t +.\" $OpenBSD: terminfo.3,v 1.11 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1999-2007,2008 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2016,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,249 +30,455 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: terminfo.3,v 1.10 2010/01/12 23:21:59 nicm Exp $ -.TH terminfo 3 "" +.\" $Id: terminfo.3,v 1.11 2023/10/17 09:52:08 nicm Exp $ +.TH terminfo 3 2023-08-19 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .ds n 5 .na .hy 0 .SH NAME -\fBdel_curterm\fR, -\fBmvcur\fR, -\fBputp\fR, -\fBrestartterm\fR, -\fBset_curterm\fR, -\fBsetterm\fR, -\fBsetupterm\fR, -\fBtigetflag\fR, -\fBtigetnum\fR, -\fBtigetstr\fR, -\fBtparm\fR, -\fBtputs\fR, -\fBvid_attr\fR, -\fBvid_puts\fR, -\fBvidattr\fR, -\fBvidputs\fR - \fBcurses\fR interfaces to terminfo database +\fBdel_curterm\fP, +\fBmvcur\fP, +\fBputp\fP, +\fBrestartterm\fP, +\fBset_curterm\fP, +\fBsetupterm\fP, +\fBtigetflag\fP, +\fBtigetnum\fP, +\fBtigetstr\fP, +\fBtiparm\fP, +\fBtiparm_s\fP, +\fBtiscan_s\fP, +\fBtparm\fP, +\fBtputs\fP, +\fBvid_attr\fP, +\fBvid_puts\fP, +\fBvidattr\fP, +\fBvidputs\fP \- \fBcurses\fP interfaces to terminfo database .ad .hy .SH SYNOPSIS .nf -\fB#include \fR -.br -\fB#include \fR -.PP -\fBint setupterm(char *\fR\fIterm\fR\fB, int \fR\fIfildes\fR\fB, int *\fR\fIerrret\fR\fB);\fR -.br -\fBint setterm(char *\fR\fIterm\fR\fB);\fR -.br -\fBTERMINAL *set_curterm(TERMINAL *\fR\fInterm\fR\fB);\fR +\fB#include \fP +\fB#include \fP +.sp +\fBTERMINAL *cur_term;\fP +.sp +\fBconst char * const boolnames[];\fP +\fBconst char * const boolcodes[];\fP +\fBconst char * const boolfnames[];\fP +\fBconst char * const numnames[];\fP +\fBconst char * const numcodes[];\fP +\fBconst char * const numfnames[];\fP +\fBconst char * const strnames[];\fP +\fBconst char * const strcodes[];\fP +\fBconst char * const strfnames[];\fP +.sp +\fBint setupterm(const char *\fIterm\fB, int \fIfiledes\fB, int *\fIerrret\fB);\fR .br -\fBint del_curterm(TERMINAL *\fR\fIoterm\fR\fB);\fR +\fBTERMINAL *set_curterm(TERMINAL *\fInterm\fB);\fR .br -\fBint restartterm(char *\fR\fIterm\fR\fB, int \fR\fIfildes\fR\fB, int *\fR\fIerrret\fR\fB);\fR +\fBint del_curterm(TERMINAL *\fIoterm\fB);\fR .br -\fBchar *tparm(char *\fR\fIstr\fR\fB, ...);\fR +\fBint restartterm(const char *\fIterm\fB, int \fIfiledes\fB, int *\fIerrret\fB);\fR +.sp +\fBchar *tparm(const char *\fIstr\fB, ...);\fR .br -\fBint tputs(const char *\fR\fIstr\fR\fB, int \fR\fIaffcnt\fR\fB, int (*\fR\fIputc\fR\fB)(int));\fR + \fIor\fP .br -\fBint putp(const char *\fR\fIstr\fR\fB);\fR +\fBchar *tparm(const char *\fIstr\fB, long \fIp1 ... \fBlong \fIp9\fB);\fR +.sp +\fBint tputs(const char *\fIstr\fB, int \fIaffcnt\fB, int (*\fIputc\fB)(int));\fR .br -\fBint vidputs(chtype \fR\fIattrs\fR\fB, int (*\fR\fIputc\fR\fB)(int));\fR +\fBint putp(const char *\fIstr\fB);\fR +.sp +\fBint vidputs(chtype \fIattrs\fB, int (*\fIputc\fB)(int));\fR .br -\fBint vidattr(chtype \fR\fIattrs\fR\fB);\fR +\fBint vidattr(chtype \fIattrs\fB);\fR .br -\fBint vid_puts(attr_t \fR\fIattrs\fR\fB, short \fR\fIpair\fR\fB, void *\fR\fIopts\fR\fB, int (*\fR\fIputc\fR\fB)(char));\fR +\fBint vid_puts(attr_t \fIattrs\fB, short \fIpair\fB, void *\fIopts\fB, int (*\fIputc\fB)(int));\fR .br -\fBint vid_attr(attr_t \fR\fIattrs\fR\fB, short \fR\fIpair\fR\fB, void *\fR\fIopts\fR\fB);\fR +\fBint vid_attr(attr_t \fIattrs\fB, short \fIpair\fB, void *\fIopts\fB);\fR +.sp +\fBint mvcur(int \fIoldrow\fB, int \fIoldcol\fB, int \fInewrow\fR, int \fInewcol\fB);\fR +.sp +\fBint tigetflag(const char *\fIcapname\fB);\fR .br -\fBint mvcur(int \fR\fIoldrow\fR\fB, int \fR\fIoldcol\fR\fB, int \fR\fInewrow\fR, int \fR\fInewcol\fR\fB);\fR +\fBint tigetnum(const char *\fIcapname\fB);\fR .br -\fBint tigetflag(char *\fR\fIcapname\fR\fB);\fR +\fBchar *tigetstr(const char *\fIcapname\fB);\fR +.sp +\fBchar *tiparm(const char *\fIstr\fB, ...);\fR +.sp +/* extensions */ .br -\fBint tigetnum(char *\fR\fIcapname\fR\fB);\fR +\fBchar *tiparm_s(int \fIexpected\fB, int \fImask\fB, const char *\fIstr\fB, ...);\fR .br -\fBchar *tigetstr(char *\fR\fIcapname\fR\fB);\fR +\fBint tiscan_s(int *\fIexpected\fB, int *\fImask\fB, const char *\fIstr\fB);\fR .br .fi .SH DESCRIPTION These low-level routines must be called by programs that have to deal -directly with the \fBterminfo\fR database to handle certain terminal -capabilities, such as programming function keys. For all other -functionality, \fBcurses\fR routines are more suitable and their use is +directly with the \fBterminfo\fP database to handle certain terminal +capabilities, such as programming function keys. +For all other +functionality, \fBcurses\fP routines are more suitable and their use is recommended. .PP -Initially, \fBsetupterm\fR should be called. Note that -\fBsetupterm\fR is automatically called by \fBinitscr\fR and -\fBnewterm\fR. This defines the set of terminal-dependent variables -[listed in \fBterminfo\fR(\*n)]. -The \fBterminfo\fR variables -\fBlines\fR and \fBcolumns\fR are initialized by \fBsetupterm\fR as -follows: -.RS -.PP -If \fBuse_env(FALSE)\fR has been called, values for -\fBlines\fR and \fBcolumns\fR specified in \fBterminfo\fR are used. +None of these functions use (or are aware of) multibyte character strings +such as UTF-8: +.bP +capability names use the POSIX portable character set +.bP +capability string values have no associated encoding; +they are strings of 8-bit characters. +.SS Initialization +Initially, \fBsetupterm\fP should be called. +The high-level curses functions \fBinitscr\fP and +\fBnewterm\fP call \fBsetupterm\fP to initialize the +low-level set of terminal-dependent variables +[listed in \fBterminfo\fP(\*n)]. +.PP +Applications can use the +terminal capabilities either directly (via header definitions), +or by special functions. +The header files \fBcurses.h\fP and \fBterm.h\fP should be included (in this +order) to get the definitions for these strings, numbers, and flags. .PP -Otherwise, if the environment variables \fBLINES\fR and \fBCOLUMNS\fR -exist, their values are used. If these environment variables do not +The \fBterminfo\fP variables +\fBlines\fP and \fBcolumns\fP are initialized by \fBsetupterm\fP as +follows: +.bP +If \fBuse_env(FALSE)\fP has been called, values for +\fBlines\fP and \fBcolumns\fP specified in \fBterminfo\fP are used. +.bP +Otherwise, if the environment variables \fBLINES\fP and \fBCOLUMNS\fP +exist, their values are used. +If these environment variables do not exist and the program is running in a window, the current window size -is used. Otherwise, if the environment variables do not exist, the -values for \fBlines\fR and \fBcolumns\fR specified in the -\fBterminfo\fR database are used. -.RE -.PP -The header files \fBcurses.h\fR and \fBterm.h\fR should be included (in this -order) to get the definitions for these strings, numbers, and flags. -Parameterized strings should be passed through \fBtparm\fR to instantiate them. -All \fBterminfo\fR strings [including the output of \fBtparm\fR] should be printed -with \fBtputs\fR or \fBputp\fR. Call the \fBreset_shell_mode\fR to restore the -tty modes before exiting [see \fBcurs_kernel\fR(3)]. Programs which use -cursor addressing should output \fBenter_ca_mode\fR upon startup and should -output \fBexit_ca_mode\fR before exiting. Programs desiring shell escapes -should call -.PP -\fBreset_shell_mode\fR and output \fBexit_ca_mode\fR before the shell -is called and should output \fBenter_ca_mode\fR and call -\fBreset_prog_mode\fR after returning from the shell. -.PP -The \fBsetupterm\fR routine reads in the \fBterminfo\fR database, -initializing the \fBterminfo\fR structures, but does not set up the -output virtualization structures used by \fBcurses\fR. The terminal -type is the character string \fIterm\fR; if \fIterm\fR is null, the -environment variable \fBTERM\fR is used. -All output is to file descriptor \fBfildes\fR which is initialized for output. -If \fIerrret\fR is not null, -then \fBsetupterm\fR returns \fBOK\fR or -\fBERR\fR and stores a status value in the integer pointed to by -\fIerrret\fR. -A return value of \fBOK\fR combined with status of \fB1\fR in \fIerrret\fR +is used. +Otherwise, if the environment variables do not exist, the +values for \fBlines\fP and \fBcolumns\fP specified in the +\fBterminfo\fP database are used. +.PP +Parameterized strings should be passed through \fBtparm\fP to instantiate them. +All \fBterminfo\fP strings +(including the output of \fBtparm\fP) +should be printed +with \fBtputs\fP or \fBputp\fP. +Call \fBreset_shell_mode\fP to restore the +tty modes before exiting [see \fBcurs_kernel\fP(3)]. +.PP +Programs which use +cursor addressing should +.bP +output \fBenter_ca_mode\fP upon startup and +.bP +output \fBexit_ca_mode\fP before exiting. +.PP +Programs which execute shell subprocesses should +.bP +call \fBreset_shell_mode\fP and +output \fBexit_ca_mode\fP before the shell +is called and +.bP +output \fBenter_ca_mode\fP and +call \fBreset_prog_mode\fP after returning from the shell. +.PP +The \fBsetupterm\fP routine reads in the \fBterminfo\fP database, +initializing the \fBterminfo\fP structures, but does not set up the +output virtualization structures used by \fBcurses\fP. +These are its parameters: +.RS 3 +.TP 5 +\fIterm\fP +is the terminal type, a character string. +If \fIterm\fP is null, the environment variable \fBTERM\fP is used. +.TP 5 +\fIfiledes\fP +is the file descriptor used for getting and setting terminal I/O modes. +.IP +Higher-level applications use \fBnewterm\fP(3) for initializing the terminal, +passing an output \fIstream\fP rather than a \fIdescriptor\fP. +In curses, the two are the same because \fBnewterm\fP calls \fBsetupterm\fP, +passing the file descriptor derived from its output stream parameter. +.TP 5 +\fIerrret\fP +points to an optional location where an error status can be returned to +the caller. +If \fIerrret\fP is not null, +then \fBsetupterm\fP returns \fBOK\fP or +\fBERR\fP and stores a status value in the integer pointed to by +\fIerrret\fP. +A return value of \fBOK\fP combined with status of \fB1\fP in \fIerrret\fP is normal. -If \fBERR\fR is returned, examine \fIerrret\fR: +.IP +If \fBERR\fP is returned, examine \fIerrret\fP: .RS .TP 5 .B 1 means that the terminal is hardcopy, cannot be used for curses applications. +.IP +\fBsetupterm\fP determines if the entry is a hardcopy type by +checking the \fBhc\fP (\fBhardcopy\fP) capability. .TP 5 .B 0 means that the terminal could not be found, or that it is a generic type, having too little information for curses applications to run. +.IP +\fBsetupterm\fP determines if the entry is a generic type by +checking the \fBgn\fP (\fBgeneric_type\fP) capability. .TP 5 -.B -1 -means that the \fBterminfo\fR database could not be found. +.B \-1 +means that the \fBterminfo\fP database could not be found. .RE -.PP -If \fIerrret\fR is -null, \fBsetupterm\fR prints an error message upon finding an error -and exits. Thus, the simplest call is: -.sp - \fBsetupterm((char *)0, 1, (int *)0);\fR, -.sp -which uses all the defaults and sends the output to \fBstdout\fR. -.PP -The \fBsetterm\fR routine is being replaced by \fBsetupterm\fR. The call: +.IP +If \fIerrret\fP is +null, \fBsetupterm\fP prints an error message upon finding an error +and exits. +Thus, the simplest call is: .sp - \fBsetupterm(\fR\fIterm\fR\fB, 1, (int *)0)\fR + \fBsetupterm((char *)0, 1, (int *)0);\fP, .sp -provides the same functionality as \fBsetterm(\fR\fIterm\fR\fB)\fR. -The \fBsetterm\fR routine is included here for BSD compatibility, and -is not recommended for new programs. -.PP -The \fBset_curterm\fR routine sets the variable \fBcur_term\fR to -\fInterm\fR, and makes all of the \fBterminfo\fR boolean, numeric, and -string variables use the values from \fInterm\fR. It returns the old value -of \fBcur_term\fR. -.PP -The \fBdel_curterm\fR routine frees the space pointed to by -\fIoterm\fR and makes it available for further use. If \fIoterm\fR is -the same as \fBcur_term\fR, references to any of the \fBterminfo\fR +which uses all the defaults and sends the output to \fBstdout\fP. +.RE +.\" *************************************************************************** +.SS The Terminal State +The \fBsetupterm\fP routine stores its information about the terminal +in a \fBTERMINAL\fP structure pointed to by the global variable \fBcur_term\fP. +If it detects an error, +or decides that the terminal is unsuitable (hardcopy or generic), +it discards this information, +making it not available to applications. +.PP +If \fBsetupterm\fP is called repeatedly for the same terminal type, +it will reuse the information. +It maintains only one copy of a given terminal's capabilities in memory. +If it is called for different terminal types, +\fBsetupterm\fP allocates new storage for each set of terminal capabilities. +.PP +The \fBset_curterm\fP routine sets \fBcur_term\fP to +\fInterm\fP, and makes all of the \fBterminfo\fP boolean, numeric, and +string variables use the values from \fInterm\fP. +It returns the old value of \fBcur_term\fP. +.PP +The \fBdel_curterm\fP routine frees the space pointed to by +\fIoterm\fP and makes it available for further use. +If \fIoterm\fP is +the same as \fBcur_term\fP, references to any of the \fBterminfo\fP boolean, numeric, and string variables thereafter may refer to invalid -memory locations until another \fBsetupterm\fR has been called. +memory locations until another \fBsetupterm\fP has been called. .PP -The \fBrestartterm\fR routine is similar to \fBsetupterm\fR and \fBinitscr\fR, +The \fBrestartterm\fP routine is similar to \fBsetupterm\fP and \fBinitscr\fP, except that it is called after restoring memory to a previous state (for -example, when reloading a game saved as a core image dump). It assumes that -the windows and the input and output options are the same as when memory was -saved, but the terminal type and baud rate may be different. Accordingly, -it saves various tty state bits, calls \fBsetupterm\fP, -and then restores the bits. -.PP -The \fBtparm\fR routine instantiates the string \fIstr\fR with -parameters \fIpi\fR. A pointer is returned to the result of \fIstr\fR +example, when reloading a game saved as a core image dump). +\fBrestartterm\fP assumes that the windows and the input and output options +are the same as when memory was saved, +but the terminal type and baud rate may be different. +Accordingly, \fBrestartterm\fP saves various tty state bits, +calls \fBsetupterm\fP, and then restores the bits. +.\" *************************************************************************** +.SS Formatting Output +The \fBtparm\fP routine instantiates the string \fIstr\fP with +parameters \fIpi\fP. A pointer is returned to the result of \fIstr\fP with the parameters applied. -.PP -The \fBtputs\fR routine applies padding information to the string -\fIstr\fR and outputs it. The \fIstr\fR must be a terminfo string -variable or the return value from \fBtparm\fR, \fBtgetstr\fR, or -\fBtgoto\fR. \fIaffcnt\fR is the number of lines affected, or 1 if -not applicable. \fIputc\fR is a \fBputchar\fR-like routine to which +Application developers should keep in mind these quirks of the interface: +.bP +Although \fBtparm\fP's actual parameters may be integers or strings, +the prototype expects \fBlong\fP (integer) values. +.bP +Aside from the \fBset_attributes\fP (\fBsgr\fP) capability, +most terminal capabilities require no more than one or two parameters. +.bP +Padding information is ignored by \fBtparm\fP; +it is interpreted by \fBtputs\fP. +.bP +The capability string is null-terminated. +Use \*(``\\200\*('' where an ASCII NUL is needed in the output. +.PP +\fBtiparm\fP is a newer form of \fBtparm\fP which uses \fI\fP +rather than a fixed-parameter list. +Its numeric parameters are integers (int) rather than longs. +.PP +Both \fBtparm\fP and \fBtiparm\fP assume that the application passes +parameters consistent with the terminal description. +Two extensions are provided as alternatives to deal with untrusted data: +.bP +\fBtiparm_s\fP is an extension which is a safer formatting function +than \fBtparm\fR or \fBtiparm\fR, +because it allows the developer to tell the curses +library how many parameters to expect in the parameter list, +and which may be string parameters. +.IP +The \fImask\fP parameter has one bit set for each of the parameters +(up to 9) which will be passed as char* rather than numbers. +.bP +The extension \fBtiscan_s\fP allows the application +to inspect a formatting capability to see what the curses library would assume. +.\" *************************************************************************** +.SS Output Functions +The \fBtputs\fP routine applies padding information +(i.e., by interpreting marker embedded in the terminfo capability +such as \*(``$<5>\*('' as 5 milliseconds) +to the string +\fIstr\fP and outputs it: +.bP +The \fIstr\fP parameter must be a terminfo string +variable or the return value from +\fBtparm\fP, \fBtiparm\fP, \fBtgetstr\fP, or \fBtgoto\fP. +.IP +The \fBtgetstr\fP and \fBtgoto\fP functions are part of the \fItermcap\fP +interface, +which happens to share this function name with the \fIterminfo\fP interface. +.bP +\fIaffcnt\fP is the number of lines affected, or 1 if +not applicable. +.bP +\fIputc\fP is a \fBputchar\fP-like routine to which the characters are passed, one at a time. .PP -The \fBputp\fR routine calls \fBtputs(\fR\fIstr\fR\fB, 1, putchar)\fR. -Note that the output of \fBputp\fR always goes to \fBstdout\fR, not to -the \fIfildes\fR specified in \fBsetupterm\fR. +The \fBputp\fR routine calls \fBtputs(\fIstr\fB, 1, putchar)\fR. +The output of \fBputp\fP always goes to \fBstdout\fP, rather than +the \fIfiledes\fP specified in \fBsetupterm\fP. .PP -The \fBvidputs\fR routine displays the string on the terminal in the -video attribute mode \fIattrs\fR, which is any combination of the -attributes listed in \fBcurses\fR(3). The characters are passed to -the \fBputchar\fR-like routine \fIputc\fR. +The \fBvidputs\fP routine displays the string on the terminal in the +video attribute mode \fIattrs\fP, which is any combination of the +attributes listed in \fBcurses\fP(3). +The characters are passed to +the \fBputchar\fP-like routine \fIputc\fP. .PP -The \fBvidattr\fR routine is like the \fBvidputs\fR routine, except -that it outputs through \fBputchar\fR. +The \fBvidattr\fP routine is like the \fBvidputs\fP routine, except +that it outputs through \fBputchar\fP. .PP -The \fBvid_attr\fR and \fBvid_puts\fR routines correspond to vidattr and vidputs, -respectively. +The \fBvid_attr\fP and \fBvid_puts\fP routines correspond +to vidattr and vidputs, respectively. They use a set of arguments for representing the video attributes plus color, i.e., -one of type attr_t for the attributes and one of short for -the color_pair number. -The \fBvid_attr\fR and \fBvid_puts\fR routines -are designed to use the attribute constants with the \fIWA_\fR prefix. -The opts argument is reserved for future use. -Currently, applications must provide a null pointer for that argument. -.PP -The \fBmvcur\fR routine provides low-level cursor motion. It takes -effect immediately (rather than at the next refresh). -.PP -The \fBtigetflag\fR, \fBtigetnum\fR and \fBtigetstr\fR routines return -the value of the capability corresponding to the \fBterminfo\fR -\fIcapname\fR passed to them, such as \fBxenl\fR. -.PP -The \fBtigetflag\fR routine returns the value \fB-1\fR if -\fIcapname\fR is not a boolean capability, -or \fB0\fR if it is canceled or absent from the terminal description. -.PP -The \fBtigetnum\fR routine returns the value \fB-2\fR if -\fIcapname\fR is not a numeric capability, -or \fB-1\fR if it is canceled or absent from the terminal description. -.PP -The \fBtigetstr\fR routine returns the value \fB(char *)-1\fR -if \fIcapname\fR is not a string capability, -or \fB0\fR if it is canceled or absent from the terminal description. -.PP -The \fIcapname\fR for each capability is given in the table column entitled -\fIcapname\fR code in the capabilities section of \fBterminfo\fR(\*n). +.bP +\fIattrs\fP of type \fBattr_t\fP for the attributes and +.bP +\fIpair\fP of type \fBshort\fP for the color-pair number. +.PP +The \fBvid_attr\fP and \fBvid_puts\fP routines +are designed to use the attribute constants with the \fBWA_\fP prefix. +.PP +X/Open Curses reserves the \fIopts\fP argument for future use, +saying that applications must provide a null pointer for that argument. +As an extension, +this implementation allows \fIopts\fP to be used as a pointer to \fBint\fP, +which overrides the \fIpair\fP (\fBshort\fP) argument. +.PP +The \fBmvcur\fP routine provides low-level cursor motion. +It takes effect immediately (rather than at the next refresh). +Unlike the other low-level output functions, +which either write to the standard output or pass an output function parameter, +\fBmvcur\fP uses an output file descriptor derived from +the output stream parameter of \fBnewterm\fP(3). +.PP +While \fBputp\fP and \fBmvcur\fP are low-level functions which +do not use the high-level curses state, +they are declared in \fB\fP because SystemV did this +(see \fIHISTORY\fP). +.\" *************************************************************************** +.SS Terminal Capability Functions +The \fBtigetflag\fP, \fBtigetnum\fP and \fBtigetstr\fP routines return +the value of the capability corresponding to the \fBterminfo\fP +\fIcapname\fP passed to them, such as \fBxenl\fP. +The \fIcapname\fP for each capability is given in the table column entitled +\fIcapname\fP code in the capabilities section of \fBterminfo\fP(\*n). +.PP +These routines return special values to denote errors. +.PP +The \fBtigetflag\fP routine returns +.TP +\fB\-1\fP +if \fIcapname\fP is not a boolean capability, +or +.TP +\fB0\fP +if it is canceled or absent from the terminal description. +.PP +The \fBtigetnum\fP routine returns +.TP +\fB\-2\fP +if \fIcapname\fP is not a numeric capability, or +.TP +\fB\-1\fP +if it is canceled or absent from the terminal description. +.PP +The \fBtigetstr\fP routine returns +.TP +\fB(char *)\-1\fP +if \fIcapname\fP is not a string capability, +or +.TP +\fB0\fP +if it is canceled or absent from the terminal description. +.\" *************************************************************************** +.SS Terminal Capability Names +These null-terminated arrays contain +.bP +the short terminfo names (\*(``codes\*(''), +.bP +the \fBtermcap\fP names (\*(``names\*(''), and +.bP +the long terminfo names (\*(``fnames\*('') +.PP +for each of the predefined \fBterminfo\fP variables: .sp .RS -\fBchar *boolnames[]\fR, \fB*boolcodes[]\fR, \fB*boolfnames[]\fR +\fBconst char *boolnames[]\fP, \fB*boolcodes[]\fP, \fB*boolfnames[]\fP +.br +\fBconst char *numnames[]\fP, \fB*numcodes[]\fP, \fB*numfnames[]\fP +.br +\fBconst char *strnames[]\fP, \fB*strcodes[]\fP, \fB*strfnames[]\fP +.RE +.\" *************************************************************************** +.SS Releasing Memory +Each successful call to \fBsetupterm\fP allocates memory to hold the terminal +description. +As a side-effect, it sets \fBcur_term\fP to point to this memory. +If an application calls .sp -\fBchar *numnames[]\fR, \fB*numcodes[]\fR, \fB*numfnames[]\fR + \fBdel_curterm(cur_term);\fP .sp -\fBchar *strnames[]\fR, \fB*strcodes[]\fR, \fB*strfnames[]\fR -.RE -.PP -These null-terminated arrays contain the \fIcapnames\fR, the -\fBtermcap\fR codes, and the full C names, for each of the -\fBterminfo\fR variables. +the memory will be freed. +.PP +The formatting functions \fBtparm\fP and \fBtiparm\fP extend the storage +allocated by \fBsetupterm\fP: +.bP +the \*(``static\*('' terminfo variables [a-z]. +Before ncurses 6.3, those were shared by all screens. +With ncurses 6.3, those are allocated per screen. +See \fBterminfo\fP(\*n) for details. +.bP +to improve performance, ncurses 6.3 caches the result of analyzing terminfo +strings for their parameter types. +That is stored as a binary tree referenced from the \fBTERMINAL\fP structure. +.PP +The higher-level \fBinitscr\fP and \fBnewterm\fP functions use \fBsetupterm\fP. +Normally they do not free this memory, but it is possible to do that using +the \fBdelscreen\fP(3) function. +.\" *************************************************************************** .SH RETURN VALUE -Routines that return an integer return \fBERR\fR upon failure and \fBOK\fR -(SVr4 only specifies "an integer value other than \fBERR\fR") upon successful -completion, unless otherwise noted in the preceding routine descriptions. +Routines that return an integer return \fBERR\fP upon failure and \fBOK\fP +(SVr4 only specifies \*(``an integer value other than \fBERR\fP\*('') +upon successful completion, +unless otherwise noted in the preceding routine descriptions. .PP -Routines that return pointers always return \fBNULL\fR on error. +Routines that return pointers always return \fBNULL\fP on error. .PP X/Open defines no error conditions. In this implementation -.RS +.RS 3 .TP 5 \fBdel_curterm\fP returns an error @@ -289,66 +497,288 @@ if it cannot allocate enough memory, or create the initial windows (stdscr, curscr, newscr). Other error conditions are documented above. .TP 5 +\fBtparm\fP +returns a null if the capability would require unexpected parameters, +e.g., too many, too few, or incorrect types +(strings where integers are expected, or vice versa). +.TP 5 \fBtputs\fP returns an error if the string parameter is null. It does not detect I/O errors: X/Open states that \fBtputs\fP ignores the return value of the output function \fIputc\fP. .RE -.SH NOTES -The \fBsetupterm\fR routine should be used in place of \fBsetterm\fR. -It may be useful when you want to test for terminal capabilities without -committing to the allocation of storage involved in \fBinitscr\fR. -.PP -Note that \fBvidattr\fR and \fBvidputs\fR may be macros. +.\" *************************************************************************** +.SS Compatibility macros +This implementation provides a few macros for compatibility with systems +before SVr4 (see \fIHISTORY\fP). +Those include +\fBcrmode\fP, +\fBfixterm\fP, +\fBgettmode\fP, +\fBnocrmode\fP, +\fBresetterm\fP, +\fBsaveterm\fP, and +\fBsetterm\fP. +.PP +In SVr4, those are found in \fB\fP, +but except for \fBsetterm\fP, are likewise macros. +The one function, \fBsetterm\fP, is mentioned in the manual page. +The manual page notes that the \fBsetterm\fP routine +was replaced by \fBsetupterm\fP, stating that the call: +.sp + \fBsetupterm(\fIterm\fB, 1, (int *)0)\fR +.sp +provides the same functionality as \fBsetterm(\fIterm\fB)\fR, +and is not recommended for new programs. +This implementation provides each of those symbols +as macros for BSD compatibility, +.\" *************************************************************************** +.SH HISTORY +SVr2 introduced the terminfo feature. +Its programming manual mentioned these low-level functions: +.PP +.TS +l l. +\fBFunction\fP \fBDescription\fP +_ +fixterm restore tty to \*(``in curses\*('' state +gettmode establish current tty modes +mvcur low level cursor motion +putp T{ +utility function that uses \fBtputs\fP to send characters via \fBputchar\fP. +T} +resetterm set tty modes to \*(``out of curses\*('' state +resetty reset tty flags to stored value +saveterm save current modes as \*(``in curses\*('' state +savetty store current tty flags +setterm establish terminal with given type +setupterm establish terminal with given type +tparm instantiate a string expression with parameters +tputs apply padding information to a string +vidattr like \fBvidputs\fP, but outputs through \fBputchar\fP +vidputs T{ +output a string to put terminal in a specified video attribute mode +T} +.TE +.PP +The programming manual also mentioned +functions provided for termcap compatibility +(commenting that they \*(``may go away at a later date\*(''): +.PP +.TS +l l +_ _ +l l. +\fBFunction\fP \fBDescription\fP +tgetent look up termcap entry for given \fIname\fP +tgetflag get boolean entry for given \fIid\fP +tgetnum get numeric entry for given \fIid\fP +tgetstr get string entry for given \fIid\fP +tgoto apply parameters to given capability +tputs T{ +apply padding to capability, calling a function to put characters +T} +.TE +.PP +Early terminfo programs obtained capability values from the +\fBTERMINAL\fP structure initialized by \fBsetupterm\fP. +.PP +SVr3 extended terminfo by adding functions to retrieve capability values +(like the termcap interface), +and reusing tgoto and tputs: +.PP +.TS +l l +_ _ +l l. +\fBFunction\fP \fBDescription\fP +tigetflag get boolean entry for given \fIid\fP +tigetnum get numeric entry for given \fIid\fP +tigetstr get string entry for given \fIid\fP +.TE +.PP +SVr3 also replaced several of the SVr2 terminfo functions +which had no counterpart in the termcap interface, +documenting them as obsolete: +.TS +l l +_ _ +l l. +\fBFunction\fP \fBReplaced by\fP +crmode cbreak +fixterm reset_prog_mode +gettmode N/A +nocrmode nocbreak +resetterm reset_shell_mode +saveterm def_prog_mode +setterm setupterm +.TE +.PP +SVr3 kept the \fBmvcur\fP, \fBvidattr\fP and \fBvidputs\fP functions, +along with \fBputp\fP, \fBtparm\fP and \fBtputs\fP. +The latter were needed to support padding, +and handling functions such as \fBvidattr\fP +(which used more than the two parameters supported by \fBtgoto\fP). +.PP +SVr3 introduced the functions for switching between terminal +descriptions, e.g., \fBset_curterm\fP. +Some of that was incremental improvements to the SVr2 library: +.bP +The \fBTERMINAL\fP type definition was introduced in SVr3.01, +for the \fBterm\fP structure provided in SVr2. +.bP +The various global variables such as \fBboolnames\fP were mentioned +in the programming manual at this point, +though the variables were provided in SVr2. +.PP +SVr4 added the \fBvid_attr\fP and \fBvid_puts\fP functions. +.PP +There are other low-level functions declared in the curses header files +on Unix systems, +but none were documented. +The functions marked \*(``obsolete\*('' remained in use +by the Unix \fBvi\fP(1) editor. .SH PORTABILITY -The function \fBsetterm\fR is not described by X/Open and must -be considered non-portable. All other functions are as described by X/Open. -.PP +.SS Extensions +The functions marked as extensions were designed for \fBncurses\fP(3), +and are not found in SVr4 curses, 4.4BSD curses, +or any other previous version of curses. +.SS Legacy functions +X/Open notes that \fBvidattr\fP and \fBvidputs\fP may be macros. +.PP +The function \fBsetterm\fP is not described by X/Open and must +be considered non-portable. +All other functions are as described by X/Open. +.SS Legacy data \fBsetupterm\fP copies the terminal name to the array \fBttytype\fP. This is not part of X/Open Curses, but is assumed by some applications. .PP -In System V Release 4, \fBset_curterm\fR has an \fBint\fR return type and -returns \fBOK\fR or \fBERR\fR. We have chosen to implement the X/Open Curses +Other implementions may not declare the capability name arrays. +Some provide them without declaring them. +X/Open does not specify them. +.PP +Extended terminal capability names, e.g., as defined by \fBtic\ \-x\fP, +are not stored in the arrays described here. +.SS Output buffering +Older versions of \fBncurses\fP assumed that the file descriptor passed to +\fBsetupterm\fP from \fBinitscr\fP or \fBnewterm\fP uses buffered I/O, +and would write to the corresponding stream. +In addition to the limitation that the terminal was left in block-buffered +mode on exit (like System V curses), +it was problematic because \fBncurses\fP +did not allow a reliable way to cleanup on receiving SIGTSTP. +.PP +The current version (ncurses6) +uses output buffers managed directly by \fBncurses\fP. +Some of the low-level functions described in this manual page write +to the standard output. +They are not signal-safe. +The high-level functions in \fBncurses\fP use +alternate versions of these functions +using the more reliable buffering scheme. +.SS Function prototypes +The X/Open Curses prototypes are based on the SVr4 curses header declarations, +which were defined at the same time the C language was first standardized in +the late 1980s. +.bP +X/Open Curses uses \fBconst\fP less effectively than a later design might, +in some cases applying it needlessly to values are already constant, +and in most cases overlooking parameters which normally would use \fBconst\fP. +Using constant parameters for functions which do not use \fBconst\fP +may prevent the program from compiling. +On the other hand, \fIwritable strings\fP are an obsolescent feature. +.IP +As an extension, this implementation can be configured to change the +function prototypes to use the \fBconst\fP keyword. +The ncurses ABI 6 enables this feature by default. +.bP +X/Open Curses prototypes \fBtparm\fP with a fixed number of parameters, +rather than a variable argument list. +.IP +This implementation uses a variable argument list, but can be +configured to use the fixed-parameter list. +Portable applications should provide 9 parameters after the format; +zeroes are fine for this purpose. +.IP +In response to review comments by Thomas E. Dickey, +X/Open Curses Issue 7 proposed the \fBtiparm\fP function in mid-2009. +.IP +While \fBtiparm\fP is always provided in ncurses, +the older form is only available as a build-time configuration option. +If not specially configured, \fBtparm\fP is the same as \fBtiparm\fP. +.PP +Both forms of \fBtparm\fP have drawbacks: +.bP +Most of the calls to \fBtparm\fP use only one or two parameters. +Passing nine on each call is awkward. +.IP +Using \fBlong\fP for the numeric parameter type is a workaround +to make the parameter use the same amount of stack as a pointer. +That approach dates back to the mid-1980s, before C was standardized. +Since then, there is a standard +(and pointers are not required to fit in a long). +.bP +Providing the right number of parameters for a variadic function +such as \fBtiparm\fP can be a problem, in particular for string parameters. +However, only a few terminfo capabilities use string parameters +(e.g., the ones used for programmable function keys). +.IP +The ncurses library checks usage of these capabilities, +and returns an error if the capability mishandles string parameters. +But it cannot check if a calling program provides strings in the right +places for the \fBtparm\fP calls. +.IP +The \fBtput\fR(1) program checks its use of these capabilities with a table, +so that it calls \fBtparm\fP correctly. +.SS Special TERM treatment +If configured to use the terminal-driver, +e.g., for the MinGW port, +.bP +\fBsetupterm\fP interprets a missing/empty TERM variable as the +special value \*(``unknown\*(''. +.IP +SVr4 curses uses the +special value \*(``dumb\*(''. +.IP +The difference between the two is that +the former uses the \fBgn\fP (\fBgeneric_type\fR) terminfo capability, +while the latter does not. +A generic terminal is unsuitable for full-screen applications. +.bP +\fBsetupterm\fP allows explicit use of the +the windows console driver by checking if $TERM is set to +\*(``#win32con\*('' or an abbreviation of that string. +.SS Other portability issues +In System V Release 4, \fBset_curterm\fP has an \fBint\fP return type and +returns \fBOK\fP or \fBERR\fP. We have chosen to implement the X/Open Curses semantics. .PP -In System V Release 4, the third argument of \fBtputs\fR has the type -\fBint (*putc)(char)\fR. +In System V Release 4, the third argument of \fBtputs\fP has the type +\fBint (*putc)(char)\fP. .PP At least one implementation of X/Open Curses (Solaris) returns a value -other than OK/ERR from \fBtputs\fP. +other than \fBOK\fP/\fBERR\fP from \fBtputs\fP. That returns the length of the string, and does no error-checking. .PP -X/Open Curses prototypes \fBtparm\fR with a fixed number of parameters, -rather than a variable argument list. -This implementation uses a variable argument list. -Portable applications should provide 9 parameters after the format; -zeroes are fine for this purpose. -.PP -X/Open notes that after calling \fBmvcur\fR, the curses state may not match the +X/Open notes that after calling \fBmvcur\fP, the curses state may not match the actual terminal state, and that an application should touch and refresh the window before resuming normal curses calls. -Both ncurses and System V Release 4 curses implement \fBmvcur\fR using -the SCREEN data allocated in either \fBinitscr\fR or \fBnewterm\fR. +Both \fBncurses\fP and System V Release 4 curses implement \fBmvcur\fP using +the SCREEN data allocated in either \fBinitscr\fP or \fBnewterm\fP. So though it is documented as a terminfo function, -\fBmvcur\fR is really a curses function which is not well specified. +\fBmvcur\fP is really a curses function which is not well specified. .PP X/Open states that the old location must be given for \fBmvcur\fP. -This implementation allows the caller to use -1's for the old ordinates. +This implementation allows the caller to use \-1's for the old ordinates. In that case, the old location is unknown. -.PP -Extended terminal capability names, e.g., as defined by \fBtic\ -x\fP, -are not stored in the arrays described in this section. .SH SEE ALSO -\fBcurses\fR(3), -\fBcurs_initscr\fR(3), -\fBcurs_kernel\fR(3), -\fBputc\fR(3), -\fBtermcap\fR(3), -\fBterminfo\fR(\*n) -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3), +\fBcurs_initscr\fP(3), +\fBcurs_kernel\fP(3), +\fBcurs_memleaks\fP(3), +\fBtermcap\fP(3), +\fBcurs_variables\fP(3), +\fBterm_variables\fP(3), +\fBputc\fP(3), +\fBterminfo\fP(\*n) diff --git a/lib/libcurses/terminfo.5 b/lib/libcurses/terminfo.5 index ab46a95d14e..f79728bbb60 100644 --- a/lib/libcurses/terminfo.5 +++ b/lib/libcurses/terminfo.5 @@ -1,11 +1,12 @@ '\" t .\" DO NOT EDIT THIS FILE BY HAND! -.\" It is generated from terminfo.head, Caps, and terminfo.tail. +.\" It is generated from terminfo.head, ./../include/Caps ./../include/Caps-ncurses, and terminfo.tail. .\" .\" Note: this must be run through tbl before nroff. .\" The magic cookie on the first line triggers this under some man programs. .\"*************************************************************************** -.\" Copyright (c) 1998-2004,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2021,2023 Thomas E. Dickey * +.\" Copyright 1998-2016,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -32,59 +33,111 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: terminfo.5,v 1.1 2019/02/13 07:18:57 nicm Exp $ -.TH terminfo 5 "" "" "File Formats" +.\" $Id: terminfo.5,v 1.2 2023/10/17 09:52:08 nicm Exp $ +.TH terminfo 5 2023-07-01 "ncurses 6.4" "File formats" .ds n 5 .ds d /usr/share/terminfo +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.de NS +.ie n .sp +.el .sp .5 +.ie n .in +4 +.el .in +2 +.nf +.ft C \" Courier +.. +.de NE +.fi +.ft R +.ie n .in -4 +.el .in -2 +.. .SH NAME terminfo \- terminal capability database .SH SYNOPSIS \*d/*/* .SH DESCRIPTION .I Terminfo -is a data base describing terminals, used by screen-oriented programs such as -\fBnvi\fR(1), -\fBrogue\fR(1) -and libraries such as -\fBcurses\fR(3). +is a database describing terminals, +used by screen-oriented programs such as +\fBnvi\fP(1), +\fBlynx\fP(1), +\fBmutt\fP(1), +and other curses applications, +using high-level calls to libraries such as \fBcurses\fP(3). +It is also used via low-level calls by non-curses applications +which may be screen-oriented (such as \fB?\fP(1)) +or non-screen (such as \fB?\fP(1)). +.PP .I Terminfo describes terminals by giving a set of capabilities which they have, by specifying how to perform screen operations, and by specifying padding requirements and initialization sequences. -This describes \fBncurses\fR -version 5.7. .PP +This manual describes \fBncurses\fP +version 6.4 (patch 20230826). +.SS Terminfo Entry Syntax Entries in .I terminfo -consist of a sequence of `,' separated fields (embedded commas may be -escaped with a backslash or notated as \\054). -White space after the `,' separator is ignored. -The first entry for each terminal gives the names which are known for the -terminal, separated by `|' characters. -The first name given is the most common abbreviation for the terminal, -the last name given should be a long name fully identifying the terminal, -and all others are understood as synonyms for the terminal name. -All names but the last should be in lower case and contain no blanks; +consist of a sequence of fields: +.bP +Each field ends with a comma \*(``,\*('' +(embedded commas may be +escaped with a backslash or written as \*(``\\054\*(''). +.bP +White space between fields is ignored. +.bP +The first field in a \fIterminfo\fP entry begins in the first column. +.bP +Newlines and leading whitespace (spaces or tabs) +may be used for formatting entries for readability. +These are removed from parsed entries. +.IP +The \fBinfocmp\fP \fB\-f\fP and \fB\-W\fP options rely on this to +format if-then-else expressions, +or to enforce maximum line-width. +The resulting formatted terminal description can be read by \fBtic\fP. +.bP +The first field for each terminal gives the names which are known for the +terminal, separated by \*(``|\*('' characters. +.IP +The first name given is the most common abbreviation for the terminal +(its primary name), +the last name given should be a long name fully identifying the terminal +(see \fBlongname\fP(3)), +and all others are treated as synonyms (aliases) for the primary terminal name. +.IP +X/Open Curses advises that all names but the last should be in lower case +and contain no blanks; the last name may well contain upper case and blanks for readability. -.PP -Lines beginning with a `#' in the first column are treated as comments. +.IP +This implementation is not so strict; +it allows mixed case in the primary name and aliases. +If the last name has no embedded blanks, +it allows that to be both an alias and a verbose name +(but will warn about this ambiguity). +.bP +Lines beginning with a \*(``#\*('' in the first column are treated as comments. +.IP While comment lines are legal at any point, the output of \fBcaptoinfo\fP and \fBinfotocap\fP (aliases for \fBtic\fP) will move comments so they occur only between entries. .PP -Newlines and leading tabs may be used for formatting entries for readability. -These are removed from parsed entries. -The \fBinfocmp\ -f\fP option relies on this to format if-then-else expressions: -the result can be read by \fB@tic\fP. -.PP Terminal names (except for the last, verbose entry) should be chosen using the following conventions. The particular piece of hardware making up the terminal should -have a root name, thus ``hp2621''. +have a root name, thus \*(``hp2621\*(''. This name should not contain hyphens. Modes that the hardware can be in, or user preferences, should be indicated by appending a hyphen and a mode suffix. -Thus, a vt100 in 132 column mode would be vt100-w. +Thus, a vt100 in 132-column mode would be vt100\-w. The following suffixes should be used where possible: .PP .TS @@ -92,23 +145,87 @@ center ; l c l l l l. \fBSuffix Meaning Example\fP --\fInn\fP Number of lines on the screen aaa-60 --\fIn\fPp Number of pages of memory c100-4p --am With automargins (usually the default) vt100-am --m Mono mode; suppress color ansi-m --mc Magic cookie; spaces when highlighting wy30-mc --na No arrow keys (leave them in local) c100-na --nam Without automatic margins vt100-nam --nl No status line att4415-nl --ns No status line hp2626-ns --rv Reverse video c100-rv --s Enable status line vt100-s --vb Use visible bell instead of beep wy370-vb --w Wide mode (> 80 columns, usually 132) vt100-w +\-\fInn\fP Number of lines on the screen aaa\-60 +\-\fIn\fPp Number of pages of memory c100\-4p +\-am With automargins (usually the default) vt100\-am +\-m Mono mode; suppress color ansi\-m +\-mc Magic cookie; spaces when highlighting wy30\-mc +\-na No arrow keys (leave them in local) c100\-na +\-nam Without automatic margins vt100\-nam +\-nl No status line att4415\-nl +\-ns No status line hp2626\-ns +\-rv Reverse video c100\-rv +\-s Enable status line vt100\-s +\-vb Use visible bell instead of beep wy370\-vb +\-w Wide mode (> 80 columns, usually 132) vt100\-w .TE .PP -For more on terminal naming conventions, see the \fBterm(7)\fR manual page. -.SS Capabilities +For more on terminal naming conventions, see the \fBterm\fP(7) manual page. +.SS Terminfo Capabilities Syntax +The terminfo entry consists of several \fIcapabilities\fP, +i.e., features that the terminal has, +or methods for exercising the terminal's features. +.PP +After the first field (giving the name(s) of the terminal entry), +there should be one or more \fIcapability\fP fields. +These are boolean, numeric or string names with corresponding values: +.bP +Boolean capabilities are true when present, false when absent. +There is no explicit value for boolean capabilities. +.bP +Numeric capabilities have a \*(``#\*('' following the name, +then an unsigned decimal integer value. +.bP +String capabilities have a \*(``=\*('' following the name, +then an string of characters making up the capability value. +.IP +String capabilities can be split into multiple lines, +just as the fields comprising a terminal entry can be +split into multiple lines. +While blanks between fields are ignored, +blanks embedded within a string value are retained, +except for leading blanks on a line. +.PP +Any capability can be \fIcanceled\fP, +i.e., suppressed from the terminal entry, +by following its name with \*(``@\*('' +rather than a capability value. +.SS Similar Terminals +If there are two very similar terminals, one (the variant) can be defined as +being just like the other (the base) with certain exceptions. +In the +definition of the variant, the string capability \fBuse\fP can be given with +the name of the base terminal: +.bP +The capabilities given before +.B use +override those in the base type named by +.BR use . +.bP +If there are multiple \fBuse\fP capabilities, they are merged in reverse order. +That is, the rightmost \fBuse\fP reference is processed first, then the one to +its left, and so forth. +.bP +Capabilities given explicitly in the entry override +those brought in by \fBuse\fP references. +.PP +A capability can be canceled by placing \fBxx@\fP to the left of the +use reference that imports it, where \fIxx\fP is the capability. +For example, the entry +.RS +.PP +2621\-nl, smkx@, rmkx@, use=2621, +.RE +.PP +defines a 2621\-nl that does not have the \fBsmkx\fP or \fBrmkx\fP capabilities, +and hence does not turn on the function key labels when in visual mode. +This is useful for different modes for a terminal, or for different +user preferences. +.PP +An entry included via \fBuse\fP can contain canceled capabilities, +which have the same effect as if those cancels were inline in the +using terminal entry. +.SS Predefined Capabilities .\" Head of terminfo man page ends here .ps -1 The following is a complete table of the capabilities included in a @@ -143,8 +260,12 @@ capability. You may find some codes in the description field: indicates that padding may be specified .TP #[1-9] -in the description field indicates that the string is passed through tparm with -parms as given (#\fIi\fP). +in the description field indicates that the string is passed +through \fBtparm\fP(3) with parameters as given (#\fIi\fP). +.IP +If no parameters are listed in the description, +passing the string through \fBtparm\fP(3) may give unexpected results, +e.g., if it contains percent (%%) signs. .TP (P*) indicates that padding may vary in proportion to the number of @@ -158,10 +279,10 @@ These are the boolean capabilities: .na .TS H -center expand; +center; c l l c c l l c -lw25 lw6 lw2 lw20. +lw25 lw7 lw2 lw20. \fBVariable Cap- TCap Description\fR \fBBooleans name Code\fR auto_left_margin bw bw T{ @@ -267,7 +388,7 @@ status_line_esc_ok eslok es T{ escape can be used on the status line T} tilde_glitch hz hz T{ -cannot print ~'s (hazeltine) +cannot print ~'s (Hazeltine) T} transparent_underline ul ul T{ underline character overstrikes @@ -282,10 +403,10 @@ These are the numeric capabilities: .na .TS H -center expand; +center; c l l c c l l c -lw25 lw6 lw2 lw20. +lw25 lw7 lw2 lw20. \fBVariable Cap- TCap Description\fR \fBNumeric name Code\fR columns cols co T{ @@ -319,7 +440,7 @@ max_pairs pairs pa T{ maximum number of color-pairs on the screen T} maximum_windows wnum MW T{ -maximum number of defineable windows +maximum number of definable windows T} no_color_video ncv NC T{ video attributes that cannot be used with colors @@ -345,10 +466,10 @@ printer support. .na .TS H -center expand; +center; c l l c c l l c -lw25 lw6 lw2 lw20. +lw25 lw7 lw2 lw20. \fBVariable Cap- TCap Description\fR \fBNumeric name Code\fR bit_image_entwining bitwin Yo T{ @@ -409,10 +530,10 @@ These are the string capabilities: .na .TS H -center expand; +center; c l l c c l l c -lw25 lw6 lw2 lw20. +lw25 lw7 lw2 lw20. \fBVariable Cap- TCap Description\fR \fBString name Code\fR acs_chars acsc ac T{ @@ -1376,7 +1497,7 @@ set_foreground setf Sf T{ Set foreground color #1 T} set_left_margin smgl ML T{ -set left soft margin at current column. See smgl. (ML is not in BSD termcap). +set left soft margin at current column. (ML is not in BSD termcap). T} set_left_margin_parm smglp Zm T{ Set left (right) margin at column #1 @@ -1485,10 +1606,10 @@ but were originally not documented in the man page. .na .TS H -center expand; +center; c l l c c l l c -lw25 lw6 lw2 lw18. +lw25 lw7 lw2 lw18. \fBVariable Cap- TCap Description\fR \fBString name Code\fR alt_scancode_esc scesa S8 T{ @@ -1513,7 +1634,7 @@ color_names colornm Yw T{ Give name for color #1 T} define_bit_image_region defbi Yx T{ -Define rectangualar bit image region +Define rectangular bit image region T} device_type devt dv T{ Indicate language/codeset support @@ -1591,19 +1712,21 @@ T} .ad .in .8i -The XSI Curses standard added these. They are some post-4.1 -versions of System V curses, e.g., Solaris 2.5 and IRIX 6.x. -The \fBncurses\fR termcap names for them are invented; according to the -XSI Curses standard, they have no termcap names. If your compiled terminfo -entries use these, they may not be binary-compatible with System V terminfo +The XSI Curses standard added these hardcopy capabilities. +They were used in some post-4.1 versions of System V curses, +e.g., Solaris 2.5 and IRIX 6.x. +Except for \fBYI\fP, the \fBncurses\fR termcap names for them are invented. +According to the XSI Curses standard, they have no termcap names. +If your compiled terminfo entries use these, +they may not be binary-compatible with System V terminfo entries after SVr4.1; beware! .na .TS H -center expand; +center; c l l c c l l c -lw25 lw6 lw2 lw20. +lw25 lw7 lw2 lw20. \fBVariable Cap- TCap Description\fR \fBString name Code\fR enter_horizontal_hl_mode ehhlm Xh T{ @@ -1627,116 +1750,248 @@ T} set_a_attributes sgr1 sA T{ Define second set of video attributes #1-#6 T} -set_pglen_inch slength sL T{ -YI Set page length to #1 hundredth of an inch +set_pglen_inch slength YI T{ +Set page length to #1 hundredth of an inch (some implementations use sL for termcap). T} .TE .ad -.\" $Id: terminfo.5,v 1.1 2019/02/13 07:18:57 nicm Exp $ -.\" Beginning of terminfo.tail file -.\" This file is part of ncurses. -.\" See "terminfo.head" for copyright. +.\"*************************************************************************** +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2016,2017 Free Software Foundation, Inc. * +.\" * +.\" Permission is hereby granted, free of charge, to any person obtaining a * +.\" copy of this software and associated documentation files (the * +.\" "Software"), to deal in the Software without restriction, including * +.\" without limitation the rights to use, copy, modify, merge, publish, * +.\" distribute, distribute with modifications, sublicense, and/or sell * +.\" copies of the Software, and to permit persons to whom the Software is * +.\" furnished to do so, subject to the following conditions: * +.\" * +.\" The above copyright notice and this permission notice shall be included * +.\" in all copies or substantial portions of the Software. * +.\" * +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * +.\" IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * +.\" DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * +.\" OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * +.\" THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +.\" * +.\" Except as contained in this notice, the name(s) of the above copyright * +.\" holders shall not be used in advertising or otherwise to promote the * +.\" sale, use or other dealings in this Software without prior written * +.\" authorization. * +.\"*************************************************************************** +.\" +.\" $Id: terminfo.5,v 1.2 2023/10/17 09:52:08 nicm Exp $ .ps +1 +.SS User-Defined Capabilities +. +The preceding section listed the \fIpredefined\fP capabilities. +They deal with some special features for terminals no longer +(or possibly never) produced. +Occasionally there are special features of newer terminals which +are awkward or impossible to represent by reusing the predefined +capabilities. +.PP +\fBncurses\fP addresses this limitation by allowing user-defined capabilities. +The \fBtic\fP and \fBinfocmp\fP programs provide +the \fB\-x\fP option for this purpose. +When \fB\-x\fP is set, +\fBtic\fP treats unknown capabilities as user-defined. +That is, if \fBtic\fP encounters a capability name +which it does not recognize, +it infers its type (boolean, number or string) from the syntax +and makes an extended table entry for that capability. +The \fBuse_extended_names\fP(3) function makes this information +conditionally available to applications. +The ncurses library provides the data leaving most of the behavior +to applications: +.bP +User-defined capability strings whose name begins +with \*(``k\*('' are treated as function keys. +.bP +The types (boolean, number, string) determined by \fBtic\fP +can be inferred by successful calls on \fBtigetflag\fP, etc. +.bP +If the capability name happens to be two characters, +the capability is also available through the termcap interface. +.PP +While termcap is said to be extensible because it does not use a predefined set +of capabilities, +in practice it has been limited to the capabilities defined by +terminfo implementations. +As a rule, +user-defined capabilities intended for use by termcap applications should +be limited to booleans and numbers to avoid running past the 1023 byte +limit assumed by termcap implementations and their applications. +In particular, providing extended sets of function keys (past the 60 +numbered keys and the handful of special named keys) is best done using +the longer names available using terminfo. +.PP +The ncurses library uses a few of these user-defined capabilities, +as described in \fBuser_caps\fR(5). +Other user-defined capabilities (including function keys) are +described in the terminal database, in the section on +.I "NCURSES USER-DEFINABLE CAPABILITIES" . .SS A Sample Entry . The following entry, describing an ANSI-standard terminal, is representative -of what a \fBterminfo\fR entry for a modern terminal typically looks like. +of what a \fBterminfo\fP entry for a modern terminal typically looks like. .PP .nf -.in -2 -.ta .3i .ft CW \s-2ansi|ansi/pc-term compatible with color, - mc5i, - colors#8, ncv#3, pairs#64, - cub=\\E[%p1%dD, cud=\\E[%p1%dB, cuf=\\E[%p1%dC, - cuu=\\E[%p1%dA, dch=\\E[%p1%dP, dl=\\E[%p1%dM, - ech=\\E[%p1%dX, el1=\\E[1K, hpa=\\E[%p1%dG, ht=\\E[I, - ich=\\E[%p1%d@, il=\\E[%p1%dL, indn=\\E[%p1%dS, .indn=\\E[%p1%dT, - kbs=^H, kcbt=\\E[Z, kcub1=\\E[D, kcud1=\\E[B, - kcuf1=\\E[C, kcuu1=\\E[A, kf1=\\E[M, kf10=\\E[V, - kf11=\\E[W, kf12=\\E[X, kf2=\\E[N, kf3=\\E[O, kf4=\\E[P, - kf5=\\E[Q, kf6=\\E[R, kf7=\\E[S, kf8=\\E[T, kf9=\\E[U, - kich1=\\E[L, mc4=\\E[4i, mc5=\\E[5i, nel=\\r\\E[S, - op=\\E[37;40m, rep=%p1%c\\E[%p2%{1}%-%db, - rin=\\E[%p1%dT, s0ds=\\E(B, s1ds=\\E)B, s2ds=\\E*B, - s3ds=\\E+B, setab=\\E[4%p1%dm, setaf=\\E[3%p1%dm, - setb=\\E[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, - setf=\\E[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m, - sgr=\\E[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p6%t;1%;%?%p7%t;8%;%?%p8%t;11%;%?%p9%t;12%;m, - sgr0=\\E[0;10m, tbc=\\E[2g, u6=\\E[%d;%dR, u7=\\E[6n, - u8=\\E[?%[;0123456789]c, u9=\\E[c, vpa=\\E[%p1%dd,\s+2 -.in +2 + am, mc5i, mir, msgr, + colors#8, cols#80, it#8, lines#24, ncv#3, pairs#64, + acsc=+\\020\\,\\021-\\030.^Y0\\333`\\004a\\261f\\370g\\361h\\260 + j\\331k\\277l\\332m\\300n\\305o~p\\304q\\304r\\304s_t\\303 + u\\264v\\301w\\302x\\263y\\363z\\362{\\343|\\330}\\234~\\376, + bel=^G, blink=\\E[5m, bold=\\E[1m, cbt=\\E[Z, clear=\\E[H\\E[J, + cr=^M, cub=\\E[%p1%dD, cub1=\\E[D, cud=\\E[%p1%dB, cud1=\\E[B, + cuf=\\E[%p1%dC, cuf1=\\E[C, cup=\\E[%i%p1%d;%p2%dH, + cuu=\\E[%p1%dA, cuu1=\\E[A, dch=\\E[%p1%dP, dch1=\\E[P, + dl=\\E[%p1%dM, dl1=\\E[M, ech=\\E[%p1%dX, ed=\\E[J, el=\\E[K, + el1=\\E[1K, home=\\E[H, hpa=\\E[%i%p1%dG, ht=\\E[I, hts=\\EH, + ich=\\E[%p1%d@, il=\\E[%p1%dL, il1=\\E[L, ind=^J, + indn=\\E[%p1%dS, invis=\\E[8m, kbs=^H, kcbt=\\E[Z, kcub1=\\E[D, + kcud1=\\E[B, kcuf1=\\E[C, kcuu1=\\E[A, khome=\\E[H, kich1=\\E[L, + mc4=\\E[4i, mc5=\\E[5i, nel=\\r\\E[S, op=\\E[39;49m, + rep=%p1%c\\E[%p2%{1}%-%db, rev=\\E[7m, rin=\\E[%p1%dT, + rmacs=\\E[10m, rmpch=\\E[10m, rmso=\\E[m, rmul=\\E[m, + s0ds=\\E(B, s1ds=\\E)B, s2ds=\\E*B, s3ds=\\E+B, + setab=\\E[4%p1%dm, setaf=\\E[3%p1%dm, + sgr=\\E[0;10%?%p1%t;7%; + %?%p2%t;4%; + %?%p3%t;7%; + %?%p4%t;5%; + %?%p6%t;1%; + %?%p7%t;8%; + %?%p9%t;11%;m, + sgr0=\\E[0;10m, smacs=\\E[11m, smpch=\\E[11m, smso=\\E[7m, + smul=\\E[4m, tbc=\\E[3g, u6=\\E[%i%d;%dR, u7=\\E[6n, + u8=\\E[?%[;0123456789]c, u9=\\E[c, vpa=\\E[%i%p1%dd, .fi .ft R .PP Entries may continue onto multiple lines by placing white space at the beginning of each line except the first. -Comments may be included on lines beginning with ``#''. +Comments may be included on lines beginning with \*(``#\*(''. Capabilities in .I terminfo are of three types: +.bP Boolean capabilities which indicate that the terminal has -some particular feature, numeric capabilities giving the size of the terminal -or the size of particular delays, and string +some particular feature, +.bP +numeric capabilities giving the size of the terminal +or the size of particular delays, and +.bP +string capabilities, which give a sequence which can be used to perform particular terminal operations. -.PP .SS Types of Capabilities -.PP All capabilities have names. For instance, the fact that ANSI-standard terminals have .I "automatic margins" (i.e., an automatic return and line-feed -when the end of a line is reached) is indicated by the capability \fBam\fR. -Hence the description of ansi includes \fBam\fR. -Numeric capabilities are followed by the character `#' and then a positive value. -Thus \fBcols\fR, which indicates the number of columns the terminal has, -gives the value `80' for ansi. -Values for numeric capabilities may be specified in decimal, octal or hexadecimal, -using the C programming language conventions (e.g., 255, 0377 and 0xff or 0xFF). -.PP -Finally, string valued capabilities, such as \fBel\fR (clear to end of line -sequence) are given by the two-character code, an `=', and then a string -ending at the next following `,'. +when the end of a line is reached) is indicated by the capability \fBam\fP. +Hence the description of ansi includes \fBam\fP. +Numeric capabilities are followed by the character \*(``#\*('' +and then a positive value. +Thus \fBcols\fP, which indicates the number of columns the terminal has, +gives the value \*(``80\*('' for ansi. +Values for numeric capabilities may be specified in +decimal, +octal, or +hexadecimal, +using the C programming language conventions +(e.g., 255, 0377 and 0xff or 0xFF). +.PP +Finally, string valued capabilities, +such as \fBel\fP (clear to end of line sequence) +are given by the two-character code, +an \*(``=\*('', and then +a string ending at the next following \*(``,\*(''. .PP A number of escape sequences are provided in the string valued capabilities -for easy encoding of characters there. -Both \fB\eE\fR and \fB\ee\fR +for easy encoding of characters there: +.bP +Both \fB\eE\fP and \fB\ee\fP map to an \s-1ESCAPE\s0 character, -\fB^x\fR maps to a control-x for any appropriate x, and the sequences -\fB\en \el \er \et \eb \ef \es\fR give -a newline, line-feed, return, tab, backspace, form-feed, and space. -Other escapes include \fB\e^\fR for \fB^\fR, -\fB\e\e\fR for \fB\e\fR, -\fB\e\fR, for comma, -\fB\e:\fR for \fB:\fR, -and \fB\e0\fR for null. -(\fB\e0\fR will produce \e200, which does not terminate a string but behaves +.bP +\fB^x\fP maps to a control-x for any appropriate \fIx\fP, and +.bP +the sequences +.RS 6 +.PP +\fB\en\fP, \fB\el\fP, \fB\er\fP, \fB\et\fP, \fB\eb\fP, \fB\ef\fP, and \fB\es\fP +.RE +.IP +produce +.RS 6 +.PP +\fInewline\fP, \fIline-feed\fP, \fIreturn\fP, \fItab\fP, \fIbackspace\fP, \fIform-feed\fP, and \fIspace\fP, +.RE +.IP +respectively. +.PP +X/Open Curses does not say what \*(``appropriate \fIx\fP\*('' might be. +In practice, that is a printable ASCII graphic character. +The special case \*(``^?\*('' is interpreted as DEL (127). +In all other cases, the character value is AND'd with 0x1f, +mapping to ASCII control codes in the range 0 through 31. +.PP +Other escapes include +.bP +\fB\e^\fP for \fB^\fP, +.bP +\fB\e\e\fP for \fB\e\fP, +.bP +\fB\e\fP, for comma, +.bP +\fB\e:\fP for \fB:\fP, +.bP +and \fB\e0\fP for null. +.IP +\fB\e0\fP will produce \e200, which does not terminate a string but behaves as a null character on most terminals, providing CS7 is specified. -See stty(1).) -Finally, characters may be given as three octal digits after a \fB\e\fR. +See \fBstty\fP(1). +.IP +The reason for this quirk is to maintain binary compatibility of the +compiled terminfo files with other implementations, +e.g., the SVr4 systems, which document this. +Compiled terminfo files use null-terminated strings, with no lengths. +Modifying this would require a new binary format, +which would not work with other implementations. +.PP +Finally, characters may be given as three octal digits after a \fB\e\fP. .PP A delay in milliseconds may appear anywhere in a string capability, enclosed in -$<..> brackets, as in \fBel\fP=\eEK$<5>, and padding characters are supplied by -.I tputs +$<..> brackets, as in \fBel\fP=\eEK$<5>, +and padding characters are supplied by \fBtputs\fP(3) to provide this delay. +.bP The delay must be a number with at most one decimal -place of precision; it may be followed by suffixes `*' or '/' or both. -A `*' +place of precision; +it may be followed by suffixes \*(``*\*('' or \*(``/\*('' or both. +.bP +A \*(``*\*('' indicates that the padding required is proportional to the number of lines affected by the operation, and the amount given is the per-affected-unit padding required. (In the case of insert character, the factor is still the -number of -.IR lines -affected.) Normally, padding is advisory if the device has the \fBxon\fR +number of \fIlines\fP affected.) +.IP +Normally, padding is advisory if the device has the \fBxon\fP capability; it is used for cost computation but does not trigger delays. -A `/' +.bP +A \*(``/\*('' suffix indicates that the padding is mandatory and forces a delay of the given -number of milliseconds even on devices for which \fBxon\fR is present to +number of milliseconds even on devices for which \fBxon\fP is present to indicate flow control. .PP Sometimes individual capabilities must be commented out. @@ -1746,32 +2001,38 @@ For example, see the second in the example above. .br .ne 5 -.PP .SS Fetching Compiled Descriptions -.PP +The \fBncurses\fP library searches for terminal descriptions in several places. +It uses only the first description found. +The library has a compiled-in list of places to search +which can be overridden by environment variables. +Before starting to search, +\fBncurses\fP eliminates duplicates in its search list. +.bP If the environment variable TERMINFO is set, it is interpreted as the pathname of a directory containing the compiled description you are working on. -Only -that directory is searched. -.PP -If TERMINFO is not set, the \fBncurses\fR version of the terminfo reader code -will instead look in the directory \fB$HOME/.terminfo\fR +Only that directory is searched. +.bP +If TERMINFO is not set, +\fBncurses\fP will instead look in the directory \fB$HOME/.terminfo\fP for a compiled description. -If it fails to find one there, and the environment variable TERMINFO_DIRS is -set, it will interpret the contents of that variable as a list of colon- -separated directories to be searched (an empty entry is interpreted as a -command to search \fI\*d\fR). -If no description is found in any of the -TERMINFO_DIRS directories, the fetch fails. -.PP -If neither TERMINFO nor TERMINFO_DIRS is set, the last place tried will be the -system terminfo directory, \fI\*d\fR. -.PP -(Neither the \fB$HOME/.terminfo\fR lookups nor TERMINFO_DIRS extensions are -supported under stock System V terminfo/curses.) -.PP +.bP +Next, if the environment variable TERMINFO_DIRS is set, +\fBncurses\fP will interpret the contents of that variable +as a list of colon-separated directories (or database files) to be searched. +.IP +An empty directory name (i.e., if the variable begins or ends +with a colon, or contains adjacent colons) +is interpreted as the system location \fI\*d\fP. +.bP +Finally, \fBncurses\fP searches these compiled-in locations: +.RS +.bP +a list of directories (?), and +.bP +the system terminfo directory, \fI\*d\fP (the compiled-in default). +.RE .SS Preparing Descriptions -.PP We now outline how to prepare descriptions of terminals. The most effective way to prepare a terminal description is by imitating the description of a similar terminal in @@ -1788,24 +2049,22 @@ or bugs in the screen-handling code of the test program. .PP To get the padding for insert line right (if the terminal manufacturer did not document it) a severe test is to edit a large file at 9600 baud, -delete 16 or so lines from the middle of the screen, then hit the `u' +delete 16 or so lines from the middle of the screen, then hit the \*(``u\*('' key several times quickly. If the terminal messes up, more padding is usually needed. A similar test can be used for insert character. -.PP .SS Basic Capabilities -.PP The number of columns on each line for the terminal is given by the -\fBcols\fR numeric capability. +\fBcols\fP numeric capability. If the terminal is a \s-1CRT\s0, then the -number of lines on the screen is given by the \fBlines\fR capability. +number of lines on the screen is given by the \fBlines\fP capability. If the terminal wraps around to the beginning of the next line when -it reaches the right margin, then it should have the \fBam\fR capability. +it reaches the right margin, then it should have the \fBam\fP capability. If the terminal can clear its screen, leaving the cursor in the home -position, then this is given by the \fBclear\fR string capability. +position, then this is given by the \fBclear\fP string capability. If the terminal overstrikes (rather than clearing a position when a character is struck over) -then it should have the \fBos\fR capability. +then it should have the \fBos\fP capability. If the terminal is a printing terminal, with no soft copy unit, give it both .B hc @@ -1817,7 +2076,7 @@ series, as well as hard copy and APL terminals.) If there is a code to move the cursor to the left edge of the current row, give this as .BR cr . -(Normally this will be carriage return, control M.) +(Normally this will be carriage return, control/M.) If there is a code to produce an audible signal (bell, beep, etc) give this as .BR bel . @@ -1832,7 +2091,7 @@ given as and .BR cud1 . These local cursor motions should not alter the text they pass over, -for example, you would not normally use `\fBcuf1\fP=\ ' because the +for example, you would not normally use \*(``\fBcuf1\fP=\ \*('' because the space would erase the character moved over. .PP A very important point here is that the local cursor motions encoded @@ -1870,7 +2129,7 @@ and except that they take one parameter, and scroll that many lines. They are also undefined except at the appropriate edge of the screen. .PP -The \fBam\fR capability tells whether the cursor sticks at the right +The \fBam\fP capability tells whether the cursor sticks at the right edge of the screen when text is output, but this does not necessarily apply to a .B cuf1 @@ -1887,7 +2146,7 @@ This is useful for drawing a box around the edge of the screen, for example. If the terminal has switch selectable automatic margins, the .I terminfo -file usually assumes that this is on; i.e., \fBam\fR. +file usually assumes that this is on; i.e., \fBam\fP. If the terminal has a command which moves to the first column of the next line, that command can be given as .B nel @@ -1901,7 +2160,8 @@ it may still be possible to craft a working .B nel out of one or both of them. .PP -These capabilities suffice to describe hard-copy and \*(lqglass-tty\*(rq terminals. +These capabilities suffice to describe +hard-copy and \*(``glass-tty\*('' terminals. Thus the model 33 teletype is described as .PP .DT @@ -1909,9 +2169,10 @@ Thus the model 33 teletype is described as .ft CW .\".in -2 \s-133\||\|tty33\||\|tty\||\|model 33 teletype, - bel=^G, cols#72, cr=^M, cud1=^J, hc, ind=^J, os,\s+1 + bel=^G, cols#72, cr=^M, cud1=^J, hc, ind=^J, os,\s+1 .\".in +2 .ft R +.fi .PP while the Lear Siegler \s-1ADM-3\s0 is described as .PP @@ -1920,19 +2181,16 @@ while the Lear Siegler \s-1ADM-3\s0 is described as .ft CW .\".in -2 \s-1adm3\||\|3\||\|lsi adm3, - am, bel=^G, clear=^Z, cols#80, cr=^M, cub1=^H, cud1=^J, - ind=^J, lines#24,\s+1 + am, bel=^G, clear=^Z, cols#80, cr=^M, cub1=^H, cud1=^J, + ind=^J, lines#24,\s+1 .\".in +2 .ft R .fi -.PP .SS Parameterized Strings -.PP Cursor addressing and other strings requiring parameters in the terminal are described by a -parameterized string capability, with -.IR printf (3) -like escapes \fB%x\fR in it. +parameterized string capability, +with \fIprintf\fP-like escapes such as \fI%x\fP in it. For example, to address the cursor, the .B cup capability is given, using two parameters: @@ -1947,136 +2205,181 @@ The parameter mechanism uses a stack and special \fB%\fP codes to manipulate it. Typically a sequence will push one of the parameters onto the stack and then print it in some format. -Print (e.g., "%d") is a special case. -Other operations, including "%t" pop their operand from the stack. +Print (e.g., \*(``%d\*('') is a special case. +Other operations, including \*(``%t\*('' pop their operand from the stack. It is noted that more complex operations are often necessary, e.g., in the \fBsgr\fP string. .PP -The \fB%\fR encodings have the following meanings: -.PP +The \fB%\fP encodings have the following meanings: .TP 5 -\s-1%% -outputs `%' +\fB%%\fP +outputs \*(``%\*('' .TP -%\fI[[\fP:\fI]flags][width[.precision]][\fPdoxXs\fI]\fP -as in \fBprintf\fP, flags are [-+#] and space. -Use a `:' to allow the next character to be a `-' flag, -avoiding interpreting "%-" as an operator. +\fB%\fI[[\fR:\fI]flags][width[.precision]][\fBdoxXs\fI]\fR +as in \fBprintf\fP(3), flags are \fI[\-+#]\fP and \fIspace\fP. +Use a \*(``:\*('' to allow the next character to be a \*(``\-\*('' flag, +avoiding interpreting \*(``%\-\*('' as an operator. .TP -%c -print pop() like %c in \fBprintf\fP +\f(CW%c\fP +print \fIpop()\fP like %c in \fBprintf\fP .TP -%s -print pop() like %s in \fBprintf\fP +\fB%s\fP +print \fIpop()\fP like %s in \fBprintf\fP .TP -%p[1-9] +\fB%p\fI[1\-9]\fR push \fIi\fP'th parameter .TP -%P[a-z] -set dynamic variable [a-z] to pop() +\fB%P\fI[a\-z]\fR +set dynamic variable \fI[a\-z]\fP to \fIpop()\fP .TP -%g[a-z] -get dynamic variable [a-z] and push it +\fB%g\fI[a\-z]\fR +get dynamic variable \fI[a\-z]\fP and push it .TP -%P[A-Z] -set static variable [a-z] to pop() +\fB%P\fI[A\-Z]\fR +set static variable \fI[a\-z]\fP to \fIpop()\fP .TP -%g[A-Z] -get static variable [a-z] and push it +\fB%g\fI[A\-Z]\fR +get static variable \fI[a\-z]\fP and push it .IP -The terms "static" and "dynamic" are misleading. +The terms \*(``static\*('' and \*(``dynamic\*('' are misleading. Historically, these are simply two different sets of variables, -whose values are not reset between calls to \fBtparm\fP. +whose values are not reset between calls to \fBtparm\fP(3). However, that fact is not documented in other implementations. -Relying on it will adversely impact portability to other implementations. +Relying on it will adversely impact portability to other implementations: +.RS +.bP +SVr2 curses supported \fIdynamic\fP variables. +Those are set only by a \fB%P\fP operator. +A \fB%g\fP for a given variable without first setting it with \fB%P\fP +will give unpredictable results, because dynamic variables are +an uninitialized local array on the stack in the \fBtparm\fP function. +.bP +SVr3.2 curses supported \fIstatic\fP variables. +Those are an array in the \fBTERMINAL\fP +structure (declared in \fBterm.h\fP), +and are zeroed automatically when the \fBsetupterm\fP function +allocates the data. +.bP +SVr4 curses made no further improvements +to the \fIdynamic/static\fP variable feature. +.bP +Solaris XPG4 curses does not distinguish between \fIdynamic\fP and +\fIstatic\fP variables. +They are the same. +Like SVr4 curses, XPG4 curses does not initialize these explicitly. +.bP +Before version 6.3, ncurses stores both \fIdynamic\fP and \fIstatic\fP +variables in persistent storage, initialized to zeros. +.bP +Beginning with version 6.3, ncurses stores \fIstatic\fP and \fIdynamic\fP +variables in the same manner as SVr4. +.RS +.bP +Unlike other implementations, ncurses zeros dynamic variables +before the first \fB%g\fP or \fB%P\fP operator. +.bP +Like SVr2, +the scope of dynamic variables in ncurses +is within the current call to +\fBtparm\fP. +Use static variables if persistent storage is needed. +.RE +.RE .TP -%'\fIc\fP' +\fB%\(aq\fIc\fB\(aq\fR char constant \fIc\fP .TP -%{\fInn\fP} +\fB%{\fInn\fB}\fR integer constant \fInn\fP .TP -%l +\fB%l\fP push strlen(pop) .TP -%+ %- %* %/ %m -arithmetic (%m is mod): push(pop() op pop()) +\fB%+\fP, \fB%\-\fP, \fB%*\fP, \fB%/\fP, \fB%m\fP +arithmetic (%m is \fImod\fP): \fIpush(pop() op pop())\fP .TP -%& %| %^ -bit operations (AND, OR and exclusive-OR): push(pop() op pop()) +\fB%&\fP, \fB%|\fP, \fB%^\fP +bit operations (AND, OR and exclusive-OR): \fIpush(pop() op pop())\fP .TP -%= %> %< -logical operations: push(pop() op pop()) +\fB%=\fP, \fB%>\fP, \fB%<\fP +logical operations: \fIpush(pop() op pop())\fP .TP -%A, %O +\fB%A\fP, \fB%O\fP logical AND and OR operations (for conditionals) .TP -%! %~ -unary operations (logical and bit complement): push(op pop()) +\fB%!\fP, \fB%~\fP +unary operations (logical and bit complement): \fIpush(op pop())\fP .TP -%i +\fB%i\fP add 1 to first two parameters (for ANSI terminals) .TP -%? \fIexpr\fP %t \fIthenpart\fP %e \fIelsepart\fP %; +\fB%?\fP \fIexpr\fP \fB%t\fP \fIthenpart\fP \fB%e\fP \fIelsepart\fP \fB%;\fP This forms an if-then-else. -The %e \fIelsepart\fP is optional. -Usually the %? \fIexpr\fP part pushes a value onto the stack, -and %t pops it from the stack, testing if it is nonzero (true). -If it is zero (false), control passes to the %e (else) part. +The \fB%e\fP \fIelsepart\fP is optional. +Usually the \fB%?\fP \fIexpr\fP part pushes a value onto the stack, +and \fB%t\fP pops it from the stack, testing if it is nonzero (true). +If it is zero (false), control passes to the \fB%e\fP (else) part. .IP It is possible to form else-if's a la Algol 68: .RS -%? c\d1\u %t b\d1\u %e c\d2\u %t b\d2\u %e c\d3\u %t b\d3\u %e c\d4\u %t b\d4\u %e %; +\fB%?\fP c\d1\u \fB%t\fP b\d1\u \fB%e\fP c\d2\u \fB%t\fP b\d2\u \fB%e\fP c\d3\u \fB%t\fP b\d3\u \fB%e\fP c\d4\u \fB%t\fP b\d4\u \fB%e\fP \fB%;\fP .RE .IP where c\di\u are conditions, b\di\u are bodies. .IP -Use the \fB-f\fP option of \fBtic\fP or \fBinfocmp\fP to see -the structure of if-the-else's. +Use the \fB\-f\fP option of \fBtic\fP or \fBinfocmp\fP to see +the structure of if-then-else's. Some strings, e.g., \fBsgr\fP can be very complicated when written on one line. -The \fB-f\fP option splits the string into lines with the parts indented. +The \fB\-f\fP option splits the string into lines with the parts indented. .PP Binary operations are in postfix form with the operands in the usual order. -That is, to get x-5 one would use "%gx%{5}%-". -%P and %g variables are +That is, to get x\-5 one would use \*(``%gx%{5}%\-\*(''. +\fB%P\fP and \fB%g\fP variables are persistent across escape-string evaluations. .PP Consider the HP2645, which, to get to row 3 and column 12, needs to be sent \eE&a12c03Y padded for 6 milliseconds. -Note that the order -of the rows and columns is inverted here, and that the row and column -are printed as two digits. -Thus its \fBcup\fR capability is \*(lqcup=6\eE&%p2%2dc%p1%2dY\*(rq. +The order of the rows and columns is inverted here, +and the row and column are printed as two digits. +The corresponding terminal description is expressed thus: +.RS +cup=\eE&a%p2%dc%p1%dY$<6>, +.RE .PP The Microterm \s-1ACT-IV\s0 needs the current row and column sent -preceded by a \fB^T\fR, with the row and column simply encoded in binary, -\*(lqcup=^T%p1%c%p2%c\*(rq. -Terminals which use \*(lq%c\*(rq need to be able to -backspace the cursor (\fBcub1\fR), -and to move the cursor up one line on the screen (\fBcuu1\fR). -This is necessary because it is not always safe to transmit \fB\en\fR -\fB^D\fR and \fB\er\fR, as the system may change or discard them. +preceded by a \fB^T\fP, with the row and column simply encoded in binary, +.RS +cup=^T%p1%c%p2%c +.RE +.PP +Terminals which use \*(``%c\*('' need to be able to +backspace the cursor (\fBcub1\fP), +and to move the cursor up one line on the screen (\fBcuu1\fP). +This is necessary because it is not always safe to transmit \fB\en\fP +\fB^D\fP and \fB\er\fP, as the system may change or discard them. (The library routines dealing with terminfo set tty modes so that tabs are never expanded, so \et is safe to send. This turns out to be essential for the Ann Arbor 4080.) .PP A final example is the \s-1LSI ADM\s0-3a, which uses row and column -offset by a blank character, thus \*(lqcup=\eE=%p1%' '%+%c%p2%' '%+%c\*(rq. -After sending `\eE=', this pushes the first parameter, pushes the +offset by a blank character, thus +.RS +cup=\eE=%p1%\(aq \(aq%+%c%p2%\(aq \(aq%+%c +.RE +.PP +After sending \*(``\eE=\*('', this pushes the first parameter, pushes the ASCII value for a space (32), adds them (pushing the sum on the stack in place of the two previous values) and outputs that value as a character. Then the same is done for the second parameter. More complex arithmetic is possible using the stack. -.PP .SS Cursor Motions -.PP If the terminal has a fast way to home the cursor (to very upper left corner of screen) then this can be given as -\fBhome\fR; similarly a fast way of getting to the lower left-hand corner -can be given as \fBll\fR; this may involve going up with \fBcuu1\fR +\fBhome\fP; similarly a fast way of getting to the lower left-hand corner +can be given as \fBll\fP; this may involve going up with \fBcuu1\fP from the home position, -but a program should never do this itself (unless \fBll\fR does) because it +but a program should never do this itself (unless \fBll\fP does) because it can make no assumption about the effect of moving up from the home position. Note that the home position is the same as addressing to (0,0): to the top left corner of the screen, not of memory. @@ -2100,7 +2403,7 @@ spaces to the right) these can be given as .BR cub , .BR cuf , and -.BR cuu +.B cuu with a single parameter indicating how many spaces to move. These are primarily useful if the terminal does not have .BR cup , @@ -2108,7 +2411,8 @@ such as the \s-1TEKTRONIX\s+1 4025. .PP If the terminal needs to be in a special mode when running a program that uses these capabilities, -the codes to enter and exit this mode can be given as \fBsmcup\fR and \fBrmcup\fR. +the codes to enter and exit this mode can be given +as \fBsmcup\fP and \fBrmcup\fP. This arises, for example, from terminals like the Concept with more than one page of memory. If the terminal has only memory relative cursor addressing and not screen @@ -2121,30 +2425,151 @@ sets the command character to be the one used by terminfo. If the \fBsmcup\fP sequence will not restore the screen after an \fBrmcup\fP sequence is output (to the state prior to outputting \fBrmcup\fP), specify \fBnrrmc\fP. +.SS Margins +SVr4 (and X/Open Curses) +list several string capabilities for setting margins. +Two were intended for use with terminals, +and another six were intended for use with printers. +.bP +The two terminal capabilities assume that the terminal may have +the capability of setting the left and/or right margin at the current +cursor column position. +.bP +The printer capabilities assume that the printer may have +two types of capability: +.RS +.bP +the ability to set a top and/or bottom margin using the current +line position, and +.bP +parameterized capabilities for setting the top, bottom, left, right margins +given the number of rows or columns. +.RE .PP -.SS Area Clears +In practice, the categorization into \*(``terminal\*('' and \*(``printer\*('' +is not suitable: +.bP +The AT&T SVr4 terminal database uses \fBsmgl\fP four times, +for AT&T hardware. +.IP +Three of the four are printers. +They lack the ability to set left/right margins by specifying the column. +.bP +Other (non-AT&T) terminals may support margins +but using different assumptions from AT&T. +.IP +For instance, the DEC VT420 supports left/right margins, +but only using a column parameter. +As an added complication, the VT420 uses two settings to fully enable +left/right margins (left/right margin mode, and origin mode). +The former enables the margins, which causes printed text +to wrap within margins, but the latter is needed to prevent +cursor-addressing outside those margins. +.bP +Both DEC VT420 left/right margins are set with a single control sequence. +If either is omitted, the corresponding margin is set to the left or +right edge of the display (rather than leaving the margin unmodified). +.PP +These are the margin-related capabilities: +.TS +center; +l l +_ _ +lw8 l. +\fBName Description\fP +smgl Set left margin at current column +smgr Set right margin at current column +smgb Set bottom margin at current line +smgt Set top margin at current line +smgbp Set bottom margin at line \fIN\fP +smglp Set left margin at column \fIN\fP +smgrp Set right margin at column \fIN\fP +smgtp Set top margin at line \fIN\fP +smglr Set both left and right margins to \fIL\fP and \fIR\fP +smgtb Set both top and bottom margins to \fIT\fP and \fIB\fP +.TE .PP +When writing an application that +uses these string capabilities, +the pairs should be first checked to see +if each capability in the pair is set or only one is set: +.bP +If both \fBsmglp\fP and \fBsmgrp\fP are set, +each is used with a single argument, \fIN\fP, +that gives the column number of the left and right margin, respectively. +.bP +If both \fBsmgtp\fP and \fBsmgbp\fP are set, +each is used to set the top and bottom margin, +respectively: +.RS 4 +.bP +\fBsmgtp\fP is used with a single argument, \fIN\fP, +the line number of the top margin. +.bP +\fBsmgbp\fP is used with two arguments, \fIN\fP and \fIM\fP, +that give the line number of the bottom margin, +the first counting from the top of the +page and the second counting from the bottom. +This accommodates the two styles of specifying +the bottom margin in different manufacturers' printers. +.RE +.IP +When designing a terminfo entry for a +printer that has a settable bottom margin, +only the first or second argument should be used, depending on the printer. +When developing an application that uses \fBsmgbp\fP to set the bottom margin, +both arguments must be given. +.PP +Conversely, when only one capability in the pair is set: +.bP +If only one of \fBsmglp\fP and \fBsmgrp\fP is set, +then it is used with two arguments, +the column number of the left and right margins, in that order. +.bP +Likewise, if only one of \fBsmgtp\fP and \fBsmgbp\fP is set, then it +is used with two arguments that give the top and bottom margins, +in that order, counting from the top of the page. +.IP +When designing a terminfo entry for a printer that requires setting both +left and right or top and bottom margins simultaneously, +only one capability in the pairs +\fBsmglp\fP and \fBsmgrp\fP or +\fBsmgtp\fP and \fBsmgbp\fP should be defined, +leaving the other unset. +.PP +Except for very old terminal descriptions, e.g., those developed for SVr4, +the scheme just described should be considered obsolete. +An improved set of capabilities was added late in the SVr4 releases +(\fBsmglr\fP and \fBsmgtb\fP), +which explicitly use two parameters for setting the left/right or top/bottom +margins. +.PP +When setting margins, the line- and column-values are zero-based. +.PP +The \fBmgc\fP string capability should be defined. +Applications such as \fBtabs\fP(1) rely upon this to reset all margins. +.\" +.SS Area Clears If the terminal can clear from the current position to the end of the -line, leaving the cursor where it is, this should be given as \fBel\fR. +line, leaving the cursor where it is, this should be given as \fBel\fP. If the terminal can clear from the beginning of the line to the current position inclusive, leaving the cursor where it is, this should be given as \fBel1\fP. If the terminal can clear from the current position to the end of the -display, then this should be given as \fBed\fR. -\fBEd\fR is only defined from the first column of a line. +display, then this should be given as \fBed\fP. +\fBEd\fP is only defined from the first column of a line. (Thus, it can be simulated by a request to delete a large number of lines, if a true .B ed is not available.) -.PP +.\" .SS Insert/delete line and vertical motions -.PP If the terminal can open a new blank line before the line where the cursor -is, this should be given as \fBil1\fR; this is done only from the first +is, this should be given as \fBil1\fP; this is done only from the first position of a line. The cursor must then appear on the newly blank line. If the terminal can delete the line which the cursor is on, then this -should be given as \fBdl1\fR; this is done only from the first position on +should be given as \fBdl1\fP; this is done only from the first position on the line to be deleted. Versions of .B il1 @@ -2171,12 +2596,12 @@ and .B rc (save and restore cursor) commands may be useful for ensuring that your synthesized insert/delete string does not move the cursor. -(Note that the \fBncurses\fR(3) library does this synthesis +(Note that the \fBncurses\fP(3) library does this synthesis automatically, so you need not compose insert/delete strings for -an entry with \fBcsr\fR). +an entry with \fBcsr\fP). .PP Yet another way to construct insert and delete might be to use a combination of -index with the memory-lock feature found on some terminals (like the HP-700/90 +index with the memory-lock feature found on some terminals (like the HP\-700/90 series, which however also has insert/delete). .PP Inserting lines at the top or bottom of the screen can also be @@ -2187,20 +2612,20 @@ or on many terminals without a true insert/delete line, and is often faster even on terminals with those features. .PP -The boolean \fBnon_dest_scroll_region\fR should be set if each scrolling +The boolean \fBnon_dest_scroll_region\fP should be set if each scrolling window is effectively a view port on a screen-sized canvas. To test for this capability, create a scrolling region in the middle of the screen, write something to the bottom line, move the cursor to the top of the region, -and do \fBri\fR followed by \fBdl1\fR or \fBind\fR. +and do \fBri\fP followed by \fBdl1\fP or \fBind\fP. If the data scrolled -off the bottom of the region by the \fBri\fR re-appears, then scrolling +off the bottom of the region by the \fBri\fP re-appears, then scrolling is non-destructive. -System V and XSI Curses expect that \fBind\fR, \fBri\fR, -\fBindn\fR, and \fBrin\fR will simulate destructive scrolling; their -documentation cautions you not to define \fBcsr\fR unless this is true. -This \fBcurses\fR implementation is more liberal and will do explicit erases -after scrolling if \fBndstr\fR is defined. +System V and XSI Curses expect that \fBind\fP, \fBri\fP, +\fBindn\fP, and \fBrin\fP will simulate destructive scrolling; their +documentation cautions you not to define \fBcsr\fP unless this is true. +This \fBcurses\fP implementation is more liberal and will do explicit erases +after scrolling if \fBndsrc\fP is defined. .PP If the terminal has the ability to define a window as part of memory, which all commands affect, @@ -2210,14 +2635,12 @@ The four parameters are the starting and ending lines in memory and the starting and ending columns in memory, in that order. .PP If the terminal can retain display memory above, then the -\fBda\fR capability should be given; if display memory can be retained -below, then \fBdb\fR should be given. +\fBda\fP capability should be given; if display memory can be retained +below, then \fBdb\fP should be given. These indicate that deleting a line or scrolling may bring non-blank lines up from below -or that scrolling back with \fBri\fR may bring down non-blank lines. -.PP +or that scrolling back with \fBri\fP may bring down non-blank lines. .SS Insert/Delete Character -.PP There are two basic kinds of intelligent terminals with respect to insert/delete character which can be described using .I terminfo. @@ -2227,56 +2650,58 @@ Other terminals, such as the Concept 100 and the Perkin Elmer Owl, make a distinction between typed and untyped blanks on the screen, shifting upon an insert or delete only to an untyped blank on the screen which is either eliminated, or expanded to two untyped blanks. +.PP You can determine the kind of terminal you have by clearing the screen and then typing text separated by cursor motions. -Type \*(lqabc\ \ \ \ def\*(rq using local -cursor motions (not spaces) between the \*(lqabc\*(rq and the \*(lqdef\*(rq. -Then position the cursor before the \*(lqabc\*(rq and put the terminal in insert +Type \*(``abc\ \ \ \ def\*('' using local +cursor motions (not spaces) between the \*(``abc\*('' and the \*(``def\*(''. +Then position the cursor before the \*(``abc\*('' and put the terminal in insert mode. If typing characters causes the rest of the line to shift rigidly and characters to fall off the end, then your terminal does not distinguish between blanks and untyped positions. -If the \*(lqabc\*(rq -shifts over to the \*(lqdef\*(rq which then move together around the end of the +If the \*(``abc\*('' +shifts over to the \*(``def\*('' which then move together around the end of the current line and onto the next as you insert, you have the second type of -terminal, and should give the capability \fBin\fR, which stands for -\*(lqinsert null\*(rq. +terminal, and should give the capability \fBin\fP, which stands for +\*(``insert null\*(''. +.PP While these are two logically separate attributes (one line versus multi-line insert mode, and special treatment of untyped spaces) we have seen no terminals whose insert mode cannot be described with the single attribute. .PP Terminfo can describe both terminals which have an insert mode, and terminals which send a simple sequence to open a blank position on the current line. -Give as \fBsmir\fR the sequence to get into insert mode. -Give as \fBrmir\fR the sequence to leave insert mode. -Now give as \fBich1\fR any sequence needed to be sent just before sending +Give as \fBsmir\fP the sequence to get into insert mode. +Give as \fBrmir\fP the sequence to leave insert mode. +Now give as \fBich1\fP any sequence needed to be sent just before sending the character to be inserted. Most terminals with a true insert mode -will not give \fBich1\fR; terminals which send a sequence to open a screen +will not give \fBich1\fP; terminals which send a sequence to open a screen position should give it here. .PP -If your terminal has both, insert mode is usually preferable to \fBich1\fR. +If your terminal has both, insert mode is usually preferable to \fBich1\fP. Technically, you should not give both unless the terminal actually requires both to be used in combination. Accordingly, some non-curses applications get confused if both are present; the symptom is doubled characters in an update using insert. -This requirement is now rare; most \fBich\fR sequences do not -require previous smir, and most smir insert modes do not require \fBich1\fR +This requirement is now rare; most \fBich\fP sequences do not +require previous smir, and most smir insert modes do not require \fBich1\fP before each character. -Therefore, the new \fBcurses\fR actually assumes this -is the case and uses either \fBrmir\fR/\fBsmir\fR or \fBich\fR/\fBich1\fR as +Therefore, the new \fBcurses\fP actually assumes this +is the case and uses either \fBrmir\fP/\fBsmir\fP or \fBich\fP/\fBich1\fP as appropriate (but not both). If you have to write an entry to be used under new curses for a terminal old enough to need both, include the -\fBrmir\fR/\fBsmir\fR sequences in \fBich1\fR. +\fBrmir\fP/\fBsmir\fP sequences in \fBich1\fP. .PP If post insert padding is needed, give this as a number of milliseconds -in \fBip\fR (a string option). +in \fBip\fP (a string option). Any other sequence which may need to be -sent after an insert of a single character may also be given in \fBip\fR. -If your terminal needs both to be placed into an `insert mode' and +sent after an insert of a single character may also be given in \fBip\fP. +If your terminal needs both to be placed into an \*(``insert mode\*('' and a special code to precede each inserted character, then both .BR smir / rmir and @@ -2298,11 +2723,11 @@ It is occasionally necessary to move around while in insert mode to delete characters on the same line (e.g., if there is a tab after the insertion position). If your terminal allows motion while in -insert mode you can give the capability \fBmir\fR to speed up inserting +insert mode you can give the capability \fBmir\fP to speed up inserting in this case. -Omitting \fBmir\fR will affect only speed. +Omitting \fBmir\fP will affect only speed. Some terminals -(notably Datamedia's) must not have \fBmir\fR because of the way their +(notably Datamedia's) must not have \fBmir\fP because of the way their insert mode works. .PP Finally, you can specify @@ -2313,7 +2738,7 @@ with one parameter, .IR n , to delete .I n characters, -and delete mode by giving \fBsmdc\fR and \fBrmdc\fR +and delete mode by giving \fBsmdc\fP and \fBrmdc\fP to enter and exit delete mode (any mode the terminal needs to be placed in for .B dch1 @@ -2327,30 +2752,28 @@ blanks without moving the cursor) can be given as .B ech with one parameter. -.PP .SS "Highlighting, Underlining, and Visible Bells" -.PP If your terminal has one or more kinds of display attributes, these can be represented in a number of different ways. You should choose one display form as -\f2standout mode\fR, +\f2standout mode\fP, representing a good, high contrast, easy-on-the-eyes, format for highlighting error messages and other attention getters. (If you have a choice, reverse video plus half-bright is good, or reverse video alone.) The sequences to enter and exit standout mode -are given as \fBsmso\fR and \fBrmso\fR, respectively. +are given as \fBsmso\fP and \fBrmso\fP, respectively. If the code to change into or out of standout mode leaves one or even two blank spaces on the screen, as the TVI 912 and Teleray 1061 do, -then \fBxmc\fR should be given to tell how many spaces are left. +then \fBxmc\fP should be given to tell how many spaces are left. .PP -Codes to begin underlining and end underlining can be given as \fBsmul\fR -and \fBrmul\fR respectively. +Codes to begin underlining and end underlining can be given as \fBsmul\fP +and \fBrmul\fP respectively. If the terminal has a code to underline the current character and move the cursor one space to the right, such as the Microterm Mime, -this can be given as \fBuc\fR. +this can be given as \fBuc\fP. .PP Other capabilities to enter various highlighting modes include .B blink @@ -2381,7 +2804,8 @@ this should be given as .B sgr (set attributes), taking 9 parameters. -Each parameter is either 0 or nonzero, as the corresponding attribute is on or off. +Each parameter is either zero (0) or nonzero, +as the corresponding attribute is on or off. The 9 parameters are, in order: standout, underline, reverse, blink, dim, bold, blank, protect, alternate character set. @@ -2393,9 +2817,9 @@ For example, the DEC vt220 supports most of the modes: .PP .TS center; -l c c -l c c -lw28 lw6 lw2 lw20. +l l l +l l l +lw18 lw14 l. \fBtparm parameter attribute escape sequence\fP none none \\E[0m @@ -2426,13 +2850,15 @@ either standout or reverse modes are turned on. .PP Writing out the above sequences, along with their dependencies yields .PP +.ne 11 .TS center; -l c c -l c c -lw28 lw6 lw2 lw20. +l l l +l l l +lw18 lw14 l. \fBsequence when to output terminfo translation\fP +.ft CW \\E[0 always \\E[0 ;1 if p1 or p6 %?%p1%p6%|%t;1%; ;4 if p2 %?%p2%|%t;4%; @@ -2441,14 +2867,17 @@ lw28 lw6 lw2 lw20. ;8 if p7 %?%p7%|%t;8%; m always m ^N or ^O if p9 ^N, else ^O %?%p9%t^N%e^O%; +.ft R .TE .PP Putting this all together into the sgr sequence gives: .PP +.ft CW .nf - sgr=\\E[0%?%p1%p6%|%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%; - %?%p4%t;5%;%?%p7%t;8%;m%?%p9%t\\016%e\\017%;, + sgr=\\E[0%?%p1%p6%|%t;1%;%?%p2%t;4%;%?%p4%t;5%; + %?%p1%p3%|%t;7%;%?%p7%t;8%;m%?%p9%t\\016%e\\017%;, .fi +.ft R .PP Remember that if you specify sgr, you must also specify sgr0. Also, some implementations rely on sgr being given if sgr0 is, @@ -2458,9 +2887,9 @@ which have no sgr string. The only drawback to adding an sgr string is that termcap also assumes that sgr0 does not exit alternate character set mode. .PP -Terminals with the ``magic cookie'' glitch +Terminals with the \*(``magic cookie\*('' glitch .RB ( xmc ) -deposit special ``cookies'' when they receive mode-setting sequences, +deposit special \*(``cookies\*('' when they receive mode-setting sequences, which affect the display algorithm rather than having extra bits for each character. Some terminals, such as the HP 2621, automatically leave standout @@ -2473,7 +2902,7 @@ capability, asserting that it is safe to move in standout mode, is present. .PP If the terminal has a way of flashing the screen to indicate an error quietly (a bell replacement) -then this can be given as \fBflash\fR; it must not move the cursor. +then this can be given as \fBflash\fP; it must not move the cursor. .PP If the cursor needs to be made more visible than normal when it is not on the bottom line (to make, for example, a non-blinking underline into an @@ -2483,70 +2912,88 @@ give this sequence as If there is a way to make the cursor completely invisible, give that as .BR civis . The capability -.BR cnorm +.B cnorm should be given which undoes the effects of both of these modes. .PP If your terminal correctly generates underlined characters (with no special codes needed) even though it does not overstrike, -then you should give the capability \fBul\fR. +then you should give the capability \fBul\fP. If a character overstriking another leaves both characters on the screen, specify the capability \fBos\fP. If overstrikes are erasable with a blank, -then this should be indicated by giving \fBeo\fR. -.PP +then this should be indicated by giving \fBeo\fP. .SS Keypad and Function Keys -.PP If the terminal has a keypad that transmits codes when the keys are pressed, this information can be given. Note that it is not possible to handle terminals where the keypad only works in local (this applies, for example, to the unshifted HP 2621 keys). If the keypad can be set to transmit or not transmit, -give these codes as \fBsmkx\fR and \fBrmkx\fR. +give these codes as \fBsmkx\fP and \fBrmkx\fP. Otherwise the keypad is assumed to always transmit. +.PP The codes sent by the left arrow, right arrow, up arrow, down arrow, and home keys can be given as -\fBkcub1, kcuf1, kcuu1, kcud1, \fRand\fB khome\fR respectively. +\fBkcub1, kcuf1, kcuu1, kcud1, \fRand\fB khome\fP respectively. If there are function keys such as f0, f1, ..., f10, the codes they send -can be given as \fBkf0, kf1, ..., kf10\fR. +can be given as \fBkf0, kf1, ..., kf10\fP. If these keys have labels other than the default f0 through f10, the labels -can be given as \fBlf0, lf1, ..., lf10\fR. +can be given as \fBlf0, lf1, ..., lf10\fP. +.PP The codes transmitted by certain other special keys can be given: +.bP .B kll (home down), +.bP .B kbs (backspace), +.bP .B ktbc (clear all tabs), +.bP .B kctab (clear the tab stop in this column), +.bP .B kclr (clear screen or erase key), +.bP .B kdch1 (delete character), +.bP .B kdl1 (delete line), +.bP .B krmir (exit insert mode), +.bP .B kel (clear to end of line), +.bP .B ked (clear to end of screen), +.bP .B kich1 (insert character or enter insert mode), +.bP .B kil1 (insert line), +.bP .B knp (next page), +.bP .B kpp (previous page), +.bP .B kind (scroll forward/down), +.bP .B kri (scroll backward/up), +.bP .B khts (set a tab stop in this column). +.PP In addition, if the keypad has a 3 by 3 array of keys including the four arrow keys, the other five keys can be given as .BR ka1 , @@ -2583,16 +3030,18 @@ If there are commands to turn the labels on and off, give them in \fBsmln\fP and \fBrmln\fP. \fBsmln\fP is normally output after one or more pln sequences to make sure that the change becomes visible. -.PP .SS Tabs and Initialization -.PP +A few capabilities are used only for tabs: +.bP If the terminal has hardware tabs, the command to advance to the next tab stop can be given as .B ht -(usually control I). -A ``back-tab'' command which moves leftward to the preceding tab stop can +(usually control/I). +.bP +A \*(``back-tab\*('' command which moves leftward to the preceding tab stop can be given as .BR cbt . +.IP By convention, if the teletype modes indicate that tabs are being expanded by the computer rather than being sent to the terminal, programs should not use @@ -2601,14 +3050,15 @@ or .B cbt even if they are present, since the user may not have the tab stops properly set. +.bP If the terminal has hardware tabs which are initially set every .I n spaces when the terminal is powered up, the numeric parameter .B it is given, showing the number of spaces the tabs are set to. -This is normally used by the -.IR tset +.IP +The \fBit\fP capability is normally used by the \fBtset\fP command to determine whether to set the mode for hardware tab expansion, and whether to set the tab stops. If the terminal has tab stops that can be saved in non-volatile memory, @@ -2616,48 +3066,52 @@ the terminfo description can assume that they are properly set. .PP Other capabilities include +.bP .BR is1 , .BR is2 , and .BR is3 , initialization strings for the terminal, +.bP .BR iprog , the path name of a program to be run to initialize the terminal, -and \fBif\fR, the name of a file containing long initialization strings. +.bP +and \fBif\fP, the name of a file containing long initialization strings. +.PP These strings are expected to set the terminal into modes consistent with the rest of the terminfo description. They are normally sent to the terminal, by the .I init -option of the -.IR tput -program, each time the user logs in. +option of the \fBtput\fP program, each time the user logs in. They will be printed in the following order: .RS .TP run the program -.BR iprog +.B iprog .TP output -.BR is1 -.BR is2 +.br +\fBis1\fP and +.br +\fBis2\fP .TP set the margins using -.BR mgc , -.BR smgl -and -.BR smgr +\fBmgc\fP or +.br +\fBsmglp\fP and \fBsmgrp\fP or +.br +\fBsmgl\fP and \fBsmgr\fP .TP set tabs using .B tbc and -.BR hts +.B hts .TP print the file -.BR if +\fBif\fP .TP -and finally -output -.BR is3 . +and finally output +\fBis3\fP. .RE .PP Most initialization is done with @@ -2674,7 +3128,7 @@ A set of sequences that does a harder reset from a totally unknown state can be given as .BR rs1 , .BR rs2 , -.BR rf +.B rf and .BR rs3 , analogous to @@ -2682,14 +3136,16 @@ analogous to .B is2 , .B if and -.BR is3 +.B is3 respectively. -These strings are output by the -.IR reset -program, which is used when the terminal gets into a wedged state. +These strings are output +by \fIreset\fP option of \fBtput\fP, +or by the \fB?\fP program +(an alias of \fBtset\fP), +which is used when the terminal gets into a wedged state. Commands are normally placed in .BR rs1 , -.BR rs2 +.B rs2 .B rs3 and .B rf @@ -2699,16 +3155,13 @@ For example, the command to set the vt100 into 80-column mode would normally be part of .BR is2 , but it causes an annoying glitch of the screen and is not normally -needed since the terminal is usually already in 80 column mode. +needed since the terminal is usually already in 80-column mode. .PP -The -.IR reset -program writes strings -including +The \fB?\fP program writes strings including .BR iprog , etc., in the same order as the -.IR init -program, using +.I init +program, using .BR rs1 , etc., instead of .BR is1 , @@ -2718,10 +3171,10 @@ If any of .BR rs2 , .BR rs3 , or -.BR rf -reset capability strings are missing, the -.IR reset -program falls back upon the corresponding initialization capability string. +.B rf +reset capability strings are missing, +the \fB?\fP program +falls back upon the corresponding initialization capability string. .PP If there are commands to set and clear tab stops, they can be given as .B tbc @@ -2734,8 +3187,34 @@ described by this, the sequence can be placed in .B is2 or .BR if . -.SS Delays and Padding .PP +The \fBtput reset\fP command uses the same capability strings +as the \fB?\fP command, +although the two programs (\fBtput\fP and \fB?\fP) +provide different command-line options. +.PP +In practice, these terminfo capabilities are not often used in +initialization of tabs +(though they are required for the \fB?\fP program): +.bP +Almost all hardware terminals (at least those which supported tabs) +initialized those to every \fIeight\fP columns: +.IP +The only exception was the AT&T 2300 series, +which set tabs to every \fIfive\fP columns. +.bP +In particular, developers of the hardware terminals which are commonly used +as models for modern terminal emulators provided documentation demonstrating +that \fIeight\fP columns were the standard. +.bP +Because of this, the terminal initialization programs +\fBtput\fP and \fBtset\fP +use the +\fBtbc\fP (\fBclear_all_tabs\fP) and +\fBhts\fP (\fBset_tab\fP) capabilities directly +only when the \fBit\fP (\fBinit_tabs\fP) capability +is set to a value other than \fIeight\fP. +.SS Delays and Padding Many older and slower terminals do not support either XON/XOFF or DTR handshaking, including hard copy terminals and some very archaic CRTs (including, for example, DEC VT100s). @@ -2753,155 +3232,185 @@ Padding information should still be included so that routines can make better decisions about relative costs, but actual pad characters will not be transmitted. .PP -If \fBpb\fR (padding baud rate) is given, padding is suppressed at baud rates -below the value of \fBpb\fR. +If \fBpb\fP (padding baud rate) is given, padding is suppressed at baud rates +below the value of \fBpb\fP. If the entry has no padding baud rate, then -whether padding is emitted or not is completely controlled by \fBxon\fR. +whether padding is emitted or not is completely controlled by \fBxon\fP. .PP If the terminal requires other than a null (zero) character as a pad, -then this can be given as \fBpad\fR. +then this can be given as \fBpad\fP. Only the first character of the .B pad string is used. -.PP .SS Status Lines -Some terminals have an extra `status line' which is not normally used by -software (and thus not counted in the terminal's \fBlines\fR capability). +Some terminals have an extra \*(``status line\*('' which is not normally used by +software (and thus not counted in the terminal's \fBlines\fP capability). .PP The simplest case is a status line which is cursor-addressable but not part of the main scrolling region on the screen; the Heathkit H19 has a status line of this kind, as would a 24-line VT100 with a 23-line scrolling region set up on initialization. This situation is indicated -by the \fBhs\fR capability. +by the \fBhs\fP capability. .PP Some terminals with status lines need special sequences to access the status line. These may be expressed as a string with single parameter -\fBtsl\fR which takes the cursor to a given zero-origin column on the +\fBtsl\fP which takes the cursor to a given zero-origin column on the status line. -The capability \fBfsl\fR must return to the main-screen -cursor positions before the last \fBtsl\fR. +The capability \fBfsl\fP must return to the main-screen +cursor positions before the last \fBtsl\fP. You may need to embed the -string values of \fBsc\fR (save cursor) and \fBrc\fR (restore cursor) -in \fBtsl\fR and \fBfsl\fR to accomplish this. +string values of \fBsc\fP (save cursor) and \fBrc\fP (restore cursor) +in \fBtsl\fP and \fBfsl\fP to accomplish this. .PP The status line is normally assumed to be the same width as the width of the terminal. If this is untrue, you can specify it with the numeric -capability \fBwsl\fR. +capability \fBwsl\fP. .PP -A command to erase or blank the status line may be specified as \fBdsl\fR. +A command to erase or blank the status line may be specified as \fBdsl\fP. .PP -The boolean capability \fBeslok\fR specifies that escape sequences, tabs, +The boolean capability \fBeslok\fP specifies that escape sequences, tabs, etc., work ordinarily in the status line. .PP -The \fBncurses\fR implementation does not yet use any of these capabilities. +The \fBncurses\fP implementation does not yet use any of these capabilities. They are documented here in case they ever become important. -.PP .SS Line Graphics -.PP Many terminals have alternate character sets useful for forms-drawing. -Terminfo and \fBcurses\fR build in support for the drawing characters +Terminfo and \fBcurses\fP have built-in support +for most of the drawing characters supported by the VT100, with some characters from the AT&T 4410v1 added. -This alternate character set may be specified by the \fBacsc\fR capability. +This alternate character set may be specified by the \fBacsc\fP capability. .PP .TS H -center expand; -c l l c -c l l c -lw28 lw6 lw2 lw20. +center; +l l l l l +l l l l l +_ _ _ _ _ +lw25 lw10 lw6 lw6 l. .\".TH -\fBGlyph ACS Ascii VT100\fR -\fBName Name Default Name\fR -UK pound sign ACS_STERLING f } -arrow pointing down ACS_DARROW v . -arrow pointing left ACS_LARROW < , -arrow pointing right ACS_RARROW > + -arrow pointing up ACS_UARROW ^ - -board of squares ACS_BOARD # h -bullet ACS_BULLET o ~ -checker board (stipple) ACS_CKBOARD : a -degree symbol ACS_DEGREE \e f -diamond ACS_DIAMOND + ` -greater-than-or-equal-to ACS_GEQUAL > z -greek pi ACS_PI * { -horizontal line ACS_HLINE - q -lantern symbol ACS_LANTERN # i -large plus or crossover ACS_PLUS + n -less-than-or-equal-to ACS_LEQUAL < y -lower left corner ACS_LLCORNER + m -lower right corner ACS_LRCORNER + j -not-equal ACS_NEQUAL ! | -plus/minus ACS_PLMINUS # g -scan line 1 ACS_S1 ~ o -scan line 3 ACS_S3 - p -scan line 7 ACS_S7 - r -scan line 9 ACS_S9 \&_ s -solid square block ACS_BLOCK # 0 -tee pointing down ACS_TTEE + w -tee pointing left ACS_RTEE + u -tee pointing right ACS_LTEE + t -tee pointing up ACS_BTEE + v -upper left corner ACS_ULCORNER + l -upper right corner ACS_URCORNER + k -vertical line ACS_VLINE | x +\fBGlyph ACS Ascii acsc acsc\fP +\fBName Name Default Char Value\fP +arrow pointing right ACS_RARROW > + 0x2b +arrow pointing left ACS_LARROW < , 0x2c +arrow pointing up ACS_UARROW ^ \- 0x2d +arrow pointing down ACS_DARROW v . 0x2e +solid square block ACS_BLOCK # 0 0x30 +diamond ACS_DIAMOND + ` 0x60 +checker board (stipple) ACS_CKBOARD : a 0x61 +degree symbol ACS_DEGREE \e f 0x66 +plus/minus ACS_PLMINUS # g 0x67 +board of squares ACS_BOARD # h 0x68 +lantern symbol ACS_LANTERN # i 0x69 +lower right corner ACS_LRCORNER + j 0x6a +upper right corner ACS_URCORNER + k 0x6b +upper left corner ACS_ULCORNER + l 0x6c +lower left corner ACS_LLCORNER + m 0x6d +large plus or crossover ACS_PLUS + n 0x6e +scan line 1 ACS_S1 ~ o 0x6f +scan line 3 ACS_S3 \- p 0x70 +horizontal line ACS_HLINE \- q 0x71 +scan line 7 ACS_S7 \- r 0x72 +scan line 9 ACS_S9 \&_ s 0x73 +tee pointing right ACS_LTEE + t 0x74 +tee pointing left ACS_RTEE + u 0x75 +tee pointing up ACS_BTEE + v 0x76 +tee pointing down ACS_TTEE + w 0x77 +vertical line ACS_VLINE | x 0x78 +less-than-or-equal-to ACS_LEQUAL < y 0x79 +greater-than-or-equal-to ACS_GEQUAL > z 0x7a +greek pi ACS_PI * { 0x7b +not-equal ACS_NEQUAL ! | 0x7c +UK pound sign ACS_STERLING f } 0x7d +bullet ACS_BULLET o ~ 0x7e .TE .PP +A few notes apply to the table itself: +.bP +X/Open Curses incorrectly states that the mapping for \fIlantern\fP is +uppercase \*(``I\*('' although Unix implementations use the +lowercase \*(``i\*('' mapping. +.bP +The DEC VT100 implemented graphics using the alternate character set +feature, temporarily switching \fImodes\fP and sending characters +in the range 0x60 (96) to 0x7e (126) +(the \fBacsc Value\fP column in the table). +.bP +The AT&T terminal added graphics characters outside that range. +.IP +Some of the characters within the range do not match the VT100; +presumably they were used in the AT&T terminal: +\fIboard of squares\fP replaces the VT100 \fInewline\fP symbol, while +\fIlantern symbol\fP replaces the VT100 \fIvertical tab\fP symbol. +The other VT100 symbols for control characters (\fIhorizontal tab\fP, +\fIcarriage return\fP and \fIline-feed\fP) are not (re)used in curses. +.PP The best way to define a new device's graphics set is to add a column to a copy of this table for your terminal, giving the character which -(when emitted between \fBsmacs\fR/\fBrmacs\fR switches) will be rendered +(when emitted between \fBsmacs\fP/\fBrmacs\fP switches) will be rendered as the corresponding graphic. Then read off the VT100/your terminal character pairs right to left in sequence; these become the ACSC string. -.PP .SS Color Handling +The curses library functions \fBinit_pair\fP and \fBinit_color\fP +manipulate the \fIcolor pairs\fP and \fIcolor values\fP discussed in this +section +(see \fBcurs_color\fP(3) for details on these and related functions). .PP -Most color terminals are either `Tektronix-like' or `HP-like'. +Most color terminals are either \*(``Tektronix-like\*('' or \*(``HP-like\*('': +.bP Tektronix-like -terminals have a predefined set of N colors (where N usually 8), and can set +terminals have a predefined set of \fIN\fP colors +(where \fIN\fP is usually 8), +and can set character-cell foreground and background characters independently, mixing them -into N * N color-pairs. -On HP-like terminals, the use must set each color +into \fIN\fP\ *\ \fIN\fP color-pairs. +.bP +On HP-like terminals, the user must set each color pair up separately (foreground and background are not independently settable). -Up to M color-pairs may be set up from 2*M different colors. -ANSI-compatible -terminals are Tektronix-like. +Up to \fIM\fP color-pairs may be set up from 2*\fIM\fP different colors. +ANSI-compatible terminals are Tektronix-like. .PP Some basic color capabilities are independent of the color method. The numeric -capabilities \fBcolors\fR and \fBpairs\fR specify the maximum numbers of colors +capabilities \fBcolors\fP and \fBpairs\fP specify the maximum numbers of colors and color-pairs that can be displayed simultaneously. -The \fBop\fR (original +The \fBop\fP (original pair) string resets foreground and background colors to their default values for the terminal. -The \fBoc\fR string resets all colors or color-pairs to +The \fBoc\fP string resets all colors or color-pairs to their default values for the terminal. Some terminals (including many PC terminal emulators) erase screen areas with the current background color rather than the power-up default background; these should have the boolean capability -\fBbce\fR. +\fBbce\fP. .PP +While the curses library works with \fIcolor pairs\fP +(reflecting the inability of some devices to set foreground +and background colors independently), +there are separate capabilities for setting these features: +.bP To change the current foreground or background color on a Tektronix-type -terminal, use \fBsetaf\fR (set ANSI foreground) and \fBsetab\fR (set ANSI -background) or \fBsetf\fR (set foreground) and \fBsetb\fR (set background). +terminal, use \fBsetaf\fP (set ANSI foreground) and \fBsetab\fP (set ANSI +background) or \fBsetf\fP (set foreground) and \fBsetb\fP (set background). These take one parameter, the color number. The SVr4 documentation describes -only \fBsetaf\fR/\fBsetab\fR; the XPG4 draft says that "If the terminal +only \fBsetaf\fP/\fBsetab\fP; the XPG4 draft says that "If the terminal supports ANSI escape sequences to set background and foreground, they should -be coded as \fBsetaf\fR and \fBsetab\fR, respectively. +be coded as \fBsetaf\fP and \fBsetab\fP, respectively. +.bP If the terminal supports other escape sequences to set background and foreground, they should -be coded as \fBsetf\fR and \fBsetb\fR, respectively. -The \fIvidputs()\fR -function and the refresh functions use \fBsetaf\fR and \fBsetab\fR if they are -defined." +be coded as \fBsetf\fP and \fBsetb\fP, respectively. +The \fBvidputs\fP and the \fBrefresh\fP(3) functions +use the \fBsetaf\fP and \fBsetab\fP capabilities if they are defined. .PP -The \fBsetaf\fR/\fBsetab\fR and \fBsetf\fR/\fBsetb\fR capabilities take a +The \fBsetaf\fP/\fBsetab\fP and \fBsetf\fP/\fBsetb\fP capabilities take a single numeric argument each. -Argument values 0-7 of \fBsetaf\fR/\fBsetab\fR are portably defined as +Argument values 0-7 of \fBsetaf\fP/\fBsetab\fP are portably defined as follows (the middle column is the symbolic #define available in the header for -the \fBcurses\fR or \fBncurses\fR libraries). +the \fBcurses\fP or \fBncurses\fP libraries). The terminal hardware is free to map these as it likes, but the RGB values indicate normal locations in color space. @@ -2910,99 +3419,108 @@ space. center; l c c c l l n l. -\fBColor #define Value RGB\fR -black \fBCOLOR_BLACK\fR 0 0, 0, 0 -red \fBCOLOR_RED\ \fR 1 max,0,0 -green \fBCOLOR_GREEN\fR 2 0,max,0 -yellow \fBCOLOR_YELLOW\fR 3 max,max,0 -blue \fBCOLOR_BLUE\fR 4 0,0,max -magenta \fBCOLOR_MAGENTA\fR 5 max,0,max -cyan \fBCOLOR_CYAN\fR 6 0,max,max -white \fBCOLOR_WHITE\fR 7 max,max,max +\fBColor #define Value RGB\fP +black \fBCOLOR_BLACK\fP 0 0, 0, 0 +red \fBCOLOR_RED\ \fP 1 max,0,0 +green \fBCOLOR_GREEN\fP 2 0,max,0 +yellow \fBCOLOR_YELLOW\fP 3 max,max,0 +blue \fBCOLOR_BLUE\fP 4 0,0,max +magenta \fBCOLOR_MAGENTA\fP 5 max,0,max +cyan \fBCOLOR_CYAN\fP 6 0,max,max +white \fBCOLOR_WHITE\fP 7 max,max,max .TE .PP -The argument values of \fBsetf\fR/\fBsetb\fR historically correspond to +The argument values of \fBsetf\fP/\fBsetb\fP historically correspond to a different mapping, i.e., .TS H center; l c c c l l n l. -\fBColor #define Value RGB\fR -black \fBCOLOR_BLACK\fR 0 0, 0, 0 -blue \fBCOLOR_BLUE\fR 1 0,0,max -green \fBCOLOR_GREEN\fR 2 0,max,0 -cyan \fBCOLOR_CYAN\fR 3 0,max,max -red \fBCOLOR_RED\ \fR 4 max,0,0 -magenta \fBCOLOR_MAGENTA\fR 5 max,0,max -yellow \fBCOLOR_YELLOW\fR 6 max,max,0 -white \fBCOLOR_WHITE\fR 7 max,max,max +\fBColor #define Value RGB\fP +black \fBCOLOR_BLACK\fP 0 0, 0, 0 +blue \fBCOLOR_BLUE\fP 1 0,0,max +green \fBCOLOR_GREEN\fP 2 0,max,0 +cyan \fBCOLOR_CYAN\fP 3 0,max,max +red \fBCOLOR_RED\ \fP 4 max,0,0 +magenta \fBCOLOR_MAGENTA\fP 5 max,0,max +yellow \fBCOLOR_YELLOW\fP 6 max,max,0 +white \fBCOLOR_WHITE\fP 7 max,max,max .TE +.PP It is important to not confuse the two sets of color capabilities; otherwise red/blue will be interchanged on the display. .PP -On an HP-like terminal, use \fBscp\fR with a color-pair number parameter to set +On an HP-like terminal, use \fBscp\fP with a color-pair number parameter to set which color pair is current. .PP -On a Tektronix-like terminal, the capability \fBccc\fR may be present to +Some terminals allow the \fIcolor values\fP to be modified: +.bP +On a Tektronix-like terminal, the capability \fBccc\fP may be present to indicate that colors can be modified. -If so, the \fBinitc\fR capability will -take a color number (0 to \fBcolors\fR - 1)and three more parameters which +If so, the \fBinitc\fP capability will +take a color number (0 to \fBcolors\fP \- 1)and three more parameters which describe the color. These three parameters default to being interpreted as RGB (Red, Green, Blue) values. -If the boolean capability \fBhls\fR is present, +If the boolean capability \fBhls\fP is present, they are instead as HLS (Hue, Lightness, Saturation) indices. The ranges are terminal-dependent. -.PP -On an HP-like terminal, \fBinitp\fR may give a capability for changing a +.bP +On an HP-like terminal, \fBinitp\fP may give a capability for changing a color-pair value. It will take seven parameters; a color-pair number (0 to -\fBmax_pairs\fR - 1), and two triples describing first background and then +\fBmax_pairs\fP \- 1), and two triples describing first background and then foreground colors. These parameters must be (Red, Green, Blue) or -(Hue, Lightness, Saturation) depending on \fBhls\fR. +(Hue, Lightness, Saturation) depending on \fBhls\fP. .PP On some color terminals, colors collide with highlights. You can register -these collisions with the \fBncv\fR capability. +these collisions with the \fBncv\fP capability. This is a bit-mask of attributes not to be used when colors are enabled. The correspondence with the -attributes understood by \fBcurses\fR is as follows: +attributes understood by \fBcurses\fP is as follows: .PP .TS center; -l c c -lw25 lw2 lw10. -\fBAttribute Bit Decimal\fR -A_STANDOUT 0 1 -A_UNDERLINE 1 2 -A_REVERSE 2 4 -A_BLINK 3 8 -A_DIM 4 16 -A_BOLD 5 32 -A_INVIS 6 64 -A_PROTECT 7 128 -A_ALTCHARSET 8 256 +l l l l +lw20 lw2 lw10 l. +\fBAttribute Bit Decimal Set by\fP +A_STANDOUT 0 1 sgr +A_UNDERLINE 1 2 sgr +A_REVERSE 2 4 sgr +A_BLINK 3 8 sgr +A_DIM 4 16 sgr +A_BOLD 5 32 sgr +A_INVIS 6 64 sgr +A_PROTECT 7 128 sgr +A_ALTCHARSET 8 256 sgr +A_HORIZONTAL 9 512 sgr1 +A_LEFT 10 1024 sgr1 +A_LOW 11 2048 sgr1 +A_RIGHT 12 4096 sgr1 +A_TOP 13 8192 sgr1 +A_VERTICAL 14 16384 sgr1 +A_ITALIC 15 32768 sitm .TE .PP For example, on many IBM PC consoles, the underline attribute collides with the foreground color blue and is not available in color mode. These should have -an \fBncv\fR capability of 2. +an \fBncv\fP capability of 2. .PP -SVr4 curses does nothing with \fBncv\fR, ncurses recognizes it and optimizes +SVr4 curses does nothing with \fBncv\fP, ncurses recognizes it and optimizes the output in favor of colors. -.PP .SS Miscellaneous If the terminal requires other than a null (zero) character as a pad, then this can be given as pad. Only the first character of the pad string is used. If the terminal does not have a pad character, specify npc. -Note that ncurses implements the termcap-compatible \fBPC\fR variable; +Note that ncurses implements the termcap-compatible \fBPC\fP variable; though the application may set this value to something other than -a null, ncurses will test \fBnpc\fR first and use napms if the terminal +a null, ncurses will test \fBnpc\fP first and use napms if the terminal has no pad character. .PP If the terminal can move up or down half a line, @@ -3015,7 +3533,7 @@ and This is primarily useful for superscripts and subscripts on hard-copy terminals. If a hard-copy terminal can eject to the next page (form feed), give this as .B ff -(usually control L). +(usually control/L). .PP If there is a command to repeat a given character a given number of times (to save time transmitting a large number of identical characters) @@ -3023,9 +3541,10 @@ this can be indicated with the parameterized string .BR rep . The first parameter is the character to be repeated and the second is the number of times to repeat it. -Thus, tparm(repeat_char, 'x', 10) is the same as `xxxxxxxxxx'. +Thus, tparm(repeat_char, \(aqx\(aq, 10) is the same as \*(``xxxxxxxxxx\*(''. .PP -If the terminal has a settable command character, such as the \s-1TEKTRONIX\s+1 4025, +If the terminal has a settable command character, +such as the \s-1TEKTRONIX\s+1 4025, this can be indicated with .BR cmdch . A prototype command character is chosen which is used in all capabilities. @@ -3054,13 +3573,13 @@ how to talk to the terminal. .I virtual terminal descriptions for which the escape sequences are known.) .PP -If the terminal has a ``meta key'' which acts as a shift key, +If the terminal has a \*(``meta key\*('' which acts as a shift key, setting the 8th bit of any character transmitted, this fact can be indicated with .BR km . Otherwise, software will assume that the 8th bit is parity and it will usually be cleared. -If strings exist to turn this ``meta mode'' on and off, they +If strings exist to turn this \*(``meta mode\*('' on and off, they can be given as .B smm and @@ -3101,15 +3620,14 @@ All text, including is transparently passed to the printer while an .B mc5p is in effect. -.PP .SS Glitches and Braindamage +Hazeltine terminals, +which do not allow \*(``~\*('' characters to be displayed should +indicate \fBhz\fP. .PP -Hazeltine terminals, which do not allow `~' characters to be displayed should -indicate \fBhz\fR. -.PP -Terminals which ignore a line-feed immediately after an \fBam\fR wrap, +Terminals which ignore a line-feed immediately after an \fBam\fP wrap, such as the Concept and vt100, -should indicate \fBxenl\fR. +should indicate \fBxenl\fP. .PP If .B el @@ -3118,112 +3636,85 @@ is required to get rid of standout \fBxhp\fP should be given. .PP Teleray terminals, where tabs turn all characters moved over to blanks, -should indicate \fBxt\fR (destructive tabs). -Note: the variable indicating this is now `dest_tabs_magic_smso'; in +should indicate \fBxt\fP (destructive tabs). +Note: the variable indicating this is now \*(``dest_tabs_magic_smso\*(''; in older versions, it was teleray_glitch. This glitch is also taken to mean that it is not possible to position -the cursor on top of a ``magic cookie'', +the cursor on top of a \*(``magic cookie\*('', that to erase standout mode it is instead necessary to use delete and insert line. The ncurses implementation ignores this glitch. .PP The Beehive Superbee, which is unable to correctly transmit the escape -or control C characters, has +or control/C characters, has .BR xsb , -indicating that the f1 key is used for escape and f2 for control C. +indicating that the f1 key is used for escape and f2 for control/C. (Only certain Superbees have this problem, depending on the ROM.) Note that in older terminfo versions, this capability was called -`beehive_glitch'; it is now `no_esc_ctl_c'. +\*(``beehive_glitch\*(''; it is now \*(``no_esc_ctl_c\*(''. .PP Other specific terminal problems may be corrected by adding more -capabilities of the form \fBx\fR\fIx\fR. -.PP -.SS Similar Terminals -.PP -If there are two very similar terminals, one (the variant) can be defined as -being just like the other (the base) with certain exceptions. -In the -definition of the variant, the string capability \fBuse\fR can be given with -the name of the base terminal. -The capabilities given before -.B use -override those in the base type named by -.BR use . -If there are multiple \fBuse\fR capabilities, they are merged in reverse order. -That is, the rightmost \fBuse\fR reference is processed first, then the one to -its left, and so forth. -Capabilities given explicitly in the entry override -those brought in by \fBuse\fR references. -.PP -A capability can be canceled by placing \fBxx@\fR to the left of the -use reference that imports it, where \fIxx\fP is the capability. -For example, the entry -.PP - 2621-nl, smkx@, rmkx@, use=2621, -.PP -defines a 2621-nl that does not have the \fBsmkx\fR or \fBrmkx\fR capabilities, -and hence does not turn on the function key labels when in visual mode. -This is useful for different modes for a terminal, or for different -user preferences. -.PP +capabilities of the form \fBx\fIx\fR. .SS Pitfalls of Long Entries -.PP Long terminfo entries are unlikely to be a problem; to date, no entry has even approached terminfo's 4096-byte string-table maximum. Unfortunately, the termcap -translations are much more strictly limited (to 1023 bytes), thus termcap translations -of long terminfo entries can cause problems. +translations are much more strictly limited (to 1023 bytes), +thus termcap translations of long terminfo entries can cause problems. .PP -The man pages for 4.3BSD and older versions of \fBtgetent()\fP instruct the user to +The man pages for 4.3BSD +and older versions of \fBtgetent\fP instruct the user to allocate a 1024-byte buffer for the termcap entry. The entry gets null-terminated by the termcap library, so that makes the maximum safe length for a termcap entry -1k-1 (1023) bytes. -Depending on what the application and the termcap library -being used does, and where in the termcap file the terminal type that \fBtgetent()\fP -is searching for is, several bad things can happen. -.PP -Some termcap libraries print a warning message or exit if they find an -entry that's longer than 1023 bytes; others do not; others truncate the -entries to 1023 bytes. +1k\-1 (1023) bytes. +Depending on what the application and the termcap library being used does, +and where in the termcap file the terminal type that \fBtgetent\fP +is searching for is, several bad things can happen: +.bP +some termcap libraries print a warning message, +.bP +some exit if they find an entry that's longer than 1023 bytes, +.bP +some neither exit nor warn, doing nothing useful, and +.bP +some simply truncate the entries to 1023 bytes. +.PP Some application programs allocate more than the recommended 1K for the termcap entry; others do not. .PP Each termcap entry has two important sizes associated with it: before -"tc" expansion, and after "tc" expansion. -"tc" is the capability that +\*(``tc\*('' expansion, and after \*(``tc\*('' expansion. +\*(``tc\*('' is the capability that tacks on another termcap entry to the end of the current one, to add on its capabilities. -If a termcap entry does not use the "tc" +If a termcap entry does not use the \*(``tc\*('' capability, then of course the two lengths are the same. .PP -The "before tc expansion" length is the most important one, because it +The \*(``before tc expansion\*('' length is the most important one, because it affects more than just users of that particular terminal. This is the length of the entry as it exists in /etc/termcap, minus the -backslash-newline pairs, which \fBtgetent()\fP strips out while reading it. +backslash-newline pairs, which \fBtgetent\fP strips out while reading it. Some termcap libraries strip off the final newline, too (GNU termcap does not). Now suppose: -.TP 5 -* +.bP a termcap entry before expansion is more than 1023 bytes long, -.TP 5 -* +.bP and the application has only allocated a 1k buffer, -.TP 5 -* +.bP and the termcap library (like the one in BSD/OS 1.1 and GNU) reads the whole entry into the buffer, no matter what its length, to see if it is the entry it wants, -.TP 5 -* -and \fBtgetent()\fP is searching for a terminal type that either is the +.bP +and \fBtgetent\fP is searching for a terminal type that either is the long entry, appears in the termcap file after the long entry, or -does not appear in the file at all (so that \fBtgetent()\fP has to search +does not appear in the file at all (so that \fBtgetent\fP has to search the whole termcap file). .PP -Then \fBtgetent()\fP will overwrite memory, perhaps its stack, and probably core dump -the program. +Then \fBtgetent\fP will overwrite memory, +perhaps its stack, +and probably core dump the program. Programs like telnet are particularly vulnerable; modern telnets pass along values like the terminal type automatically. The results are almost @@ -3233,105 +3724,119 @@ If a termcap library truncates long entries, like OSF/1 3.0, it is immune to dying here but will return incorrect data for the terminal. .PP -The "after tc expansion" length will have a similar effect to the +The \*(``after tc expansion\*('' length will have a similar effect to the above, but only for people who actually set TERM to that terminal -type, since \fBtgetent()\fP only does "tc" expansion once it is found the +type, since \fBtgetent\fP only does \*(``tc\*('' expansion once it is found the terminal type it was looking for, not while searching. .PP In summary, a termcap entry that is longer than 1023 bytes can cause, on various combinations of termcap libraries and applications, a core dump, warnings, or incorrect operation. If it is too long even before -"tc" expansion, it will have this effect even for users of some other +\*(``tc\*('' expansion, it will have this effect even for users of some other terminal types and users whose TERM variable does not have a termcap entry. .PP -When in -C (translate to termcap) mode, the \fBncurses\fR implementation of -\fBtic\fR(1) issues warning messages when the pre-tc length of a termcap +When in \-C (translate to termcap) mode, the \fBncurses\fP implementation of +\fBtic\fP(1) issues warning messages when the pre-tc length of a termcap translation is too long. -The -c (check) option also checks resolved (after tc +The \-c (check) option also checks resolved (after tc expansion) lengths. .SS Binary Compatibility It is not wise to count on portability of binary terminfo entries between commercial UNIX versions. The problem is that there are at least two versions -of terminfo (under HP-UX and AIX) which diverged from System V terminfo after +of terminfo (under HP\-UX and AIX) which diverged from System V terminfo after SVr1, and have added extension capabilities to the string table that (in the binary format) collide with System V and XSI Curses extensions. .SH EXTENSIONS -Some SVr4 \fBcurses\fR implementations, and all previous to SVr4, do not +Searching for terminal descriptions in +\fB$HOME/.terminfo\fP and TERMINFO_DIRS +is not supported by older implementations. +.PP +Some SVr4 \fBcurses\fP implementations, and all previous to SVr4, do not interpret the %A and %O operators in parameter strings. .PP -SVr4/XPG4 do not specify whether \fBmsgr\fR licenses movement while in +SVr4/XPG4 do not specify whether \fBmsgr\fP licenses movement while in an alternate-character-set mode (such modes may, among other things, map CR and NL to characters that do not trigger local motions). -The \fBncurses\fR implementation ignores \fBmsgr\fR in \fBALTCHARSET\fR +The \fBncurses\fP implementation ignores \fBmsgr\fP in \fBALTCHARSET\fP mode. This raises the possibility that an XPG4 implementation making the opposite interpretation may need terminfo -entries made for \fBncurses\fR to have \fBmsgr\fR turned off. +entries made for \fBncurses\fP to have \fBmsgr\fP turned off. .PP -The \fBncurses\fR library handles insert-character and insert-character modes +The \fBncurses\fP library handles insert-character and insert-character modes in a slightly non-standard way to get better update efficiency. See -the \fBInsert/Delete Character\fR subsection above. +the \fBInsert/Delete Character\fP subsection above. .PP -The parameter substitutions for \fBset_clock\fR and \fBdisplay_clock\fR are +The parameter substitutions for \fBset_clock\fP and \fBdisplay_clock\fP are not documented in SVr4 or the XSI Curses standard. They are deduced from the documentation for the AT&T 505 terminal. .PP -Be careful assigning the \fBkmous\fR capability. -The \fBncurses\fR wants to -interpret it as \fBKEY_MOUSE\fR, for use by terminals and emulators like xterm +Be careful assigning the \fBkmous\fP capability. +The \fBncurses\fP library wants to interpret it as \fBKEY_MOUSE\fP, +for use by terminals and emulators like xterm that can return mouse-tracking information in the keyboard-input stream. .PP +X/Open Curses does not mention italics. +Portable applications must assume that numeric capabilities are +signed 16-bit values. +This includes the \fIno_color_video\fP (\fBncv\fP) capability. +The 32768 mask value used for italics with \fBncv\fP can be confused with +an absent or cancelled \fBncv\fP. +If italics should work with colors, +then the \fBncv\fP value must be specified, even if it is zero. +.PP Different commercial ports of terminfo and curses support different subsets of the XSI Curses standard and (in some cases) different extension sets. Here is a summary, accurate as of October 1995: -.PP -\fBSVR4, Solaris, ncurses\fR -- +.bP +\fBSVR4, Solaris, ncurses\fP \-\- These support all SVr4 capabilities. -.PP -\fBSGI\fR -- +.bP +\fBSGI\fP \-\- Supports the SVr4 set, adds one undocumented extended string -capability (\fBset_pglen\fR). -.PP -\fBSVr1, Ultrix\fR -- +capability (\fBset_pglen\fP). +.bP +\fBSVr1, Ultrix\fP \-\- These support a restricted subset of terminfo capabilities. -The booleans -end with \fBxon_xoff\fR; the numerics with \fBwidth_status_line\fR; and the -strings with \fBprtr_non\fR. -.PP -\fBHP/UX\fR -- -Supports the SVr1 subset, plus the SVr[234] numerics \fBnum_labels\fR, -\fBlabel_height\fR, \fBlabel_width\fR, plus function keys 11 through 63, plus -\fBplab_norm\fR, \fBlabel_on\fR, and \fBlabel_off\fR, plus some incompatible +The booleans end with \fBxon_xoff\fP; +the numerics with \fBwidth_status_line\fP; +and the strings with \fBprtr_non\fP. +.bP +\fBHP/UX\fP \-\- +Supports the SVr1 subset, plus the SVr[234] numerics \fBnum_labels\fP, +\fBlabel_height\fP, \fBlabel_width\fP, plus function keys 11 through 63, plus +\fBplab_norm\fP, \fBlabel_on\fP, and \fBlabel_off\fP, plus some incompatible extensions in the string table. -.PP -\fBAIX\fR -- +.bP +\fBAIX\fP \-\- Supports the SVr1 subset, plus function keys 11 through 63, plus a number of incompatible string table extensions. -.PP -\fBOSF\fR -- +.bP +\fBOSF\fP \-\- Supports both the SVr4 set and the AIX extensions. .SH FILES .TP 25 \*d/?/* files containing terminal descriptions .SH SEE ALSO -\fBtic\fR(1), -\fBinfocmp\fR(1), -\fBcurses\fR(3), -\fBprintf\fR(3), -\fBterm\fR(\*n). +.na +.hy 0 +\fBinfocmp\fP(1), +\fB?\fP(1), +\fBtic\fP(1), +\fBcurses\fP(3), +\fBcurs_color\fP(3), +\fBcurs_variables\fP(3), +\fBprintf\fP(3), +\fBterm_variables\fP(3). +\fBterm\fP(\*n). +\fBuser_caps\fP(5). .SH AUTHORS Zeyd M. Ben-Halim, Eric S. Raymond, Thomas E. Dickey. -Based on pcurses by Pavel Curtis. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Based on \fIpcurses\fP by Pavel Curtis. diff --git a/lib/libcurses/tic.h b/lib/libcurses/tic.h index 97181a66132..b6af4722f11 100644 --- a/lib/libcurses/tic.h +++ b/lib/libcurses/tic.h @@ -1,7 +1,8 @@ -/* $OpenBSD: tic.h,v 1.14 2010/01/12 23:21:59 nicm Exp $ */ +/* $OpenBSD: tic.h,v 1.15 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * + * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2012,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -35,22 +36,23 @@ ****************************************************************************/ /* - * $Id: tic.h,v 1.14 2010/01/12 23:21:59 nicm Exp $ - * tic.h - Global variables and structures for the terminfo - * compiler. + * $Id: tic.h,v 1.15 2023/10/17 09:52:08 nicm Exp $ + * tic.h - Global variables and structures for the terminfo compiler. */ #ifndef __TIC_H #define __TIC_H - +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif +#include + #include /* for the _tracef() prototype, ERR/OK, bool defs */ /* -** The format of compiled terminfo files is as follows: +** The format of SVr2 compiled terminfo files is as follows: ** ** Header (12 bytes), containing information given below ** Names Section, containing the names of the terminal @@ -66,6 +68,11 @@ extern "C" { ** String Table, containing the actual characters of the string ** capabilities. ** +** In the SVr2 format, "short" means signed 16-bit numbers, which is sometimes +** inconvenient. The numbers are signed, to provide for absent and canceled +** values. ncurses6.1 introduced an extension to this compiled format, by +** making the Number Section a list of signed 32-bit integers. +** ** NOTE that all short integers in the file are stored using VAX/PDP-style ** byte-order, i.e., least-significant byte first. ** @@ -78,6 +85,7 @@ extern "C" { */ #define MAGIC 0432 /* first two bytes of a compiled entry */ +#define MAGIC2 01036 /* first two bytes of a compiled 32-bit entry */ #undef BYTE #define BYTE(p,n) (unsigned char)((p)[n]) @@ -86,14 +94,23 @@ extern "C" { #define IS_NEG2(p) ((BYTE(p,0) == 0376) && (BYTE(p,1) == 0377)) #define LOW_MSB(p) (BYTE(p,0) + 256*BYTE(p,1)) -#define IS_TIC_MAGIC(p) (LOW_MSB(p) == MAGIC) +#define IS_TIC_MAGIC(p) (LOW_MSB(p) == MAGIC || LOW_MSB(p) == MAGIC2) + +#define quick_prefix(s) (!strncmp((s), "b64:", (size_t)4) || !strncmp((s), "hex:", (size_t)4)) /* * The "maximum" here is misleading; XSI guarantees minimum values, which a * given implementation may exceed. */ #define MAX_NAME_SIZE 512 /* maximum legal name field size (XSI:127) */ -#define MAX_ENTRY_SIZE 4096 /* maximum legal entry size */ +#define MAX_ENTRY_SIZE1 4096 /* maximum legal entry size (SVr2) */ +#define MAX_ENTRY_SIZE2 32768 /* maximum legal entry size (ncurses6.1) */ + +#if NCURSES_EXT_COLORS && HAVE_INIT_EXTENDED_COLOR +#define MAX_ENTRY_SIZE MAX_ENTRY_SIZE2 +#else +#define MAX_ENTRY_SIZE MAX_ENTRY_SIZE1 +#endif /* * The maximum size of individual name or alias is guaranteed in XSI to be at @@ -120,7 +137,7 @@ extern "C" { #define DEBUG_LEVEL(n) ((n) << TRACE_SHIFT) #define set_trace_level(n) \ - _nc_tracing &= DEBUG_LEVEL(MAX_DEBUG_LEVEL), \ + _nc_tracing &= TRACE_MAXIMUM, \ _nc_tracing |= DEBUG_LEVEL(n) #ifdef TRACE @@ -129,11 +146,6 @@ extern "C" { #define DEBUG(n, a) /*nothing*/ #endif -extern NCURSES_EXPORT_VAR(unsigned) _nc_tracing; -extern NCURSES_EXPORT(void) _nc_tracef (char *, ...) GCC_PRINTFLIKE(1,2); -extern NCURSES_EXPORT(const char *) _nc_visbuf (const char *); -extern NCURSES_EXPORT(const char *) _nc_visbuf2 (int, const char *); - /* * These are the types of tokens returned by the scanner. The first * three are also used in the hash table of capability names. The scanner @@ -150,55 +162,51 @@ extern NCURSES_EXPORT(const char *) _nc_visbuf2 (int, const char *); #define NO_PUSHBACK -1 /* used in pushtype to indicate no pushback */ - /* - * The global structure in which the specific parts of a - * scanned token are returned. - * - */ +/* + * The global structure in which the specific parts of a + * scanned token are returned. + */ struct token { - char *tk_name; /* name of capability */ + char *tk_name; /* name of capability */ int tk_valnumber; /* value of capability (if a number) */ char *tk_valstring; /* value of capability (if a string) */ }; -extern NCURSES_EXPORT_VAR(struct token) _nc_curr_token; - - /* - * Offsets to string capabilities, with the corresponding functionkey - * codes. - */ +/* + * Offsets to string capabilities, with the corresponding functionkey codes. + */ struct tinfo_fkeys { unsigned offset; chtype code; }; -#if BROKEN_LINKER - -#define _nc_tinfo_fkeys _nc_tinfo_fkeysf() -extern NCURSES_EXPORT(const struct tinfo_fkeys *) _nc_tinfo_fkeysf (void); - -#else - -extern NCURSES_EXPORT_VAR(const struct tinfo_fkeys) _nc_tinfo_fkeys[]; - -#endif - - /* - * The file comp_captab.c contains an array of these structures, one - * per possible capability. These are indexed by a hash table array of - * pointers to the same structures for use by the parser. - */ +typedef short HashValue; +/* + * The file comp_captab.c contains an array of these structures, one per + * possible capability. These are indexed by a hash table array of pointers to + * the same structures for use by the parser. + */ struct name_table_entry { const char *nte_name; /* name to hash on */ int nte_type; /* BOOLEAN, NUMBER or STRING */ - short nte_index; /* index of associated variable in its array */ - short nte_link; /* index in table of next hash, or -1 */ + HashValue nte_index; /* index of associated variable in its array */ + HashValue nte_link; /* index in table of next hash, or -1 */ }; +/* + * Use this structure to hide differences between terminfo and termcap tables. + */ +typedef struct { + unsigned table_size; + const HashValue *table_data; + HashValue (*hash_of)(const char *); + int (*compare_names)(const char *, const char *); +} HashData; + struct alias { const char *from; @@ -206,12 +214,29 @@ struct alias const char *source; }; -extern NCURSES_EXPORT(const struct name_table_entry *) _nc_get_table (bool); -extern NCURSES_EXPORT(const short *) _nc_get_hash_table (bool); -extern NCURSES_EXPORT(const struct alias *) _nc_get_alias_table (bool); - #define NOTFOUND ((struct name_table_entry *) 0) +/* + * The file comp_userdefs.c contains an array of these structures, one per + * possible capability. These are indexed by a hash table array of pointers to + * the same structures for use by the parser. + */ +struct user_table_entry +{ + const char *ute_name; /* name to hash on */ + int ute_type; /* mask (BOOLEAN, NUMBER, STRING) */ + unsigned ute_argc; /* number of parameters */ + unsigned ute_args; /* bit-mask for string parameters */ + HashValue ute_index; /* index of associated variable in its array */ + HashValue ute_link; /* index in table of next hash, or -1 */ +}; + +/* + * The casts are required for correct sign-propagation with systems such as + * AIX, IRIX64, Solaris which default to unsigned characters. The C standard + * leaves this detail unspecified. + */ + /* out-of-band values for representing absent capabilities */ #define ABSENT_BOOLEAN ((signed char)-1) /* 255 */ #define ABSENT_NUMERIC (-1) @@ -236,6 +261,12 @@ extern NCURSES_EXPORT(const struct alias *) _nc_get_alias_table (bool); #define TERMINFO "/usr/share/terminfo" #endif +#ifdef NCURSES_TERM_ENTRY_H_incl + +/* + * These entrypoints are used only by the ncurses utilities such as tic. + */ +#ifdef NCURSES_INTERNALS /* access.c */ extern NCURSES_EXPORT(unsigned) _nc_pathlast (const char *); extern NCURSES_EXPORT(bool) _nc_is_abs_path (const char *); @@ -244,20 +275,25 @@ extern NCURSES_EXPORT(bool) _nc_is_file_path (const char *); extern NCURSES_EXPORT(char *) _nc_basename (char *); extern NCURSES_EXPORT(char *) _nc_rootname (char *); +/* comp_captab.c */ +extern NCURSES_EXPORT(const struct name_table_entry *) _nc_get_table (bool); +extern NCURSES_EXPORT(const HashData *) _nc_get_hash_info (bool); +extern NCURSES_EXPORT(const struct alias *) _nc_get_alias_table (bool); + /* comp_hash.c: name lookup */ -extern NCURSES_EXPORT(struct name_table_entry const *) _nc_find_entry - (const char *, const short *); extern NCURSES_EXPORT(struct name_table_entry const *) _nc_find_type_entry - (const char *, int, const struct name_table_entry *); + (const char *, int, bool); +extern NCURSES_EXPORT(struct user_table_entry const *) _nc_find_user_entry + (const char *); /* comp_scan.c: lexical analysis */ extern NCURSES_EXPORT(int) _nc_get_token (bool); extern NCURSES_EXPORT(void) _nc_panic_mode (char); extern NCURSES_EXPORT(void) _nc_push_token (int); -extern NCURSES_EXPORT(void) _nc_reset_input (FILE *, char *); extern NCURSES_EXPORT_VAR(int) _nc_curr_col; extern NCURSES_EXPORT_VAR(int) _nc_curr_line; extern NCURSES_EXPORT_VAR(int) _nc_syntax; +extern NCURSES_EXPORT_VAR(int) _nc_strict_bsd; extern NCURSES_EXPORT_VAR(long) _nc_comment_end; extern NCURSES_EXPORT_VAR(long) _nc_comment_start; extern NCURSES_EXPORT_VAR(long) _nc_curr_file_pos; @@ -267,19 +303,20 @@ extern NCURSES_EXPORT_VAR(long) _nc_start_line; /* comp_error.c: warning & abort messages */ extern NCURSES_EXPORT(const char *) _nc_get_source (void); -extern NCURSES_EXPORT(void) _nc_err_abort (const char *const,...) GCC_PRINTFLIKE(1,2) GCC_NORETURN; +extern GCC_NORETURN NCURSES_EXPORT(void) _nc_err_abort (const char *const,...) GCC_PRINTFLIKE(1,2); extern NCURSES_EXPORT(void) _nc_get_type (char *name); extern NCURSES_EXPORT(void) _nc_set_source (const char *const); extern NCURSES_EXPORT(void) _nc_set_type (const char *const); -extern NCURSES_EXPORT(void) _nc_syserr_abort (const char *const,...) GCC_PRINTFLIKE(1,2) GCC_NORETURN; +extern GCC_NORETURN NCURSES_EXPORT(void) _nc_syserr_abort (const char *const,...) GCC_PRINTFLIKE(1,2); extern NCURSES_EXPORT(void) _nc_warning (const char *const,...) GCC_PRINTFLIKE(1,2); extern NCURSES_EXPORT_VAR(bool) _nc_suppress_warnings; -/* comp_expand.c: expand string into readable form */ -extern NCURSES_EXPORT(char *) _nc_tic_expand (const char *, bool, int); +/* comp_scan.c */ +extern NCURSES_EXPORT_VAR(struct token) _nc_curr_token; -/* comp_scan.c: decode string from readable form */ -extern NCURSES_EXPORT(int) _nc_trans_string (char *, char *); +/* comp_userdefs.c */ +NCURSES_EXPORT(const struct user_table_entry *) _nc_get_userdefs_table (void); +NCURSES_EXPORT(const HashData *) _nc_get_hash_user (void); /* captoinfo.c: capability conversion */ extern NCURSES_EXPORT(char *) _nc_captoinfo (const char *, const char *, int const); @@ -288,37 +325,42 @@ extern NCURSES_EXPORT(char *) _nc_infotocap (const char *, const char *, int con /* home_terminfo.c */ extern NCURSES_EXPORT(char *) _nc_home_terminfo (void); +/* init_keytry.c */ +#if BROKEN_LINKER +#define _nc_tinfo_fkeys _nc_tinfo_fkeysf() +extern NCURSES_EXPORT(const struct tinfo_fkeys *) _nc_tinfo_fkeysf (void); +#else +extern NCURSES_EXPORT_VAR(const struct tinfo_fkeys) _nc_tinfo_fkeys[]; +#endif + /* lib_tparm.c */ #define NUM_PARM 9 extern NCURSES_EXPORT_VAR(int) _nc_tparm_err; -extern NCURSES_EXPORT(int) _nc_tparm_analyze(const char *, char **, int *); +extern NCURSES_EXPORT(int) _nc_tparm_analyze(TERMINAL *, const char *, char **, int *); +extern NCURSES_EXPORT(void) _nc_reset_tparm(TERMINAL *); + +/* lib_trace.c */ +extern NCURSES_EXPORT_VAR(unsigned) _nc_tracing; +extern NCURSES_EXPORT(const char *) _nc_visbuf (const char *); +extern NCURSES_EXPORT(const char *) _nc_visbuf2 (int, const char *); /* lib_tputs.c */ -extern NCURSES_EXPORT_VAR(int) _nc_nulls_sent; /* Add one for every null sent */ +extern NCURSES_EXPORT_VAR(int) _nc_nulls_sent; /* Add one for every null sent */ + +/* comp_expand.c: expand string into readable form */ +extern NCURSES_EXPORT(char *) _nc_tic_expand (const char *, bool, int); + +/* comp_hash.c: name lookup */ +extern NCURSES_EXPORT(struct name_table_entry const *) _nc_find_entry + (const char *, const HashValue *); +extern NCURSES_EXPORT(const HashValue *) _nc_get_hash_table (bool); /* comp_main.c: compiler main */ extern const char * _nc_progname; /* db_iterator.c */ -typedef enum { - dbdTIC = 0, -#if USE_DATABASE - dbdEnvOnce, - dbdHome, - dbdEnvList, - dbdCfgList, - dbdCfgOnce, -#endif -#if USE_TERMCAP - dbdEnvOnce2, - dbdEnvList2, - dbdCfgList2, -#endif - dbdLAST -} DBDIRS; - extern NCURSES_EXPORT(const char *) _nc_next_db(DBDIRS *, int *); extern NCURSES_EXPORT(const char *) _nc_tic_dir (const char *); extern NCURSES_EXPORT(void) _nc_first_db(DBDIRS *, int *); @@ -327,8 +369,13 @@ extern NCURSES_EXPORT(void) _nc_last_db(void); /* write_entry.c */ extern NCURSES_EXPORT(int) _nc_tic_written (void); +#endif /* NCURSES_INTERNALS */ + +#endif /* NCURSES_TERM_ENTRY_H_incl */ + #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* __TIC_H */ diff --git a/lib/libcurses/tinfo/MKcaptab.awk b/lib/libcurses/tinfo/MKcaptab.awk index b105931c55d..f4b9c270661 100644 --- a/lib/libcurses/tinfo/MKcaptab.awk +++ b/lib/libcurses/tinfo/MKcaptab.awk @@ -1,6 +1,7 @@ -# $OpenBSD: MKcaptab.awk,v 1.4 2010/01/12 23:22:06 nicm Exp $ +# $OpenBSD: MKcaptab.awk,v 1.5 2023/10/17 09:52:09 nicm Exp $ ############################################################################## -# Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. # +# Copyright 2020 Thomas E. Dickey # +# Copyright 1998-2006,2007 Free Software Foundation, Inc. # # # # Permission is hereby granted, free of charge, to any person obtaining a # # copy of this software and associated documentation files (the "Software"), # @@ -26,7 +27,7 @@ # use or other dealings in this Software without prior written # # authorization. # ############################################################################## -# $Id: MKcaptab.awk,v 1.4 2010/01/12 23:22:06 nicm Exp $ +# $Id: MKcaptab.awk,v 1.5 2023/10/17 09:52:09 nicm Exp $ function add_string(text) { if (text != "IGNORE") { offsets[num_strings] = offset; diff --git a/lib/libcurses/tinfo/MKcaptab.sh b/lib/libcurses/tinfo/MKcaptab.sh index d7305f2f88e..1a789e3c64c 100644 --- a/lib/libcurses/tinfo/MKcaptab.sh +++ b/lib/libcurses/tinfo/MKcaptab.sh @@ -1,7 +1,8 @@ +# $OpenBSD: MKcaptab.sh,v 1.2 2023/10/17 09:52:09 nicm Exp $ #!/bin/sh -# $OpenBSD: MKcaptab.sh,v 1.1 2010/01/12 23:22:06 nicm Exp $ ############################################################################## -# Copyright (c) 2007 Free Software Foundation, Inc. # +# Copyright 2019-2020,2023 Thomas E. Dickey # +# Copyright 2007-2010,2011 Free Software Foundation, Inc. # # # # Permission is hereby granted, free of charge, to any person obtaining a # # copy of this software and associated documentation files (the "Software"), # @@ -27,11 +28,35 @@ # use or other dealings in this Software without prior written # # authorization. # ############################################################################## -# $Id: MKcaptab.sh,v 1.1 2010/01/12 23:22:06 nicm Exp $ -AWK=${1-awk} -OPT1=${2-0} -OPT2=${3-tinfo/MKcaptab.awk} -DATA=${4-../include/Caps} +# $Id: MKcaptab.sh,v 1.2 2023/10/17 09:52:09 nicm Exp $ + +if test $# != 0 +then + AWK="$1"; shift 1 +else + AWK=awk +fi + +if test $# != 0 +then + OPT1="$1"; shift 1 +else + OPT1="-0" +fi + +if test $# != 0 +then + OPT2="$1"; shift 1 +else + OPT2="tinfo/MKcaptab.awk" +fi + +cat < #include +/* *INDENT-OFF* */ EOF -./make_hash 1 info $OPT1 <$DATA -./make_hash 3 cap $OPT1 <$DATA +cat "$@" |./make_hash 1 info $OPT1 +cat "$@" |./make_hash 3 cap $OPT1 -$AWK -f $OPT2 bigstrings=$OPT1 tablename=capalias <$DATA +cat "$@" |$AWK -f $OPT2 bigstrings=$OPT1 tablename=capalias -$AWK -f $OPT2 bigstrings=$OPT1 tablename=infoalias <$DATA +cat "$@" |$AWK -f $OPT2 bigstrings=$OPT1 tablename=infoalias cat <= TCAP_LEN) + break; + } + temp[limit] = '\0'; + return info_hash(temp); } -NCURSES_EXPORT(const struct alias *) _nc_get_alias_table (bool termcap) +static int +compare_tcap_names(const char *a, const char *b) +{ + return !strncmp(a, b, (size_t) TCAP_LEN); +} + +static int +compare_info_names(const char *a, const char *b) +{ + return !strcmp(a, b); +} + +static const HashData hash_data[2] = +{ + {HASHTABSIZE, _nc_info_hash_table, info_hash, compare_info_names}, + {HASHTABSIZE, _nc_cap_hash_table, tcap_hash, compare_tcap_names} +}; + +NCURSES_EXPORT(const HashData *) +_nc_get_hash_info(bool termcap) { - return termcap ? build_alias(cap) : build_alias(info) ; + return &hash_data[(termcap != FALSE)]; } #if NO_LEAKS -NCURSES_EXPORT(void) _nc_comp_captab_leaks(void) +NCURSES_EXPORT(void) +_nc_comp_captab_leaks(void) { #if $OPT1 - FreeIfNeeded(_nc_cap_table); - FreeIfNeeded(_nc_info_table); - FreeIfNeeded(_nc_capalias_table); - FreeIfNeeded(_nc_infoalias_table); + FreeIfNeeded(_nc_cap_table); + FreeIfNeeded(_nc_info_table); + FreeIfNeeded(_nc_capalias_table); + FreeIfNeeded(_nc_infoalias_table); #endif } #endif /* NO_LEAKS */ diff --git a/lib/libcurses/tinfo/MKcodes.awk b/lib/libcurses/tinfo/MKcodes.awk index 669f673c91b..454a5c83419 100644 --- a/lib/libcurses/tinfo/MKcodes.awk +++ b/lib/libcurses/tinfo/MKcodes.awk @@ -1,6 +1,7 @@ -# $OpenBSD: MKcodes.awk,v 1.1 2010/01/12 23:22:06 nicm Exp $ +# $OpenBSD: MKcodes.awk,v 1.2 2023/10/17 09:52:09 nicm Exp $ ############################################################################## -# Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. # +# Copyright 2019,2020 Thomas E. Dickey # +# Copyright 2007-2009,2010 Free Software Foundation, Inc. # # # # Permission is hereby granted, free of charge, to any person obtaining a # # copy of this software and associated documentation files (the "Software"), # @@ -26,7 +27,7 @@ # use or other dealings in this Software without prior written # # authorization. # ############################################################################## -# $Id: MKcodes.awk,v 1.1 2010/01/12 23:22:06 nicm Exp $ +# $Id: MKcodes.awk,v 1.2 2023/10/17 09:52:09 nicm Exp $ function large_item(value) { result = sprintf("%d,", offset); offset = offset + length(value) + 1; @@ -80,7 +81,9 @@ BEGIN { } $1 ~ /^#/ {next;} +$1 ~ /^(cap|info)alias/ {next;} +$1 == "userdef" {next;} $1 == "SKIPWARN" {next;} $3 == "bool" { @@ -102,8 +105,6 @@ END { print "" print "#if BROKEN_LINKER || USE_REENTRANT" print "" - print "#include " - print "" if (bigstrings) { printf "static const char _nc_code_blob[] = \n" printf "%s;\n", bigstr; @@ -118,28 +119,39 @@ END { print " if ((*value = typeCalloc(NCURSES_CONST char *, size + 1)) != 0) {" print " unsigned n;" print " for (n = 0; n < size; ++n) {" - print " (*value)[n] = _nc_code_blob + offsets[n];" + print " (*value)[n] = (NCURSES_CONST char *) _nc_code_blob + offsets[n];" print " }" print " }" print " }" print " return *value;" print "}" print "" - print "#define FIX(it) NCURSES_IMPEXP IT * NCURSES_API _nc_##it(void) { return alloc_array(&ptr_##it, _nc_offset_##it, SIZEOF(_nc_offset_##it)); }" + print "#define FIX(it) NCURSES_IMPEXP IT * NCURSES_API NCURSES_PUBLIC_VAR(it)(void) { return alloc_array(&ptr_##it, _nc_offset_##it, SIZEOF(_nc_offset_##it)); }" } else { print "#define DCL(it) static IT data##it[]" print "" print_strings("boolcodes", small_boolcodes); print_strings("numcodes", small_numcodes); print_strings("strcodes", small_strcodes); - print "#define FIX(it) NCURSES_IMPEXP IT * NCURSES_API _nc_##it(void) { return data##it; }" + print "#define FIX(it) NCURSES_IMPEXP IT * NCURSES_API NCURSES_PUBLIC_VAR(it)(void) { return data##it; }" } print "" + print "/* remove public definition which conflicts with FIX() */" + print "#undef boolcodes" + print "#undef numcodes" + print "#undef strcodes" + print "" + print "/* add local definition */" print "FIX(boolcodes)" print "FIX(numcodes)" print "FIX(strcodes)" print "" + print "/* restore the public definition */" + print "" print "#define FREE_FIX(it) if (ptr_##it) { FreeAndNull(ptr_##it); }" + print "#define boolcodes NCURSES_PUBLIC_VAR(boolcodes())" + print "#define numcodes NCURSES_PUBLIC_VAR(numcodes())" + print "#define strcodes NCURSES_PUBLIC_VAR(strcodes())" print "" print "#if NO_LEAKS" print "NCURSES_EXPORT(void)" diff --git a/lib/libcurses/tinfo/MKfallback.sh b/lib/libcurses/tinfo/MKfallback.sh index c33d8489e9f..190ef58a62a 100644 --- a/lib/libcurses/tinfo/MKfallback.sh +++ b/lib/libcurses/tinfo/MKfallback.sh @@ -1,7 +1,8 @@ +# $OpenBSD: MKfallback.sh,v 1.5 2023/10/17 09:52:09 nicm Exp $ #!/bin/sh -# $OpenBSD: MKfallback.sh,v 1.4 2010/01/12 23:22:06 nicm Exp $ ############################################################################## -# Copyright (c) 1998-2001,2006 Free Software Foundation, Inc. # +# Copyright 2020,2023 Thomas E. Dickey # +# Copyright 1998-2019,2020 Free Software Foundation, Inc. # # # # Permission is hereby granted, free of charge, to any person obtaining a # # copy of this software and associated documentation files (the "Software"), # @@ -27,7 +28,7 @@ # use or other dealings in this Software without prior written # # authorization. # ############################################################################## -# $Id: MKfallback.sh,v 1.4 2010/01/12 23:22:06 nicm Exp $ +# $Id: MKfallback.sh,v 1.5 2023/10/17 09:52:09 nicm Exp $ # # MKfallback.sh -- create fallback table for entry reads # @@ -37,13 +38,51 @@ # specified list of types generated in. # +terminfo_dir=$1 +test $# != 0 && shift + +terminfo_src=$1 +test $# != 0 && shift + +tic_path=$1 +test -z "$tic_path" && tic_path=tic +test $# != 0 && shift + +infocmp_path=$1 +test -z "$infocmp_path" && infocmp_path=infocmp +test $# != 0 && shift + +case "$tic_path" in #(vi +/*) + tic_head=`echo "$tic_path" | sed -e 's,/[^/]*$,,'` + PATH=$tic_head:$PATH + export PATH + ;; +esac + +if test $# != 0 ; then + tmp_info=tmp_info + echo creating temporary terminfo directory... >&2 + + TERMINFO=`pwd`/$tmp_info + export TERMINFO + + TERMINFO_DIRS=$TERMINFO:$terminfo_dir + export TERMINFO_DIRS + + "$tic_path" -x "$terminfo_src" >&2 +else + tmp_info= +fi + cat < -#include EOF @@ -54,21 +93,21 @@ then /* fallback entries for: $* */ EOF - for x in $* + for x in "$@" do echo "/* $x */" - infocmp -E $x + "$infocmp_path" -E "$x" | sed -e 's/\/NCURSES_INT2/g' done cat <term_names, name, "|")) + tp < fallbacks + sizeof(fallbacks)/sizeof(TERMTYPE2); + tp++) { + if (_nc_name_match(tp->term_names, name, "|")) { return(tp); + } + } EOF else echo " /* the fallback list is empty */"; fi cat <&2 + rm -rf $tmp_info +fi diff --git a/lib/libcurses/tinfo/MKkeys_list.sh b/lib/libcurses/tinfo/MKkeys_list.sh index e28d899fedf..5c3b8cea830 100644 --- a/lib/libcurses/tinfo/MKkeys_list.sh +++ b/lib/libcurses/tinfo/MKkeys_list.sh @@ -1,8 +1,9 @@ +# $OpenBSD: MKkeys_list.sh,v 1.2 2023/10/17 09:52:09 nicm Exp $ #! /bin/sh -# $OpenBSD: MKkeys_list.sh,v 1.1 2010/01/12 23:22:06 nicm Exp $ -# $Id: MKkeys_list.sh,v 1.1 2010/01/12 23:22:06 nicm Exp $ +# $Id: MKkeys_list.sh,v 1.2 2023/10/17 09:52:09 nicm Exp $ ############################################################################## -# Copyright (c) 2001,2003 Free Software Foundation, Inc. # +# Copyright 2019-2020,2022 Thomas E. Dickey # +# Copyright 2001-2003,2017 Free Software Foundation, Inc. # # # # Permission is hereby granted, free of charge, to any person obtaining a # # copy of this software and associated documentation files (the "Software"), # @@ -36,11 +37,17 @@ # Extract function-key names from the Caps file # : ${AWK-awk} -DATA=${1-../../include/Caps} +if test $# != 0 +then + DATA="$*" +else + DATA=../../include/Caps +fi data=data$$ -trap 'rm -f $data' 0 1 2 5 15 -sed -e 's/[ ][ ]*/ /g' < $DATA >$data +trap 'rm -f $data; exit 1' 1 2 3 15 +trap 'rm -f $data' 0 +cat $DATA | sed -e 's/[ ][ ]*/ /g' >$data cat <" - print "" if (bigstrings) { printf "static const char _nc_name_blob[] = \n" printf "%s;\n", bigstr; @@ -134,7 +135,7 @@ END { print " return *value;" print "}" print "" - print "#define FIX(it) NCURSES_IMPEXP IT * NCURSES_API _nc_##it(void) { return alloc_array(&ptr_##it, _nc_offset_##it, SIZEOF(_nc_offset_##it)); }" + print "#define FIX(it) NCURSES_IMPEXP IT * NCURSES_API NCURSES_PUBLIC_VAR(it)(void) { return alloc_array(&ptr_##it, _nc_offset_##it, SIZEOF(_nc_offset_##it)); }" } else { print "#define DCL(it) static IT data##it[]" print "" @@ -144,9 +145,18 @@ END { print_strings("numfnames", small_numfnames); print_strings("strnames", small_strnames); print_strings("strfnames", small_strfnames); - print "#define FIX(it) NCURSES_IMPEXP IT * NCURSES_API _nc_##it(void) { return data##it; }" + print "#define FIX(it) NCURSES_IMPEXP IT * NCURSES_API NCURSES_PUBLIC_VAR(it)(void) { return data##it; }" } print "" + print "/* remove public definition which conflicts with FIX() */" + print "#undef boolnames" + print "#undef boolfnames" + print "#undef numnames" + print "#undef numfnames" + print "#undef strnames" + print "#undef strfnames" + print "" + print "/* add local definition */" print "FIX(boolnames)" print "FIX(boolfnames)" print "FIX(numnames)" @@ -154,6 +164,13 @@ END { print "FIX(strnames)" print "FIX(strfnames)" print "" + print "/* restore the public definition */" + print "#define boolnames NCURSES_PUBLIC_VAR(boolnames())" + print "#define boolfnames NCURSES_PUBLIC_VAR(boolfnames())" + print "#define numnames NCURSES_PUBLIC_VAR(numnames())" + print "#define numfnames NCURSES_PUBLIC_VAR(numfnames())" + print "#define strnames NCURSES_PUBLIC_VAR(strnames())" + print "#define strfnames NCURSES_PUBLIC_VAR(strfnames())" print "" print "#define FREE_FIX(it) if (ptr_##it) { FreeAndNull(ptr_##it); }" print "" diff --git a/lib/libcurses/tinfo/MKuserdefs.sh b/lib/libcurses/tinfo/MKuserdefs.sh new file mode 100644 index 00000000000..9348eb7e4e8 --- /dev/null +++ b/lib/libcurses/tinfo/MKuserdefs.sh @@ -0,0 +1,146 @@ +#!/bin/sh +############################################################################## +# Copyright 2019,2020 Thomas E. Dickey # +# # +# Permission is hereby granted, free of charge, to any person obtaining a # +# copy of this software and associated documentation files (the "Software"), # +# to deal in the Software without restriction, including without limitation # +# the rights to use, copy, modify, merge, publish, distribute, distribute # +# with modifications, sublicense, and/or sell copies of the Software, and to # +# permit persons to whom the Software is furnished to do so, subject to the # +# following conditions: # +# # +# The above copyright notice and this permission notice shall be included in # +# all copies or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # +# THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # +# DEALINGS IN THE SOFTWARE. # +# # +# Except as contained in this notice, the name(s) of the above copyright # +# holders shall not be used in advertising or otherwise to promote the sale, # +# use or other dealings in this Software without prior written # +# authorization. # +############################################################################## +# $Id: MKuserdefs.sh,v 1.1 2023/10/17 09:52:09 nicm Exp $ +AWK=${1-awk}; shift 1 +OPT1=${1-0}; shift 1 + +cat < +#include +#include + +#if NCURSES_XNAMES +EOF + +cat "$@" | ./make_hash 1 user $OPT1 + +cat < #include + +#ifndef USE_ROOT_ACCESS +#if HAVE_SETFSUID +#include +#else #include +#endif +#endif + +#if HAVE_GETAUXVAL && HAVE_SYS_AUXV_H && defined(__GLIBC__) && (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 19) +#include +#define USE_GETAUXVAL 1 +#else +#define USE_GETAUXVAL 0 +#endif #include -#include -MODULE_ID("$Id: access.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: access.c,v 1.6 2023/10/17 09:52:09 nicm Exp $") #define LOWERCASE(c) ((isalpha(UChar(c)) && isupper(UChar(c))) ? tolower(UChar(c)) : (c)) +#ifdef _NC_MSC +# define ACCESS(FN, MODE) access((FN), (MODE)&(R_OK|W_OK)) +#else +# define ACCESS access +#endif + NCURSES_EXPORT(char *) _nc_rootname(char *path) { @@ -52,11 +72,11 @@ _nc_rootname(char *path) static char *temp; char *s; - temp = strdup(result); - result = temp; + if ((temp = strdup(result)) != 0) + result = temp; #if !MIXEDCASE_FILENAMES for (s = result; *s != '\0'; ++s) { - *s = LOWERCASE(*s); + *s = (char) LOWERCASE(*s); } #endif #if defined(PROG_EXT) @@ -99,7 +119,7 @@ _nc_pathlast(const char *path) test = path; else test++; - return (test - path); + return (unsigned) (test - path); } NCURSES_EXPORT(char *) @@ -111,24 +131,33 @@ _nc_basename(char *path) NCURSES_EXPORT(int) _nc_access(const char *path, int mode) { - if (access(path, mode) < 0) { + int result; + + if (path == 0) { + result = -1; + } else if (ACCESS(path, mode) < 0) { if ((mode & W_OK) != 0 && errno == ENOENT && strlen(path) < PATH_MAX) { - char *leaf, head[PATH_MAX]; + char head[PATH_MAX]; + char *leaf; - strlcpy(head, path, sizeof(head)); - if ((leaf = _nc_basename(head)) == 0) - leaf = head; - *leaf = '\0'; + _nc_STRCPY(head, path, sizeof(head)); + leaf = _nc_basename(head); + if (leaf == 0) + leaf = head; + *leaf = '\0'; if (head == leaf) - (void) strlcpy(head, ".", sizeof(head)); + _nc_STRCPY(head, ".", sizeof(head)); - return access(head, R_OK | W_OK | X_OK); + result = ACCESS(head, R_OK | W_OK | X_OK); + } else { + result = -1; } - return -1; + } else { + result = 0; } - return 0; + return result; } NCURSES_EXPORT(bool) @@ -138,7 +167,7 @@ _nc_is_dir_path(const char *path) struct stat sb; if (stat(path, &sb) == 0 - && (sb.st_mode & S_IFMT) == S_IFDIR) { + && S_ISDIR(sb.st_mode)) { result = TRUE; } return result; @@ -151,28 +180,107 @@ _nc_is_file_path(const char *path) struct stat sb; if (stat(path, &sb) == 0 - && (sb.st_mode & S_IFMT) == S_IFREG) { + && S_ISREG(sb.st_mode)) { result = TRUE; } return result; } -#ifndef USE_ROOT_ENVIRON +#if HAVE_GETEUID && HAVE_GETEGID +#define is_posix_elevated() \ + (getuid() != geteuid() \ + || getgid() != getegid()) +#else +#define is_posix_elevated() FALSE +#endif + +#if HAVE_ISSETUGID +#define is_elevated() issetugid() +#elif USE_GETAUXVAL && defined(AT_SECURE) +#define is_elevated() \ + (getauxval(AT_SECURE) \ + ? TRUE \ + : (errno != ENOENT \ + ? FALSE \ + : is_posix_elevated())) +#else +#define is_elevated() is_posix_elevated() +#endif + +#if HAVE_SETFSUID +#define lower_privileges() \ + int save_err = errno; \ + setfsuid(getuid()); \ + setfsgid(getgid()); \ + errno = save_err +#define resume_elevation() \ + save_err = errno; \ + setfsuid(geteuid()); \ + setfsgid(getegid()); \ + errno = save_err +#else +#define lower_privileges() /* nothing */ +#define resume_elevation() /* nothing */ +#endif + /* - * Returns true if we allow application to use environment variables that are - * used for searching lists of directories, etc. + * Returns true if not running as root or setuid. We use this check to allow + * applications to use environment variables that are used for searching lists + * of directories, etc. */ NCURSES_EXPORT(int) _nc_env_access(void) { -#if HAVE_ISSETUGID - if (issetugid()) - return FALSE; -#elif HAVE_GETEUID && HAVE_GETEGID - if (getuid() != geteuid() - || getgid() != getegid()) - return FALSE; -#endif - return getuid() != 0 && geteuid() != 0; /* ...finally, disallow root */ + int result = TRUE; + +#if HAVE_GETUID && HAVE_GETEUID +#if !defined(USE_SETUID_ENVIRON) + if (is_elevated()) { + result = FALSE; + } +#endif +#if !defined(USE_ROOT_ENVIRON) + if ((getuid() == ROOT_UID) || (geteuid() == ROOT_UID)) { + result = FALSE; + } +#endif +#endif /* HAVE_GETUID && HAVE_GETEUID */ + return result; +} + +#ifndef USE_ROOT_ACCESS +/* + * Limit privileges if possible; otherwise disallow access for updating files. + */ +NCURSES_EXPORT(FILE *) +_nc_safe_fopen(const char *path, const char *mode) +{ + FILE *result = NULL; +#if HAVE_SETFSUID + lower_privileges(); + result = fopen(path, mode); + resume_elevation(); +#else + if (!is_elevated() || *mode == 'r') { + result = fopen(path, mode); + } +#endif + return result; } + +NCURSES_EXPORT(int) +_nc_safe_open3(const char *path, int flags, mode_t mode) +{ + int result = -1; +#if HAVE_SETFSUID + lower_privileges(); + result = open(path, flags, mode); + resume_elevation(); +#else + if (!is_elevated() || (flags & O_RDONLY)) { + result = open(path, flags, mode); + } #endif + return result; +} +#endif /* USE_ROOT_ACCESS */ diff --git a/lib/libcurses/tinfo/add_tries.c b/lib/libcurses/tinfo/add_tries.c index 247087fd815..f2adb76dd63 100644 --- a/lib/libcurses/tinfo/add_tries.c +++ b/lib/libcurses/tinfo/add_tries.c @@ -1,7 +1,8 @@ -/* $OpenBSD: add_tries.c,v 1.4 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: add_tries.c,v 1.5 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * + * Copyright 2019-2020,2023 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -40,8 +41,9 @@ */ #include +#include -MODULE_ID("$Id: add_tries.c,v 1.4 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: add_tries.c,v 1.5 2023/10/17 09:52:09 nicm Exp $") #define SET_TRY(dst,src) if ((dst->ch = *src++) == 128) dst->ch = '\0' #define CMP_TRY(a,b) ((a)? (a == b) : (b == 128)) @@ -52,8 +54,9 @@ _nc_add_to_try(TRIES ** tree, const char *str, unsigned code) TRIES *ptr, *savedptr; unsigned const char *txt = (unsigned const char *) str; - T((T_CALLED("_nc_add_to_try(%p, %s, %u)"), *tree, _nc_visbuf(str), code)); - if (txt == 0 || *txt == '\0' || code == 0) + T((T_CALLED("_nc_add_to_try(%p, %s, %u)"), + (void *) *tree, _nc_visbuf(str), code)); + if (!VALID_STRING(str) || *txt == '\0' || code == 0) returnCode(ERR); if ((*tree) != 0) { @@ -68,7 +71,7 @@ _nc_add_to_try(TRIES ** tree, const char *str, unsigned code) if (CMP_TRY(ptr->ch, cmp)) { if (*(++txt) == '\0') { - ptr->value = code; + ptr->value = (unsigned short) code; returnCode(OK); } if (ptr->child != 0) @@ -110,6 +113,7 @@ _nc_add_to_try(TRIES ** tree, const char *str, unsigned code) savedptr = ptr->child; free(ptr); } + *tree = NULL; returnCode(ERR); } @@ -117,6 +121,6 @@ _nc_add_to_try(TRIES ** tree, const char *str, unsigned code) ptr->value = 0; } - ptr->value = code; + ptr->value = (unsigned short) code; returnCode(OK); } diff --git a/lib/libcurses/tinfo/alloc_entry.c b/lib/libcurses/tinfo/alloc_entry.c index a55be808818..713cbb59361 100644 --- a/lib/libcurses/tinfo/alloc_entry.c +++ b/lib/libcurses/tinfo/alloc_entry.c @@ -1,7 +1,8 @@ -/* $OpenBSD: alloc_entry.c,v 1.7 2018/06/28 15:34:10 deraadt Exp $ */ +/* $OpenBSD: alloc_entry.c,v 1.8 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. * + * Copyright 2018-2021,2022 Thomas E. Dickey * + * Copyright 1998-2013,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -48,97 +49,90 @@ #include #include -#include -MODULE_ID("$Id: alloc_entry.c,v 1.7 2018/06/28 15:34:10 deraadt Exp $") +MODULE_ID("$Id: alloc_entry.c,v 1.8 2023/10/17 09:52:09 nicm Exp $") #define ABSENT_OFFSET -1 #define CANCELLED_OFFSET -2 -#define MAX_STRTAB 4096 /* documented maximum entry size */ - static char *stringbuf; /* buffer for string capabilities */ static size_t next_free; /* next free character in stringbuf */ NCURSES_EXPORT(void) -_nc_init_entry(TERMTYPE *const tp) +_nc_init_entry(ENTRY * const tp) /* initialize a terminal type data block */ { - unsigned i; + DEBUG(2, (T_CALLED("_nc_init_entry(tp=%p)"), (void *) tp)); + if (tp == NULL) { #if NO_LEAKS - if (tp == 0 && stringbuf != 0) { - FreeAndNull(stringbuf); + if (stringbuf != NULL) { + FreeAndNull(stringbuf); + } return; - } -#endif - - if (stringbuf == 0) - stringbuf = (char *) malloc(MAX_STRTAB); - -#if NCURSES_XNAMES - tp->num_Booleans = BOOLCOUNT; - tp->num_Numbers = NUMCOUNT; - tp->num_Strings = STRCOUNT; - tp->ext_Booleans = 0; - tp->ext_Numbers = 0; - tp->ext_Strings = 0; +#else + _nc_err_abort("_nc_init_entry called without initialization"); #endif - if (tp->Booleans == 0) - tp->Booleans = typeMalloc(NCURSES_SBOOL, BOOLCOUNT); - if (tp->Numbers == 0) - tp->Numbers = typeMalloc(short, NUMCOUNT); - if (tp->Strings == 0) - tp->Strings = typeMalloc(char *, STRCOUNT); + } - for_each_boolean(i, tp) - tp->Booleans[i] = FALSE; + if (stringbuf == NULL) + TYPE_CALLOC(char, (size_t) MAX_ENTRY_SIZE, stringbuf); - for_each_number(i, tp) - tp->Numbers[i] = ABSENT_NUMERIC; + next_free = 0; - for_each_string(i, tp) - tp->Strings[i] = ABSENT_STRING; + _nc_init_termtype(&(tp->tterm)); - next_free = 0; + DEBUG(2, (T_RETURN(""))); } NCURSES_EXPORT(ENTRY *) _nc_copy_entry(ENTRY * oldp) { - ENTRY *newp = typeCalloc(ENTRY, 1); + ENTRY *newp; - if (newp != 0) { + DEBUG(2, (T_CALLED("_nc_copy_entry(oldp=%p)"), (void *) oldp)); + + newp = typeCalloc(ENTRY, 1); + if (newp != NULL) { *newp = *oldp; - _nc_copy_termtype(&(newp->tterm), &(oldp->tterm)); + _nc_copy_termtype2(&(newp->tterm), &(oldp->tterm)); } - return newp; + + DEBUG(2, (T_RETURN("%p"), (void *) newp)); + return (newp); } /* save a copy of string in the string buffer */ NCURSES_EXPORT(char *) -_nc_save_str(const char *const string) +_nc_save_str(const char *string) { char *result = 0; size_t old_next_free = next_free; - size_t len = strlen(string) + 1; - - if (len == 1 && next_free != 0) { - /* - * Cheat a little by making an empty string point to the end of the - * previous string. - */ - if (next_free < MAX_STRTAB) { - result = (stringbuf + next_free - 1); + + if (stringbuf != NULL) { + size_t len; + + if (!VALID_STRING(string)) + string = ""; + len = strlen(string) + 1; + + if (len == 1 && next_free != 0) { + /* + * Cheat a little by making an empty string point to the end of the + * previous string. + */ + if (next_free < MAX_ENTRY_SIZE) { + result = (stringbuf + next_free - 1); + } + } else if (next_free + len < MAX_ENTRY_SIZE) { + _nc_STRCPY(&stringbuf[next_free], string, MAX_ENTRY_SIZE); + DEBUG(7, ("Saved string %s", _nc_visbuf(string))); + DEBUG(7, ("at location %d", (int) next_free)); + next_free += len; + result = (stringbuf + old_next_free); + } else { + _nc_warning("Too much data, some is lost: %s", string); } - } else if (next_free + len < MAX_STRTAB) { - strlcpy(&stringbuf[next_free], string, MAX_STRTAB - next_free); - DEBUG(7, ("Saved string %s", _nc_visbuf(string))); - DEBUG(7, ("at location %d", (int) next_free)); - next_free += len; - result = (stringbuf + old_next_free); - } else { - _nc_warning("Too much data, some is lost"); } return result; } @@ -150,9 +144,16 @@ _nc_wrap_entry(ENTRY * const ep, bool copy_strings) int offsets[MAX_ENTRY_SIZE / sizeof(short)]; int useoffsets[MAX_USES]; unsigned i, n; - unsigned nuses = ep->nuses; - TERMTYPE *tp = &(ep->tterm); + unsigned nuses; + TERMTYPE2 *tp; + DEBUG(2, (T_CALLED("_nc_wrap_entry(ep=%p, copy_strings=%d)"), (void *) + ep, copy_strings)); + if (ep == NULL || stringbuf == NULL) + _nc_err_abort("_nc_wrap_entry called without initialization"); + + nuses = ep->nuses; + tp = &(ep->tterm); if (copy_strings) { next_free = 0; /* clear static storage */ @@ -183,7 +184,7 @@ _nc_wrap_entry(ENTRY * const ep, bool copy_strings) } else if (tp->Strings[i] == CANCELLED_STRING) { offsets[i] = CANCELLED_OFFSET; } else { - offsets[i] = tp->Strings[i] - stringbuf; + offsets[i] = (int) (tp->Strings[i] - stringbuf); } } } @@ -192,11 +193,10 @@ _nc_wrap_entry(ENTRY * const ep, bool copy_strings) if (ep->uses[i].name == 0) useoffsets[i] = ABSENT_OFFSET; else - useoffsets[i] = ep->uses[i].name - stringbuf; + useoffsets[i] = (int) (ep->uses[i].name - stringbuf); } - if ((tp->str_table = typeMalloc(char, next_free)) == (char *) 0) - _nc_err_abort(MSG_NO_MEMORY); + TYPE_MALLOC(char, next_free, tp->str_table); (void) memcpy(tp->str_table, stringbuf, next_free); tp->term_names = tp->str_table + n; @@ -216,21 +216,19 @@ _nc_wrap_entry(ENTRY * const ep, bool copy_strings) if (!copy_strings) { if ((n = (unsigned) NUM_EXT_NAMES(tp)) != 0) { if (n < SIZEOF(offsets)) { - size_t copied, length, strtabsize = 0; + size_t length = 0; + size_t offset; for (i = 0; i < n; i++) { - strtabsize += strlen(tp->ext_Names[i]) + 1; - offsets[i] = tp->ext_Names[i] - stringbuf; + length += strlen(tp->ext_Names[i]) + 1; + offsets[i] = (int) (tp->ext_Names[i] - stringbuf); } - if ((tp->ext_str_table = typeMalloc(char, strtabsize)) == 0) - _nc_err_abort(MSG_NO_MEMORY); - for (i = 0, length = 0; i < n; i++) { - tp->ext_Names[i] = tp->ext_str_table + length; - copied = strlcpy(tp->ext_Names[i], stringbuf + offsets[i], - strtabsize) + 1; - if (copied > strtabsize) - _nc_err_abort("Buffer overflow"); - length += copied; - strtabsize -= copied; + TYPE_MALLOC(char, length, tp->ext_str_table); + for (i = 0, offset = 0; i < n; i++) { + tp->ext_Names[i] = tp->ext_str_table + offset; + _nc_STRCPY(tp->ext_Names[i], + stringbuf + offsets[i], + length - offset); + offset += strlen(tp->ext_Names[i]) + 1; } } } @@ -238,41 +236,148 @@ _nc_wrap_entry(ENTRY * const ep, bool copy_strings) #endif for (i = 0; i < nuses; i++) { - if (useoffsets[i] == ABSENT_OFFSET) + if (useoffsets[i] == ABSENT_OFFSET) { ep->uses[i].name = 0; - else - ep->uses[i].name = (tp->str_table + useoffsets[i]); + } else { + ep->uses[i].name = strdup(tp->str_table + useoffsets[i]); + } } + DEBUG(2, (T_RETURN(""))); } NCURSES_EXPORT(void) -_nc_merge_entry(TERMTYPE *const to, TERMTYPE *const from) +_nc_merge_entry(ENTRY * const target, ENTRY * const source) /* merge capabilities from `from' entry into `to' entry */ { + TERMTYPE2 *to = &(target->tterm); + TERMTYPE2 *from = &(source->tterm); +#if NCURSES_XNAMES + TERMTYPE2 copy; + size_t str_size, copy_size; + char *str_table; +#endif unsigned i; + if (source == 0 || from == 0 || target == 0 || to == 0) + return; + #if NCURSES_XNAMES + _nc_copy_termtype2(©, from); + from = © _nc_align_termtype(to, from); + /* + * compute the maximum size of the string-table. + */ + str_size = strlen(to->term_names) + 1; + for_each_string(i, from) { + if (VALID_STRING(from->Strings[i])) + str_size += strlen(from->Strings[i]) + 1; + } + for_each_string(i, to) { + if (VALID_STRING(to->Strings[i])) + str_size += strlen(to->Strings[i]) + 1; + } + /* allocate a string-table large enough for both source/target, and + * copy all of the strings into that table. In the merge, we will + * select from the original source/target lists to construct a new + * target list. + */ + if (str_size != 0) { + char *str_copied; + if ((str_table = malloc(str_size)) == NULL) + _nc_err_abort(MSG_NO_MEMORY); + str_copied = str_table; + _nc_STRCPY(str_copied, to->term_names, str_size); + to->term_names = str_copied; + copy_size = strlen(str_copied) + 1; + str_copied += copy_size; + str_size -= copy_size; + for_each_string(i, from) { + if (VALID_STRING(from->Strings[i])) { + _nc_STRCPY(str_copied, from->Strings[i], str_size); + from->Strings[i] = str_copied; + copy_size = strlen(str_copied) + 1; + str_copied += copy_size; + str_size -= copy_size; + } + } + for_each_string(i, to) { + if (VALID_STRING(to->Strings[i])) { + _nc_STRCPY(str_copied, to->Strings[i], str_size); + to->Strings[i] = str_copied; + copy_size = strlen(str_copied) + 1; + str_copied += copy_size; + str_size -= copy_size; + } + } + free(to->str_table); + to->str_table = str_table; + free(from->str_table); + } + /* + * Do the same for the extended-strings (i.e., lists of capabilities). + */ + str_size = 0; + for (i = 0; i < NUM_EXT_NAMES(from); ++i) { + if (VALID_STRING(from->ext_Names[i])) + str_size += strlen(from->ext_Names[i]) + 1; + } + for (i = 0; i < NUM_EXT_NAMES(to); ++i) { + if (VALID_STRING(to->ext_Names[i])) + str_size += strlen(to->ext_Names[i]) + 1; + } + /* allocate a string-table large enough for both source/target, and + * copy all of the strings into that table. In the merge, we will + * select from the original source/target lists to construct a new + * target list. + */ + if (str_size != 0) { + char *str_copied; + if ((str_table = malloc(str_size)) == NULL) + _nc_err_abort(MSG_NO_MEMORY); + str_copied = str_table; + for (i = 0; i < NUM_EXT_NAMES(from); ++i) { + if (VALID_STRING(from->ext_Names[i])) { + _nc_STRCPY(str_copied, from->ext_Names[i], str_size); + from->ext_Names[i] = str_copied; + copy_size = strlen(str_copied) + 1; + str_copied += copy_size; + str_size -= copy_size; + } + } + for (i = 0; i < NUM_EXT_NAMES(to); ++i) { + if (VALID_STRING(to->ext_Names[i])) { + _nc_STRCPY(str_copied, to->ext_Names[i], str_size); + to->ext_Names[i] = str_copied; + copy_size = strlen(str_copied) + 1; + str_copied += copy_size; + str_size -= copy_size; + } + } + free(to->ext_str_table); + to->ext_str_table = str_table; + free(from->ext_str_table); + } #endif for_each_boolean(i, from) { - if (to->Booleans[i] != CANCELLED_BOOLEAN) { + if (to->Booleans[i] != (NCURSES_SBOOL) CANCELLED_BOOLEAN) { int mergebool = from->Booleans[i]; if (mergebool == CANCELLED_BOOLEAN) to->Booleans[i] = FALSE; else if (mergebool == TRUE) - to->Booleans[i] = (char) mergebool; + to->Booleans[i] = (NCURSES_SBOOL) mergebool; } } for_each_number(i, from) { if (to->Numbers[i] != CANCELLED_NUMERIC) { - short mergenum = from->Numbers[i]; + int mergenum = from->Numbers[i]; if (mergenum == CANCELLED_NUMERIC) to->Numbers[i] = ABSENT_NUMERIC; else if (mergenum != ABSENT_NUMERIC) - to->Numbers[i] = mergenum; + to->Numbers[i] = (NCURSES_INT2) mergenum; } } @@ -291,13 +396,20 @@ _nc_merge_entry(TERMTYPE *const to, TERMTYPE *const from) to->Strings[i] = mergestring; } } +#if NCURSES_XNAMES + /* cleanup */ + free(copy.Booleans); + free(copy.Numbers); + free(copy.Strings); + free(copy.ext_Names); +#endif } #if NO_LEAKS NCURSES_EXPORT(void) _nc_alloc_entry_leaks(void) { - if (stringbuf != 0) { + if (stringbuf != NULL) { FreeAndNull(stringbuf); } next_free = 0; diff --git a/lib/libcurses/tinfo/alloc_ttype.c b/lib/libcurses/tinfo/alloc_ttype.c index f474e502be4..d4817582008 100644 --- a/lib/libcurses/tinfo/alloc_ttype.c +++ b/lib/libcurses/tinfo/alloc_ttype.c @@ -1,7 +1,8 @@ -/* $OpenBSD: alloc_ttype.c,v 1.6 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: alloc_ttype.c,v 1.7 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1999-2006,2008 Free Software Foundation, Inc. * + * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1999-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -43,9 +44,8 @@ #include #include -#include -MODULE_ID("$Id: alloc_ttype.c,v 1.6 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: alloc_ttype.c,v 1.7 2023/10/17 09:52:09 nicm Exp $") #if NCURSES_XNAMES /* @@ -64,7 +64,7 @@ merge_names(char **dst, char **a, int na, char **b, int nb) } else if (cmp > 0) { dst[n++] = *b++; nb--; - } else if (cmp == 0) { + } else { dst[n++] = *a; a++, b++; na--, nb--; @@ -81,78 +81,111 @@ merge_names(char **dst, char **a, int na, char **b, int nb) } static bool -find_name(char **table, int length, char *name) +find_name(char **table, int item, int length, const char *name) { - while (length-- > 0) { - if (!strcmp(*table++, name)) { - DEBUG(4, ("found name '%s'", name)); - return TRUE; + int n; + int result = -1; + + for (n = item; n < length; ++n) { + if (!strcmp(table[n], name)) { + DEBUG(4, ("found name '%s' @%d", name, n)); + result = n; + break; } } - DEBUG(4, ("did not find name '%s'", name)); - return FALSE; + if (result < 0) { + DEBUG(4, ("did not find name '%s'", name)); + } + return (result >= 0); } +#define EXTEND_NUM(num, ext) \ + DEBUG(4, ("extending " #num " from %d to %d", \ + to->num, (unsigned short) (to->num + (ext - to->ext)))); \ + to->num = (unsigned short) (to->num + (ext - to->ext)) + static void -realign_data(TERMTYPE *to, char **ext_Names, +realign_data(TERMTYPE2 *to, char **ext_Names, int ext_Booleans, int ext_Numbers, int ext_Strings) { int n, m, base; - int limit = (to->ext_Booleans + to->ext_Numbers + to->ext_Strings); + int to_Booleans = to->ext_Booleans; + int to_Numbers = to->ext_Numbers; + int to_Strings = to->ext_Strings; + int to1, to2, from; + + DEBUG(4, ("realign_data %d/%d/%d vs %d/%d/%d", + ext_Booleans, + ext_Numbers, + ext_Strings, + to->ext_Booleans, + to->ext_Numbers, + to->ext_Strings)); if (to->ext_Booleans != ext_Booleans) { - to->num_Booleans += (ext_Booleans - to->ext_Booleans); - to->Booleans = typeRealloc(NCURSES_SBOOL, to->num_Booleans, to->Booleans); + to1 = 0; + to2 = to_Booleans + to1; + from = 0; + EXTEND_NUM(num_Booleans, ext_Booleans); + TYPE_REALLOC(NCURSES_SBOOL, to->num_Booleans, to->Booleans); for (n = to->ext_Booleans - 1, m = ext_Booleans - 1, base = to->num_Booleans - (m + 1); m >= 0; m--) { - if (find_name(to->ext_Names, limit, ext_Names[m])) { + if (find_name(to->ext_Names, to1, to2, ext_Names[m + from])) { to->Booleans[base + m] = to->Booleans[base + n--]; } else { to->Booleans[base + m] = FALSE; } } - to->ext_Booleans = ext_Booleans; + to->ext_Booleans = UShort(ext_Booleans); } + if (to->ext_Numbers != ext_Numbers) { - to->num_Numbers += (ext_Numbers - to->ext_Numbers); - to->Numbers = typeRealloc(short, to->num_Numbers, to->Numbers); + to1 = to_Booleans; + to2 = to_Numbers + to1; + from = ext_Booleans; + EXTEND_NUM(num_Numbers, ext_Numbers); + TYPE_REALLOC(NCURSES_INT2, to->num_Numbers, to->Numbers); for (n = to->ext_Numbers - 1, m = ext_Numbers - 1, base = to->num_Numbers - (m + 1); m >= 0; m--) { - if (find_name(to->ext_Names, limit, ext_Names[m + ext_Booleans])) { + if (find_name(to->ext_Names, to1, to2, ext_Names[m + from])) { to->Numbers[base + m] = to->Numbers[base + n--]; } else { to->Numbers[base + m] = ABSENT_NUMERIC; } } - to->ext_Numbers = ext_Numbers; + to->ext_Numbers = UShort(ext_Numbers); } + if (to->ext_Strings != ext_Strings) { - to->num_Strings += (ext_Strings - to->ext_Strings); - to->Strings = typeRealloc(char *, to->num_Strings, to->Strings); + to1 = to_Booleans + to_Numbers; + to2 = to_Strings + to1; + from = ext_Booleans + ext_Numbers; + EXTEND_NUM(num_Strings, ext_Strings); + TYPE_REALLOC(char *, to->num_Strings, to->Strings); for (n = to->ext_Strings - 1, m = ext_Strings - 1, base = to->num_Strings - (m + 1); m >= 0; m--) { - if (find_name(to->ext_Names, limit, ext_Names[m + ext_Booleans + ext_Numbers])) { + if (find_name(to->ext_Names, to1, to2, ext_Names[m + from])) { to->Strings[base + m] = to->Strings[base + n--]; } else { to->Strings[base + m] = ABSENT_STRING; } } - to->ext_Strings = ext_Strings; + to->ext_Strings = UShort(ext_Strings); } } /* * Returns the first index in ext_Names[] for the given token-type */ -static int -_nc_first_ext_name(TERMTYPE *tp, int token_type) +static unsigned +_nc_first_ext_name(TERMTYPE2 *tp, int token_type) { - int first; + unsigned first; switch (token_type) { case BOOLEAN: @@ -162,7 +195,7 @@ _nc_first_ext_name(TERMTYPE *tp, int token_type) first = tp->ext_Booleans; break; case STRING: - first = tp->ext_Booleans + tp->ext_Numbers; + first = (unsigned) (tp->ext_Booleans + tp->ext_Numbers); break; default: first = 0; @@ -174,17 +207,17 @@ _nc_first_ext_name(TERMTYPE *tp, int token_type) /* * Returns the last index in ext_Names[] for the given token-type */ -static int -_nc_last_ext_name(TERMTYPE *tp, int token_type) +static unsigned +_nc_last_ext_name(TERMTYPE2 *tp, int token_type) { - int last; + unsigned last; switch (token_type) { case BOOLEAN: last = tp->ext_Booleans; break; case NUMBER: - last = tp->ext_Booleans + tp->ext_Numbers; + last = (unsigned) (tp->ext_Booleans + tp->ext_Numbers); break; default: case STRING: @@ -198,7 +231,7 @@ _nc_last_ext_name(TERMTYPE *tp, int token_type) * Lookup an entry from extended-names, returning -1 if not found */ static int -_nc_find_ext_name(TERMTYPE *tp, char *name, int token_type) +_nc_find_ext_name(TERMTYPE2 *tp, char *name, int token_type) { unsigned j; unsigned first = _nc_first_ext_name(tp, token_type); @@ -206,7 +239,7 @@ _nc_find_ext_name(TERMTYPE *tp, char *name, int token_type) for (j = first; j < last; j++) { if (!strcmp(name, tp->ext_Names[j])) { - return j; + return (int) j; } } return -1; @@ -217,7 +250,7 @@ _nc_find_ext_name(TERMTYPE *tp, char *name, int token_type) * (e.g., Booleans[]). */ static int -_nc_ext_data_index(TERMTYPE *tp, int n, int token_type) +_nc_ext_data_index(TERMTYPE2 *tp, int n, int token_type) { switch (token_type) { case BOOLEAN: @@ -240,13 +273,14 @@ _nc_ext_data_index(TERMTYPE *tp, int n, int token_type) * data. */ static bool -_nc_del_ext_name(TERMTYPE *tp, char *name, int token_type) +_nc_del_ext_name(TERMTYPE2 *tp, char *name, int token_type) { - int j; - int first, last; + int first; if ((first = _nc_find_ext_name(tp, name, token_type)) >= 0) { - last = NUM_EXT_NAMES(tp) - 1; + int j; + int last = (int) NUM_EXT_NAMES(tp) - 1; + for (j = first; j < last; j++) { tp->ext_Names[j] = tp->ext_Names[j + 1]; } @@ -256,22 +290,22 @@ _nc_del_ext_name(TERMTYPE *tp, char *name, int token_type) last = tp->num_Booleans - 1; for (j = first; j < last; j++) tp->Booleans[j] = tp->Booleans[j + 1]; - tp->ext_Booleans -= 1; - tp->num_Booleans -= 1; + tp->ext_Booleans--; + tp->num_Booleans--; break; case NUMBER: last = tp->num_Numbers - 1; for (j = first; j < last; j++) tp->Numbers[j] = tp->Numbers[j + 1]; - tp->ext_Numbers -= 1; - tp->num_Numbers -= 1; + tp->ext_Numbers--; + tp->num_Numbers--; break; case STRING: last = tp->num_Strings - 1; for (j = first; j < last; j++) tp->Strings[j] = tp->Strings[j + 1]; - tp->ext_Strings -= 1; - tp->num_Strings -= 1; + tp->ext_Strings--; + tp->num_Strings--; break; } return TRUE; @@ -284,7 +318,7 @@ _nc_del_ext_name(TERMTYPE *tp, char *name, int token_type) * index into the corresponding data array is returned. */ static int -_nc_ins_ext_name(TERMTYPE *tp, char *name, int token_type) +_nc_ins_ext_name(TERMTYPE2 *tp, char *name, int token_type) { unsigned first = _nc_first_ext_name(tp, token_type); unsigned last = _nc_last_ext_name(tp, token_type); @@ -301,36 +335,36 @@ _nc_ins_ext_name(TERMTYPE *tp, char *name, int token_type) } } - tp->ext_Names = typeRealloc(char *, total, tp->ext_Names); + TYPE_REALLOC(char *, total, tp->ext_Names); for (k = total - 1; k > j; k--) tp->ext_Names[k] = tp->ext_Names[k - 1]; tp->ext_Names[j] = name; - j = _nc_ext_data_index(tp, (int) j, token_type); + j = (unsigned) _nc_ext_data_index(tp, (int) j, token_type); switch (token_type) { case BOOLEAN: - tp->ext_Booleans += 1; - tp->num_Booleans += 1; - tp->Booleans = typeRealloc(NCURSES_SBOOL, tp->num_Booleans, tp->Booleans); - for (k = tp->num_Booleans - 1; k > j; k--) + tp->ext_Booleans++; + tp->num_Booleans++; + TYPE_REALLOC(NCURSES_SBOOL, tp->num_Booleans, tp->Booleans); + for (k = (unsigned) (tp->num_Booleans - 1); k > j; k--) tp->Booleans[k] = tp->Booleans[k - 1]; break; case NUMBER: - tp->ext_Numbers += 1; - tp->num_Numbers += 1; - tp->Numbers = typeRealloc(short, tp->num_Numbers, tp->Numbers); - for (k = tp->num_Numbers - 1; k > j; k--) + tp->ext_Numbers++; + tp->num_Numbers++; + TYPE_REALLOC(NCURSES_INT2, tp->num_Numbers, tp->Numbers); + for (k = (unsigned) (tp->num_Numbers - 1); k > j; k--) tp->Numbers[k] = tp->Numbers[k - 1]; break; case STRING: - tp->ext_Strings += 1; - tp->num_Strings += 1; - tp->Strings = typeRealloc(char *, tp->num_Strings, tp->Strings); - for (k = tp->num_Strings - 1; k > j; k--) + tp->ext_Strings++; + tp->num_Strings++; + TYPE_REALLOC(char *, tp->num_Strings, tp->Strings); + for (k = (unsigned) (tp->num_Strings - 1); k > j; k--) tp->Strings[k] = tp->Strings[k - 1]; break; } - return j; + return (int) j; } /* @@ -339,18 +373,21 @@ _nc_ins_ext_name(TERMTYPE *tp, char *name, int token_type) * cancellation of a name that is inherited from another entry. */ static void -adjust_cancels(TERMTYPE *to, TERMTYPE *from) +adjust_cancels(TERMTYPE2 *to, TERMTYPE2 *from) { int first = to->ext_Booleans + to->ext_Numbers; int last = first + to->ext_Strings; int j, k; + DEBUG(3, (T_CALLED("adjust_cancels(%s), from(%s)"), + NonNull(to->term_names), + NonNull(from->term_names))); for (j = first; j < last;) { char *name = to->ext_Names[j]; - unsigned j_str = to->num_Strings - first - to->ext_Strings; + int j_str = to->num_Strings - first - to->ext_Strings; if (to->Strings[j + j_str] == CANCELLED_STRING) { - if ((k = _nc_find_ext_name(from, to->ext_Names[j], BOOLEAN)) >= 0) { + if (_nc_find_ext_name(from, to->ext_Names[j], BOOLEAN) >= 0) { if (_nc_del_ext_name(to, name, STRING) || _nc_del_ext_name(to, name, NUMBER)) { k = _nc_ins_ext_name(to, name, BOOLEAN); @@ -358,8 +395,7 @@ adjust_cancels(TERMTYPE *to, TERMTYPE *from) } else { j++; } - } else if ((k = _nc_find_ext_name(from, to->ext_Names[j], - NUMBER)) >= 0) { + } else if (_nc_find_ext_name(from, to->ext_Names[j], NUMBER) >= 0) { if (_nc_del_ext_name(to, name, STRING) || _nc_del_ext_name(to, name, BOOLEAN)) { k = _nc_ins_ext_name(to, name, NUMBER); @@ -367,8 +403,7 @@ adjust_cancels(TERMTYPE *to, TERMTYPE *from) } else { j++; } - } else if ((k = _nc_find_ext_name(from, to->ext_Names[j], - STRING)) >= 0) { + } else if (_nc_find_ext_name(from, to->ext_Names[j], STRING) >= 0) { if (_nc_del_ext_name(to, name, NUMBER) || _nc_del_ext_name(to, name, BOOLEAN)) { k = _nc_ins_ext_name(to, name, STRING); @@ -383,43 +418,52 @@ adjust_cancels(TERMTYPE *to, TERMTYPE *from) j++; } } + DEBUG(3, (T_RETURN(""))); } NCURSES_EXPORT(void) -_nc_align_termtype(TERMTYPE *to, TERMTYPE *from) +_nc_align_termtype(TERMTYPE2 *to, TERMTYPE2 *from) { - int na = NUM_EXT_NAMES(to); - int nb = NUM_EXT_NAMES(from); - int n; - bool same; + int na; + int nb; char **ext_Names; - int ext_Booleans, ext_Numbers, ext_Strings; - bool used_ext_Names = FALSE; - DEBUG(2, ("align_termtype to(%d:%s), from(%d:%s)", na, to->term_names, - nb, from->term_names)); + na = to ? ((int) NUM_EXT_NAMES(to)) : 0; + nb = from ? ((int) NUM_EXT_NAMES(from)) : 0; + + DEBUG(2, (T_CALLED("_nc_align_termtype to(%d:%s), from(%d:%s)"), + na, to ? NonNull(to->term_names) : "?", + nb, from ? NonNull(from->term_names) : "?")); + + if (to != NULL && from != NULL && (na != 0 || nb != 0)) { + int ext_Booleans, ext_Numbers, ext_Strings; + bool used_ext_Names = FALSE; - if (na != 0 || nb != 0) { if ((na == nb) /* check if the arrays are equivalent */ &&(to->ext_Booleans == from->ext_Booleans) && (to->ext_Numbers == from->ext_Numbers) && (to->ext_Strings == from->ext_Strings)) { + int n; + bool same; + for (n = 0, same = TRUE; n < na; n++) { if (strcmp(to->ext_Names[n], from->ext_Names[n])) { same = FALSE; break; } } - if (same) + if (same) { + DEBUG(2, (T_RETURN(""))); return; + } } /* - * This is where we pay for having a simple extension representation. + * This is where we pay for having a simple extension representation. * Allocate a new ext_Names array and merge the two ext_Names arrays * into it, updating to's counts for booleans, etc. Fortunately we do * this only for the terminfo compiler (tic) and comparer (infocmp). */ - ext_Names = typeMalloc(char *, na + nb); + TYPE_MALLOC(char *, (size_t)(na + nb), ext_Names); if (to->ext_Strings && (from->ext_Booleans + from->ext_Numbers)) adjust_cancels(to, from); @@ -463,46 +507,208 @@ _nc_align_termtype(TERMTYPE *to, TERMTYPE *from) if (nb != (ext_Booleans + ext_Numbers + ext_Strings)) { nb = (ext_Booleans + ext_Numbers + ext_Strings); realign_data(from, ext_Names, ext_Booleans, ext_Numbers, ext_Strings); - from->ext_Names = typeRealloc(char *, nb, from->ext_Names); - memcpy(from->ext_Names, ext_Names, sizeof(char *) * nb); + TYPE_REALLOC(char *, (size_t) nb, from->ext_Names); + memcpy(from->ext_Names, ext_Names, sizeof(char *) * (size_t) nb); DEBUG(2, ("realigned %d extended names for '%s' (from)", NUM_EXT_NAMES(from), from->term_names)); } if (!used_ext_Names) free(ext_Names); } + DEBUG(2, (T_RETURN(""))); } #endif -NCURSES_EXPORT(void) -_nc_copy_termtype(TERMTYPE *dst, TERMTYPE *src) +#define srcINT 1 +#define dstINT 2 + +/* + * TERMTYPE and TERMTYPE2 differ only with regard to the values in Numbers. + * Use 'mode' to decide which to use. + */ +static void +copy_termtype(TERMTYPE2 *dst, const TERMTYPE2 *src, int mode) { unsigned i; + int pass; + char *new_table; + size_t new_table_size; +#if NCURSES_EXT_NUMBERS + short *oldptr = 0; + int *newptr = 0; +#endif + DEBUG(2, (T_CALLED("copy_termtype(dst=%p, src=%p, mode=%d)"), (void *) + dst, (const void *) src, mode)); *dst = *src; /* ...to copy the sizes and string-tables */ - dst->Booleans = typeMalloc(NCURSES_SBOOL, NUM_BOOLEANS(dst)); - dst->Numbers = typeMalloc(short, NUM_NUMBERS(dst)); - dst->Strings = typeMalloc(char *, NUM_STRINGS(dst)); - - /* FIXME: use memcpy for these and similar loops */ - for_each_boolean(i, dst) - dst->Booleans[i] = src->Booleans[i]; - for_each_number(i, dst) - dst->Numbers[i] = src->Numbers[i]; - for_each_string(i, dst) - dst->Strings[i] = src->Strings[i]; - - /* FIXME: we probably should also copy str_table and ext_str_table, - * but tic and infocmp are not written to exploit that (yet). - */ + + TYPE_MALLOC(NCURSES_SBOOL, NUM_BOOLEANS(dst), dst->Booleans); + TYPE_MALLOC(char *, NUM_STRINGS(dst), dst->Strings); + + memcpy(dst->Booleans, + src->Booleans, + NUM_BOOLEANS(dst) * sizeof(dst->Booleans[0])); + memcpy(dst->Strings, + src->Strings, + NUM_STRINGS(dst) * sizeof(dst->Strings[0])); + + new_table = NULL; + new_table_size = 0; + for (pass = 0; pass < 2; ++pass) { + size_t str_size = 0; + if (src->term_names != NULL) { + if (pass) { + dst->term_names = new_table + str_size; + _nc_STRCPY(dst->term_names + str_size, + src->term_names, + new_table_size - str_size); + } + str_size += strlen(src->term_names) + 1; + } + for_each_string(i, src) { + if (VALID_STRING(src->Strings[i])) { + if (pass) { + _nc_STRCPY(new_table + str_size, + src->Strings[i], + new_table_size - str_size); + dst->Strings[i] = new_table + str_size; + } + str_size += strlen(src->Strings[i]) + 1; + } + } + if (pass) { + dst->str_table = new_table; + } else { + ++str_size; + if ((new_table = malloc(str_size)) == NULL) + _nc_err_abort(MSG_NO_MEMORY); + new_table_size = str_size; + } + } + +#if NCURSES_EXT_NUMBERS + if ((mode & dstINT) == 0) { + DEBUG(2, ("...convert int ->short")); + TYPE_MALLOC(short, NUM_NUMBERS(dst), oldptr); + ((TERMTYPE *) dst)->Numbers = oldptr; + } else { + DEBUG(2, ("...copy without changing size")); + TYPE_MALLOC(int, NUM_NUMBERS(dst), newptr); + dst->Numbers = newptr; + } + if ((mode == srcINT) && (oldptr != 0)) { + DEBUG(2, ("...copy int ->short")); + for (i = 0; i < NUM_NUMBERS(dst); ++i) { + if (src->Numbers[i] > MAX_OF_TYPE(short)) { + oldptr[i] = MAX_OF_TYPE(short); + } else { + oldptr[i] = (short) src->Numbers[i]; + } + } + } else if ((mode == dstINT) && (newptr != 0)) { + DEBUG(2, ("...copy short ->int")); + for (i = 0; i < NUM_NUMBERS(dst); ++i) { + newptr[i] = ((const short *) (src->Numbers))[i]; + } + } else { + DEBUG(2, ("...copy %s without change", + (mode & dstINT) + ? "int" + : "short")); + memcpy(dst->Numbers, + src->Numbers, + NUM_NUMBERS(dst) * ((mode & dstINT) + ? sizeof(int) + : sizeof(short))); + } +#else + (void) mode; + TYPE_MALLOC(short, NUM_NUMBERS(dst), dst->Numbers); + memcpy(dst->Numbers, + src->Numbers, + NUM_NUMBERS(dst) * sizeof(dst->Numbers[0])); +#endif #if NCURSES_XNAMES if ((i = NUM_EXT_NAMES(src)) != 0) { - dst->ext_Names = typeMalloc(char *, i); + TYPE_MALLOC(char *, i, dst->ext_Names); memcpy(dst->ext_Names, src->ext_Names, i * sizeof(char *)); + + new_table = NULL; + new_table_size = 0; + for (pass = 0; pass < 2; ++pass) { + size_t str_size = 0; + char *raw_data = src->ext_str_table; + if (raw_data != NULL) { + for (i = 0; i < src->ext_Strings; ++i) { + size_t skip = strlen(raw_data) + 1; + if (skip != 1) { + if (pass) { + _nc_STRCPY(new_table + str_size, + raw_data, + new_table_size - str_size); + } + str_size += skip; + raw_data += skip; + } + } + } + for (i = 0; i < NUM_EXT_NAMES(dst); ++i) { + if (VALID_STRING(src->ext_Names[i])) { + if (pass) { + _nc_STRCPY(new_table + str_size, + src->ext_Names[i], + new_table_size - str_size); + dst->ext_Names[i] = new_table + str_size; + } + str_size += strlen(src->ext_Names[i]) + 1; + } + } + if (pass) { + dst->ext_str_table = new_table; + } else { + ++str_size; + if ((new_table = calloc(str_size, 1)) == NULL) + _nc_err_abort(MSG_NO_MEMORY); + new_table_size = str_size; + } + } } else { dst->ext_Names = 0; } #endif + DEBUG(2, (T_RETURN(""))); +} + +NCURSES_EXPORT(void) +_nc_copy_termtype(TERMTYPE *dst, const TERMTYPE *src) +{ + DEBUG(2, (T_CALLED("_nc_copy_termtype(dst=%p, src=%p)"), (void *) dst, + (const void *) src)); + copy_termtype((TERMTYPE2 *) dst, (const TERMTYPE2 *) src, 0); + DEBUG(2, (T_RETURN(""))); +} +#if NCURSES_EXT_NUMBERS +NCURSES_EXPORT(void) +_nc_copy_termtype2(TERMTYPE2 *dst, const TERMTYPE2 *src) +{ + DEBUG(2, (T_CALLED("_nc_copy_termtype2(dst=%p, src=%p)"), (void *) dst, + (const void *) src)); + copy_termtype(dst, src, srcINT | dstINT); + DEBUG(2, (T_RETURN(""))); +} + +/* + * Use this for exporting the internal TERMTYPE2 to the legacy format used via + * the CUR macro by applications. + */ +NCURSES_EXPORT(void) +_nc_export_termtype2(TERMTYPE *dst, const TERMTYPE2 *src) +{ + DEBUG(2, (T_CALLED("_nc_export_termtype2(dst=%p, src=%p)"), (void *) + dst, (const void *) src)); + copy_termtype((TERMTYPE2 *) dst, src, srcINT); + DEBUG(2, (T_RETURN(""))); } +#endif /* NCURSES_EXT_NUMBERS */ diff --git a/lib/libcurses/tinfo/captoinfo.c b/lib/libcurses/tinfo/captoinfo.c index 6caf24560d1..3ba75b17dfd 100644 --- a/lib/libcurses/tinfo/captoinfo.c +++ b/lib/libcurses/tinfo/captoinfo.c @@ -1,7 +1,8 @@ -/* $OpenBSD: captoinfo.c,v 1.16 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: captoinfo.c,v 1.17 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. * + * Copyright 2018-2020,2021 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -35,12 +36,16 @@ ****************************************************************************/ /* - * captoinfo.c --- conversion between termcap and terminfo formats + * captoinfo.c + * + * Provide conversion in both directions between termcap and terminfo. + * + * cap-to-info --- conversion between termcap and terminfo formats * * The captoinfo() code was swiped from Ross Ridge's mytinfo package, * adapted to fit ncurses by Eric S. Raymond . * - * There is just one entry point: + * It has just one entry point: * * char *_nc_captoinfo(n, s, parameterized) * @@ -95,7 +100,13 @@ #include #include -MODULE_ID("$Id: captoinfo.c,v 1.16 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: captoinfo.c,v 1.17 2023/10/17 09:52:09 nicm Exp $") + +#if 0 +#define DEBUG_THIS(p) DEBUG(9, p) +#else +#define DEBUG_THIS(p) /* nothing */ +#endif #define MAX_PUSHED 16 /* max # args we can push onto the stack */ @@ -116,9 +127,7 @@ init_string(void) /* initialize 'my_string', 'my_length' */ { if (my_string == 0) - my_string = typeMalloc(char, my_length = 256); - if (my_string == 0) - _nc_err_abort(MSG_NO_MEMORY); + TYPE_MALLOC(char, my_length = 256, my_string); *my_string = '\0'; return my_string; @@ -127,18 +136,16 @@ init_string(void) static char * save_string(char *d, const char *const s) { - size_t have = (d - my_string); + size_t have = (size_t) (d - my_string); size_t need = have + strlen(s) + 2; - size_t copied; if (need > my_length) { - my_string = (char *) realloc(my_string, my_length = (need + need)); + my_string = (char *) _nc_doalloc(my_string, my_length = (need + need)); if (my_string == 0) _nc_err_abort(MSG_NO_MEMORY); d = my_string + have; } - if ((copied = strlcpy(d, s, my_length - have)) >= my_length - have) - _nc_err_abort("Buffer overflow"); - return d + copied; + _nc_STRCPY(d, s, my_length - have); + return d + strlen(d); } static NCURSES_INLINE char * @@ -187,7 +194,7 @@ cvtchar(register const char *sp) case '$': case '\\': case '%': - c = (unsigned char) (*sp); + c = UChar(*sp); len = 2; break; case '\0': @@ -200,29 +207,36 @@ cvtchar(register const char *sp) case '3': len = 1; while (isdigit(UChar(*sp))) { - c = 8 * c + (*sp++ - '0'); + c = UChar(8 * c + (*sp++ - '0')); len++; } break; default: - c = (unsigned char) (*sp); - len = 2; + c = UChar(*sp); + len = (c != '\0') ? 2 : 1; break; } break; case '^': - c = (*++sp & 0x1f); len = 2; + c = UChar(*++sp); + if (c == '?') { + c = 127; + } else if (c == '\0') { + len = 1; + } else { + c &= 0x1f; + } break; default: - c = (unsigned char) (*sp); - len = 1; + c = UChar(*sp); + len = (c != '\0') ? 1 : 0; } if (isgraph(c) && c != ',' && c != '\'' && c != '\\' && c != ':') { dp = save_string(dp, "%\'"); dp = save_char(dp, c); dp = save_char(dp, '\''); - } else { + } else if (c != '\0') { dp = save_string(dp, "%{"); if (c > 99) dp = save_char(dp, c / 100 + '0'); @@ -238,17 +252,25 @@ static void getparm(int parm, int n) /* push n copies of param on the terminfo stack if not already there */ { + int nn; + if (seenr) { if (parm == 1) parm = 2; else if (parm == 2) parm = 1; } + + for (nn = 0; nn < n; ++nn) { + dp = save_string(dp, "%p"); + dp = save_char(dp, '0' + parm); + } + if (onstack == parm) { if (n > 1) { _nc_warning("string may not be optimal"); dp = save_string(dp, "%Pa"); - while (n--) { + while (n-- > 0) { dp = save_string(dp, "%ga"); } } @@ -259,11 +281,6 @@ getparm(int parm, int n) onstack = parm; - while (n--) { - dp = save_string(dp, "%p"); - dp = save_char(dp, '0' + parm); - } - if (seenn && parm < 3) { dp = save_string(dp, "%{96}%^"); } @@ -293,6 +310,8 @@ _nc_captoinfo(const char *cap, const char *s, int const parameterized) seenr = 0; param = 1; + DEBUG_THIS(("_nc_captoinfo params %d, %s", parameterized, s)); + dp = init_string(); /* skip the initial padding (if we haven't been told not to) */ @@ -300,7 +319,7 @@ _nc_captoinfo(const char *cap, const char *s, int const parameterized) if (s == 0) s = ""; if (parameterized >= 0 && isdigit(UChar(*s))) - for (capstart = s;; s++) + for (capstart = s; *s != '\0'; s++) if (!(isdigit(UChar(*s)) || *s == '*' || *s == '.')) break; @@ -314,7 +333,7 @@ _nc_captoinfo(const char *cap, const char *s, int const parameterized) } switch (*s++) { case '%': - dp = save_char(dp, '%'); + dp = save_string(dp, "%%"); break; case 'r': if (seenr++ == 1) { @@ -347,13 +366,18 @@ _nc_captoinfo(const char *cap, const char *s, int const parameterized) dp = save_string(dp, "%{2}%*%-"); break; case '>': - getparm(param, 2); /* %?%{x}%>%t%{y}%+%; */ - dp = save_string(dp, "%?"); - s += cvtchar(s); - dp = save_string(dp, "%>%t"); - s += cvtchar(s); - dp = save_string(dp, "%+%;"); + if (s[0] && s[1]) { + getparm(param, 2); + dp = save_string(dp, "%?"); + s += cvtchar(s); + dp = save_string(dp, "%>%t"); + s += cvtchar(s); + dp = save_string(dp, "%+%;"); + } else { + _nc_warning("expected two characters after %%>"); + dp = save_string(dp, "%>"); + } break; case 'a': if ((*s == '=' || *s == '+' || *s == '-' @@ -434,12 +458,17 @@ _nc_captoinfo(const char *cap, const char *s, int const parameterized) pop(); break; case '0': /* not clear any of the historical termcaps did this */ - if (*s == '3') + if (*s == '3') { + ++s; goto see03; - else if (*s != '2') - goto invalid; - /* FALLTHRU */ + } + if (*s == '2') { + ++s; + goto see02; + } + goto invalid; case '2': + see02: getparm(param, 1); dp = save_string(dp, "%2d"); pop(); @@ -473,73 +502,10 @@ _nc_captoinfo(const char *cap, const char *s, int const parameterized) break; } break; -#ifdef REVISIBILIZE - case '\\': - dp = save_char(dp, *s++); - dp = save_char(dp, *s++); - break; - case '\n': - dp = save_string(dp, "\\n"); - s++; - break; - case '\t': - dp = save_string(dp, "\\t"); - s++; - break; - case '\r': - dp = save_string(dp, "\\r"); - s++; - break; - case '\200': - dp = save_string(dp, "\\0"); - s++; - break; - case '\f': - dp = save_string(dp, "\\f"); - s++; - break; - case '\b': - dp = save_string(dp, "\\b"); - s++; - break; - case ' ': - dp = save_string(dp, "\\s"); - s++; - break; - case '^': - dp = save_string(dp, "\\^"); - s++; - break; - case ':': - dp = save_string(dp, "\\:"); - s++; - break; - case ',': - dp = save_string(dp, "\\,"); - s++; - break; default: - if (*s == '\033') { - dp = save_string(dp, "\\E"); - s++; - } else if (*s > 0 && *s < 32) { - dp = save_char(dp, '^'); - dp = save_char(dp, *s + '@'); - s++; - } else if (*s <= 0 || *s >= 127) { - dp = save_char(dp, '\\'); - dp = save_char(dp, ((*s & 0300) >> 6) + '0'); - dp = save_char(dp, ((*s & 0070) >> 3) + '0'); - dp = save_char(dp, (*s & 0007) + '0'); - s++; - } else + if (*s != '\0') dp = save_char(dp, *s++); break; -#else - default: - dp = save_char(dp, *s++); - break; -#endif } } @@ -549,7 +515,7 @@ _nc_captoinfo(const char *cap, const char *s, int const parameterized) */ if (capstart) { dp = save_string(dp, "$<"); - for (s = capstart;; s++) + for (s = capstart; *s != '\0'; s++) if (isdigit(UChar(*s)) || *s == '*' || *s == '.') dp = save_char(dp, *s); else @@ -558,6 +524,9 @@ _nc_captoinfo(const char *cap, const char *s, int const parameterized) } (void) save_char(dp, '\0'); + + DEBUG_THIS(("... _nc_captoinfo %s", NonNull(my_string))); + return (my_string); } @@ -582,7 +551,7 @@ bcd_expression(const char *str) { char buffer[80]; int tst; - snprintf(buffer, sizeof(buffer), fmt, ch1, ch2); + _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) fmt, ch1, ch2); tst = strlen(buffer) - 1; assert(len == tst); } @@ -594,17 +563,20 @@ bcd_expression(const char *str) static char * save_tc_char(char *bufptr, int c1) { - char temp[80]; - if (is7bits(c1) && isprint(c1)) { if (c1 == ':' || c1 == '\\') bufptr = save_char(bufptr, '\\'); bufptr = save_char(bufptr, c1); } else { - if (c1 == (c1 & 0x1f)) /* iscntrl() returns T on 255 */ - (void) strlcpy(temp, unctrl((chtype) c1), sizeof(temp)); - else - (void) snprintf(temp, sizeof(temp), "\\%03o", c1); + char temp[80]; + + if (c1 == (c1 & 0x1f)) { /* iscntrl() returns T on 255 */ + _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) + "%.20s", unctrl((chtype) c1)); + } else { + _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) + "\\%03o", c1); + } bufptr = save_string(bufptr, temp); } return bufptr; @@ -620,6 +592,8 @@ save_tc_inequality(char *bufptr, int c1, int c2) } /* + * info-to-cap --- conversion between terminfo and termcap formats + * * Here are the capabilities infotocap assumes it can translate to: * * %% output `%' @@ -637,6 +611,8 @@ save_tc_inequality(char *bufptr, int c1, int c2) * %m exclusive-or all parameters with 0177 (not in 4.4BSD) */ +#define octal_fixup(n, c) fixups[n].ch = ((fixups[n].ch << 3) | ((c) - '0')) + /* * Convert a terminfo string to termcap format. Parameters are as in * _nc_captoinfo(). @@ -647,15 +623,29 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz int seenone = 0, seentwo = 0, saw_m = 0, saw_n = 0; const char *padding; const char *trimmed = 0; + int in0, in1, in2; char ch1 = 0, ch2 = 0; char *bufptr = init_string(); + char octal[4]; int len; + int digits; bool syntax_error = FALSE; + int myfix = 0; + struct { + int ch; + int offset; + } fixups[MAX_TC_FIXUPS]; + + DEBUG_THIS(("_nc_infotocap %s params %d, %s", + _nc_strict_bsd ? "strict" : "loose", + parameterized, + _nc_visbuf(str))); /* we may have to move some trailing mandatory padding up front */ padding = str + strlen(str) - 1; - if (padding > str && *padding == '>' && *--padding == '/') { - --padding; + if (padding > str && *padding == '>') { + if (padding > (str + 1) && *--padding == '/') + --padding; while (isdigit(UChar(*padding)) || *padding == '.' || *padding == '*') padding--; if (padding > str && *padding == '<' && *--padding == '$') @@ -666,12 +656,152 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz bufptr = save_char(bufptr, *padding++); } - for (; *str && str != trimmed; str++) { + for (; !syntax_error && + *str && + ((trimmed == 0) || (str < trimmed)); str++) { int c1, c2; char *cp = 0; - if (str[0] == '\\' && (str[1] == '^' || str[1] == ',')) { - bufptr = save_char(bufptr, *++str); + if (str[0] == '^') { + if (str[1] == '\0' || (str + 1) == trimmed) { + bufptr = save_string(bufptr, "\\136"); + ++str; + } else if (str[1] == '?') { + /* + * Although the 4.3BSD termcap file has an instance of "kb=^?", + * that appears to be just cut/paste since neither 4.3BSD nor + * 4.4BSD termcap interprets "^?" as DEL. + */ + bufptr = save_string(bufptr, "\\177"); + ++str; + } else { + bufptr = save_char(bufptr, *str++); + bufptr = save_char(bufptr, *str); + } + } else if (str[0] == ':') { + bufptr = save_char(bufptr, '\\'); + bufptr = save_char(bufptr, '0'); + bufptr = save_char(bufptr, '7'); + bufptr = save_char(bufptr, '2'); + } else if (str[0] == '\\') { + if (str[1] == '\0' || (str + 1) == trimmed) { + bufptr = save_string(bufptr, "\\134"); + ++str; + } else if (str[1] == '^') { + bufptr = save_string(bufptr, "\\136"); + ++str; + } else if (str[1] == ',') { + bufptr = save_char(bufptr, *++str); + } else { + int xx1; + + bufptr = save_char(bufptr, *str++); + xx1 = *str; + if (_nc_strict_bsd) { + + if (isoctal(UChar(xx1))) { + int pad = 0; + int xx2; + int fix = 0; + + if (!isoctal(UChar(str[1]))) + pad = 2; + else if (str[1] && !isoctal(UChar(str[2]))) + pad = 1; + + /* + * Test for "\0", "\00" or "\000" and transform those + * into "\200". + */ + if (xx1 == '0' + && ((pad == 2) || (str[1] == '0')) + && ((pad >= 1) || (str[2] == '0'))) { + xx2 = '2'; + } else { + xx2 = '0'; + pad = 0; /* FIXME - optionally pad to 3 digits */ + } + if (myfix < MAX_TC_FIXUPS) { + fix = 3 - pad; + fixups[myfix].ch = 0; + fixups[myfix].offset = (int) (bufptr + - my_string + - 1); + } + while (pad-- > 0) { + bufptr = save_char(bufptr, xx2); + if (myfix < MAX_TC_FIXUPS) { + fixups[myfix].ch <<= 3; + fixups[myfix].ch |= (xx2 - '0'); + } + xx2 = '0'; + } + if (myfix < MAX_TC_FIXUPS) { + int n; + for (n = 0; n < fix; ++n) { + fixups[myfix].ch <<= 3; + fixups[myfix].ch |= (str[n] - '0'); + } + if (fixups[myfix].ch < 32) { + ++myfix; + } + } + } else if (strchr("E\\nrtbf", xx1) == 0) { + switch (xx1) { + case 'e': + xx1 = 'E'; + break; + case 'l': + xx1 = 'n'; + break; + case 's': + bufptr = save_char(bufptr, '0'); + bufptr = save_char(bufptr, '4'); + xx1 = '0'; + break; + case ':': + /* + * Note: termcap documentation claims that ":" + * must be escaped as "\072", however the + * documentation is incorrect - read the code. + * The replacement does not work reliably, + * so the advice is not helpful. + */ + bufptr = save_char(bufptr, '0'); + bufptr = save_char(bufptr, '7'); + xx1 = '2'; + break; + default: + /* should not happen, but handle this anyway */ + _nc_SPRINTF(octal, _nc_SLIMIT(sizeof(octal)) + "%03o", UChar(xx1)); + bufptr = save_char(bufptr, octal[0]); + bufptr = save_char(bufptr, octal[1]); + xx1 = octal[2]; + break; + } + } + } else { + if (myfix < MAX_TC_FIXUPS && isoctal(UChar(xx1))) { + bool will_fix = TRUE; + int n; + + fixups[myfix].ch = 0; + fixups[myfix].offset = (int) (bufptr - my_string - 1); + for (n = 0; n < 3; ++n) { + if (isoctal(str[n])) { + octal_fixup(myfix, str[n]); + } else { + will_fix = FALSE; + break; + } + } + if (will_fix && (fixups[myfix].ch < 32)) + ++myfix; + } + } + bufptr = save_char(bufptr, xx1); + } } else if (str[0] == '$' && str[1] == '<') { /* discard padding */ str += 2; while (isdigit(UChar(*str)) @@ -681,6 +811,20 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz || *str == '>') str++; --str; + } else if (sscanf(str, + "[%%?%%p1%%{8}%%<%%t%d%%p1%%d%%e%%p1%%{16}%%<%%t%d%%p1%%{8}%%-%%d%%e%d;5;%%p1%%d%%;m", + &in0, &in1, &in2) == 3 + && ((in0 == 4 && in1 == 10 && in2 == 48) + || (in0 == 3 && in1 == 9 && in2 == 38))) { + /* dumb-down an optimized case from xterm-256color for termcap */ + if ((str = strstr(str, ";m")) == 0) + break; /* cannot happen */ + ++str; + if (in2 == 48) { + bufptr = save_string(bufptr, "[48;5;%dm"); + } else { + bufptr = save_string(bufptr, "[38;5;%dm"); + } } else if (str[0] == '%' && str[1] == '%') { /* escaped '%' */ bufptr = save_string(bufptr, "%%"); ++str; @@ -691,18 +835,19 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz bufptr = save_tc_inequality(bufptr, c1, c2); } else if (sscanf(str, "%%?%%{%d}%%>%%t%%'%c'%%+%%;", &c1, &ch2) == 2) { str = strchr(str, ';'); - bufptr = save_tc_inequality(bufptr, c1, c2); + bufptr = save_tc_inequality(bufptr, c1, ch2); } else if (sscanf(str, "%%?%%'%c'%%>%%t%%{%d}%%+%%;", &ch1, &c2) == 2) { str = strchr(str, ';'); - bufptr = save_tc_inequality(bufptr, c1, c2); + bufptr = save_tc_inequality(bufptr, ch1, c2); } else if (sscanf(str, "%%?%%'%c'%%>%%t%%'%c'%%+%%;", &ch1, &ch2) == 2) { str = strchr(str, ';'); - bufptr = save_tc_inequality(bufptr, c1, c2); + bufptr = save_tc_inequality(bufptr, ch1, ch2); } else if ((len = bcd_expression(str)) != 0) { str += len; bufptr = save_string(bufptr, "%B"); - } else if ((sscanf(str, "%%{%d}%%+%%c", &c1) == 1 - || sscanf(str, "%%'%c'%%+%%c", &ch1) == 1) + } else if ((sscanf(str, "%%{%d}%%+%%%c", &c1, &ch2) == 2 + || sscanf(str, "%%'%c'%%+%%%c", &ch1, &ch2) == 2) + && ch2 == 'c' && (cp = strchr(str, '+'))) { str = cp + 2; bufptr = save_string(bufptr, "%+"); @@ -712,15 +857,15 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz bufptr = save_tc_char(bufptr, c1); } /* FIXME: this "works" for 'delta' */ - else if (strncmp(str, "%{2}%*%-", 8) == 0) { + else if (strncmp(str, "%{2}%*%-", (size_t) 8) == 0) { str += 7; bufptr = save_string(bufptr, "%D"); - } else if (strncmp(str, "%{96}%^", 7) == 0) { + } else if (strncmp(str, "%{96}%^", (size_t) 7) == 0) { str += 6; if (saw_m++ == 0) { bufptr = save_string(bufptr, "%n"); } - } else if (strncmp(str, "%{127}%^", 8) == 0) { + } else if (strncmp(str, "%{127}%^", (size_t) 8) == 0) { str += 7; if (saw_n++ == 0) { bufptr = save_string(bufptr, "%m"); @@ -743,11 +888,48 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz case '8': case '9': bufptr = save_char(bufptr, '%'); - while (isdigit(UChar(*str))) - bufptr = save_char(bufptr, *str++); - if (strchr("doxX.", *str)) { - if (*str != 'd') /* termcap doesn't have octal, hex */ - return 0; + ch1 = 0; + ch2 = 0; + digits = 0; + while (isdigit(UChar(*str))) { + if (++digits > 2) { + syntax_error = TRUE; + break; + } + ch2 = ch1; + ch1 = *str++; + if (digits == 2 && ch2 != '0') { + syntax_error = TRUE; + break; + } else if (_nc_strict_bsd) { + if (ch1 > '3') { + syntax_error = TRUE; + break; + } + } else { + bufptr = save_char(bufptr, ch1); + } + } + if (syntax_error) + break; + /* + * Convert %02 to %2 and %03 to %3 + */ + if (ch2 == '0' && !_nc_strict_bsd) { + ch2 = 0; + bufptr[-2] = bufptr[-1]; + *--bufptr = 0; + } + if (_nc_strict_bsd) { + if (ch2 != 0 && ch2 != '0') { + syntax_error = TRUE; + } else if (ch1 < '2') { + ch1 = 'd'; + } + bufptr = save_char(bufptr, ch1); + } + if (strchr("oxX.", *str)) { + syntax_error = TRUE; /* termcap doesn't have octal, hex */ } break; @@ -760,12 +942,16 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz break; /* - * %s isn't in termcap, but it's convenient to pass it through + * %s isn't in termcap, but it is convenient to pass it through * so we can represent things like terminfo pfkey strings in * termcap notation. */ case 's': - bufptr = save_string(bufptr, "%s"); + if (_nc_strict_bsd) { + syntax_error = TRUE; + } else { + bufptr = save_string(bufptr, "%s"); + } break; case 'p': @@ -777,8 +963,9 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz bufptr = save_string(bufptr, "%r"); seentwo++; } - } else if (*str >= '3') - return (0); + } else if (*str >= '3') { + syntax_error = TRUE; + } break; case 'i': @@ -797,11 +984,29 @@ _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameteriz * but that may not be the end of the string. */ assert(str != 0); - if (*str == '\0') + if (str == 0 || *str == '\0') break; } /* endwhile (*str) */ + if (!syntax_error && + myfix > 0 && + ((int) strlen(my_string) - (4 * myfix)) < MIN_TC_FIXUPS) { + while (--myfix >= 0) { + char *p = fixups[myfix].offset + my_string; + *p++ = '^'; + *p++ = (char) (fixups[myfix].ch | '@'); + while ((p[0] = p[2]) != '\0') { + ++p; + } + } + } + + DEBUG_THIS(("... _nc_infotocap %s", + syntax_error + ? "" + : _nc_visbuf(my_string))); + return (syntax_error ? NULL : my_string); } @@ -826,11 +1031,9 @@ main(int argc, char *argv[]) char buf[BUFSIZ]; ++curr_line; - if (fgets(buf, sizeof(buf), stdin) == NULL) + if (fgets(buf, sizeof(buf), stdin) == 0) break; - buflen = strlen(buf); - if (buflen > 0 && buf[buflen - 1] == '\n') - buf[buflen - 1] = '\0'; + buf[strlen(buf) - 1] = '\0'; _nc_set_source(buf); if (tc) { diff --git a/lib/libcurses/tinfo/comp_error.c b/lib/libcurses/tinfo/comp_error.c index 319bd5fb35b..ee4b5b8ba37 100644 --- a/lib/libcurses/tinfo/comp_error.c +++ b/lib/libcurses/tinfo/comp_error.c @@ -1,7 +1,8 @@ -/* $OpenBSD: comp_error.c,v 1.6 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: comp_error.c,v 1.7 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2007 Free Software Foundation, Inc. * + * Copyright 2019-2020,2023 Thomas E. Dickey * + * Copyright 1998-2012,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -43,7 +44,7 @@ #include -MODULE_ID("$Id: comp_error.c,v 1.6 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: comp_error.c,v 1.7 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT_VAR(bool) _nc_suppress_warnings = FALSE; NCURSES_EXPORT_VAR(int) _nc_curr_line = 0; /* current line # in input */ @@ -61,18 +62,28 @@ _nc_get_source(void) NCURSES_EXPORT(void) _nc_set_source(const char *const name) { - SourceName = name; + if (name == NULL) { + free(SourceName); + SourceName = NULL; + } else if (SourceName == NULL) { + SourceName = strdup(name); + } else if (strcmp(name, SourceName)) { + free(SourceName); + SourceName = strdup(name); + } } NCURSES_EXPORT(void) _nc_set_type(const char *const name) { +#define MY_SIZE (size_t) MAX_NAME_SIZE if (TermType == 0) - TermType = typeMalloc(char, MAX_NAME_SIZE + 1); + TermType = typeMalloc(char, MY_SIZE + 1); if (TermType != 0) { TermType[0] = '\0'; - if (name) - strncat(TermType, name, MAX_NAME_SIZE); + if (name) { + _nc_STRNCAT(TermType, name, MY_SIZE, MY_SIZE); + } } } @@ -86,16 +97,16 @@ _nc_get_type(char *name) } #endif if (name != 0) - strlcpy(name, TermType != 0 ? TermType : "", MAX_NAME_SIZE + 1); + _nc_STRCPY(name, TermType != 0 ? TermType : "", MAX_NAME_SIZE); } static NCURSES_INLINE void where_is_problem(void) { fprintf(stderr, "\"%s\"", SourceName ? SourceName : "?"); - if (_nc_curr_line >= 0) + if (_nc_curr_line > 0) fprintf(stderr, ", line %d", _nc_curr_line); - if (_nc_curr_col >= 0) + if (_nc_curr_col > 0) fprintf(stderr, ", col %d", _nc_curr_col); if (TermType != 0 && TermType[0] != '\0') fprintf(stderr, ", terminal '%s'", TermType); @@ -104,7 +115,7 @@ where_is_problem(void) } NCURSES_EXPORT(void) -_nc_warning(const char *const fmt,...) +_nc_warning(const char *const fmt, ...) { va_list argp; @@ -119,7 +130,7 @@ _nc_warning(const char *const fmt,...) } NCURSES_EXPORT(void) -_nc_err_abort(const char *const fmt,...) +_nc_err_abort(const char *const fmt, ...) { va_list argp; @@ -132,7 +143,7 @@ _nc_err_abort(const char *const fmt,...) } NCURSES_EXPORT(void) -_nc_syserr_abort(const char *const fmt,...) +_nc_syserr_abort(const char *const fmt, ...) { va_list argp; @@ -142,14 +153,23 @@ _nc_syserr_abort(const char *const fmt,...) fprintf(stderr, "\n"); va_end(argp); +#if defined(TRACE) || !defined(NDEBUG) /* If we're debugging, try to show where the problem occurred - this * will dump core. */ -#if defined(TRACE) || !defined(NDEBUG) - abort(); -#else + if (_nc_env_access()) + abort(); +#endif /* Dumping core in production code is not a good idea. */ exit(EXIT_FAILURE); -#endif } + +#if NO_LEAKS +NCURSES_EXPORT(void) +_nc_comp_error_leaks(void) +{ + FreeAndNull(SourceName); + FreeAndNull(TermType); +} +#endif diff --git a/lib/libcurses/tinfo/comp_expand.c b/lib/libcurses/tinfo/comp_expand.c index 598592856da..bb295ca4449 100644 --- a/lib/libcurses/tinfo/comp_expand.c +++ b/lib/libcurses/tinfo/comp_expand.c @@ -1,7 +1,8 @@ -/* $OpenBSD: comp_expand.c,v 1.7 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: comp_expand.c,v 1.8 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020-2021,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,7 +30,7 @@ ****************************************************************************/ /**************************************************************************** - * Author: Thomas E. Dickey 1998 * + * Author: Thomas E. Dickey 1998 * ****************************************************************************/ #include @@ -37,7 +38,13 @@ #include #include -MODULE_ID("$Id: comp_expand.c,v 1.7 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: comp_expand.c,v 1.8 2023/10/17 09:52:09 nicm Exp $") + +#if 0 +#define DEBUG_THIS(p) DEBUG(9, p) +#else +#define DEBUG_THIS(p) /* nothing */ +#endif static int trailing_spaces(const char *src) @@ -48,9 +55,10 @@ trailing_spaces(const char *src) } /* this deals with differences over whether 0x7f and 0x80..0x9f are controls */ -#define REALCTL(s) (UChar(*(s)) < 127 && iscntrl(UChar(*(s)))) #define REALPRINT(s) (UChar(*(s)) < 127 && isprint(UChar(*(s)))) +#define P_LIMIT(p) (length - (size_t)(p)) + NCURSES_EXPORT(char *) _nc_tic_expand(const char *srcp, bool tic_format, int numbers) { @@ -59,24 +67,32 @@ _nc_tic_expand(const char *srcp, bool tic_format, int numbers) int bufp; const char *str = VALID_STRING(srcp) ? srcp : "\0\0"; - bool islong = (strlen(str) > 3); size_t need = (2 + strlen(str)) * 4; int ch; + int octals = 0; + struct { + int ch; + int offset; + } fixups[MAX_TC_FIXUPS]; -#if NO_LEAKS if (srcp == 0) { +#if NO_LEAKS if (buffer != 0) { FreeAndNull(buffer); length = 0; } +#endif return 0; } -#endif if (buffer == 0 || need > length) { if ((buffer = typeRealloc(char, length = need, buffer)) == 0) return 0; } + DEBUG_THIS(("_nc_tic_expand %s:%s:%s", + tic_format ? "ti" : "tc", + numbers ? "#" : "", + _nc_visbuf(srcp))); bufp = 0; while ((ch = UChar(*str)) != 0) { if (ch == '%' && REALPRINT(str + 1)) { @@ -92,8 +108,9 @@ _nc_tic_expand(const char *srcp, bool tic_format, int numbers) && str[1] != '\\' && REALPRINT(str + 1) && str[2] == S_QUOTE) { - snprintf(buffer + bufp, length - bufp, "{%d}", str[1]); - bufp += strlen(buffer + bufp); + _nc_SPRINTF(buffer + bufp, _nc_SLIMIT(P_LIMIT(bufp)) + "{%d}", str[1]); + bufp += (int) strlen(buffer + bufp); str += 2; } else { buffer[bufp++] = *str; @@ -114,7 +131,6 @@ _nc_tic_expand(const char *srcp, bool tic_format, int numbers) if (dst != 0 && *dst == R_BRACE && value < 127 - && value != '\\' /* FIXME */ && isprint((int) value)) { ch = (int) value; buffer[bufp++] = S_QUOTE; @@ -132,6 +148,8 @@ _nc_tic_expand(const char *srcp, bool tic_format, int numbers) } break; default: + if (*str == ',') /* minitel1 uses this */ + buffer[bufp++] = '\\'; buffer[bufp++] = *str; break; } @@ -148,47 +166,64 @@ _nc_tic_expand(const char *srcp, bool tic_format, int numbers) trailing_spaces(str))) { buffer[bufp++] = '\\'; buffer[bufp++] = 's'; - } else if ((ch == ',' || ch == ':' || ch == '^') && tic_format) { + } else if ((ch == ',' || ch == '^') && tic_format) { buffer[bufp++] = '\\'; buffer[bufp++] = (char) ch; } else if (REALPRINT(str) && (ch != ',' - && ch != ':' + && !(ch == ':' && !tic_format) && !(ch == '!' && !tic_format) && ch != '^')) buffer[bufp++] = (char) ch; -#if 0 /* FIXME: this would be more readable (in fact the whole 'islong' logic should be removed) */ - else if (ch == '\b') { - buffer[bufp++] = '\\'; - buffer[bufp++] = 'b'; - } else if (ch == '\f') { - buffer[bufp++] = '\\'; - buffer[bufp++] = 'f'; - } else if (ch == '\t' && islong) { - buffer[bufp++] = '\\'; - buffer[bufp++] = 't'; - } -#endif - else if (ch == '\r' && (islong || (strlen(srcp) > 2 && str[1] == '\0'))) { + else if (ch == '\r') { buffer[bufp++] = '\\'; buffer[bufp++] = 'r'; - } else if (ch == '\n' && islong) { + } else if (ch == '\n') { buffer[bufp++] = '\\'; buffer[bufp++] = 'n'; } #define UnCtl(c) ((c) + '@') - else if (REALCTL(str) && ch != '\\' - && (!islong || isdigit(UChar(str[1])))) { - (void) snprintf(buffer + bufp, length - bufp, "^%c", UnCtl(ch)); - bufp += strlen(buffer + bufp); + else if (UChar(ch) < 32 + && isdigit(UChar(str[1]))) { + _nc_SPRINTF(&buffer[bufp], _nc_SLIMIT(P_LIMIT(bufp)) + "^%c", UnCtl(ch)); + bufp += 2; } else { - (void) snprintf(buffer + bufp, length - bufp, "\\%03o", ch); - bufp += strlen(buffer + bufp); + _nc_SPRINTF(&buffer[bufp], _nc_SLIMIT(P_LIMIT(bufp)) + "\\%03o", ch); + if ((octals < MAX_TC_FIXUPS) && + ((tic_format && (ch == 127)) || ch < 32)) { + fixups[octals].ch = UChar(ch); + fixups[octals].offset = bufp; + ++octals; + } + bufp += 4; } str++; } buffer[bufp] = '\0'; + + /* + * If most of a short string is ASCII control characters, reformat the + * string to show those in up-arrow format. For longer strings, it is + * more likely that the characters are just binary coding. + * + * If we're formatting termcap, just use the shorter format (up-arrows). + */ + if (octals != 0 && (!tic_format || (bufp - (4 * octals)) < MIN_TC_FIXUPS)) { + while (--octals >= 0) { + char *p = buffer + fixups[octals].offset; + *p++ = '^'; + *p++ = (char) ((fixups[octals].ch == 127) + ? '?' + : (fixups[octals].ch + (int) '@')); + while ((p[0] = p[2]) != 0) { + ++p; + } + } + } + DEBUG_THIS(("... %s", _nc_visbuf(buffer))); return (buffer); } diff --git a/lib/libcurses/tinfo/comp_hash.c b/lib/libcurses/tinfo/comp_hash.c index 87856a7e040..60af8e40237 100644 --- a/lib/libcurses/tinfo/comp_hash.c +++ b/lib/libcurses/tinfo/comp_hash.c @@ -1,7 +1,8 @@ -/* $OpenBSD: comp_hash.c,v 1.8 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: comp_hash.c,v 1.9 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2019-2020,2023 Thomas E. Dickey * + * Copyright 1998-2008,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -46,110 +47,37 @@ #include #include -#ifdef MAIN_PROGRAM -#include -#undef DEBUG -#define DEBUG(level, params) /*nothing */ -#endif - -MODULE_ID("$Id: comp_hash.c,v 1.8 2010/01/12 23:22:06 nicm Exp $") - -static int hash_function(const char *); +MODULE_ID("$Id: comp_hash.c,v 1.9 2023/10/17 09:52:09 nicm Exp $") /* - * _nc_make_hash_table() - * - * Takes the entries in table[] and hashes them into hash_table[] - * by name. There are CAPTABSIZE entries in table[] and HASHTABSIZE - * slots in hash_table[]. - * + * Finds the entry for the given string in the hash table if present. + * Returns a pointer to the entry in the table or 0 if not found. */ - -#ifdef MAIN_PROGRAM - -#undef MODULE_ID -#define MODULE_ID(id) /*nothing */ -#include - -static void -_nc_make_hash_table(struct name_table_entry *table, - short *hash_table) -{ - short i; - int hashvalue; - int collisions = 0; - - for (i = 0; i < HASHTABSIZE; i++) { - hash_table[i] = -1; - } - for (i = 0; i < CAPTABSIZE; i++) { - hashvalue = hash_function(table[i].nte_name); - - if (hash_table[hashvalue] >= 0) - collisions++; - - if (hash_table[hashvalue] != 0) - table[i].nte_link = hash_table[hashvalue]; - hash_table[hashvalue] = i; - } - - DEBUG(4, ("Hash table complete: %d collisions out of %d entries", - collisions, CAPTABSIZE)); -} -#endif - -/* - * int hash_function(string) - * - * Computes the hashing function on the given string. - * - * The current hash function is the sum of each consectutive pair - * of characters, taken as two-byte integers, mod HASHTABSIZE. - * - */ - -static int -hash_function(const char *string) -{ - long sum = 0; - - DEBUG(9, ("hashing %s", string)); - while (*string) { - sum += (long) (*string + (*(string + 1) << 8)); - string++; - } - - DEBUG(9, ("sum is %ld", sum)); - return (int) (sum % HASHTABSIZE); -} - -/* - * struct name_table_entry * - * find_entry(string) - * - * Finds the entry for the given string in the hash table if present. - * Returns a pointer to the entry in the table or 0 if not found. - * - */ - -#ifndef MAIN_PROGRAM NCURSES_EXPORT(struct name_table_entry const *) _nc_find_entry(const char *string, - const short *hash_table) + const HashValue * hash_table) { + bool termcap = (hash_table != _nc_get_hash_table(FALSE)); + const HashData *data = _nc_get_hash_info(termcap); int hashvalue; struct name_table_entry const *ptr = 0; struct name_table_entry const *real_table; - hashvalue = hash_function(string); + hashvalue = data->hash_of(string); + + if (hashvalue >= 0 + && (unsigned) hashvalue < data->table_size + && data->table_data[hashvalue] >= 0) { - if (hash_table[hashvalue] >= 0) { - real_table = _nc_get_table(hash_table != _nc_get_hash_table(FALSE)); - ptr = real_table + hash_table[hashvalue]; - while (strcmp(ptr->nte_name, string) != 0) { - if (ptr->nte_link < 0) - return 0; - ptr = real_table + (ptr->nte_link + hash_table[HASHTABSIZE]); + real_table = _nc_get_table(termcap); + ptr = real_table + data->table_data[hashvalue]; + while (!data->compare_names(ptr->nte_name, string)) { + if (ptr->nte_link < 0) { + ptr = 0; + break; + } + ptr = real_table + (ptr->nte_link + + data->table_data[data->table_size]); } } @@ -157,216 +85,69 @@ _nc_find_entry(const char *string, } /* - * struct name_table_entry * - * find_type_entry(string, type, table) + * Finds the entry for the given name with the given type in the given table if + * present (as distinct from _nc_find_entry, which finds the last entry + * regardless of type). * - * Finds the first entry for the given name with the given type in the - * given table if present (as distinct from find_entry, which finds the - * the last entry regardless of type). You can use this if you detect - * a name clash. It's slower, though. Returns a pointer to the entry - * in the table or 0 if not found. + * Returns a pointer to the entry in the table or 0 if not found. */ - NCURSES_EXPORT(struct name_table_entry const *) _nc_find_type_entry(const char *string, int type, - const struct name_table_entry *table) -{ - struct name_table_entry const *ptr; - - for (ptr = table; ptr < table + CAPTABSIZE; ptr++) { - if (ptr->nte_type == type && strcmp(string, ptr->nte_name) == 0) - return (ptr); - } - - return ((struct name_table_entry *) NULL); -} -#endif - -#ifdef MAIN_PROGRAM -/* - * This filter reads from standard input a list of tab-delimited columns, - * (e.g., from Caps.filtered) computes the hash-value of a specified column and - * writes the hashed tables to standard output. - * - * By compiling the hash table at build time, we're able to make the entire - * set of terminfo and termcap tables readonly (and also provide some runtime - * performance enhancement). - */ - -#define MAX_COLUMNS BUFSIZ /* this _has_ to be worst-case */ - -static char ** -parse_columns(char *buffer) + bool termcap) { - static char **list; - - int col = 0; - - if (list == 0 && (list = typeCalloc(char *, MAX_COLUMNS)) == 0) - return (0); - - if (*buffer != '#') { - while (*buffer != '\0') { - char *s; - for (s = buffer; (*s != '\0') && !isspace(UChar(*s)); s++) - /*EMPTY */ ; - if (s != buffer) { - char mark = *s; - *s = '\0'; - if ((s - buffer) > 1 - && (*buffer == '"') - && (s[-1] == '"')) { /* strip the quotes */ - assert(s > buffer + 1); - s[-1] = '\0'; - buffer++; - } - list[col] = buffer; - col++; - if (mark == '\0') + struct name_table_entry const *ptr = NULL; + const HashData *data = _nc_get_hash_info(termcap); + int hashvalue = data->hash_of(string); + + if (hashvalue >= 0 + && (unsigned) hashvalue < data->table_size + && data->table_data[hashvalue] >= 0) { + const struct name_table_entry *const table = _nc_get_table(termcap); + + if (table != NULL) { + ptr = table + data->table_data[hashvalue]; + while (ptr->nte_type != type + || !data->compare_names(ptr->nte_name, string)) { + if (ptr->nte_link < 0) { + ptr = 0; break; - while (*++s && isspace(UChar(*s))) - /*EMPTY */ ; - buffer = s; - } else - break; + } + ptr = table + (ptr->nte_link + data->table_data[data->table_size]); + } } } - return col ? list : 0; + + return ptr; } -int -main(int argc, char **argv) +#if NCURSES_XNAMES +NCURSES_EXPORT(struct user_table_entry const *) +_nc_find_user_entry(const char *string) { - struct name_table_entry *name_table = typeCalloc(struct - name_table_entry, CAPTABSIZE); - short *hash_table = typeCalloc(short, HASHTABSIZE); - const char *root_name = ""; - int column = 0; - int bigstring = 0; - int n; - char buffer[BUFSIZ]; - - static const char *typenames[] = - {"BOOLEAN", "NUMBER", "STRING"}; - - short BoolCount = 0; - short NumCount = 0; - short StrCount = 0; - - /* The first argument is the column-number (starting with 0). - * The second is the root name of the tables to generate. - */ - if (argc <= 3 - || (column = atoi(argv[1])) <= 0 - || (column >= MAX_COLUMNS) - || *(root_name = argv[2]) == 0 - || (bigstring = atoi(argv[3])) < 0 - || name_table == 0 - || hash_table == 0) { - fprintf(stderr, "usage: make_hash column root_name bigstring\n"); - exit(EXIT_FAILURE); - } + const HashData *data = _nc_get_hash_user(); + int hashvalue; + struct user_table_entry const *ptr = 0; + struct user_table_entry const *real_table; - /* - * Read the table into our arrays. - */ - for (n = 0; (n < CAPTABSIZE) && fgets(buffer, BUFSIZ, stdin);) { - char **list, *nlp = strchr(buffer, '\n'); - if (nlp) - *nlp = '\0'; - list = parse_columns(buffer); - if (list == 0) /* blank or comment */ - continue; - name_table[n].nte_link = -1; /* end-of-hash */ - name_table[n].nte_name = strdup(list[column]); - if (!strcmp(list[2], "bool")) { - name_table[n].nte_type = BOOLEAN; - name_table[n].nte_index = BoolCount++; - } else if (!strcmp(list[2], "num")) { - name_table[n].nte_type = NUMBER; - name_table[n].nte_index = NumCount++; - } else if (!strcmp(list[2], "str")) { - name_table[n].nte_type = STRING; - name_table[n].nte_index = StrCount++; - } else { - fprintf(stderr, "Unknown type: %s\n", list[2]); - exit(EXIT_FAILURE); - } - n++; - } - _nc_make_hash_table(name_table, hash_table); + hashvalue = data->hash_of(string); - /* - * Write the compiled tables to standard output - */ - if (bigstring) { - int len = 0; - int nxt; + if (hashvalue >= 0 + && (unsigned) hashvalue < data->table_size + && data->table_data[hashvalue] >= 0) { - printf("static const char %s_names_text[] = \\\n", root_name); - for (n = 0; n < CAPTABSIZE; n++) { - nxt = (int) strlen(name_table[n].nte_name) + 5; - if (nxt + len > 72) { - printf("\\\n"); - len = 0; + real_table = _nc_get_userdefs_table(); + ptr = real_table + data->table_data[hashvalue]; + while (!data->compare_names(ptr->ute_name, string)) { + if (ptr->ute_link < 0) { + ptr = 0; + break; } - printf("\"%s\\0\" ", name_table[n].nte_name); - len += nxt; - } - printf(";\n\n"); - - len = 0; - printf("static name_table_data const %s_names_data[] =\n", - root_name); - printf("{\n"); - for (n = 0; n < CAPTABSIZE; n++) { - printf("\t{ %15d,\t%10s,\t%3d, %3d }%c\n", - len, - typenames[name_table[n].nte_type], - name_table[n].nte_index, - name_table[n].nte_link, - n < CAPTABSIZE - 1 ? ',' : ' '); - len += (int) strlen(name_table[n].nte_name) + 1; - } - printf("};\n\n"); - printf("static struct name_table_entry *_nc_%s_table = 0;\n\n", root_name); - } else { - - printf("static struct name_table_entry %s _nc_%s_table[] =\n", - bigstring ? "" : "const", - root_name); - printf("{\n"); - for (n = 0; n < CAPTABSIZE; n++) { - snprintf(buffer, sizeof(buffer), "\"%s\"", - name_table[n].nte_name); - printf("\t{ %15s,\t%10s,\t%3d, %3d }%c\n", - buffer, - typenames[name_table[n].nte_type], - name_table[n].nte_index, - name_table[n].nte_link, - n < CAPTABSIZE - 1 ? ',' : ' '); + ptr = real_table + (ptr->ute_link + + data->table_data[data->table_size]); } - printf("};\n\n"); } - printf("static const short _nc_%s_hash_table[%d] =\n", - root_name, - HASHTABSIZE + 1); - printf("{\n"); - for (n = 0; n < HASHTABSIZE; n++) { - printf("\t%3d,\n", hash_table[n]); - } - printf("\t0\t/* base-of-table */\n"); - printf("};\n\n"); - - printf("#if (BOOLCOUNT!=%d)||(NUMCOUNT!=%d)||(STRCOUNT!=%d)\n", - BoolCount, NumCount, StrCount); - printf("#error\t--> term.h and comp_captab.c disagree about the <--\n"); - printf("#error\t--> numbers of booleans, numbers and/or strings <--\n"); - printf("#endif\n\n"); - - free(hash_table); - return EXIT_SUCCESS; + return (ptr); } -#endif +#endif /* NCURSES_XNAMES */ diff --git a/lib/libcurses/tinfo/comp_parse.c b/lib/libcurses/tinfo/comp_parse.c index 1cf53acb120..de263b2bb2b 100644 --- a/lib/libcurses/tinfo/comp_parse.c +++ b/lib/libcurses/tinfo/comp_parse.c @@ -1,7 +1,8 @@ -/* $OpenBSD: comp_parse.c,v 1.12 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: comp_parse.c,v 1.13 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -37,15 +38,10 @@ /* * comp_parse.c -- parser driver loop and use handling. * - * _nc_read_entry_source(FILE *, literal, bool, bool (*hook)()) - * _nc_resolve_uses2(void) - * _nc_free_entries(void) - * * Use this code by calling _nc_read_entry_source() on as many source * files as you like (either terminfo or termcap syntax). If you * want use-resolution, call _nc_resolve_uses2(). To free the list * storage, do _nc_free_entries(). - * */ #include @@ -53,23 +49,23 @@ #include #include -#include -MODULE_ID("$Id: comp_parse.c,v 1.12 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: comp_parse.c,v 1.13 2023/10/17 09:52:09 nicm Exp $") -static void sanity_check2(TERMTYPE *, bool); -NCURSES_IMPEXP void NCURSES_API(*_nc_check_termtype2) (TERMTYPE *, bool) = sanity_check2; +static void sanity_check2(TERMTYPE2 *, bool); +NCURSES_IMPEXP void (NCURSES_API *_nc_check_termtype2) (TERMTYPE2 *, bool) = sanity_check2; -/* obsolete: 20040705 */ -static void sanity_check(TERMTYPE *); -NCURSES_IMPEXP void NCURSES_API(*_nc_check_termtype) (TERMTYPE *) = sanity_check; +static void fixup_acsc(TERMTYPE2 *, int); static void enqueue(ENTRY * ep) /* add an entry to the in-core list */ { - ENTRY *newp = _nc_copy_entry(ep); + ENTRY *newp; + DEBUG(2, (T_CALLED("enqueue(ep=%p)"), (void *) ep)); + + newp = _nc_copy_entry(ep); if (newp == 0) _nc_err_abort(MSG_NO_MEMORY); @@ -79,43 +75,138 @@ enqueue(ENTRY * ep) newp->next = 0; if (newp->last) newp->last->next = newp; + DEBUG(2, (T_RETURN(""))); } +#define NAMEBUFFER_SIZE (MAX_NAME_SIZE + 2) + static char * -force_bar(char *dst, char *src, size_t siz) +force_bar(char *dst, char *src) { if (strchr(src, '|') == 0) { - size_t len; - - len = strlcpy(dst, src, siz); - if (len > siz - 2) - len = siz - 2; - dst[len++] = '|'; - dst[len] = '\0'; - src = dst; + size_t len = strlen(src); + if (len > MAX_NAME_SIZE) + len = MAX_NAME_SIZE; + _nc_STRNCPY(dst, src, MAX_NAME_SIZE); + _nc_STRCPY(dst + len, "|", NAMEBUFFER_SIZE - len); + src = dst; } return src; } +#define ForceBar(dst, src) ((strchr(src, '|') == 0) ? force_bar(dst, src) : src) -NCURSES_EXPORT(bool) -_nc_entry_match(char *n1, char *n2) -/* do any of the aliases in a pair of terminal names match? */ +#if NCURSES_USE_TERMCAP && NCURSES_XNAMES +static char * +skip_index(char *name) +{ + char *bar = strchr(name, '|'); + + if (bar != 0 && (bar - name) == 2) + name = bar + 1; + + return name; +} +#endif + +static bool +check_collisions(char *n1, char *n2, int counter) { char *pstart, *qstart, *pend, *qend; - char nc1[MAX_NAME_SIZE + 2], nc2[MAX_NAME_SIZE + 2]; + char nc1[NAMEBUFFER_SIZE]; + char nc2[NAMEBUFFER_SIZE]; - n1 = force_bar(nc1, n1, sizeof(nc1)); - n2 = force_bar(nc2, n2, sizeof(nc2)); + n1 = ForceBar(nc1, n1); + n2 = ForceBar(nc2, n2); - for (pstart = n1; (pend = strchr(pstart, '|')); pstart = pend + 1) - for (qstart = n2; (qend = strchr(qstart, '|')); qstart = qend + 1) +#if NCURSES_USE_TERMCAP && NCURSES_XNAMES + if ((_nc_syntax == SYN_TERMCAP) && _nc_user_definable) { + n1 = skip_index(n1); + n2 = skip_index(n2); + } +#endif + + for (pstart = n1; (pend = strchr(pstart, '|')); pstart = pend + 1) { + for (qstart = n2; (qend = strchr(qstart, '|')); qstart = qend + 1) { if ((pend - pstart == qend - qstart) - && memcmp(pstart, qstart, (size_t) (pend - pstart)) == 0) + && memcmp(pstart, qstart, (size_t) (pend - pstart)) == 0) { + if (counter > 0) + (void) fprintf(stderr, "Name collision '%.*s' between\n", + (int) (pend - pstart), pstart); return (TRUE); + } + } + } return (FALSE); } +static char * +next_name(char *name) +{ + if (*name != '\0') + ++name; + return name; +} + +static char * +name_ending(char *name) +{ + if (*name == '\0') { + name = 0; + } else { + while (*name != '\0' && *name != '|') + ++name; + } + return name; +} + +/* + * Essentially, find the conflict reported in check_collisions() and remove + * it from the second name, unless that happens to be the last alias. + */ +static bool +remove_collision(char *n1, char *n2) +{ + char *p2 = n2; + char *pstart, *qstart, *pend, *qend; + bool removed = FALSE; + +#if NCURSES_USE_TERMCAP && NCURSES_XNAMES + if ((_nc_syntax == SYN_TERMCAP) && _nc_user_definable) { + n1 = skip_index(n1); + p2 = n2 = skip_index(n2); + } +#endif + + for (pstart = n1; (pend = name_ending(pstart)); pstart = next_name(pend)) { + for (qstart = n2; (qend = name_ending(qstart)); qstart = next_name(qend)) { + if ((pend - pstart == qend - qstart) + && memcmp(pstart, qstart, (size_t) (pend - pstart)) == 0) { + if (qstart != p2 || *qend == '|') { + if (*qend == '|') + ++qend; + while ((*qstart++ = *qend++) != '\0') ; + fprintf(stderr, "...now\t%s\n", p2); + removed = TRUE; + } else { + fprintf(stderr, "Cannot remove alias '%.*s'\n", + (int) (qend - qstart), qstart); + } + break; + } + } + } + + return removed; +} + +/* do any of the aliases in a pair of terminal names match? */ +NCURSES_EXPORT(bool) +_nc_entry_match(char *n1, char *n2) +{ + return check_collisions(n1, n2, 0); +} + /**************************************************************************** * * Entry compiler and resolution logic @@ -132,6 +223,12 @@ _nc_read_entry_source(FILE *fp, char *buf, bool oldsuppress = _nc_suppress_warnings; int immediate = 0; + DEBUG(2, + (T_CALLED("_nc_read_entry_source(" + "file=%p, buf=%p, literal=%d, silent=%d, hook=%#" + PRIxPTR ")"), + (void *) fp, buf, literal, silent, CASTxPTR(hook))); + if (silent) _nc_suppress_warnings = TRUE; /* shut the lexer up, too */ @@ -159,38 +256,159 @@ _nc_read_entry_source(FILE *fp, char *buf, FreeIfNeeded(thisentry.tterm.Booleans); FreeIfNeeded(thisentry.tterm.Numbers); FreeIfNeeded(thisentry.tterm.Strings); + FreeIfNeeded(thisentry.tterm.str_table); #if NCURSES_XNAMES FreeIfNeeded(thisentry.tterm.ext_Names); + FreeIfNeeded(thisentry.tterm.ext_str_table); #endif } } if (_nc_tail) { /* set up the head pointer */ - for (_nc_head = _nc_tail; _nc_head->last; _nc_head = _nc_head->last) - continue; + for (_nc_head = _nc_tail; _nc_head->last; _nc_head = _nc_head->last) { + /* EMPTY */ ; + } - DEBUG(1, ("head = %s", _nc_head->tterm.term_names)); - DEBUG(1, ("tail = %s", _nc_tail->tterm.term_names)); + DEBUG(2, ("head = %s", _nc_head->tterm.term_names)); + DEBUG(2, ("tail = %s", _nc_tail->tterm.term_names)); } #ifdef TRACE else if (!immediate) - DEBUG(1, ("no entries parsed")); + DEBUG(2, ("no entries parsed")); #endif _nc_suppress_warnings = oldsuppress; + DEBUG(2, (T_RETURN(""))); +} + +#if 0 && NCURSES_XNAMES +static unsigned +find_capname(TERMTYPE2 *p, const char *name) +{ + unsigned num_names = NUM_EXT_NAMES(p); + unsigned n; + if (name != 0) { + for (n = 0; n < num_names; ++n) { + if (!strcmp(p->ext_Names[n], name)) + break; + } + } else { + n = num_names + 1; + } + return n; } +static int +extended_captype(TERMTYPE2 *p, unsigned which) +{ + int result = UNDEF; + unsigned limit = 0; + limit += p->ext_Booleans; + if (limit != 0 && which < limit) { + result = BOOLEAN; + } else { + limit += p->ext_Numbers; + if (limit != 0 && which < limit) { + result = NUMBER; + } else { + limit += p->ext_Strings; + if (limit != 0 && which < limit) { + result = ((p->Strings[STRCOUNT + which] != CANCELLED_STRING) + ? STRING + : CANCEL); + } else if (which >= limit) { + result = CANCEL; + } + } + } + return result; +} + +static const char * +name_of_captype(int which) +{ + const char *result = "?"; + switch (which) { + case BOOLEAN: + result = "boolean"; + break; + case NUMBER: + result = "number"; + break; + case STRING: + result = "string"; + break; + } + return result; +} + +#define valid_TERMTYPE2(p) \ + ((p) != 0 && \ + (p)->term_names != 0 && \ + (p)->ext_Names != 0) + +/* + * Disallow changing the type of an extended capability when doing a "use" + * if one or the other is a string. + */ +static int +invalid_merge(TERMTYPE2 *to, TERMTYPE2 *from) +{ + int rc = FALSE; + if (valid_TERMTYPE2(to) + && valid_TERMTYPE2(from)) { + char *to_name = _nc_first_name(to->term_names); + char *from_name = strdup(_nc_first_name(from->term_names)); + unsigned num_names = NUM_EXT_NAMES(from); + unsigned n; + + for (n = 0; n < num_names; ++n) { + const char *capname = from->ext_Names[n]; + int tt = extended_captype(to, find_capname(to, capname)); + int tf = extended_captype(from, n); + + if (tt <= STRING + && tf <= STRING + && (tt == STRING) != (tf == STRING)) { + if (from_name != 0 && strcmp(to_name, from_name)) { + _nc_warning("merge of %s to %s changes type of %s from %s to %s", + from_name, + to_name, + from->ext_Names[n], + name_of_captype(tf), + name_of_captype(tt)); + } else { + _nc_warning("merge of %s changes type of %s from %s to %s", + to_name, + from->ext_Names[n], + name_of_captype(tf), + name_of_captype(tt)); + } + rc = TRUE; + } + } + free(from_name); + } + return rc; +} +#define validate_merge(p, q) \ + if (invalid_merge(&((p)->tterm), &((q)->tterm))) \ + return FALSE +#else +#define validate_merge(p, q) /* nothing */ +#endif + NCURSES_EXPORT(int) _nc_resolve_uses2(bool fullresolve, bool literal) /* try to resolve all use capabilities */ { ENTRY *qp, *rp, *lastread = 0; bool keepgoing; - unsigned i; + unsigned i, j; int unresolved, total_unresolved, multiples; - DEBUG(2, ("RESOLUTION BEGINNING")); + DEBUG(2, (T_CALLED("_nc_resolve_uses2"))); /* * Check for multiple occurrences of the same name. @@ -199,24 +417,26 @@ _nc_resolve_uses2(bool fullresolve, bool literal) for_entry_list(qp) { int matchcount = 0; - for_entry_list(rp) { + for_entry_list2(rp, qp->next) { if (qp > rp - && _nc_entry_match(qp->tterm.term_names, rp->tterm.term_names)) { - matchcount++; - if (matchcount == 1) { - (void) fprintf(stderr, "Name collision between %s", - _nc_first_name(qp->tterm.term_names)); - multiples++; + && check_collisions(qp->tterm.term_names, + rp->tterm.term_names, + matchcount + 1)) { + if (!matchcount++) { + (void) fprintf(stderr, "\t%s\n", rp->tterm.term_names); + } + (void) fprintf(stderr, "and\t%s\n", qp->tterm.term_names); + if (!remove_collision(rp->tterm.term_names, + qp->tterm.term_names)) { + ++multiples; } - if (matchcount >= 1) - (void) fprintf(stderr, " %s", _nc_first_name(rp->tterm.term_names)); } } - if (matchcount >= 1) - (void) putc('\n', stderr); } - if (multiples > 0) + if (multiples > 0) { + DEBUG(2, (T_RETURN("false"))); return (FALSE); + } DEBUG(2, ("NO MULTIPLE NAME OCCURRENCES")); @@ -233,6 +453,9 @@ _nc_resolve_uses2(bool fullresolve, bool literal) char *lookfor = qp->uses[i].name; long lookline = qp->uses[i].line; + if (lookfor == 0) + continue; + foundit = FALSE; _nc_set_type(child); @@ -241,27 +464,35 @@ _nc_resolve_uses2(bool fullresolve, bool literal) for_entry_list(rp) { if (rp != qp && _nc_name_match(rp->tterm.term_names, lookfor, "|")) { - DEBUG(2, ("%s: resolving use=%s (in core)", - child, lookfor)); + DEBUG(2, ("%s: resolving use=%s %p (in core)", + child, lookfor, lookfor)); qp->uses[i].link = rp; foundit = TRUE; + + /* verify that there are no earlier uses */ + for (j = 0; j < i; ++j) { + if (qp->uses[j].link != NULL + && !strcmp(qp->uses[j].link->tterm.term_names, + rp->tterm.term_names)) { + _nc_warning("duplicate use=%s", lookfor); + break; + } + } } } /* if that didn't work, try to merge in a compiled entry */ if (!foundit) { - TERMTYPE thisterm; + TERMTYPE2 thisterm; char filename[PATH_MAX]; memset(&thisterm, 0, sizeof(thisterm)); - if (_nc_read_entry(lookfor, filename, &thisterm) == 1) { + if (_nc_read_entry2(lookfor, filename, &thisterm) == 1) { DEBUG(2, ("%s: resolving use=%s (compiled)", child, lookfor)); - rp = typeMalloc(ENTRY, 1); - if (rp == 0) - _nc_err_abort(MSG_NO_MEMORY); + TYPE_MALLOC(ENTRY, 1, rp); rp->tterm = thisterm; rp->nuses = 0; rp->next = lastread; @@ -269,6 +500,16 @@ _nc_resolve_uses2(bool fullresolve, bool literal) qp->uses[i].link = rp; foundit = TRUE; + + /* verify that there are no earlier uses */ + for (j = 0; j < i; ++j) { + if (qp->uses[j].link != NULL + && !strcmp(qp->uses[j].link->tterm.term_names, + rp->tterm.term_names)) { + _nc_warning("duplicate use=%s", lookfor); + break; + } + } } } @@ -277,7 +518,7 @@ _nc_resolve_uses2(bool fullresolve, bool literal) unresolved++; total_unresolved++; - _nc_curr_line = lookline; + _nc_curr_line = (int) lookline; _nc_warning("resolution of use=%s failed", lookfor); qp->uses[i].link = 0; } @@ -286,6 +527,7 @@ _nc_resolve_uses2(bool fullresolve, bool literal) if (total_unresolved) { /* free entries read in off disk */ _nc_free_entries(lastread); + DEBUG(2, (T_RETURN("false"))); return (FALSE); } @@ -298,25 +540,28 @@ _nc_resolve_uses2(bool fullresolve, bool literal) */ if (fullresolve) { do { - TERMTYPE merged; + ENTRY merged; keepgoing = FALSE; for_entry_list(qp) { if (qp->nuses > 0) { - DEBUG(2, ("%s: attempting merge", - _nc_first_name(qp->tterm.term_names))); + DEBUG(2, ("%s: attempting merge of %d entries", + _nc_first_name(qp->tterm.term_names), + qp->nuses)); /* * If any of the use entries we're looking for is * incomplete, punt. We'll catch this entry on a * subsequent pass. */ - for (i = 0; i < qp->nuses; i++) - if (qp->uses[i].link->nuses) { + for (i = 0; i < qp->nuses; i++) { + if (qp->uses[i].link + && qp->uses[i].link->nuses) { DEBUG(2, ("%s: use entry %d unresolved", _nc_first_name(qp->tterm.term_names), i)); goto incomplete; } + } /* * First, make sure there is no garbage in the @@ -324,20 +569,24 @@ _nc_resolve_uses2(bool fullresolve, bool literal) * the merged entry the name field and string * table pointer. */ - _nc_copy_termtype(&merged, &(qp->tterm)); + _nc_copy_termtype2(&(merged.tterm), &(qp->tterm)); /* * Now merge in each use entry in the proper * (reverse) order. */ - for (; qp->nuses; qp->nuses--) - _nc_merge_entry(&merged, - &qp->uses[qp->nuses - 1].link->tterm); + for (; qp->nuses; qp->nuses--) { + int n = (int) (qp->nuses - 1); + validate_merge(&merged, qp->uses[n].link); + _nc_merge_entry(&merged, qp->uses[n].link); + free(qp->uses[n].name); + } /* * Now merge in the original entry. */ - _nc_merge_entry(&merged, &qp->tterm); + validate_merge(&merged, qp); + _nc_merge_entry(&merged, qp); /* * Replace the original entry with the merged one. @@ -345,10 +594,12 @@ _nc_resolve_uses2(bool fullresolve, bool literal) FreeIfNeeded(qp->tterm.Booleans); FreeIfNeeded(qp->tterm.Numbers); FreeIfNeeded(qp->tterm.Strings); + FreeIfNeeded(qp->tterm.str_table); #if NCURSES_XNAMES FreeIfNeeded(qp->tterm.ext_Names); + FreeIfNeeded(qp->tterm.ext_str_table); #endif - qp->tterm = merged; + qp->tterm = merged.tterm; _nc_wrap_entry(qp, TRUE); /* @@ -366,36 +617,57 @@ _nc_resolve_uses2(bool fullresolve, bool literal) DEBUG(2, ("MERGES COMPLETED OK")); } - /* - * We'd like to free entries read in off disk at this point, but can't. - * The merge_entry() code doesn't copy the strings in the use entries, - * it just aliases them. If this ever changes, do a - * free_entries(lastread) here. - */ - DEBUG(2, ("RESOLUTION FINISHED")); - if (fullresolve) - if (_nc_check_termtype != 0) { - _nc_curr_col = -1; - for_entry_list(qp) { - _nc_curr_line = qp->startline; - _nc_set_type(_nc_first_name(qp->tterm.term_names)); + if (fullresolve) { + _nc_curr_col = -1; + for_entry_list(qp) { + _nc_curr_line = (int) qp->startline; + _nc_set_type(_nc_first_name(qp->tterm.term_names)); + /* + * tic overrides this function pointer to provide more verbose + * checking. + */ + if (_nc_check_termtype2 != sanity_check2) { + SCREEN *save_SP = SP; + SCREEN fake_sp; + TERMINAL fake_tm; + TERMINAL *save_tm = cur_term; + + /* + * Setup so that tic can use ordinary terminfo interface to + * obtain capability information. + */ + memset(&fake_sp, 0, sizeof(fake_sp)); + memset(&fake_tm, 0, sizeof(fake_tm)); + fake_sp._term = &fake_tm; + TerminalType(&fake_tm) = qp->tterm; + _nc_set_screen(&fake_sp); + set_curterm(&fake_tm); + _nc_check_termtype2(&qp->tterm, literal); + + /* + * Checking calls tparm, which can allocate memory. Fix leaks. + */ +#define TPS(name) fake_tm.tparm_state.name + FreeAndNull(TPS(out_buff)); + FreeAndNull(TPS(fmt_buff)); +#undef TPS + + _nc_set_screen(save_SP); + set_curterm(save_tm); + } else { + fixup_acsc(&qp->tterm, literal); } - DEBUG(2, ("SANITY CHECK FINISHED")); } + DEBUG(2, ("SANITY CHECK FINISHED")); + } + DEBUG(2, (T_RETURN("true"))); return (TRUE); } -/* obsolete: 20040705 */ -NCURSES_EXPORT(int) -_nc_resolve_uses(bool fullresolve) -{ - return _nc_resolve_uses2(fullresolve, FALSE); -} - /* * This bit of legerdemain turns all the terminfo variable names into * references to locations in the arrays Booleans, Numbers, and Strings --- @@ -406,7 +678,18 @@ _nc_resolve_uses(bool fullresolve) #define CUR tp-> static void -sanity_check2(TERMTYPE *tp, bool literal) +fixup_acsc(TERMTYPE2 *tp, int literal) +{ + if (!literal) { + if (acs_chars == ABSENT_STRING + && PRESENT(enter_alt_charset_mode) + && PRESENT(exit_alt_charset_mode)) + acs_chars = strdup(VT_ACSC); + } +} + +static void +sanity_check2(TERMTYPE2 *tp, bool literal) { if (!PRESENT(exit_attribute_mode)) { #ifdef __UNUSED__ /* this casts too wide a net */ @@ -425,16 +708,16 @@ sanity_check2(TERMTYPE *tp, bool literal) #endif /* __UNUSED__ */ PAIRED(enter_standout_mode, exit_standout_mode); PAIRED(enter_underline_mode, exit_underline_mode); +#if defined(enter_italics_mode) && defined(exit_italics_mode) + PAIRED(enter_italics_mode, exit_italics_mode); +#endif } /* we do this check/fix in postprocess_termcap(), but some packagers * prefer to bypass it... */ if (!literal) { - if (acs_chars == 0 - && enter_alt_charset_mode != 0 - && exit_alt_charset_mode != 0) - acs_chars = strdup(VT_ACSC); + fixup_acsc(tp, literal); ANDMISSING(enter_alt_charset_mode, acs_chars); ANDMISSING(exit_alt_charset_mode, acs_chars); } @@ -458,38 +741,34 @@ sanity_check2(TERMTYPE *tp, bool literal) PAIRED(enter_xon_mode, exit_xon_mode); PAIRED(enter_am_mode, exit_am_mode); ANDMISSING(label_off, label_on); -#ifdef remove_clock +#if defined(display_clock) && defined(remove_clock) PAIRED(display_clock, remove_clock); #endif ANDMISSING(set_color_pair, initialize_pair); } -/* obsolete: 20040705 */ -static void -sanity_check(TERMTYPE *tp) -{ - sanity_check2(tp, FALSE); -} - #if NO_LEAKS NCURSES_EXPORT(void) _nc_leaks_tic(void) { + T((T_CALLED("_nc_leaks_tic()"))); + _nc_globals.leak_checking = TRUE; _nc_alloc_entry_leaks(); _nc_captoinfo_leaks(); - _nc_comp_captab_leaks(); _nc_comp_scan_leaks(); #if BROKEN_LINKER || USE_REENTRANT _nc_names_leaks(); _nc_codes_leaks(); #endif _nc_tic_expand(0, FALSE, 0); + T((T_RETURN(""))); } NCURSES_EXPORT(void) _nc_free_tic(int code) { + T((T_CALLED("_nc_free_tic(%d)"), code)); _nc_leaks_tic(); - _nc_free_tinfo(code); + exit_terminfo(code); } #endif diff --git a/lib/libcurses/tinfo/comp_scan.c b/lib/libcurses/tinfo/comp_scan.c index ff3b9ac7ff2..ddbcbb1097e 100644 --- a/lib/libcurses/tinfo/comp_scan.c +++ b/lib/libcurses/tinfo/comp_scan.c @@ -1,7 +1,8 @@ -/* $OpenBSD: comp_scan.c,v 1.15 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: comp_scan.c,v 1.16 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. * +,* Copyright 2020-2022,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -50,10 +51,9 @@ #include #include -#include #include -MODULE_ID("$Id: comp_scan.c,v 1.15 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: comp_scan.c,v 1.16 2023/10/17 09:52:09 nicm Exp $") /* * Maximum length of string capability we'll accept before raising an error. @@ -63,19 +63,14 @@ MODULE_ID("$Id: comp_scan.c,v 1.15 2010/01/12 23:22:06 nicm Exp $") #define iswhite(ch) (ch == ' ' || ch == '\t') -NCURSES_EXPORT_VAR(int) -_nc_syntax = 0; /* termcap or terminfo? */ -NCURSES_EXPORT_VAR(long) -_nc_curr_file_pos = 0; /* file offset of current line */ -NCURSES_EXPORT_VAR(long) -_nc_comment_start = 0; /* start of comment range before name */ -NCURSES_EXPORT_VAR(long) -_nc_comment_end = 0; /* end of comment range before name */ -NCURSES_EXPORT_VAR(long) -_nc_start_line = 0; /* start line of current entry */ - -NCURSES_EXPORT_VAR(struct token) -_nc_curr_token = +NCURSES_EXPORT_VAR (int) _nc_syntax = 0; /* termcap or terminfo? */ +NCURSES_EXPORT_VAR (int) _nc_strict_bsd = 1; /* ncurses extended termcap? */ +NCURSES_EXPORT_VAR (long) _nc_curr_file_pos = 0; /* file offset of current line */ +NCURSES_EXPORT_VAR (long) _nc_comment_start = 0; /* start of comment range before name */ +NCURSES_EXPORT_VAR (long) _nc_comment_end = 0; /* end of comment range before name */ +NCURSES_EXPORT_VAR (long) _nc_start_line = 0; /* start line of current entry */ + +NCURSES_EXPORT_VAR (struct token) _nc_curr_token = { 0, 0, 0 }; @@ -93,8 +88,7 @@ static int pushtype; /* type of pushback token */ static char *pushname; #if NCURSES_EXT_FUNCS -NCURSES_EXPORT_VAR(bool) -_nc_disable_period = FALSE; /* used by tic -a option */ +NCURSES_EXPORT_VAR (bool) _nc_disable_period = FALSE; /* used by tic -a option */ #endif /***************************************************************************** @@ -120,6 +114,9 @@ static FILE *yyin; /* scanner's input file descriptor */ NCURSES_EXPORT(void) _nc_reset_input(FILE *fp, char *buf) { + TR(TRACE_DATABASE, + (T_CALLED("_nc_reset_input(fp=%p, buf=%p)"), (void *) fp, buf)); + pushtype = NO_PUSHBACK; if (pushname != 0) pushname[0] = '\0'; @@ -129,6 +126,8 @@ _nc_reset_input(FILE *fp, char *buf) if (fp != 0) _nc_curr_line = 0; _nc_curr_col = 0; + + returnVoidDB; } /* @@ -137,14 +136,45 @@ _nc_reset_input(FILE *fp, char *buf) * Returns the final nonblank character on the current input buffer */ static int -last_char(void) +last_char(int from_end) { size_t len = strlen(bufptr); + int result = 0; + while (len--) { - if (!isspace(UChar(bufptr[len]))) - return bufptr[len]; + if (!isspace(UChar(bufptr[len]))) { + if (from_end <= (int) len) + result = bufptr[(int) len - from_end]; + break; + } + } + return result; +} + +/* + * Read, like fgets(), but error-out if the input contains nulls. + */ +static int +get_text(char *buffer, int length) +{ + int count = 0; + int limit = length - 1; + + while (limit-- > 0) { + int ch = fgetc(yyin); + + if (ch == '\0') { + _nc_err_abort("This is not a text-file"); + } else if (ch == EOF) { + break; + } + ++count; + *buffer++ = (char) ch; + if (ch == '\n') + break; } - return 0; + *buffer = '\0'; + return count; } /* @@ -172,6 +202,8 @@ next_char(void) if (result != 0) { FreeAndNull(result); FreeAndNull(pushname); + bufptr = 0; + bufstart = 0; allocated = 0; } /* @@ -193,35 +225,41 @@ next_char(void) * quite hard to get completely right. Try it and see. If you * succeed, don't forget to hack push_back() correspondingly. */ - size_t used; size_t len; do { + size_t used = 0; bufstart = 0; - used = 0; do { if (used + (LEXBUFSIZ / 4) >= allocated) { allocated += (allocated + LEXBUFSIZ); result = typeRealloc(char, allocated, result); if (result == 0) return (EOF); - bufstart = result; + if (bufstart) + bufstart = result; } if (used == 0) _nc_curr_file_pos = ftell(yyin); - if (fgets(result + used, (int) (allocated - used), yyin) != 0) { + if (get_text(result + used, (int) (allocated - used))) { bufstart = result; if (used == 0) { + if (_nc_curr_line == 0 + && IS_TIC_MAGIC(result)) { + _nc_err_abort("This is a compiled terminal description, not a source"); + } _nc_curr_line++; _nc_curr_col = 0; } } else { if (used != 0) - strlcat(result, "\n", allocated); + _nc_STRCAT(result, "\n", allocated); } if ((bufptr = bufstart) != 0) { used = strlen(bufptr); + if (used == 0) + return (EOF); while (iswhite(*bufptr)) { if (*bufptr == '\t') { _nc_curr_col = (_nc_curr_col | 7) + 1; @@ -262,12 +300,12 @@ next_char(void) } static void -push_back(char c) +push_back(int c) /* push a character back onto the input stream */ { if (bufptr == bufstart) - _nc_syserr_abort("Can't backspace off beginning of line"); - *--bufptr = c; + _nc_syserr_abort("cannot backspace off beginning of line"); + *--bufptr = (char) c; _nc_curr_col--; } @@ -275,14 +313,16 @@ static long stream_pos(void) /* return our current character position in the input stream */ { - return (yyin ? ftell(yyin) : (bufptr ? bufptr - bufstart : 0)); + return (yyin ? ftell(yyin) : (bufptr ? (long) (bufptr - bufstart) : 0)); } static bool end_of_stream(void) /* are we at end of input? */ { - return ((yyin ? feof(yyin) : (bufptr && *bufptr == '\0')) + return ((yyin + ? (feof(yyin) && (bufptr == NULL || *bufptr == '\0')) + : (bufptr && *bufptr == '\0')) ? TRUE : FALSE); } @@ -290,9 +330,11 @@ end_of_stream(void) static NCURSES_INLINE int eat_escaped_newline(int ch) { - if (ch == '\\') - while ((ch = next_char()) == '\n' || iswhite(ch)) - continue; + if (ch == '\\') { + while ((ch = next_char()) == '\n' || iswhite(ch)) { + /* EMPTY */ ; + } + } return ch; } @@ -305,6 +347,8 @@ eat_escaped_newline(int ch) *tok_ptr++ = (char) ch; \ *tok_ptr = '\0' +static char *tok_buf; + /* * int * get_token() @@ -342,15 +386,14 @@ NCURSES_EXPORT(int) _nc_get_token(bool silent) { static const char terminfo_punct[] = "@%&*!#"; - static char *tok_buf; - char *after_list; - char *after_name; + char *after_name; /* after primary name */ + char *after_list; /* after primary and alias list */ char *numchk; char *tok_ptr; char *s; char numbuf[80]; - int ch; + int ch, c0, c1; int dot_flag = FALSE; int type; long number; @@ -361,6 +404,8 @@ _nc_get_token(bool silent) int old_col; #endif + DEBUG(3, (T_CALLED("_nc_get_token(silent=%d)"), silent)); + if (pushtype != NO_PUSHBACK) { int retval = pushtype; @@ -373,17 +418,18 @@ _nc_get_token(bool silent) pushname[0] = '\0'; /* currtok wasn't altered by _nc_push_token() */ + DEBUG(3, (T_RETURN("%d"), retval)); return (retval); } if (end_of_stream()) { yyin = 0; - next_char(); /* frees its allocated memory */ + (void) next_char(); /* frees its allocated memory */ if (tok_buf != 0) { if (_nc_curr_token.tk_name == tok_buf) _nc_curr_token.tk_name = 0; - FreeAndNull(tok_buf); } + DEBUG(3, (T_RETURN("%d"), EOF)); return (EOF); } @@ -392,10 +438,10 @@ _nc_get_token(bool silent) while ((ch = next_char()) == '\n' || iswhite(ch)) { if (ch == '\n') had_newline = TRUE; - continue; } ch = eat_escaped_newline(ch); + _nc_curr_token.tk_valstring = 0; #ifdef TRACE old_line = _nc_curr_line; @@ -416,8 +462,9 @@ _nc_get_token(bool silent) dot_flag = TRUE; DEBUG(8, ("dot-flag set")); - while ((ch = next_char()) == '.' || iswhite(ch)) - continue; + while ((ch = next_char()) == '.' || iswhite(ch)) { + /* EMPTY */ ; + } } if (ch == EOF) { @@ -430,10 +477,10 @@ _nc_get_token(bool silent) #if NCURSES_EXT_FUNCS && !(ch == '.' && _nc_disable_period) #endif - && !strchr(terminfo_punct, (char) ch)) { + && ((strchr) (terminfo_punct, (char) ch) == 0)) { if (!silent) _nc_warning("Illegal character (expected alphanumeric or %s) - '%s'", - terminfo_punct, unctrl((chtype) ch)); + terminfo_punct, unctrl(UChar(ch))); _nc_panic_mode(separator); goto start_token; } @@ -463,7 +510,7 @@ _nc_get_token(bool silent) after_list = tok_ptr; if (after_name == 0) after_name = tok_ptr; - } else if (ch == ':' && last_char() != ',') { + } else if (ch == ':' && last_char(0) != ',') { _nc_syntax = SYN_TERMCAP; separator = ':'; break; @@ -477,19 +524,70 @@ _nc_get_token(bool silent) if (after_name == 0) break; /* - * If we see a comma, we assume this is terminfo unless we - * subsequently run into a colon. But we don't stop - * looking for a colon until hitting a newline. This - * allows commas to be embedded in description fields of - * either syntax. + * We saw a comma, but are not entirely sure this is + * terminfo format, since we can still be parsing the + * description field (for either syntax). + * + * A properly formatted termcap line ends with either a + * colon, or a backslash after a colon. It is possible + * to have a backslash in the middle of a capability, but + * then there would be no leading whitespace on the next + * line - something we want to discourage. */ + c0 = last_char(0); + c1 = last_char(1); + if (c1 != ':' && c0 != '\\' && c0 != ':') { + bool capability = FALSE; + + /* + * Since it is not termcap, assume the line is terminfo + * format. However, the comma can be embedded in a + * description field. It also can be a separator + * between a description field and a capability. + * + * Improve the guess by checking if the next word after + * the comma does not look like a capability. In that + * case, extend the description past the comma. + */ + for (s = bufptr; isspace(UChar(*s)); ++s) { + ; + } + if (islower(UChar(*s))) { + char *name = s; + while (isalnum(UChar(*s))) { + ++s; + } + if (*s == '#' || *s == '=' || *s == '@') { + /* + * Checking solely with syntax allows us to + * support extended capabilities with string + * values. + */ + capability = TRUE; + } else if (*s == ',') { + c0 = *s; + *s = '\0'; + /* + * Otherwise, we can handle predefined boolean + * capabilities, still aided by syntax. + */ + if (_nc_find_entry(name, + _nc_get_hash_table(FALSE))) { + capability = TRUE; + } + *s = (char) c0; + } + } + if (capability) { + break; + } + } } else ch = eat_escaped_newline(ch); if (OkToAdd()) { AddCh(ch); } else { - ch = EOF; break; } } @@ -499,7 +597,7 @@ _nc_get_token(bool silent) * Grrr...what we ought to do here is barf, complaining that * the entry is malformed. But because a couple of name fields * in the 8.2 termcap file end with |\, we just have to assume - * it's termcap syntax. + * it is termcap syntax. */ _nc_syntax = SYN_TERMCAP; separator = ':'; @@ -507,8 +605,9 @@ _nc_get_token(bool silent) /* throw away trailing /, *$/ */ for (--tok_ptr; iswhite(*tok_ptr) || *tok_ptr == ','; - tok_ptr--) - continue; + tok_ptr--) { + /* EMPTY */ ; + } tok_ptr[1] = '\0'; } @@ -530,14 +629,15 @@ _nc_get_token(bool silent) */ if (after_list != 0) { if (!silent) { - if (*after_list == '\0') + if (*after_list == '\0' || strchr("|", after_list[1]) != NULL) { _nc_warning("empty longname field"); - else if (strchr(after_list, ' ') == 0) + } else if (strchr(after_list, ' ') == 0) { _nc_warning("older tic versions may treat the description field as an alias"); + } } } else { after_list = tok_buf + strlen(tok_buf); - DEBUG(1, ("missing description")); + DEBUG(2, ("missing description")); } /* @@ -598,7 +698,7 @@ _nc_get_token(bool silent) case '@': if ((ch = next_char()) != separator && !silent) _nc_warning("Missing separator after `%s', have %s", - tok_buf, unctrl((chtype) ch)); + tok_buf, unctrl(UChar(ch))); _nc_curr_token.tk_name = tok_buf; type = CANCEL; break; @@ -616,10 +716,18 @@ _nc_get_token(bool silent) if (numchk == numbuf) _nc_warning("no value given for `%s'", tok_buf); if ((*numchk != '\0') || (ch != separator)) - _nc_warning("Missing separator"); + _nc_warning("Missing separator for `%s'", tok_buf); + if (number < 0) + _nc_warning("value of `%s' cannot be negative", tok_buf); + if (number > MAX_OF_TYPE(NCURSES_INT2)) { + _nc_warning("limiting value of `%s' from %#lx to %#x", + tok_buf, + number, MAX_OF_TYPE(NCURSES_INT2)); + number = MAX_OF_TYPE(NCURSES_INT2); + } } _nc_curr_token.tk_name = tok_buf; - _nc_curr_token.tk_valnumber = number; + _nc_curr_token.tk_valnumber = (int) number; type = NUMBER; break; @@ -639,7 +747,7 @@ _nc_get_token(bool silent) /* just to get rid of the compiler warning */ type = UNDEF; if (!silent) - _nc_warning("Illegal character - '%s'", unctrl((chtype) ch)); + _nc_warning("Illegal character - '%s'", unctrl(UChar(ch))); } } /* end else (first_column == FALSE) */ } /* end else (ch != EOF) */ @@ -704,6 +812,7 @@ _nc_get_token(bool silent) : ""), type)); + DEBUG(3, (T_RETURN("%d"), type)); return (type); } @@ -727,62 +836,63 @@ _nc_get_token(bool silent) */ NCURSES_EXPORT(int) -_nc_trans_string(char *ptr, char *last) +_nc_trans_string(char *ptr, const char *const last) { int count = 0; int number = 0; int i, c; - chtype ch, last_ch = '\0'; + int last_ch = '\0'; bool ignored = FALSE; bool long_warning = FALSE; - while ((ch = c = next_char()) != (chtype) separator && c != EOF) { + while ((c = next_char()) != separator && c != EOF) { if (ptr >= (last - 1)) { if (c != EOF) { while ((c = next_char()) != separator && c != EOF) { ; } - ch = c; } break; } if ((_nc_syntax == SYN_TERMCAP) && c == '\n') break; - if (ch == '^' && last_ch != '%') { - ch = c = next_char(); + if (c == '^' && last_ch != '%') { + c = next_char(); if (c == EOF) _nc_err_abort(MSG_NO_INPUTS); - if (!(is7bits(ch) && isprint(ch))) { - _nc_warning("Illegal ^ character - '%s'", unctrl(ch)); + if (!(is7bits(c) && isprint(c))) { + _nc_warning("Illegal ^ character - '%s'", unctrl(UChar(c))); } - if (ch == '?') { + if (c == '?' && (_nc_syntax != SYN_TERMCAP)) { *(ptr++) = '\177'; - if (_nc_tracing) - _nc_warning("Allow ^? as synonym for \\177"); } else { - if ((ch &= 037) == 0) - ch = 128; - *(ptr++) = (char) (ch); + if ((c &= 037) == 0) + c = 128; + *(ptr++) = (char) (c); } - } else if (ch == '\\') { - ch = c = next_char(); + } else if (c == '\\') { + bool strict_bsd = ((_nc_syntax == SYN_TERMCAP) && _nc_strict_bsd); + + c = next_char(); if (c == EOF) _nc_err_abort(MSG_NO_INPUTS); - if (ch >= '0' && ch <= '7') { - number = ch - '0'; + if (isoctal(c) || (strict_bsd && isdigit(c))) { + number = c - '0'; for (i = 0; i < 2; i++) { - ch = c = next_char(); + c = next_char(); if (c == EOF) _nc_err_abort(MSG_NO_INPUTS); - if (c < '0' || c > '7') { + if (!isoctal(c)) { if (isdigit(c)) { - _nc_warning("Non-octal digit `%c' in \\ sequence", c); - /* allow the digit; it'll do less harm */ + if (!strict_bsd) { + _nc_warning("Non-octal digit `%c' in \\ sequence", c); + /* allow the digit; it'll do less harm */ + } } else { - push_back((char) c); + push_back(c); break; } } @@ -790,21 +900,16 @@ _nc_trans_string(char *ptr, char *last) number = number * 8 + c - '0'; } - if (number == 0) + number = UChar(number); + if (number == 0 && !strict_bsd) number = 0200; *(ptr++) = (char) number; } else { switch (c) { case 'E': - case 'e': *(ptr++) = '\033'; break; - case 'a': - *(ptr++) = '\007'; - break; - - case 'l': case 'n': *(ptr++) = '\n'; break; @@ -817,10 +922,6 @@ _nc_trans_string(char *ptr, char *last) *(ptr++) = '\010'; break; - case 's': - *(ptr++) = ' '; - break; - case 'f': *(ptr++) = '\014'; break; @@ -841,40 +942,57 @@ _nc_trans_string(char *ptr, char *last) *(ptr++) = ','; break; - case ':': - *(ptr++) = ':'; - break; - case '\n': continue; default: - _nc_warning("Illegal character '%s' in \\ sequence", - unctrl(ch)); + if ((_nc_syntax == SYN_TERMINFO) || !_nc_strict_bsd) { + switch (c) { + case 'a': + c = '\007'; + break; + case 'e': + c = '\033'; + break; + case 'l': + c = '\n'; + break; + case 's': + c = ' '; + break; + case ':': + c = ':'; + break; + default: + _nc_warning("Illegal character '%s' in \\ sequence", + unctrl(UChar(c))); + break; + } + } /* FALLTHRU */ case '|': - *(ptr++) = (char) ch; - } /* endswitch (ch) */ - } /* endelse (ch < '0' || ch > '7') */ + *(ptr++) = (char) c; + } /* endswitch (c) */ + } /* endelse (c < '0' || c > '7') */ } - /* end else if (ch == '\\') */ - else if (ch == '\n' && (_nc_syntax == SYN_TERMINFO)) { + /* end else if (c == '\\') */ + else if (c == '\n' && (_nc_syntax == SYN_TERMINFO)) { /* * Newlines embedded in a terminfo string are ignored, provided * that the next line begins with whitespace. */ ignored = TRUE; } else { - *(ptr++) = (char) ch; + *(ptr++) = (char) c; } if (!ignored) { if (_nc_curr_col <= 1) { - push_back((char) ch); - ch = '\n'; + push_back(c); + c = '\n'; break; } - last_ch = ch; + last_ch = c; count++; } ignored = FALSE; @@ -887,7 +1005,7 @@ _nc_trans_string(char *ptr, char *last) *ptr = '\0'; - return (ch); + return (c); } /* @@ -924,10 +1042,8 @@ _nc_push_token(int tokclass) NCURSES_EXPORT(void) _nc_panic_mode(char ch) { - int c; - for (;;) { - c = next_char(); + int c = next_char(); if (c == ch) return; if (c == EOF) @@ -942,5 +1058,8 @@ _nc_comp_scan_leaks(void) if (pushname != 0) { FreeAndNull(pushname); } + if (tok_buf != 0) { + FreeAndNull(tok_buf); + } } #endif diff --git a/lib/libcurses/tinfo/db_iterator.c b/lib/libcurses/tinfo/db_iterator.c index 84418492672..89aacaed4e7 100644 --- a/lib/libcurses/tinfo/db_iterator.c +++ b/lib/libcurses/tinfo/db_iterator.c @@ -1,7 +1,8 @@ -/* $OpenBSD: db_iterator.c,v 1.1 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: db_iterator.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2006,2007 Free Software Foundation, Inc. * + * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 2006-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -38,13 +39,177 @@ #include +#include #include -MODULE_ID("$Id: db_iterator.c,v 1.1 2010/01/12 23:22:06 nicm Exp $") +#if USE_HASHED_DB +#include +#endif + +MODULE_ID("$Id: db_iterator.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") #define HaveTicDirectory _nc_globals.have_tic_directory #define KeepTicDirectory _nc_globals.keep_tic_directory #define TicDirectory _nc_globals.tic_directory +#define my_blob _nc_globals.dbd_blob +#define my_list _nc_globals.dbd_list +#define my_size _nc_globals.dbd_size +#define my_time _nc_globals.dbd_time +#define my_vars _nc_globals.dbd_vars + +static void +add_to_blob(const char *text, size_t limit) +{ + (void) limit; + + if (*text != '\0') { + char *last = my_blob + strlen(my_blob); + if (last != my_blob) + *last++ = NCURSES_PATHSEP; + _nc_STRCPY(last, text, limit); + } +} + +static bool +check_existence(const char *name, struct stat *sb) +{ + bool result = FALSE; + + if (quick_prefix(name)) { + result = TRUE; + } else if (stat(name, sb) == 0 + && (S_ISDIR(sb->st_mode) + || (S_ISREG(sb->st_mode) && sb->st_size))) { + result = TRUE; + } +#if USE_HASHED_DB + else if (strlen(name) < PATH_MAX - sizeof(DBM_SUFFIX)) { + char temp[PATH_MAX]; + _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) "%s%s", name, DBM_SUFFIX); + if (stat(temp, sb) == 0 && S_ISREG(sb->st_mode) && sb->st_size) { + result = TRUE; + } + } +#endif + return result; +} + +/* + * Trim newlines (and backslashes preceding those) and tab characters to + * help simplify scripting of the quick-dump feature. Leave spaces and + * other backslashes alone. + */ +static void +trim_formatting(char *source) +{ + char *target = source; + char ch; + + while ((ch = *source++) != '\0') { + if (ch == '\\' && *source == '\n') + continue; + if (ch == '\n' || ch == '\t') + continue; + *target++ = ch; + } + *target = '\0'; +} + +/* + * Store the latest value of an environment variable in my_vars[] so we can + * detect if one changes, invalidating the cached search-list. + */ +static bool +update_getenv(const char *name, DBDIRS which) +{ + bool result = FALSE; + + if (which < dbdLAST) { + char *value; + char *cached_value = my_vars[which].value; + bool same_value; + + if ((value = getenv(name)) != 0) { + value = strdup(value); + } + same_value = ((value == 0 && cached_value == 0) || + (value != 0 && + cached_value != 0 && + strcmp(value, cached_value) == 0)); + + /* Set variable name to enable checks in cache_expired(). */ + my_vars[which].name = name; + + if (!same_value) { + FreeIfNeeded(my_vars[which].value); + my_vars[which].value = value; + result = TRUE; + } else { + free(value); + } + } + return result; +} + +#if NCURSES_USE_DATABASE || NCURSES_USE_TERMCAP +static char * +cache_getenv(const char *name, DBDIRS which) +{ + char *result = 0; + + (void) update_getenv(name, which); + if (which < dbdLAST) { + result = my_vars[which].value; + } + return result; +} +#endif + +/* + * The cache expires if at least a second has passed since the initial lookup, + * or if one of the environment variables changed. + * + * Only a few applications use multiple lookups of terminal entries, seems that + * aside from bulk I/O such as tic and toe, that leaves interactive programs + * which should not be modifying the terminal databases in a way that would + * invalidate the search-list. + * + * The "1-second" is to allow for user-directed changes outside the program. + */ +static bool +cache_expired(void) +{ + bool result = FALSE; + time_t now = time((time_t *) 0); + + if (now > my_time) { + result = TRUE; + } else { + DBDIRS n; + for (n = (DBDIRS) 0; n < dbdLAST; ++n) { + if (my_vars[n].name != 0 + && update_getenv(my_vars[n].name, n)) { + result = TRUE; + break; + } + } + } + return result; +} + +static void +free_cache(void) +{ + FreeAndNull(my_blob); + FreeAndNull(my_list); +} + +static void +update_tic_dir(const char *update) +{ + free((char *) TicDirectory); + TicDirectory = update; +} /* * Record the "official" location of the terminfo directory, according to @@ -53,17 +218,21 @@ MODULE_ID("$Id: db_iterator.c,v 1.1 2010/01/12 23:22:06 nicm Exp $") NCURSES_EXPORT(const char *) _nc_tic_dir(const char *path) { + T(("_nc_tic_dir %s", NonNull(path))); if (!KeepTicDirectory) { - if (path != 0) { - TicDirectory = path; + if (path != NULL) { + if (path != TicDirectory) + update_tic_dir(strdup(path)); HaveTicDirectory = TRUE; - } else if (!HaveTicDirectory && use_terminfo_vars()) { - char *envp; - if ((envp = getenv("TERMINFO")) != 0) - return _nc_tic_dir(envp); + } else if (HaveTicDirectory == 0) { + if (use_terminfo_vars()) { + const char *envp; + if ((envp = getenv("TERMINFO")) != 0) + return _nc_tic_dir(envp); + } } } - return TicDirectory; + return TicDirectory ? TicDirectory : TERMINFO; } /* @@ -78,63 +247,17 @@ _nc_keep_tic_dir(const char *path) KeepTicDirectory = TRUE; } -/* - * Process the list of :-separated directories, looking for the terminal type. - * We don't use strtok because it does not show us empty tokens. - */ -#define ThisDbList _nc_globals.dbi_list -#define ThisDbSize _nc_globals.dbi_size - /* * Cleanup. */ NCURSES_EXPORT(void) _nc_last_db(void) { - if (ThisDbList != 0) { - FreeAndNull(ThisDbList); + if (my_blob != 0 && cache_expired()) { + free_cache(); } - ThisDbSize = 0; } -/* The TERMINFO_DIRS value, if defined by the configure script, begins with a - * ":", which will be interpreted as TERMINFO. - */ -static const char * -next_list_item(const char *source, int *offset) -{ - if (source != 0) { - FreeIfNeeded(ThisDbList); - ThisDbList = strdup(source); - ThisDbSize = strlen(source); - } - - if (ThisDbList != 0 && ThisDbSize && *offset < ThisDbSize) { - static char system_db[] = TERMINFO; - char *result = ThisDbList + *offset; - char *marker = strchr(result, NCURSES_PATHSEP); - - /* - * Put a null on the marker if a separator was found. Set the offset - * to the next position after the marker so we can call this function - * again, using the data at the offset. - */ - if (marker == 0) { - *offset += strlen(result) + 1; - marker = result + *offset; - } else { - *marker++ = 0; - *offset = marker - ThisDbList; - } - if (*result == 0 && result != (ThisDbList + ThisDbSize)) - result = system_db; - return result; - } - return 0; -} - -#define NEXT_DBD(var, offset) next_list_item((*offset == 0) ? var : 0, offset) - /* * This is a simple iterator which allows the caller to step through the * possible locations for a terminfo directory. ncurses uses this to find @@ -144,84 +267,196 @@ NCURSES_EXPORT(const char *) _nc_next_db(DBDIRS * state, int *offset) { const char *result; - char *envp; - - while (*state < dbdLAST) { - DBDIRS next = (DBDIRS) ((int) (*state) + 1); + (void) offset; + if ((int) *state < my_size + && my_list != 0 + && my_list[*state] != 0) { + result = my_list[*state]; + (*state)++; + } else { result = 0; + } + if (result != 0) { + T(("_nc_next_db %d %s", *state, result)); + } + return result; +} - switch (*state) { - case dbdTIC: - if (HaveTicDirectory) - result = _nc_tic_dir(0); - break; -#if USE_DATABASE - case dbdEnvOnce: - if (use_terminfo_vars()) { - if ((envp = getenv("TERMINFO")) != 0) - result = _nc_tic_dir(envp); - } - break; - case dbdHome: - if (use_terminfo_vars()) { - result = _nc_home_terminfo(); - } - break; - case dbdEnvList: - if (use_terminfo_vars()) { - if ((result = NEXT_DBD(getenv("TERMINFO_DIRS"), offset)) != 0) - next = *state; - } - break; - case dbdCfgList: +NCURSES_EXPORT(void) +_nc_first_db(DBDIRS * state, int *offset) +{ + bool cache_has_expired = FALSE; + *state = dbdTIC; + *offset = 0; + + T((T_CALLED("_nc_first_db"))); + + /* build a blob containing all of the strings we will use for a lookup + * table. + */ + if (my_blob == 0 || (cache_has_expired = cache_expired())) { + size_t blobsize = 0; + const char *values[dbdLAST]; + struct stat *my_stat; + int j; + + if (cache_has_expired) + free_cache(); + + for (j = 0; j < dbdLAST; ++j) + values[j] = 0; + + /* + * This is the first item in the list, and is used only when tic is + * writing to the database, as a performance improvement. + */ + values[dbdTIC] = TicDirectory; + +#if NCURSES_USE_DATABASE #ifdef TERMINFO_DIRS - if ((result = NEXT_DBD(TERMINFO_DIRS, offset)) != 0) - next = *state; + values[dbdCfgList] = TERMINFO_DIRS; #endif - break; - case dbdCfgOnce: -#ifndef TERMINFO_DIRS - result = TERMINFO; +#ifdef TERMINFO + values[dbdCfgOnce] = TERMINFO; #endif - break; -#endif /* USE_DATABASE */ -#if USE_TERMCAP - case dbdEnvOnce2: - if (use_terminfo_vars()) { - if ((envp = getenv("TERMCAP")) != 0) - result = _nc_tic_dir(envp); - } - break; - case dbdEnvList2: - if (use_terminfo_vars()) { - if ((result = NEXT_DBD(getenv("TERMPATH"), offset)) != 0) - next = *state; +#endif + +#if NCURSES_USE_TERMCAP + values[dbdCfgList2] = TERMPATH; +#endif + + if (use_terminfo_vars()) { +#if NCURSES_USE_DATABASE + values[dbdEnvOnce] = cache_getenv("TERMINFO", dbdEnvOnce); + values[dbdHome] = _nc_home_terminfo(); + (void) cache_getenv("HOME", dbdHome); + values[dbdEnvList] = cache_getenv("TERMINFO_DIRS", dbdEnvList); + +#endif +#if NCURSES_USE_TERMCAP + values[dbdEnvOnce2] = cache_getenv("TERMCAP", dbdEnvOnce2); + /* only use $TERMCAP if it is an absolute path */ + if (values[dbdEnvOnce2] != 0 + && *values[dbdEnvOnce2] != '/') { + values[dbdEnvOnce2] = 0; } - break; - case dbdCfgList2: - if ((result = NEXT_DBD(TERMPATH, offset)) != 0) - next = *state; - break; -#endif /* USE_TERMCAP */ - case dbdLAST: - break; + values[dbdEnvList2] = cache_getenv("TERMPATH", dbdEnvList2); +#endif /* NCURSES_USE_TERMCAP */ } - if (*state != next) { - *state = next; - *offset = 0; - _nc_last_db(); + + for (j = 0; j < dbdLAST; ++j) { + if (values[j] == 0) + values[j] = ""; + blobsize += 2 + strlen(values[j]); } - if (result != 0) { - return result; + + my_blob = malloc(blobsize); + if (my_blob != 0) { + *my_blob = '\0'; + for (j = 0; j < dbdLAST; ++j) { + add_to_blob(values[j], blobsize); + } + + /* Now, build an array which will be pointers to the distinct + * strings in the blob. + */ + blobsize = 2; + for (j = 0; my_blob[j] != '\0'; ++j) { + if (my_blob[j] == NCURSES_PATHSEP) + ++blobsize; + } + my_list = typeCalloc(char *, blobsize); + my_stat = typeCalloc(struct stat, blobsize); + if (my_list != 0 && my_stat != 0) { + int k = 0; + my_list[k++] = my_blob; + for (j = 0; my_blob[j] != '\0'; ++j) { + if (my_blob[j] == NCURSES_PATHSEP + && ((&my_blob[j] - my_list[k - 1]) != 3 + || !quick_prefix(my_list[k - 1]))) { + my_blob[j] = '\0'; + my_list[k++] = &my_blob[j + 1]; + } + } + + /* + * Eliminate duplicates from the list. + */ + for (j = 0; my_list[j] != 0; ++j) { +#ifdef TERMINFO + if (*my_list[j] == '\0') { + char *my_copy = strdup(TERMINFO); + if (my_copy != 0) + my_list[j] = my_copy; + } +#endif + trim_formatting(my_list[j]); + for (k = 0; k < j; ++k) { + if (!strcmp(my_list[j], my_list[k])) { + T(("duplicate %s", my_list[j])); + k = j - 1; + while ((my_list[j] = my_list[j + 1]) != 0) { + ++j; + } + j = k; + break; + } + } + } + + /* + * Eliminate non-existent databases, and those that happen to + * be symlinked to another location. + */ + for (j = 0; my_list[j] != 0; ++j) { + bool found = check_existence(my_list[j], &my_stat[j]); +#if HAVE_LINK + if (found) { + for (k = 0; k < j; ++k) { + if (my_stat[j].st_dev == my_stat[k].st_dev + && my_stat[j].st_ino == my_stat[k].st_ino) { + found = FALSE; + break; + } + } + } +#endif + if (!found) { + T(("not found %s", my_list[j])); + k = j; + while ((my_list[k] = my_list[k + 1]) != 0) { + ++k; + } + --j; + } + } + my_size = j; + my_time = time((time_t *) 0); + } else { + FreeAndNull(my_blob); + } + free(my_stat); } } - return 0; + returnVoid; } -NCURSES_EXPORT(void) -_nc_first_db(DBDIRS * state, int *offset) +#if NO_LEAKS +void +_nc_db_iterator_leaks(void) { - *state = dbdTIC; - *offset = 0; + DBDIRS which; + + if (my_blob != 0) + FreeAndNull(my_blob); + if (my_list != 0) + FreeAndNull(my_list); + for (which = 0; (int) which < dbdLAST; ++which) { + my_vars[which].name = 0; + FreeIfNeeded(my_vars[which].value); + my_vars[which].value = 0; + } + update_tic_dir(NULL); } +#endif diff --git a/lib/libcurses/tinfo/doalloc.c b/lib/libcurses/tinfo/doalloc.c index a28a5cbdffb..0050201a6b7 100644 --- a/lib/libcurses/tinfo/doalloc.c +++ b/lib/libcurses/tinfo/doalloc.c @@ -1,7 +1,8 @@ -/* $OpenBSD: doalloc.c,v 1.7 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: doalloc.c,v 1.8 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2002,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -41,15 +42,18 @@ #include -MODULE_ID("$Id: doalloc.c,v 1.7 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: doalloc.c,v 1.8 2023/10/17 09:52:09 nicm Exp $") -NCURSES_EXPORT(void *) +void * _nc_doalloc(void *oldp, size_t amount) { void *newp; - if (oldp != 0) { - if ((newp = realloc(oldp, amount)) == 0) { + if (oldp != NULL) { + if (amount == 0) { + free(oldp); + newp = NULL; + } else if ((newp = realloc(oldp, amount)) == 0) { free(oldp); errno = ENOMEM; /* just in case 'free' reset */ } @@ -58,22 +62,3 @@ _nc_doalloc(void *oldp, size_t amount) } return newp; } - -#if !HAVE_STRDUP -NCURSES_EXPORT(char *) -_nc_strdup(const char *src) -{ - char *dst; - size_t dsize; - if (src != 0) { - dsize = strlen(src) + 1; - dst = typeMalloc(char, strlen(src) + 1); - if (dst != 0) { - (void) strlcpy(dst, src, dsize); - } - } else { - dst = 0; - } - return dst; -} -#endif diff --git a/lib/libcurses/tinfo/entries.c b/lib/libcurses/tinfo/entries.c index ad76fadfb83..327ad9c2a55 100644 --- a/lib/libcurses/tinfo/entries.c +++ b/lib/libcurses/tinfo/entries.c @@ -1,7 +1,8 @@ -/* $OpenBSD: entries.c,v 1.1 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: entries.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2006-2007,2008 Free Software Foundation, Inc. * + * Copyright 2019-2022,2023 Thomas E. Dickey * + * Copyright 2006-2012,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -30,6 +31,7 @@ /**************************************************************************** * Author: Thomas E. Dickey * + * and: Juergen Pfeifer * ****************************************************************************/ #include @@ -37,9 +39,8 @@ #include #include -#include -MODULE_ID("$Id: entries.c,v 1.1 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: entries.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") /**************************************************************************** * @@ -65,30 +66,8 @@ MODULE_ID("$Id: entries.c,v 1.1 2010/01/12 23:22:06 nicm Exp $") NCURSES_EXPORT_VAR(ENTRY *) _nc_head = 0; NCURSES_EXPORT_VAR(ENTRY *) _nc_tail = 0; -NCURSES_EXPORT(void) -_nc_free_entry(ENTRY * headp, TERMTYPE *tterm) -/* free the allocated storage consumed by the given list entry */ -{ - ENTRY *ep; - - if ((ep = _nc_delink_entry(headp, tterm)) != 0) { - free(ep); - } -} - -NCURSES_EXPORT(void) -_nc_free_entries(ENTRY * headp) -/* free the allocated storage consumed by list entries */ -{ - (void) headp; /* unused - _nc_head is altered here! */ - - while (_nc_head != 0) { - _nc_free_termtype(&(_nc_head->tterm)); - } -} - -NCURSES_EXPORT(ENTRY *) -_nc_delink_entry(ENTRY * headp, TERMTYPE *tterm) +static ENTRY * +_nc_delink_entry(ENTRY * headp, const TERMTYPE2 *const tterm) /* delink the allocated storage for the given list entry */ { ENTRY *ep, *last; @@ -98,6 +77,9 @@ _nc_delink_entry(ENTRY * headp, TERMTYPE *tterm) if (last != 0) { last->next = ep->next; } + if (ep->next != 0) { + ep->next->last = last; + } if (ep == _nc_head) { _nc_head = ep->next; } @@ -110,6 +92,28 @@ _nc_delink_entry(ENTRY * headp, TERMTYPE *tterm) return ep; } +NCURSES_EXPORT(void) +_nc_free_entry(ENTRY * headp, TERMTYPE2 *tterm) +/* free the allocated storage consumed by the given list entry */ +{ + ENTRY *ep; + + if ((ep = _nc_delink_entry(headp, tterm)) != 0) { + free(ep); + } +} + +NCURSES_EXPORT(void) +_nc_free_entries(ENTRY * headp) +/* free the allocated storage consumed by list entries */ +{ + (void) headp; /* unused - _nc_head is altered here! */ + + while (_nc_head != 0) { + _nc_free_termtype2(&(_nc_head->tterm)); + } +} + NCURSES_EXPORT(void) _nc_leaks_tinfo(void) { @@ -117,22 +121,56 @@ _nc_leaks_tinfo(void) char *s; #endif - T((T_CALLED("_nc_free_tinfo()"))); + T((T_CALLED("_nc_leaks_tinfo()"))); #if NO_LEAKS - _nc_free_tparm(); + _nc_globals.leak_checking = TRUE; + _nc_free_tparm(cur_term); _nc_tgetent_leaks(); + +#ifdef USE_PTHREADS + /* + * Discard any prescreen data which is not used for the current screen. + */ + _nc_lock_global(screen); + { + PRESCREEN_LIST *p; + pthread_t id = GetThreadID(); + for (p = _nc_prescreen.allocated; p != 0; p = p->next) { + if (p->id == id && p->sp != CURRENT_SCREEN) { + FreeAndNull(p->sp); + } + } + } + _nc_unlock_global(screen); +#endif + if (TerminalOf(CURRENT_SCREEN) != 0) { + del_curterm(TerminalOf(CURRENT_SCREEN)); + } + _nc_forget_prescr(); + + _nc_comp_captab_leaks(); + _nc_comp_userdefs_leaks(); _nc_free_entries(_nc_head); _nc_get_type(0); _nc_first_name(0); + _nc_db_iterator_leaks(); _nc_keyname_leaks(); #if BROKEN_LINKER || USE_REENTRANT _nc_names_leaks(); _nc_codes_leaks(); FreeIfNeeded(_nc_prescreen.real_acs_map); #endif + _nc_comp_error_leaks(); if ((s = _nc_home_terminfo()) != 0) free(s); + +#ifdef TRACE + T((T_RETURN(""))); + curses_trace(0); + _nc_trace_buf(-1, (size_t) 0); +#endif + #endif /* NO_LEAKS */ returnVoid; } @@ -141,7 +179,18 @@ _nc_leaks_tinfo(void) NCURSES_EXPORT(void) _nc_free_tinfo(int code) { + T((T_CALLED("_nc_free_tinfo(%d)"), code)); _nc_leaks_tinfo(); exit(code); } #endif + +NCURSES_EXPORT(void) +exit_terminfo(int code) +{ + T((T_CALLED("exit_terminfo(%d)"), code)); +#if NO_LEAKS + _nc_leaks_tinfo(); +#endif + exit(code); +} diff --git a/lib/libcurses/tinfo/free_ttype.c b/lib/libcurses/tinfo/free_ttype.c index a506df3eadf..cb0079b1fdf 100644 --- a/lib/libcurses/tinfo/free_ttype.c +++ b/lib/libcurses/tinfo/free_ttype.c @@ -1,7 +1,8 @@ -/* $OpenBSD: free_ttype.c,v 1.7 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: free_ttype.c,v 1.8 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1999-2005,2006 Free Software Foundation, Inc. * + * Copyright 2020-2022,2023 Thomas E. Dickey * + * Copyright 1999-2011,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -43,27 +44,53 @@ #include #include -#include -MODULE_ID("$Id: free_ttype.c,v 1.7 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: free_ttype.c,v 1.8 2023/10/17 09:52:09 nicm Exp $") -NCURSES_EXPORT(void) -_nc_free_termtype(TERMTYPE *ptr) +static void +really_free_termtype(TERMTYPE2 *ptr, bool freeStrings) { - T(("_nc_free_termtype(%s)", ptr->term_names)); + T(("really_free_termtype(%s) %d", ptr->term_names, freeStrings)); - FreeIfNeeded(ptr->str_table); + if (freeStrings) { + FreeIfNeeded(ptr->str_table); + } FreeIfNeeded(ptr->Booleans); FreeIfNeeded(ptr->Numbers); FreeIfNeeded(ptr->Strings); #if NCURSES_XNAMES - FreeIfNeeded(ptr->ext_str_table); + if (freeStrings) { + FreeIfNeeded(ptr->ext_str_table); + } FreeIfNeeded(ptr->ext_Names); #endif memset(ptr, 0, sizeof(TERMTYPE)); _nc_free_entry(_nc_head, ptr); } +NCURSES_EXPORT(void) +_nc_free_termtype(TERMTYPE *ptr) +{ + really_free_termtype((TERMTYPE2 *) ptr, !NCURSES_EXT_NUMBERS); +} + +/* + * These similar entrypoints are not used outside of ncurses. + */ +NCURSES_EXPORT(void) +_nc_free_termtype1(TERMTYPE *ptr) +{ + really_free_termtype((TERMTYPE2 *) ptr, TRUE); +} + +#if NCURSES_EXT_NUMBERS +NCURSES_EXPORT(void) +_nc_free_termtype2(TERMTYPE2 *ptr) +{ + really_free_termtype(ptr, TRUE); +} +#endif + #if NCURSES_XNAMES NCURSES_EXPORT_VAR(bool) _nc_user_definable = TRUE; @@ -72,6 +99,7 @@ use_extended_names(bool flag) { int oldflag = _nc_user_definable; + START_TRACE(); T((T_CALLED("use_extended_names(%d)"), flag)); _nc_user_definable = flag; returnBool(oldflag); diff --git a/lib/libcurses/tinfo/getenv_num.c b/lib/libcurses/tinfo/getenv_num.c index b4c91796ca5..ca14ac2c79a 100644 --- a/lib/libcurses/tinfo/getenv_num.c +++ b/lib/libcurses/tinfo/getenv_num.c @@ -1,7 +1,8 @@ -/* $OpenBSD: getenv_num.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: getenv_num.c,v 1.4 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright 2018,2020 Thomas E. Dickey * + * Copyright 1998-2012,2013 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -38,7 +39,7 @@ #include -MODULE_ID("$Id: getenv_num.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: getenv_num.c,v 1.4 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) _nc_getenv_num(const char *name) @@ -56,3 +57,22 @@ _nc_getenv_num(const char *name) return (int) value; } + +NCURSES_EXPORT(void) +_nc_setenv_num(const char *name, int value) +{ + if (name != 0 && value >= 0) { + char buffer[128]; +#if HAVE_SETENV + _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) "%d", value); + setenv(name, buffer, 1); +#elif HAVE_PUTENV + char *s; + _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) "%s=%d", name, value); + if ((s = strdup(buffer)) != 0) + putenv(s); +#else +#error expected setenv/putenv functions +#endif + } +} diff --git a/lib/libcurses/tinfo/hashed_db.c b/lib/libcurses/tinfo/hashed_db.c index 2ce463a707f..e98a9bdad97 100644 --- a/lib/libcurses/tinfo/hashed_db.c +++ b/lib/libcurses/tinfo/hashed_db.c @@ -1,7 +1,8 @@ -/* $OpenBSD: hashed_db.c,v 1.1 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: hashed_db.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2006 Free Software Foundation, Inc. * + * Copyright 2019,2020 Thomas E. Dickey * + * Copyright 2006-2011,2013 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,7 +30,7 @@ ****************************************************************************/ /**************************************************************************** - * Author: Thomas E. Dickey 2006 * + * Author: Thomas E. Dickey 2006-on * ****************************************************************************/ #include @@ -38,12 +39,81 @@ #if USE_HASHED_DB -MODULE_ID("$Id: hashed_db.c,v 1.1 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: hashed_db.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") #if HASHED_DB_API >= 2 static DBC *cursor; #endif +typedef struct _myconn { + struct _myconn *next; + DB *db; + char *path; + bool modify; +} MYCONN; + +static MYCONN *connections; + +static void +cleanup(void) +{ + while (connections != 0) { + _nc_db_close(connections->db); + } +} + +static DB * +find_connection(const char *path, bool modify) +{ + DB *result = 0; + MYCONN *p; + + for (p = connections; p != 0; p = p->next) { + if (!strcmp(p->path, path) && p->modify == modify) { + result = p->db; + break; + } + } + + return result; +} + +static void +drop_connection(DB * db) +{ + MYCONN *p, *q; + + for (p = connections, q = 0; p != 0; q = p, p = p->next) { + if (p->db == db) { + if (q != 0) + q->next = p->next; + else + connections = p->next; + free(p->path); + free(p); + break; + } + } +} + +static void +make_connection(DB * db, const char *path, bool modify) +{ + MYCONN *p = typeCalloc(MYCONN, 1); + + if (p != 0) { + p->db = db; + p->path = strdup(path); + p->modify = modify; + if (p->path != 0) { + p->next = connections; + connections = p; + } else { + free(p); + } + } +} + /* * Open the database. */ @@ -51,49 +121,60 @@ NCURSES_EXPORT(DB *) _nc_db_open(const char *path, bool modify) { DB *result = 0; + int code; + + if (connections == 0) + atexit(cleanup); + + if ((result = find_connection(path, modify)) == 0) { #if HASHED_DB_API >= 4 - db_create(&result, NULL, 0); - result->open(result, - NULL, - path, - NULL, - DB_HASH, - modify ? DB_CREATE : DB_RDONLY, - 0644); + db_create(&result, NULL, 0); + if ((code = result->open(result, + NULL, + path, + NULL, + DB_HASH, + modify ? DB_CREATE : DB_RDONLY, + 0644)) != 0) { + result = 0; + } #elif HASHED_DB_API >= 3 - db_create(&result, NULL, 0); - result->open(result, - path, - NULL, - DB_HASH, - modify ? DB_CREATE : DB_RDONLY, - 0644); + db_create(&result, NULL, 0); + if ((code = result->open(result, + path, + NULL, + DB_HASH, + modify ? DB_CREATE : DB_RDONLY, + 0644)) != 0) { + result = 0; + } #elif HASHED_DB_API >= 2 - int code; - - if ((code = db_open(path, - DB_HASH, - modify ? DB_CREATE : DB_RDONLY, - 0644, - (DB_ENV *) 0, - (DB_INFO *) 0, - &result)) != 0) { - T(("cannot open %s: %s", path, strerror(code))); - result = 0; - } else { - T(("opened %s", path)); - } + if ((code = db_open(path, + DB_HASH, + modify ? DB_CREATE : DB_RDONLY, + 0644, + (DB_ENV *) 0, + (DB_INFO *) 0, + &result)) != 0) { + result = 0; + } #else - result = dbopen(path, - modify ? (O_CREAT | O_RDWR) : O_RDONLY, - 0644, - DB_HASH, - NULL); - if (result != 0) { - T(("opened %s", path)); - } + if ((result = dbopen(path, + modify ? (O_CREAT | O_RDWR) : O_RDONLY, + 0644, + DB_HASH, + NULL)) == 0) { + code = errno; + } #endif + if (result != 0) { + make_connection(result, path, modify); + T(("opened %s", path)); + } else { + T(("cannot open %s: %s", path, strerror(code))); + } + } return result; } @@ -105,6 +186,7 @@ _nc_db_close(DB * db) { int result; + drop_connection(db); #if HASHED_DB_API >= 2 result = db->close(db, 0); #else @@ -194,7 +276,7 @@ _nc_db_next(DB * db, DBT * key, DBT * data) result = -1; } #else - result = db->seq(db, key, data, 0); + result = db->seq(db, key, data, R_NEXT); #endif return result; } @@ -207,7 +289,7 @@ NCURSES_EXPORT(bool) _nc_db_have_index(DBT * key, DBT * data, char **buffer, int *size) { bool result = FALSE; - int used = data->size - 1; + int used = (int) data->size - 1; char *have = (char *) data->data; (void) key; @@ -230,7 +312,7 @@ NCURSES_EXPORT(bool) _nc_db_have_data(DBT * key, DBT * data, char **buffer, int *size) { bool result = FALSE; - int used = data->size - 1; + int used = (int) data->size - 1; char *have = (char *) data->data; if (*have++ == 0) { diff --git a/lib/libcurses/tinfo/home_terminfo.c b/lib/libcurses/tinfo/home_terminfo.c index a33924aa46a..e987b0799af 100644 --- a/lib/libcurses/tinfo/home_terminfo.c +++ b/lib/libcurses/tinfo/home_terminfo.c @@ -1,7 +1,8 @@ -/* $OpenBSD: home_terminfo.c,v 1.9 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: home_terminfo.c,v 1.10 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2012,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,7 +40,7 @@ #include #include -MODULE_ID("$Id: home_terminfo.c,v 1.9 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: home_terminfo.c,v 1.10 2023/10/17 09:52:09 nicm Exp $") /* ncurses extension...fall back on user's private directory */ @@ -50,16 +51,15 @@ _nc_home_terminfo(void) { char *result = 0; #if USE_HOME_TERMINFO - char *home; - if (use_terminfo_vars()) { + if (MyBuffer == 0) { - if ((home = getenv("HOME")) != 0 && *home != '\0') { + char *home; + + if ((home = getenv("HOME")) != 0) { size_t want = (strlen(home) + sizeof(PRIVATE_INFO)); - MyBuffer = typeMalloc(char, want); - if (MyBuffer == 0) - _nc_err_abort(MSG_NO_MEMORY); - (void) snprintf(MyBuffer, want, PRIVATE_INFO, home); + TYPE_MALLOC(char, want, MyBuffer); + _nc_SPRINTF(MyBuffer, _nc_SLIMIT(want) PRIVATE_INFO, home); } } result = MyBuffer; diff --git a/lib/libcurses/tinfo/init_keytry.c b/lib/libcurses/tinfo/init_keytry.c index 05bc1b62343..89239a98b44 100644 --- a/lib/libcurses/tinfo/init_keytry.c +++ b/lib/libcurses/tinfo/init_keytry.c @@ -1,7 +1,8 @@ -/* $OpenBSD: init_keytry.c,v 1.6 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: init_keytry.c,v 1.7 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1999-2006,2008 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1999-2010,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -29,16 +30,9 @@ ****************************************************************************/ #include - -#include -/* keypad_xmit, keypad_local, meta_on, meta_off */ -/* cursor_visible,cursor_normal,cursor_invisible */ - #include /* struct tinfo_fkeys */ -#include - -MODULE_ID("$Id: init_keytry.c,v 1.6 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: init_keytry.c,v 1.7 2023/10/17 09:52:09 nicm Exp $") /* ** _nc_init_keytry() @@ -52,7 +46,7 @@ MODULE_ID("$Id: init_keytry.c,v 1.6 2010/01/12 23:22:06 nicm Exp $") * than cur_term. */ #undef CUR -#define CUR (sp->_term)->type. +#define CUR SP_TERMTYPE #if BROKEN_LINKER #undef _nc_tinfo_fkeys @@ -75,14 +69,14 @@ _nc_tinfo_fkeysf(void) NCURSES_EXPORT(void) _nc_init_keytry(SCREEN *sp) { - size_t n; - /* The sp->_keytry value is initialized in newterm(), where the sp * structure is created, because we can not tell where keypad() or * mouse_activate() (which will call keyok()) are first called. */ if (sp != 0) { + unsigned n; + for (n = 0; _nc_tinfo_fkeys[n].code; n++) { if (_nc_tinfo_fkeys[n].offset < STRCOUNT) { (void) _nc_add_to_try(&(sp->_keytry), @@ -99,12 +93,13 @@ _nc_init_keytry(SCREEN *sp) { TERMTYPE *tp = &(sp->_term->type); for (n = STRCOUNT; n < NUM_STRINGS(tp); ++n) { - const char *name = ExtStrname(tp, n, strnames); + const char *name = ExtStrname(tp, (int) n, strnames); char *value = tp->Strings[n]; if (name != 0 && *name == 'k' && value != 0 - && key_defined(value) == 0) { + && NCURSES_SP_NAME(key_defined) (NCURSES_SP_ARGx + value) == 0) { (void) _nc_add_to_try(&(sp->_keytry), value, n - STRCOUNT + KEY_MAX); diff --git a/lib/libcurses/tinfo/lib_acs.c b/lib/libcurses/tinfo/lib_acs.c index b5a5c12a4be..520ea027d21 100644 --- a/lib/libcurses/tinfo/lib_acs.c +++ b/lib/libcurses/tinfo/lib_acs.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_acs.c,v 1.5 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_acs.c,v 1.6 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2019,2020 Thomas E. Dickey * + * Copyright 1998-2014,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,17 +33,21 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2008 * ****************************************************************************/ #include -#include /* ena_acs, acs_chars */ -MODULE_ID("$Id: lib_acs.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") +#ifndef CUR +#define CUR SP_TERMTYPE +#endif + +MODULE_ID("$Id: lib_acs.c,v 1.6 2023/10/17 09:52:09 nicm Exp $") #if BROKEN_LINKER || USE_REENTRANT #define MyBuffer _nc_prescreen.real_acs_map -NCURSES_EXPORT_VAR(chtype *) -_nc_acs_map(void) +NCURSES_EXPORT(chtype *) +NCURSES_PUBLIC_VAR(acs_map) (void) { if (MyBuffer == 0) MyBuffer = typeCalloc(chtype, ACS_LEN); @@ -50,17 +55,35 @@ _nc_acs_map(void) } #undef MyBuffer #else -NCURSES_EXPORT_VAR(chtype) acs_map[ACS_LEN] = +NCURSES_EXPORT_VAR (chtype) acs_map[ACS_LEN] = { 0 }; #endif +#ifdef USE_TERM_DRIVER +NCURSES_EXPORT(chtype) +NCURSES_SP_NAME(_nc_acs_char) (NCURSES_SP_DCLx int c) +{ + chtype *map; + if (c < 0 || c >= ACS_LEN) + return (chtype) 0; + map = (SP_PARM != 0) ? SP_PARM->_acs_map : +#if BROKEN_LINKER || USE_REENTRANT + _nc_prescreen.real_acs_map +#else + acs_map +#endif + ; + return map[c]; +} +#endif /* USE_TERM_DRIVER */ + NCURSES_EXPORT(void) -_nc_init_acs(void) +NCURSES_SP_NAME(_nc_init_acs) (NCURSES_SP_DCL0) { chtype *fake_map = acs_map; - chtype *real_map = SP != 0 ? SP->_acs_map : fake_map; + chtype *real_map = SP_PARM != 0 ? SP_PARM->_acs_map : fake_map; int j; T(("initializing ACS map")); @@ -73,9 +96,9 @@ _nc_init_acs(void) if (real_map != fake_map) { for (j = 1; j < ACS_LEN; ++j) { real_map[j] = 0; - fake_map[j] = A_ALTCHARSET | j; - if (SP) - SP->_screen_acs_map[j] = FALSE; + fake_map[j] = A_ALTCHARSET | (chtype) j; + if (SP_PARM) + SP_PARM->_screen_acs_map[j] = FALSE; } } else { for (j = 1; j < ACS_LEN; ++j) { @@ -120,12 +143,38 @@ _nc_init_acs(void) real_map['{'] = '*'; /* should be greek pi */ real_map['|'] = '!'; /* should be not-equal */ real_map['}'] = 'f'; /* should be pound-sterling symbol */ + /* thick-line-drawing */ + real_map['L'] = '+'; /* upper left corner */ + real_map['M'] = '+'; /* lower left corner */ + real_map['K'] = '+'; /* upper right corner */ + real_map['J'] = '+'; /* lower right corner */ + real_map['T'] = '+'; /* tee pointing left */ + real_map['U'] = '+'; /* tee pointing right */ + real_map['V'] = '+'; /* tee pointing up */ + real_map['W'] = '+'; /* tee pointing down */ + real_map['Q'] = '-'; /* horizontal line */ + real_map['X'] = '|'; /* vertical line */ + real_map['N'] = '+'; /* large plus or crossover */ + /* double-line-drawing */ + real_map['C'] = '+'; /* upper left corner */ + real_map['D'] = '+'; /* lower left corner */ + real_map['B'] = '+'; /* upper right corner */ + real_map['A'] = '+'; /* lower right corner */ + real_map['G'] = '+'; /* tee pointing left */ + real_map['F'] = '+'; /* tee pointing right */ + real_map['H'] = '+'; /* tee pointing up */ + real_map['I'] = '+'; /* tee pointing down */ + real_map['R'] = '-'; /* horizontal line */ + real_map['Y'] = '|'; /* vertical line */ + real_map['E'] = '+'; /* large plus or crossover */ +#ifdef USE_TERM_DRIVER + CallDriver_2(SP_PARM, td_initacs, real_map, fake_map); +#else if (ena_acs != NULL) { - TPUTS_TRACE("ena_acs"); - putp(ena_acs); + NCURSES_PUTP2("ena_acs", ena_acs); } -#if NCURSES_EXT_FUNCS +#if NCURSES_EXT_FUNCS && defined(enter_pc_charset_mode) && defined(exit_pc_charset_mode) /* * Linux console "supports" the "PC ROM" character set by the coincidence * that smpch/rmpch and smacs/rmacs have the same values. ncurses has @@ -142,7 +191,7 @@ _nc_init_acs(void) size_t i; for (i = 1; i < ACS_LEN; ++i) { if (real_map[i] == 0) { - real_map[i] = i; + real_map[i] = (chtype) i; if (real_map != fake_map) { if (SP != 0) SP->_screen_acs_map[i] = TRUE; @@ -159,8 +208,13 @@ _nc_init_acs(void) while (i + 1 < length) { if (acs_chars[i] != 0 && UChar(acs_chars[i]) < ACS_LEN) { real_map[UChar(acs_chars[i])] = UChar(acs_chars[i + 1]) | A_ALTCHARSET; - if (SP != 0) + T(("#%d real_map[%s] = %s", + (int) i, + _tracechar(UChar(acs_chars[i])), + _tracechtype(real_map[UChar(acs_chars[i])]))); + if (SP != 0) { SP->_screen_acs_map[UChar(acs_chars[i])] = TRUE; + } } i += 2; } @@ -193,4 +247,82 @@ _nc_init_acs(void) _nc_unlock_global(tracef); } #endif /* TRACE */ +#endif +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(void) +_nc_init_acs(void) +{ + NCURSES_SP_NAME(_nc_init_acs) (CURRENT_SCREEN); +} +#endif + +#if !NCURSES_WCWIDTH_GRAPHICS +NCURSES_EXPORT(int) +_nc_wacs_width(unsigned ch) +{ + int result; + switch (ch) { + case 0x00a3: /* FALLTHRU - ncurses pound-sterling symbol */ + case 0x00b0: /* FALLTHRU - VT100 degree symbol */ + case 0x00b1: /* FALLTHRU - VT100 plus/minus */ + case 0x00b7: /* FALLTHRU - VT100 bullet */ + case 0x03c0: /* FALLTHRU - ncurses greek pi */ + case 0x2190: /* FALLTHRU - Teletype arrow pointing left */ + case 0x2191: /* FALLTHRU - Teletype arrow pointing up */ + case 0x2192: /* FALLTHRU - Teletype arrow pointing right */ + case 0x2193: /* FALLTHRU - Teletype arrow pointing down */ + case 0x2260: /* FALLTHRU - ncurses not-equal */ + case 0x2264: /* FALLTHRU - ncurses less-than-or-equal-to */ + case 0x2265: /* FALLTHRU - ncurses greater-than-or-equal-to */ + case 0x23ba: /* FALLTHRU - VT100 scan line 1 */ + case 0x23bb: /* FALLTHRU - ncurses scan line 3 */ + case 0x23bc: /* FALLTHRU - ncurses scan line 7 */ + case 0x23bd: /* FALLTHRU - VT100 scan line 9 */ + case 0x2500: /* FALLTHRU - VT100 horizontal line */ + case 0x2501: /* FALLTHRU - thick horizontal line */ + case 0x2502: /* FALLTHRU - VT100 vertical line */ + case 0x2503: /* FALLTHRU - thick vertical line */ + case 0x250c: /* FALLTHRU - VT100 upper left corner */ + case 0x250f: /* FALLTHRU - thick upper left corner */ + case 0x2510: /* FALLTHRU - VT100 upper right corner */ + case 0x2513: /* FALLTHRU - thick upper right corner */ + case 0x2514: /* FALLTHRU - VT100 lower left corner */ + case 0x2517: /* FALLTHRU - thick lower left corner */ + case 0x2518: /* FALLTHRU - VT100 lower right corner */ + case 0x251b: /* FALLTHRU - thick lower right corner */ + case 0x251c: /* FALLTHRU - VT100 tee pointing left */ + case 0x2523: /* FALLTHRU - thick tee pointing left */ + case 0x2524: /* FALLTHRU - VT100 tee pointing right */ + case 0x252b: /* FALLTHRU - thick tee pointing right */ + case 0x252c: /* FALLTHRU - VT100 tee pointing down */ + case 0x2533: /* FALLTHRU - thick tee pointing down */ + case 0x2534: /* FALLTHRU - VT100 tee pointing up */ + case 0x253b: /* FALLTHRU - thick tee pointing up */ + case 0x253c: /* FALLTHRU - VT100 large plus or crossover */ + case 0x254b: /* FALLTHRU - thick large plus or crossover */ + case 0x2550: /* FALLTHRU - double horizontal line */ + case 0x2551: /* FALLTHRU - double vertical line */ + case 0x2554: /* FALLTHRU - double upper left corner */ + case 0x2557: /* FALLTHRU - double upper right corner */ + case 0x255a: /* FALLTHRU - double lower left corner */ + case 0x255d: /* FALLTHRU - double lower right corner */ + case 0x2560: /* FALLTHRU - double tee pointing right */ + case 0x2563: /* FALLTHRU - double tee pointing left */ + case 0x2566: /* FALLTHRU - double tee pointing down */ + case 0x2569: /* FALLTHRU - double tee pointing up */ + case 0x256c: /* FALLTHRU - double large plus or crossover */ + case 0x2592: /* FALLTHRU - VT100 checker board (stipple) */ + case 0x25ae: /* FALLTHRU - Teletype solid square block */ + case 0x25c6: /* FALLTHRU - VT100 diamond */ + case 0x2603: /* FALLTHRU - Teletype lantern symbol */ + result = 1; + break; + default: + result = wcwidth(ch); + break; + } + return result; } +#endif /* !NCURSES_WCWIDTH_GRAPHICS */ diff --git a/lib/libcurses/tinfo/lib_baudrate.c b/lib/libcurses/tinfo/lib_baudrate.c index fffd5720bd9..574889c4e52 100644 --- a/lib/libcurses/tinfo/lib_baudrate.c +++ b/lib/libcurses/tinfo/lib_baudrate.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_baudrate.c,v 1.6 2013/12/10 20:33:51 naddy Exp $ */ +/* $OpenBSD: lib_baudrate.c,v 1.7 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -40,9 +41,8 @@ */ #include -#include /* cur_term, pad_char */ #include /* ospeed */ -#if defined(__FreeBSD__) +#if defined(__FreeBSD__) || defined(__OpenBSD__) #include #endif @@ -52,7 +52,11 @@ * of the indices up to B115200 fit nicely in a 'short', allowing us to retain * ospeed's type for compatibility. */ -#if (defined(__FreeBSD__) && (__FreeBSD_version < 700000)) || defined(__NetBSD__) +#if NCURSES_OSPEED_COMPAT && \ + ((defined(__FreeBSD__) && (__FreeBSD_version < 700000)) || \ + defined(__NetBSD__) || \ + ((defined(__OpenBSD__) && OpenBSD < 201510)) || \ + defined(__APPLE__)) #undef B0 #undef B50 #undef B75 @@ -82,7 +86,7 @@ #undef USE_OLD_TTY #endif /* USE_OLD_TTY */ -MODULE_ID("$Id: lib_baudrate.c,v 1.6 2013/12/10 20:33:51 naddy Exp $") +MODULE_ID("$Id: lib_baudrate.c,v 1.7 2023/10/17 09:52:09 nicm Exp $") /* * int @@ -93,68 +97,121 @@ MODULE_ID("$Id: lib_baudrate.c,v 1.6 2013/12/10 20:33:51 naddy Exp $") */ struct speed { - int s; /* value for 'ospeed' is an index */ - int sp; /* the actual speed */ + int given_speed; /* values for 'ospeed' */ + int actual_speed; /* the actual speed */ }; +#if !defined(EXP_WIN32_DRIVER) +#define DATA(number) { B##number, number } + static struct speed const speeds[] = { - {B0, 0}, - {B50, 50}, - {B75, 75}, - {B110, 110}, - {B134, 134}, - {B150, 150}, - {B200, 200}, - {B300, 300}, - {B600, 600}, - {B1200, 1200}, - {B1800, 1800}, - {B2400, 2400}, - {B4800, 4800}, - {B9600, 9600}, + DATA(0), + DATA(50), + DATA(75), + DATA(110), + DATA(134), + DATA(150), + DATA(200), + DATA(300), + DATA(600), + DATA(1200), + DATA(1800), + DATA(2400), + DATA(4800), + DATA(9600), #ifdef B19200 - {B19200, 19200}, -#else -#ifdef EXTA + DATA(19200), +#elif defined(EXTA) {EXTA, 19200}, #endif +#ifdef B28800 + DATA(28800), #endif #ifdef B38400 - {B38400, 38400}, -#else -#ifdef EXTB + DATA(38400), +#elif defined(EXTB) {EXTB, 38400}, #endif -#endif #ifdef B57600 - {B57600, 57600}, + DATA(57600), +#endif + /* ifdef to prevent overflow when OLD_TTY is not available */ +#if !(NCURSES_OSPEED_COMPAT && defined(__FreeBSD__) && (__FreeBSD_version > 700000)) +#ifdef B76800 + DATA(76800), #endif #ifdef B115200 - {B115200, 115200}, + DATA(115200), +#endif +#ifdef B153600 + DATA(153600), #endif #ifdef B230400 - {B230400, 230400}, + DATA(230400), +#endif +#ifdef B307200 + DATA(307200), #endif #ifdef B460800 - {B460800, 460800}, + DATA(460800), +#endif +#ifdef B500000 + DATA(500000), +#endif +#ifdef B576000 + DATA(576000), #endif #ifdef B921600 - {B921600, 921600}, + DATA(921600), +#endif +#ifdef B1000000 + DATA(1000000), +#endif +#ifdef B1152000 + DATA(1152000), +#endif +#ifdef B1500000 + DATA(1500000), +#endif +#ifdef B2000000 + DATA(2000000), +#endif +#ifdef B2500000 + DATA(2500000), +#endif +#ifdef B3000000 + DATA(3000000), +#endif +#ifdef B3500000 + DATA(3500000), +#endif +#ifdef B4000000 + DATA(4000000), +#endif #endif }; +#endif /* !EXP_WIN32_DRIVER */ NCURSES_EXPORT(int) _nc_baudrate(int OSpeed) { +#if defined(EXP_WIN32_DRIVER) + /* On Windows this is a noop */ + (void) OSpeed; + return (OK); +#else #if !USE_REENTRANT static int last_OSpeed; static int last_baudrate; #endif int result = ERR; - unsigned i; + if (OSpeed < 0) + OSpeed = (NCURSES_OSPEED) OSpeed; + if (OSpeed < 0) + OSpeed = (unsigned short) OSpeed; #if !USE_REENTRANT if (OSpeed == last_OSpeed) { result = last_baudrate; @@ -162,9 +219,14 @@ _nc_baudrate(int OSpeed) #endif if (result == ERR) { if (OSpeed >= 0) { + unsigned i; + for (i = 0; i < SIZEOF(speeds); i++) { - if (speeds[i].s == OSpeed) { - result = speeds[i].sp; + if (speeds[i].given_speed > OSpeed) { + break; + } + if (speeds[i].given_speed == OSpeed) { + result = speeds[i].actual_speed; break; } } @@ -177,64 +239,81 @@ _nc_baudrate(int OSpeed) #endif } return (result); +#endif /* !EXP_WIN32_DRIVER */ } NCURSES_EXPORT(int) _nc_ospeed(int BaudRate) { int result = 1; - unsigned i; - +#if defined(EXP_WIN32_DRIVER) + (void) BaudRate; +#else if (BaudRate >= 0) { + unsigned i; + for (i = 0; i < SIZEOF(speeds); i++) { - if (speeds[i].sp == BaudRate) { - result = speeds[i].s; + if (speeds[i].actual_speed == BaudRate) { + result = speeds[i].given_speed; break; } } } +#endif return (result); } NCURSES_EXPORT(int) -baudrate(void) +NCURSES_SP_NAME(baudrate) (NCURSES_SP_DCL0) { int result; - T((T_CALLED("baudrate()"))); + T((T_CALLED("baudrate(%p)"), (void *) SP_PARM)); +#if defined(EXP_WIN32_DRIVER) + result = OK; +#else /* * In debugging, allow the environment symbol to override when we're * redirecting to a file, so we can construct repeatable test-cases * that take into account costs that depend on baudrate. */ #ifdef TRACE - if (!isatty(fileno(SP ? SP->_ofp : stdout)) + if (IsValidTIScreen(SP_PARM) + && !NC_ISATTY(fileno((SP_PARM && SP_PARM->_ofp) ? SP_PARM->_ofp : stdout)) && getenv("BAUDRATE") != 0) { int ret; if ((ret = _nc_getenv_num("BAUDRATE")) <= 0) ret = 9600; - ospeed = _nc_ospeed(ret); + ospeed = (NCURSES_OSPEED) _nc_ospeed(ret); returnCode(ret); } #endif - if (cur_term != 0) { + if (IsValidTIScreen(SP_PARM)) { #ifdef USE_OLD_TTY - result = cfgetospeed(&cur_term->Nttyb); - ospeed = _nc_ospeed(result); + result = (int) cfgetospeed(&(TerminalOf(SP_PARM)->Nttyb)); + ospeed = (NCURSES_OSPEED) _nc_ospeed(result); #else /* !USE_OLD_TTY */ #ifdef TERMIOS - ospeed = cfgetospeed(&cur_term->Nttyb); + ospeed = (NCURSES_OSPEED) cfgetospeed(&(TerminalOf(SP_PARM)->Nttyb)); #else - ospeed = cur_term->Nttyb.sg_ospeed; + ospeed = (NCURSES_OSPEED) TerminalOf(SP_PARM)->Nttyb.sg_ospeed; #endif result = _nc_baudrate(ospeed); #endif - cur_term->_baudrate = result; + TerminalOf(SP_PARM)->_baudrate = result; } else { result = ERR; } - +#endif /* !EXP_WIN32_DRIVER */ returnCode(result); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +baudrate(void) +{ + return NCURSES_SP_NAME(baudrate) (CURRENT_SCREEN); +} +#endif diff --git a/lib/libcurses/tinfo/lib_cur_term.c b/lib/libcurses/tinfo/lib_cur_term.c index 68bb567f793..71a957b7ca0 100644 --- a/lib/libcurses/tinfo/lib_cur_term.c +++ b/lib/libcurses/tinfo/lib_cur_term.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_cur_term.c,v 1.6 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_cur_term.c,v 1.7 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2008 Free Software Foundation, Inc. * +,* Copyright 2020-2021,2022 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,69 +40,163 @@ */ #include -#include /* TTY, cur_term */ #include /* ospeed */ +#include /* VALID_STRING */ -MODULE_ID("$Id: lib_cur_term.c,v 1.6 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_cur_term.c,v 1.7 2023/10/17 09:52:09 nicm Exp $") #undef CUR -#define CUR termp->type. +#define CUR TerminalType(termp). + +#if USE_REENTRANT + +NCURSES_EXPORT(TERMINAL *) +NCURSES_SP_NAME(_nc_get_cur_term) (NCURSES_SP_DCL0) +{ + return ((0 != TerminalOf(SP_PARM)) ? TerminalOf(SP_PARM) : CurTerm); +} + +#if NCURSES_SP_FUNCS + +NCURSES_EXPORT(TERMINAL *) +_nc_get_cur_term(void) +{ + return NCURSES_SP_NAME(_nc_get_cur_term) (CURRENT_SCREEN); +} +#endif -#if BROKEN_LINKER || USE_REENTRANT NCURSES_EXPORT(TERMINAL *) NCURSES_PUBLIC_VAR(cur_term) (void) { - return (SP != 0 && SP->_term != 0) ? SP->_term : _nc_prescreen._cur_term; +#if NCURSES_SP_FUNCS + return NCURSES_SP_NAME(_nc_get_cur_term) (CURRENT_SCREEN); +#else + return NCURSES_SP_NAME(_nc_get_cur_term) (NCURSES_SP_ARG); +#endif } + #else NCURSES_EXPORT_VAR(TERMINAL *) cur_term = 0; #endif NCURSES_EXPORT(TERMINAL *) -set_curterm(TERMINAL * termp) +NCURSES_SP_NAME(set_curterm) (NCURSES_SP_DCLx TERMINAL *termp) { TERMINAL *oldterm; - T((T_CALLED("set_curterm(%p)"), termp)); + T((T_CALLED("set_curterm(%p)"), (void *) termp)); _nc_lock_global(curses); oldterm = cur_term; - if (SP) - SP->_term = termp; -#if BROKEN_LINKER || USE_REENTRANT - _nc_prescreen._cur_term = termp; + if (SP_PARM) + SP_PARM->_term = termp; +#if USE_REENTRANT + CurTerm = termp; #else cur_term = termp; #endif if (termp != 0) { - ospeed = _nc_ospeed(termp->_baudrate); - if (termp->type.Strings) { - PC = (char) ((pad_char != NULL) ? pad_char[0] : 0); +#ifdef USE_TERM_DRIVER + TERMINAL_CONTROL_BLOCK *TCB = (TERMINAL_CONTROL_BLOCK *) termp; + ospeed = (NCURSES_OSPEED) _nc_ospeed(termp->_baudrate); + if (TCB->drv && + TCB->drv->isTerminfo && + TerminalType(termp).Strings) { + PC = (char) (VALID_STRING(pad_char) ? pad_char[0] : 0); + } + TCB->csp = SP_PARM; +#else + ospeed = (NCURSES_OSPEED) _nc_ospeed(termp->_baudrate); + if (TerminalType(termp).Strings) { + PC = (char) (VALID_STRING(pad_char) ? pad_char[0] : 0); } +#endif +#if !USE_REENTRANT + save_ttytype(termp); +#endif } _nc_unlock_global(curses); - T((T_RETURN("%p"), oldterm)); + T((T_RETURN("%p"), (void *) oldterm)); return (oldterm); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(TERMINAL *) +set_curterm(TERMINAL *termp) +{ + return NCURSES_SP_NAME(set_curterm) (CURRENT_SCREEN, termp); +} +#endif + NCURSES_EXPORT(int) -del_curterm(TERMINAL * termp) +NCURSES_SP_NAME(del_curterm) (NCURSES_SP_DCLx TERMINAL *termp) { int rc = ERR; - T((T_CALLED("del_curterm(%p)"), termp)); + T((T_CALLED("del_curterm(%p, %p)"), (void *) SP_PARM, (void *) termp)); - _nc_lock_global(curses); if (termp != 0) { - _nc_free_termtype(&(termp->type)); +#ifdef USE_TERM_DRIVER + TERMINAL_CONTROL_BLOCK *TCB = (TERMINAL_CONTROL_BLOCK *) termp; +#endif + TERMINAL *cur = ( +#if USE_REENTRANT + NCURSES_SP_NAME(_nc_get_cur_term) (NCURSES_SP_ARG) +#else + cur_term +#endif + ); + +#if NCURSES_EXT_NUMBERS +#if NCURSES_EXT_COLORS + _nc_free_termtype1(&termp->type); +#else + _nc_free_termtype2(&termp->type); +#endif +#endif + _nc_free_termtype2(&TerminalType(termp)); + if (termp == cur) + NCURSES_SP_NAME(set_curterm) (NCURSES_SP_ARGx 0); + FreeIfNeeded(termp->_termname); +#if USE_HOME_TERMINFO + if (_nc_globals.home_terminfo != 0) { + FreeAndNull(_nc_globals.home_terminfo); + } +#endif +#ifdef USE_TERM_DRIVER + if (TCB->drv) + TCB->drv->td_release(TCB); +#endif +#if NO_LEAKS + /* discard memory used in tgetent's cache for this terminal */ + _nc_tgetent_leak(termp); +#endif + if (--_nc_globals.terminal_count == 0) { + _nc_free_tparm(termp); + } + + free(termp->tparm_state.fmt_buff); + free(termp->tparm_state.out_buff); free(termp); - if (termp == cur_term) - set_curterm(0); + rc = OK; } - _nc_unlock_global(curses); returnCode(rc); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +del_curterm(TERMINAL *termp) +{ + int rc; + + _nc_lock_global(curses); + rc = NCURSES_SP_NAME(del_curterm) (CURRENT_SCREEN, termp); + _nc_unlock_global(curses); + + return (rc); +} +#endif diff --git a/lib/libcurses/tinfo/lib_data.c b/lib/libcurses/tinfo/lib_data.c index 57e8d7e9a06..f0318592d35 100644 --- a/lib/libcurses/tinfo/lib_data.c +++ b/lib/libcurses/tinfo/lib_data.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_data.c,v 1.4 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_data.c,v 1.5 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2021,2022 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,6 +33,7 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer * ****************************************************************************/ /* @@ -43,7 +45,7 @@ #include -MODULE_ID("$Id: lib_data.c,v 1.4 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_data.c,v 1.5 2023/10/17 09:52:09 nicm Exp $") /* * OS/2's native linker complains if we don't initialize public data when @@ -53,17 +55,17 @@ MODULE_ID("$Id: lib_data.c,v 1.4 2010/01/12 23:22:06 nicm Exp $") NCURSES_EXPORT(WINDOW *) NCURSES_PUBLIC_VAR(stdscr) (void) { - return SP ? SP->_stdscr : 0; + return CURRENT_SCREEN ? StdScreen(CURRENT_SCREEN) : 0; } NCURSES_EXPORT(WINDOW *) NCURSES_PUBLIC_VAR(curscr) (void) { - return SP ? SP->_curscr : 0; + return CURRENT_SCREEN ? CurScreen(CURRENT_SCREEN) : 0; } NCURSES_EXPORT(WINDOW *) NCURSES_PUBLIC_VAR(newscr) (void) { - return SP ? SP->_newscr : 0; + return CURRENT_SCREEN ? NewScreen(CURRENT_SCREEN) : 0; } #else NCURSES_EXPORT_VAR(WINDOW *) stdscr = 0; @@ -95,7 +97,9 @@ _nc_screen(void) NCURSES_EXPORT(int) _nc_alloc_screen(void) { - return ((my_screen = typeCalloc(SCREEN, 1)) != 0); + my_screen = _nc_alloc_screen_sp(); + T(("_nc_alloc_screen_sp %p", my_screen)); + return (my_screen != 0); } NCURSES_EXPORT(void) @@ -105,6 +109,7 @@ _nc_set_screen(SCREEN *sp) } #else + NCURSES_EXPORT_VAR(SCREEN *) SP = NULL; /* Some linkers require initialized data... */ #endif /* *INDENT-OFF* */ @@ -114,6 +119,7 @@ NCURSES_EXPORT_VAR(SCREEN *) SP = NULL; /* Some linkers require initialized data #define TGETENT_0s { TGETENT_0, TGETENT_0, TGETENT_0, TGETENT_0 } NCURSES_EXPORT_VAR(NCURSES_GLOBALS) _nc_globals = { + 0, /* have_sigtstp */ 0, /* have_sigwinch */ 0, /* cleanup_nested */ @@ -125,24 +131,45 @@ NCURSES_EXPORT_VAR(NCURSES_GLOBALS) _nc_globals = { FALSE, /* have_tic_directory */ FALSE, /* keep_tic_directory */ - TERMINFO, /* tic_directory */ + 0, /* tic_directory */ NULL, /* dbi_list */ 0, /* dbi_size */ NULL, /* first_name */ NULL, /* keyname_table */ + 0, /* init_keyname */ 0, /* slk_format */ + 2048, /* getstr_limit */ + NULL, /* safeprint_buf */ 0, /* safeprint_used */ TGETENT_0s, /* tgetent_cache */ 0, /* tgetent_index */ 0, /* tgetent_sequence */ + 0, /* terminal_count */ + + 0, /* dbd_blob */ + 0, /* dbd_list */ + 0, /* dbd_size */ + 0, /* dbd_time */ + { { 0, 0 } }, /* dbd_vars */ + +#if HAVE_TSEARCH + NULL, /* cached_tparm */ + 0, /* count_tparm */ +#endif /* HAVE_TSEARCH */ + +#ifdef USE_TERM_DRIVER + 0, /* term_driver */ +#endif +#ifndef USE_SP_WINDOWLIST 0, /* _nc_windowlist */ +#endif #if USE_HOME_TERMINFO NULL, /* home_terminfo */ @@ -153,11 +180,28 @@ NCURSES_EXPORT_VAR(NCURSES_GLOBALS) _nc_globals = { 0, /* safeprint_rows */ #endif +#ifdef USE_PTHREADS + PTHREAD_MUTEX_INITIALIZER, /* mutex_curses */ + PTHREAD_MUTEX_INITIALIZER, /* mutex_prescreen */ + PTHREAD_MUTEX_INITIALIZER, /* mutex_screen */ + PTHREAD_MUTEX_INITIALIZER, /* mutex_update */ + PTHREAD_MUTEX_INITIALIZER, /* mutex_tst_tracef */ + PTHREAD_MUTEX_INITIALIZER, /* mutex_tracef */ + 0, /* nested_tracef */ + 0, /* use_pthreads */ +#if USE_PTHREADS_EINTR + 0, /* read_thread */ +#endif +#endif +#if USE_WIDEC_SUPPORT + CHARS_0s, /* key_name */ +#endif #ifdef TRACE - FALSE, /* init_trace */ + FALSE, /* trace_opened */ CHARS_0s, /* trace_fname */ 0, /* trace_level */ NULL, /* trace_fp */ + -1, /* trace_fd */ NULL, /* tracearg_buf */ 0, /* tracearg_used */ @@ -176,14 +220,12 @@ NCURSES_EXPORT_VAR(NCURSES_GLOBALS) _nc_globals = { { CHARS_0s, CHARS_0s }, /* traceatr_color_buf */ 0, /* traceatr_color_sel */ -1, /* traceatr_color_last */ - -#endif /* TRACE */ -#ifdef USE_PTHREADS - PTHREAD_MUTEX_INITIALIZER, /* mutex_curses */ - PTHREAD_MUTEX_INITIALIZER, /* mutex_tst_tracef */ - PTHREAD_MUTEX_INITIALIZER, /* mutex_tracef */ +#if !defined(USE_PTHREADS) && USE_REENTRANT 0, /* nested_tracef */ - 0, /* use_pthreads */ +#endif +#endif /* TRACE */ +#if NO_LEAKS + FALSE, /* leak_checking */ #endif }; @@ -195,15 +237,11 @@ NCURSES_EXPORT_VAR(NCURSES_GLOBALS) _nc_globals = { #define RIPOFF_0s { RIPOFF_0 } NCURSES_EXPORT_VAR(NCURSES_PRESCREEN) _nc_prescreen = { + NULL, /* allocated */ TRUE, /* use_env */ FALSE, /* filter_mode */ A_NORMAL, /* previous_attr */ - RIPOFF_0s, /* ripoff */ - NULL, /* rsp */ { /* tparm_state */ -#ifdef TRACE - NULL, /* tname */ -#endif NULL, /* tparam_base */ STACK_FRAME_0s, /* stack */ @@ -216,10 +254,18 @@ NCURSES_EXPORT_VAR(NCURSES_PRESCREEN) _nc_prescreen = { NULL, /* fmt_buff */ 0, /* fmt_size */ - NUM_VARS_0s, /* dynamic_var */ NUM_VARS_0s, /* static_vars */ +#ifdef TRACE + NULL, /* tname */ +#endif }, NULL, /* saved_tty */ + FALSE, /* use_tioctl */ + 0, /* _outch */ +#ifndef USE_SP_RIPOFF + RIPOFF_0s, /* ripoff */ + NULL, /* rsp */ +#endif #if NCURSES_NO_PADDING FALSE, /* flag to set if padding disabled */ #endif @@ -227,8 +273,12 @@ NCURSES_EXPORT_VAR(NCURSES_PRESCREEN) _nc_prescreen = { NULL, /* real_acs_map */ 0, /* LINES */ 0, /* COLS */ + 8, /* TABSIZE */ + 1000, /* ESCDELAY */ 0, /* cur_term */ +#endif #ifdef TRACE +#if BROKEN_LINKER || USE_REENTRANT 0L, /* _outchars */ NULL, /* _tputs_trace */ #endif @@ -236,6 +286,22 @@ NCURSES_EXPORT_VAR(NCURSES_PRESCREEN) _nc_prescreen = { }; /* *INDENT-ON* */ +/* + * wgetch() and other functions with a WINDOW* parameter may use a SCREEN* + * internally, and it is useful to allow those to be invoked without switching + * SCREEN's, e.g., for multi-threaded applications. + */ +NCURSES_EXPORT(SCREEN *) +_nc_screen_of(WINDOW *win) +{ + SCREEN *sp = 0; + + if (win != 0) { + sp = WINDOW_EXT(win, screen); + } + return (sp); +} + /******************************************************************************/ #ifdef USE_PTHREADS static void @@ -246,6 +312,9 @@ init_global_mutexes(void) if (!initialized) { initialized = TRUE; _nc_mutex_init(&_nc_globals.mutex_curses); + _nc_mutex_init(&_nc_globals.mutex_prescreen); + _nc_mutex_init(&_nc_globals.mutex_screen); + _nc_mutex_init(&_nc_globals.mutex_update); _nc_mutex_init(&_nc_globals.mutex_tst_tracef); _nc_mutex_init(&_nc_globals.mutex_tracef); } @@ -296,27 +365,32 @@ _nc_mutex_init(pthread_mutex_t * obj) NCURSES_EXPORT(int) _nc_mutex_lock(pthread_mutex_t * obj) { - if (_nc_use_pthreads == 0) - return 0; - return pthread_mutex_lock(obj); + int rc = 0; + if (_nc_use_pthreads != 0) + rc = pthread_mutex_lock(obj); + return rc; } NCURSES_EXPORT(int) _nc_mutex_trylock(pthread_mutex_t * obj) { - if (_nc_use_pthreads == 0) - return 0; - return pthread_mutex_trylock(obj); + int rc = 0; + if (_nc_use_pthreads != 0) + rc = pthread_mutex_trylock(obj); + return rc; } NCURSES_EXPORT(int) _nc_mutex_unlock(pthread_mutex_t * obj) { - if (_nc_use_pthreads == 0) - return 0; - return pthread_mutex_unlock(obj); + int rc = 0; + if (_nc_use_pthreads != 0) + rc = pthread_mutex_unlock(obj); + return rc; } +#endif /* USE_PTHREADS */ +#if defined(USE_PTHREADS) || USE_PTHREADS_EINTR #if USE_WEAK_SYMBOLS /* * NB: sigprocmask(2) is global but pthread_sigmask(3p) @@ -328,7 +402,7 @@ _nc_sigprocmask(int how, const sigset_t * newmask, sigset_t * oldmask) if ((pthread_sigmask)) return pthread_sigmask(how, newmask, oldmask); else - return sigprocmask(how, newmask, oldmask); + return (sigprocmask) (how, newmask, oldmask); } #endif #endif /* USE_PTHREADS */ diff --git a/lib/libcurses/tinfo/lib_has_cap.c b/lib/libcurses/tinfo/lib_has_cap.c index 6be944be979..3847f9ca5a9 100644 --- a/lib/libcurses/tinfo/lib_has_cap.c +++ b/lib/libcurses/tinfo/lib_has_cap.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_has_cap.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_has_cap.c,v 1.4 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2003 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2009,2013 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,6 +33,7 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-2003 * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -43,25 +45,53 @@ #include -#include +#ifndef CUR +#define CUR SP_TERMTYPE +#endif -MODULE_ID("$Id: lib_has_cap.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_has_cap.c,v 1.4 2023/10/17 09:52:09 nicm Exp $") +NCURSES_EXPORT(bool) +NCURSES_SP_NAME(has_ic) (NCURSES_SP_DCL0) +{ + bool code = FALSE; + + T((T_CALLED("has_ic(%p)"), (void *) SP_PARM)); + + if (HasTInfoTerminal(SP_PARM)) { + code = ((insert_character || parm_ich + || (enter_insert_mode && exit_insert_mode)) + && (delete_character || parm_dch)) ? TRUE : FALSE; + } + + returnCode(code); +} + +#if NCURSES_SP_FUNCS NCURSES_EXPORT(bool) has_ic(void) { - T((T_CALLED("has_ic()"))); - returnCode(cur_term && - (insert_character || parm_ich - || (enter_insert_mode && exit_insert_mode)) - && (delete_character || parm_dch)); + return NCURSES_SP_NAME(has_ic) (CURRENT_SCREEN); +} +#endif + +NCURSES_EXPORT(bool) +NCURSES_SP_NAME(has_il) (NCURSES_SP_DCL0) +{ + bool code = FALSE; + T((T_CALLED("has_il(%p)"), (void *) SP_PARM)); + if (HasTInfoTerminal(SP_PARM)) { + code = ((insert_line || parm_insert_line) + && (delete_line || parm_delete_line)) ? TRUE : FALSE; + } + + returnCode(code); } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(bool) has_il(void) { - T((T_CALLED("has_il()"))); - returnCode(cur_term - && (insert_line || parm_insert_line) - && (delete_line || parm_delete_line)); + return NCURSES_SP_NAME(has_il) (CURRENT_SCREEN); } +#endif diff --git a/lib/libcurses/tinfo/lib_kernel.c b/lib/libcurses/tinfo/lib_kernel.c index 024227fdc03..013cffc8d44 100644 --- a/lib/libcurses/tinfo/lib_kernel.c +++ b/lib/libcurses/tinfo/lib_kernel.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_kernel.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_kernel.c,v 1.4 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020-2022,2023 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,7 +32,8 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * - * and: Thomas E. Dickey 2002 * + * and: Thomas E. Dickey 2002 * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -48,10 +50,10 @@ */ #include -#include /* cur_term */ -MODULE_ID("$Id: lib_kernel.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_kernel.c,v 1.4 2023/10/17 09:52:09 nicm Exp $") +#ifdef TERMIOS static int _nc_vdisable(void) { @@ -59,9 +61,9 @@ _nc_vdisable(void) #if defined(_POSIX_VDISABLE) && HAVE_UNISTD_H value = _POSIX_VDISABLE; #endif -#if defined(_PC_VDISABLE) +#if defined(_PC_VDISABLE) && HAVE_FPATHCONF if (value == -1) { - value = fpathconf(0, _PC_VDISABLE); + value = (int) fpathconf(0, _PC_VDISABLE); if (value == -1) { value = 0377; } @@ -72,6 +74,7 @@ _nc_vdisable(void) #endif return value; } +#endif /* TERMIOS */ /* * erasechar() @@ -81,23 +84,35 @@ _nc_vdisable(void) */ NCURSES_EXPORT(char) -erasechar(void) +NCURSES_SP_NAME(erasechar) (NCURSES_SP_DCL0) { int result = ERR; - T((T_CALLED("erasechar()"))); + TERMINAL *termp = TerminalOf(SP_PARM); + + T((T_CALLED("erasechar(%p)"), (void *) SP_PARM)); - if (cur_term != 0) { + if (termp != 0) { #ifdef TERMIOS - result = cur_term->Ottyb.c_cc[VERASE]; + result = termp->Ottyb.c_cc[VERASE]; if (result == _nc_vdisable()) result = ERR; +#elif defined(EXP_WIN32_DRIVER) + result = ERR; #else - result = cur_term->Ottyb.sg_erase; + result = termp->Ottyb.sg_erase; #endif } - returnCode(result); + returnChar((char) result); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(char) +erasechar(void) +{ + return NCURSES_SP_NAME(erasechar) (CURRENT_SCREEN); +} +#endif + /* * killchar() * @@ -106,51 +121,83 @@ erasechar(void) */ NCURSES_EXPORT(char) -killchar(void) +NCURSES_SP_NAME(killchar) (NCURSES_SP_DCL0) { int result = ERR; - T((T_CALLED("killchar()"))); + TERMINAL *termp = TerminalOf(SP_PARM); + + T((T_CALLED("killchar(%p)"), (void *) SP_PARM)); - if (cur_term != 0) { + if (termp != 0) { #ifdef TERMIOS - result = cur_term->Ottyb.c_cc[VKILL]; + result = termp->Ottyb.c_cc[VKILL]; if (result == _nc_vdisable()) result = ERR; +#elif defined(EXP_WIN32_DRIVER) + result = ERR; #else - result = cur_term->Ottyb.sg_kill; + result = termp->Ottyb.sg_kill; #endif } - returnCode(result); + returnChar((char) result); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(char) +killchar(void) +{ + return NCURSES_SP_NAME(killchar) (CURRENT_SCREEN); +} +#endif + +static void +flush_input(int fd) +{ +#ifdef TERMIOS + tcflush(fd, TCIFLUSH); +#else /* !TERMIOS */ + errno = 0; + do { +#if defined(EXP_WIN32_DRIVER) + _nc_console_flush(_nc_console_fd2handle(fd)); +#else + ioctl(fd, TIOCFLUSH, 0); +#endif + } while + (errno == EINTR); +#endif } /* * flushinp() * - * Flush any input on cur_term->Filedes - * + * Flush any input on tty */ NCURSES_EXPORT(int) -flushinp(void) +NCURSES_SP_NAME(flushinp) (NCURSES_SP_DCL0) { - T((T_CALLED("flushinp()"))); + T((T_CALLED("flushinp(%p)"), (void *) SP_PARM)); - if (cur_term != 0) { -#ifdef TERMIOS - tcflush(cur_term->Filedes, TCIFLUSH); -#else - errno = 0; - do { - ioctl(cur_term->Filedes, TIOCFLUSH, 0); - } while - (errno == EINTR); -#endif - if (SP) { - SP->_fifohead = -1; - SP->_fifotail = 0; - SP->_fifopeek = 0; + if (SP_PARM != 0) { + if (NC_ISATTY(SP_PARM->_ifd)) + flush_input(SP_PARM->_ifd); + else if (NC_ISATTY(SP_PARM->_ofd)) + flush_input(SP_PARM->_ofd); + if (SP_PARM) { + SP_PARM->_fifohead = -1; + SP_PARM->_fifotail = 0; + SP_PARM->_fifopeek = 0; } returnCode(OK); } returnCode(ERR); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +flushinp(void) +{ + return NCURSES_SP_NAME(flushinp) (CURRENT_SCREEN); +} +#endif diff --git a/lib/libcurses/tinfo/lib_longname.c b/lib/libcurses/tinfo/lib_longname.c index 74616fa7bc7..165940303c9 100644 --- a/lib/libcurses/tinfo/lib_longname.c +++ b/lib/libcurses/tinfo/lib_longname.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_longname.c,v 1.3 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_longname.c,v 1.4 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2010,2015 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +32,8 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -42,7 +45,49 @@ #include -MODULE_ID("$Id: lib_longname.c,v 1.3 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_longname.c,v 1.4 2023/10/17 09:52:09 nicm Exp $") + +#if USE_REENTRANT +NCURSES_EXPORT(char *) +NCURSES_SP_NAME(longname) (NCURSES_SP_DCL0) +{ + static char empty[] = + {'\0'}; + + T((T_CALLED("longname(%p)"), (void *) SP_PARM)); + + if (SP_PARM) { + char *ptr; + + for (ptr = SP_PARM->_ttytype + strlen(SP_PARM->_ttytype); + ptr > SP_PARM->_ttytype; + ptr--) + if (*ptr == '|') + returnPtr(ptr + 1); + returnPtr(SP_PARM->_ttytype); + } + return empty; +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(char *) +longname(void) +{ + return NCURSES_SP_NAME(longname) (CURRENT_SCREEN); +} +#endif + +#else + +/* a dummy entrypoint is simpler than generating a conditional in curses.h */ +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(char *) +NCURSES_SP_NAME(longname) (NCURSES_SP_DCL0) +{ + (void) SP_PARM; + return longname(); +} +#endif NCURSES_EXPORT(char *) longname(void) @@ -51,9 +96,11 @@ longname(void) T((T_CALLED("longname()"))); - for (ptr = ttytype + strlen(ttytype); ptr > ttytype; ptr--) + for (ptr = ttytype + strlen(ttytype); + ptr > ttytype; + ptr--) if (*ptr == '|') returnPtr(ptr + 1); - returnPtr(ttytype); } +#endif diff --git a/lib/libcurses/tinfo/lib_napms.c b/lib/libcurses/tinfo/lib_napms.c index b92431d9701..f91c53d8b6e 100644 --- a/lib/libcurses/tinfo/lib_napms.c +++ b/lib/libcurses/tinfo/lib_napms.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_napms.c,v 1.8 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_napms.c,v 1.9 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2008 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2014,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +32,8 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -51,13 +54,19 @@ #endif #endif -MODULE_ID("$Id: lib_napms.c,v 1.8 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_napms.c,v 1.9 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) -napms(int ms) +NCURSES_SP_NAME(napms) (NCURSES_SP_DCLx int ms) { T((T_CALLED("napms(%d)"), ms)); +#ifdef USE_TERM_DRIVER + CallDriver_1(SP_PARM, td_nap, ms); +#else /* !USE_TERM_DRIVER */ +#if NCURSES_SP_FUNCS + (void) sp; +#endif #if HAVE_NANOSLEEP { struct timespec request, remaining; @@ -68,9 +77,20 @@ napms(int ms) request = remaining; } } +#elif defined(_NC_WINDOWS) + Sleep((DWORD) ms); #else _nc_timed_wait(0, 0, ms, (int *) 0 EVENTLIST_2nd(0)); #endif +#endif /* !USE_TERM_DRIVER */ returnCode(OK); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +napms(int ms) +{ + return NCURSES_SP_NAME(napms) (CURRENT_SCREEN, ms); +} +#endif diff --git a/lib/libcurses/tinfo/lib_options.c b/lib/libcurses/tinfo/lib_options.c index 00e079fce5b..4bb8fde45fa 100644 --- a/lib/libcurses/tinfo/lib_options.c +++ b/lib/libcurses/tinfo/lib_options.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_options.c,v 1.10 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_options.c,v 1.11 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. * + * Copyright 2020-2021,2023 Thomas E. Dickey * + * Copyright 1998-2014,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,6 +33,7 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -43,53 +45,71 @@ #include -#include - -MODULE_ID("$Id: lib_options.c,v 1.10 2010/01/12 23:22:06 nicm Exp $") +#ifndef CUR +#define CUR SP_TERMTYPE +#endif -static int _nc_curs_set(SCREEN *, int); -static int _nc_meta(SCREEN *, bool); +MODULE_ID("$Id: lib_options.c,v 1.11 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) idlok(WINDOW *win, bool flag) { - T((T_CALLED("idlok(%p,%d)"), win, flag)); + int res = ERR; + T((T_CALLED("idlok(%p,%d)"), (void *) win, flag)); if (win) { - _nc_idlok = win->_idlok = (flag && (has_il() || change_scroll_region)); - returnCode(OK); - } else - returnCode(ERR); + SCREEN *sp = _nc_screen_of(win); + if (sp != 0 +#ifdef USE_TERM_DRIVER + && IsTermInfo(sp) +#endif + ) { + sp->_nc_sp_idlok = + win->_idlok = (flag && (NCURSES_SP_NAME(has_il) (NCURSES_SP_ARG) + || change_scroll_region)); + res = OK; + } + } + returnCode(res); } NCURSES_EXPORT(void) idcok(WINDOW *win, bool flag) { - T((T_CALLED("idcok(%p,%d)"), win, flag)); - - if (win) - _nc_idcok = win->_idcok = (flag && has_ic()); + T((T_CALLED("idcok(%p,%d)"), (void *) win, flag)); + if (win) { + SCREEN *sp = _nc_screen_of(win); + sp->_nc_sp_idcok = win->_idcok = (flag && NCURSES_SP_NAME(has_ic) (NCURSES_SP_ARG)); + } returnVoid; } NCURSES_EXPORT(int) -halfdelay(int t) +NCURSES_SP_NAME(halfdelay) (NCURSES_SP_DCLx int t) { - T((T_CALLED("halfdelay(%d)"), t)); + T((T_CALLED("halfdelay(%p,%d)"), (void *) SP_PARM, t)); - if (t < 1 || t > 255 || SP == 0) + if (t < 1 || t > 255 || !SP_PARM || !IsValidTIScreen(SP_PARM)) returnCode(ERR); - cbreak(); - SP->_cbreak = t + 1; + NCURSES_SP_NAME(cbreak) (NCURSES_SP_ARG); + IsCbreak(SP_PARM) = t + 1; returnCode(OK); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +halfdelay(int t) +{ + return NCURSES_SP_NAME(halfdelay) (CURRENT_SCREEN, t); +} +#endif + NCURSES_EXPORT(int) nodelay(WINDOW *win, bool flag) { - T((T_CALLED("nodelay(%p,%d)"), win, flag)); + T((T_CALLED("nodelay(%p,%d)"), (void *) win, flag)); if (win) { if (flag == TRUE) @@ -104,7 +124,7 @@ nodelay(WINDOW *win, bool flag) NCURSES_EXPORT(int) notimeout(WINDOW *win, bool f) { - T((T_CALLED("notimeout(%p,%d)"), win, f)); + T((T_CALLED("notimeout(%p,%d)"), (void *) win, f)); if (win) { win->_notimeout = f; @@ -116,7 +136,7 @@ notimeout(WINDOW *win, bool f) NCURSES_EXPORT(void) wtimeout(WINDOW *win, int delay) { - T((T_CALLED("wtimeout(%p,%d)"), win, delay)); + T((T_CALLED("wtimeout(%p,%d)"), (void *) win, delay)); if (win) { win->_delay = delay; @@ -127,11 +147,11 @@ wtimeout(WINDOW *win, int delay) NCURSES_EXPORT(int) keypad(WINDOW *win, bool flag) { - T((T_CALLED("keypad(%p,%d)"), win, flag)); + T((T_CALLED("keypad(%p,%d)"), (void *) win, flag)); if (win) { win->_use_keypad = flag; - returnCode(_nc_keypad(SP, flag)); + returnCode(_nc_keypad(_nc_screen_of(win), flag)); } else returnCode(ERR); } @@ -139,38 +159,107 @@ keypad(WINDOW *win, bool flag) NCURSES_EXPORT(int) meta(WINDOW *win GCC_UNUSED, bool flag) { - int result; + int result = ERR; + SCREEN *sp = (win == 0) ? CURRENT_SCREEN : _nc_screen_of(win); + + /* Ok, we stay relaxed and don't signal an error if win is NULL */ + T((T_CALLED("meta(%p,%d)"), (void *) win, flag)); /* Ok, we stay relaxed and don't signal an error if win is NULL */ - T((T_CALLED("meta(%p,%d)"), win, flag)); - result = _nc_meta(SP, flag); + + if (sp != 0) { + sp->_use_meta = flag; +#ifdef USE_TERM_DRIVER + if (IsTermInfo(sp)) { + if (flag) { + NCURSES_PUTP2("meta_on", meta_on); + } else { + NCURSES_PUTP2("meta_off", meta_off); + } + } +#else + if (flag) { + NCURSES_PUTP2("meta_on", meta_on); + } else { + NCURSES_PUTP2("meta_off", meta_off); + } +#endif + result = OK; + } returnCode(result); } /* curs_set() moved here to narrow the kernel interface */ NCURSES_EXPORT(int) -curs_set(int vis) +NCURSES_SP_NAME(curs_set) (NCURSES_SP_DCLx int vis) { - int result; + int code = ERR; + T((T_CALLED("curs_set(%p,%d)"), (void *) SP_PARM, vis)); - T((T_CALLED("curs_set(%d)"), vis)); - result = _nc_curs_set(SP, vis); - returnCode(result); + if (SP_PARM != 0 && vis >= 0 && vis <= 2) { + int cursor = SP_PARM->_cursor; + if (vis == cursor) { + code = cursor; + } else { +#ifdef USE_TERM_DRIVER + code = CallDriver_1(SP_PARM, td_cursorSet, vis); +#else + if (IsValidTIScreen(SP_PARM)) { + switch (vis) { + case 2: + code = NCURSES_PUTP2_FLUSH("cursor_visible", + cursor_visible); + break; + case 1: + code = NCURSES_PUTP2_FLUSH("cursor_normal", + cursor_normal); + break; + case 0: + code = NCURSES_PUTP2_FLUSH("cursor_invisible", + cursor_invisible); + break; + } + } else { + code = ERR; + } +#endif + if (code != ERR) + code = (cursor == -1 ? 1 : cursor); + SP_PARM->_cursor = vis; + } + } + returnCode(code); } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) -typeahead(int fd) +curs_set(int vis) +{ + return (NCURSES_SP_NAME(curs_set) (CURRENT_SCREEN, vis)); +} +#endif + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(typeahead) (NCURSES_SP_DCLx int fd) { - T((T_CALLED("typeahead(%d)"), fd)); - if (SP != 0) { - SP->_checkfd = fd; + T((T_CALLED("typeahead(%p, %d)"), (void *) SP_PARM, fd)); + if (SP_PARM && IsValidTIScreen(SP_PARM)) { + SP_PARM->_checkfd = fd; returnCode(OK); } else { returnCode(ERR); } } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +typeahead(int fd) +{ + return NCURSES_SP_NAME(typeahead) (CURRENT_SCREEN, fd); +} +#endif + /* ** has_key() ** @@ -191,42 +280,49 @@ has_key_internal(int keycode, TRIES * tp) || has_key_internal(keycode, tp->sibling)); } +#ifdef USE_TERM_DRIVER +NCURSES_EXPORT(int) +TINFO_HAS_KEY(SCREEN *sp, int keycode) +{ + return IsValidTIScreen(sp) ? + has_key_internal(keycode, sp->_keytry) : 0; +} +#else +NCURSES_EXPORT(int) +NCURSES_SP_NAME(has_key) (NCURSES_SP_DCLx int keycode) +{ + T((T_CALLED("has_key(%p,%d)"), (void *) SP_PARM, keycode)); + returnCode(SP != 0 ? has_key_internal(keycode, SP_PARM->_keytry) : FALSE); +} + +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) has_key(int keycode) { - T((T_CALLED("has_key(%d)"), keycode)); - returnCode(SP != 0 ? has_key_internal(keycode, SP->_keytry) : FALSE); + return NCURSES_SP_NAME(has_key) (CURRENT_SCREEN, keycode); } +#endif +#endif #endif /* NCURSES_EXT_FUNCS */ -/* - * Internal entrypoints use SCREEN* parameter to obtain capabilities rather - * than cur_term. - */ -#undef CUR -#define CUR (sp->_term)->type. - -static int -_nc_putp(const char *name GCC_UNUSED, const char *value) +NCURSES_EXPORT(int) +NCURSES_SP_NAME(_nc_putp_flush) (NCURSES_SP_DCLx + const char *name, const char *value) { - int rc = ERR; - - if (value) { - TPUTS_TRACE(name); - rc = putp(value); + int rc = NCURSES_PUTP2(name, value); + if (rc != ERR) { + _nc_flush(); } return rc; } -static int +#if 0 && NCURSES_SP_FUNCS +NCURSES_EXPORT(int) _nc_putp_flush(const char *name, const char *value) { - int rc = _nc_putp(name, value); - if (rc != ERR) { - _nc_flush(); - } - return rc; + return NCURSES_SP_NAME(_nc_putp_flush) (CURRENT_SCREEN, name, value); } +#endif /* Turn the keypad on/off * @@ -236,7 +332,7 @@ _nc_putp_flush(const char *name, const char *value) * the terminal state _before_ switching modes. */ NCURSES_EXPORT(int) -_nc_keypad(SCREEN *sp, bool flag) +_nc_keypad(SCREEN *sp, int flag) { int rc = ERR; @@ -247,12 +343,12 @@ _nc_keypad(SCREEN *sp, bool flag) * has wgetch() reading in more than one thread. putp() and below * may use SP explicitly. */ - if (_nc_use_pthreads && sp != SP) { + if (_nc_use_pthreads && sp != CURRENT_SCREEN) { SCREEN *save_sp; /* cannot use use_screen(), since that is not in tinfo library */ _nc_lock_global(curses); - save_sp = SP; + save_sp = CURRENT_SCREEN; _nc_set_screen(sp); rc = _nc_keypad(sp, flag); _nc_set_screen(save_sp); @@ -260,10 +356,15 @@ _nc_keypad(SCREEN *sp, bool flag) } else #endif { +#ifdef USE_TERM_DRIVER + rc = CallDriver_1(sp, td_kpad, flag); + if (rc == OK) + sp->_keypad_on = flag; +#else if (flag) { - (void) _nc_putp_flush("keypad_xmit", keypad_xmit); - } else if (!flag && keypad_local) { - (void) _nc_putp_flush("keypad_local", keypad_local); + (void) NCURSES_PUTP2_FLUSH("keypad_xmit", keypad_xmit); + } else if (keypad_local) { + (void) NCURSES_PUTP2_FLUSH("keypad_local", keypad_local); } if (flag && !sp->_tried) { @@ -272,58 +373,8 @@ _nc_keypad(SCREEN *sp, bool flag) } sp->_keypad_on = flag; rc = OK; +#endif } } return (rc); } - -static int -_nc_curs_set(SCREEN *sp, int vis) -{ - int result = ERR; - - T((T_CALLED("curs_set(%d)"), vis)); - if (sp != 0 && vis >= 0 && vis <= 2) { - int cursor = sp->_cursor; - - if (vis == cursor) { - result = cursor; - } else { - switch (vis) { - case 2: - result = _nc_putp_flush("cursor_visible", cursor_visible); - break; - case 1: - result = _nc_putp_flush("cursor_normal", cursor_normal); - break; - case 0: - result = _nc_putp_flush("cursor_invisible", cursor_invisible); - break; - } - if (result != ERR) - result = (cursor == -1 ? 1 : cursor); - sp->_cursor = vis; - } - } - returnCode(result); -} - -static int -_nc_meta(SCREEN *sp, bool flag) -{ - int result = ERR; - - /* Ok, we stay relaxed and don't signal an error if win is NULL */ - - if (SP != 0) { - SP->_use_meta = flag; - - if (flag) { - _nc_putp("meta_on", meta_on); - } else { - _nc_putp("meta_off", meta_off); - } - result = OK; - } - return result; -} diff --git a/lib/libcurses/tinfo/lib_print.c b/lib/libcurses/tinfo/lib_print.c index 5043c551004..bed62b3cb2a 100644 --- a/lib/libcurses/tinfo/lib_print.c +++ b/lib/libcurses/tinfo/lib_print.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_print.c,v 1.5 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_print.c,v 1.6 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2002,2006 Free Software Foundation, Inc. * + * Copyright 2018-2021,2023 Thomas E. Dickey * + * Copyright 1998-2011,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,29 +32,37 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer * ****************************************************************************/ #include -#include +#ifndef CUR +#define CUR SP_TERMTYPE +#endif -MODULE_ID("$Id: lib_print.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_print.c,v 1.6 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) -mcprint(char *data, int len) +NCURSES_SP_NAME(mcprint) (NCURSES_SP_DCLx char *data, int len) /* ship binary character data to the printer via mc4/mc5/mc5p */ { - char *mybuf, *switchon; - size_t onsize, offsize, res; + int result; + char *mybuf = NULL, *switchon; + size_t onsize, offsize; + size_t need; errno = 0; - if (!cur_term || (!prtr_non && (!prtr_on || !prtr_off))) { + if (!HasTInfoTerminal(SP_PARM) + || len <= 0 + || (!prtr_non && (!prtr_on || !prtr_off))) { errno = ENODEV; return (ERR); } if (prtr_non) { - switchon = TPARM_1(prtr_non, len); + switchon = TIPARM_1(prtr_non, len); onsize = strlen(switchon); offsize = 0; } else { @@ -62,16 +71,19 @@ mcprint(char *data, int len) offsize = strlen(prtr_off); } - res = onsize + len + offsize + 1; - if (switchon == 0 || (mybuf = typeMalloc(char, res)) == 0) { + need = onsize + (size_t) len + offsize; + + if (switchon == 0 + || (mybuf = typeMalloc(char, need + 1)) == 0) { + free(mybuf); errno = ENOMEM; return (ERR); } - (void) strlcpy(mybuf, switchon, res); - memcpy(mybuf + onsize, data, (unsigned) len); + _nc_STRCPY(mybuf, switchon, need); + memcpy(mybuf + onsize, data, (size_t) len); if (offsize) - (void) strlcpy(mybuf + onsize + len, prtr_off, res - onsize - len); + _nc_STRCPY(mybuf + onsize + len, prtr_off, need); /* * We're relying on the atomicity of UNIX writes here. The @@ -80,15 +92,24 @@ mcprint(char *data, int len) * data has actually been shipped to the terminal. If the write(2) * operation is truly atomic we're protected from this. */ - res = write(cur_term->Filedes, mybuf, onsize + len + offsize); + result = (int) write(SP_PARM->_ofd, mybuf, need); /* * By giving up our scheduler slot here we increase the odds that the * kernel will ship the contiguous clist items from the last write * immediately. */ +#ifndef _NC_WINDOWS (void) sleep(0); - +#endif free(mybuf); - return (res); + return (result); +} + +#if NCURSES_SP_FUNCS && !defined(USE_TERM_DRIVER) +NCURSES_EXPORT(int) +mcprint(char *data, int len) +{ + return NCURSES_SP_NAME(mcprint) (CURRENT_SCREEN, data, len); } +#endif diff --git a/lib/libcurses/tinfo/lib_raw.c b/lib/libcurses/tinfo/lib_raw.c index 724ba92a4a2..41a726a10c5 100644 --- a/lib/libcurses/tinfo/lib_raw.c +++ b/lib/libcurses/tinfo/lib_raw.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_raw.c,v 1.8 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_raw.c,v 1.9 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2002,2007 Free Software Foundation, Inc. * + * Copyright 2020,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,7 +32,8 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * - * and: Thomas E. Dickey 1998 on * + * and: Thomas E. Dickey 1998-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -49,13 +51,8 @@ */ #include -#include /* cur_term */ -MODULE_ID("$Id: lib_raw.c,v 1.8 2010/01/12 23:22:06 nicm Exp $") - -#if SVR4_TERMIO && !defined(_POSIX_SOURCE) -#define _POSIX_SOURCE -#endif +MODULE_ID("$Id: lib_raw.c,v 1.9 2023/10/17 09:52:09 nicm Exp $") #if HAVE_SYS_TERMIO_H #include /* needed for ISC */ @@ -63,11 +60,16 @@ MODULE_ID("$Id: lib_raw.c,v 1.8 2010/01/12 23:22:06 nicm Exp $") #ifdef __EMX__ #include -#define _nc_setmode(mode) setmode(SP->_ifd, mode) +#define _nc_setmode(mode) setmode(SP_PARM->_ifd, mode) #else #define _nc_setmode(mode) /* nothing */ #endif +#if USE_KLIBC_KBD +#define INCL_KBD +#include +#endif + #define COOKED_INPUT (IXON|BRKINT|PARMRK) #ifdef TRACE @@ -79,188 +81,276 @@ MODULE_ID("$Id: lib_raw.c,v 1.8 2010/01/12 23:22:06 nicm Exp $") #endif /* TRACE */ NCURSES_EXPORT(int) -raw(void) +NCURSES_SP_NAME(raw) (NCURSES_SP_DCL0) { int result = ERR; + TERMINAL *termp; - T((T_CALLED("raw()"))); - - if (SP != 0 && cur_term != 0) { + T((T_CALLED("raw(%p)"), (void *) SP_PARM)); + if ((termp = TerminalOf(SP_PARM)) != 0) { TTY buf; BEFORE("raw"); _nc_setmode(O_BINARY); - buf = cur_term->Nttyb; + buf = termp->Nttyb; #ifdef TERMIOS - buf.c_lflag &= ~(ICANON | ISIG | IEXTEN); - buf.c_iflag &= ~(COOKED_INPUT); + buf.c_lflag &= (unsigned) ~(ICANON | ISIG | IEXTEN); + buf.c_iflag &= (unsigned) ~(COOKED_INPUT); buf.c_cc[VMIN] = 1; buf.c_cc[VTIME] = 0; +#elif defined(EXP_WIN32_DRIVER) + buf.dwFlagIn &= (unsigned long) ~CONMODE_NORAW; #else buf.sg_flags |= RAW; #endif - if ((result = _nc_set_tty_mode(&buf)) == OK) { - SP->_raw = TRUE; - SP->_cbreak = 1; - cur_term->Nttyb = buf; + result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf); + if (result == OK) { +#if USE_KLIBC_KBD + KBDINFO kbdinfo; + + kbdinfo.cb = sizeof(kbdinfo); + KbdGetStatus(&kbdinfo, 0); + + kbdinfo.cb = sizeof(kbdinfo); + kbdinfo.fsMask &= ~KEYBOARD_ASCII_MODE; + kbdinfo.fsMask |= KEYBOARD_BINARY_MODE; + KbdSetStatus(&kbdinfo, 0); +#endif + if (SP_PARM) { + IsRaw(SP_PARM) = TRUE; + IsCbreak(SP_PARM) = 1; + } + termp->Nttyb = buf; } AFTER("raw"); } returnCode(result); } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) -cbreak(void) +raw(void) { - int result = ERR; + return NCURSES_SP_NAME(raw) (CURRENT_SCREEN); +} +#endif - T((T_CALLED("cbreak()"))); +NCURSES_EXPORT(int) +NCURSES_SP_NAME(cbreak) (NCURSES_SP_DCL0) +{ + int result = ERR; + TERMINAL *termp; - if (SP != 0 && cur_term != 0) { + T((T_CALLED("cbreak(%p)"), (void *) SP_PARM)); + if ((termp = TerminalOf(SP_PARM)) != 0) { TTY buf; BEFORE("cbreak"); _nc_setmode(O_BINARY); - buf = cur_term->Nttyb; + buf = termp->Nttyb; #ifdef TERMIOS - buf.c_lflag &= ~ICANON; - buf.c_iflag &= ~ICRNL; + buf.c_lflag &= (unsigned) ~ICANON; + buf.c_iflag &= (unsigned) ~ICRNL; buf.c_lflag |= ISIG; buf.c_cc[VMIN] = 1; buf.c_cc[VTIME] = 0; +#elif defined(EXP_WIN32_DRIVER) + buf.dwFlagIn |= CONMODE_NORAW; + buf.dwFlagIn &= (unsigned long) ~CONMODE_NOCBREAK; #else buf.sg_flags |= CBREAK; #endif - if ((result = _nc_set_tty_mode(&buf)) == OK) { - SP->_cbreak = 1; - cur_term->Nttyb = buf; + result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf); + if (result == OK) { + if (SP_PARM) { + IsCbreak(SP_PARM) = 1; + } + termp->Nttyb = buf; } AFTER("cbreak"); } returnCode(result); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +cbreak(void) +{ + return NCURSES_SP_NAME(cbreak) (CURRENT_SCREEN); +} +#endif + /* * Note: * this implementation may be wrong. See the comment under intrflush(). */ NCURSES_EXPORT(void) -qiflush(void) +NCURSES_SP_NAME(qiflush) (NCURSES_SP_DCL0) { - int result = ERR; - - T((T_CALLED("qiflush()"))); + TERMINAL *termp; - if (cur_term != 0) { + T((T_CALLED("qiflush(%p)"), (void *) SP_PARM)); + if ((termp = TerminalOf(SP_PARM)) != 0) { TTY buf; + int result; BEFORE("qiflush"); - buf = cur_term->Nttyb; + buf = termp->Nttyb; #ifdef TERMIOS - buf.c_lflag &= ~(NOFLSH); - result = _nc_set_tty_mode(&buf); + buf.c_lflag &= (unsigned) ~(NOFLSH); + result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf); #else + result = ERR; /* FIXME */ #endif if (result == OK) - cur_term->Nttyb = buf; + termp->Nttyb = buf; AFTER("qiflush"); } returnVoid; } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(void) +qiflush(void) +{ + NCURSES_SP_NAME(qiflush) (CURRENT_SCREEN); +} +#endif + NCURSES_EXPORT(int) -noraw(void) +NCURSES_SP_NAME(noraw) (NCURSES_SP_DCL0) { int result = ERR; + TERMINAL *termp; - T((T_CALLED("noraw()"))); - - if (SP != 0 && cur_term != 0) { + T((T_CALLED("noraw(%p)"), (void *) SP_PARM)); + if ((termp = TerminalOf(SP_PARM)) != 0) { TTY buf; BEFORE("noraw"); _nc_setmode(O_TEXT); - buf = cur_term->Nttyb; + buf = termp->Nttyb; #ifdef TERMIOS buf.c_lflag |= ISIG | ICANON | - (cur_term->Ottyb.c_lflag & IEXTEN); + (termp->Ottyb.c_lflag & IEXTEN); buf.c_iflag |= COOKED_INPUT; +#elif defined(EXP_WIN32_DRIVER) + buf.dwFlagIn |= CONMODE_NORAW; #else buf.sg_flags &= ~(RAW | CBREAK); #endif - if ((result = _nc_set_tty_mode(&buf)) == OK) { - SP->_raw = FALSE; - SP->_cbreak = 0; - cur_term->Nttyb = buf; + result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf); + if (result == OK) { +#if USE_KLIBC_KBD + KBDINFO kbdinfo; + + kbdinfo.cb = sizeof(kbdinfo); + KbdGetStatus(&kbdinfo, 0); + + kbdinfo.cb = sizeof(kbdinfo); + kbdinfo.fsMask &= ~KEYBOARD_BINARY_MODE; + kbdinfo.fsMask |= KEYBOARD_ASCII_MODE; + KbdSetStatus(&kbdinfo, 0); +#endif + if (SP_PARM) { + IsRaw(SP_PARM) = FALSE; + IsCbreak(SP_PARM) = 0; + } + termp->Nttyb = buf; } AFTER("noraw"); } returnCode(result); } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) -nocbreak(void) +noraw(void) { - int result = ERR; + return NCURSES_SP_NAME(noraw) (CURRENT_SCREEN); +} +#endif - T((T_CALLED("nocbreak()"))); +NCURSES_EXPORT(int) +NCURSES_SP_NAME(nocbreak) (NCURSES_SP_DCL0) +{ + int result = ERR; + TERMINAL *termp; - if (SP != 0 && cur_term != 0) { + T((T_CALLED("nocbreak(%p)"), (void *) SP_PARM)); + if ((termp = TerminalOf(SP_PARM)) != 0) { TTY buf; BEFORE("nocbreak"); _nc_setmode(O_TEXT); - buf = cur_term->Nttyb; + buf = termp->Nttyb; #ifdef TERMIOS buf.c_lflag |= ICANON; buf.c_iflag |= ICRNL; +#elif defined(EXP_WIN32_DRIVER) + buf.dwFlagIn |= (CONMODE_NOCBREAK | CONMODE_NORAW); #else buf.sg_flags &= ~CBREAK; #endif - if ((result = _nc_set_tty_mode(&buf)) == OK) { - SP->_cbreak = 0; - cur_term->Nttyb = buf; + result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf); + if (result == OK) { + if (SP_PARM) { + IsCbreak(SP_PARM) = 0; + } + termp->Nttyb = buf; } AFTER("nocbreak"); } returnCode(result); } -/* - * Note: - * this implementation may be wrong. See the comment under intrflush(). - */ -NCURSES_EXPORT(void) -noqiflush(void) +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +nocbreak(void) { - int result = ERR; + return NCURSES_SP_NAME(nocbreak) (CURRENT_SCREEN); +} +#endif - T((T_CALLED("noqiflush()"))); +NCURSES_EXPORT(void) +NCURSES_SP_NAME(noqiflush) (NCURSES_SP_DCL0) +{ + TERMINAL *termp; - if (cur_term != 0) { + T((T_CALLED("noqiflush(%p)"), (void *) SP_PARM)); + if ((termp = TerminalOf(SP_PARM)) != 0) { TTY buf; + int result; BEFORE("noqiflush"); - buf = cur_term->Nttyb; + buf = termp->Nttyb; #ifdef TERMIOS buf.c_lflag |= NOFLSH; - result = _nc_set_tty_mode(&buf); + result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf); #else /* FIXME */ + result = ERR; #endif - if (result == OK) { - cur_term->Nttyb = buf; - } + if (result == OK) + termp->Nttyb = buf; AFTER("noqiflush"); } returnVoid; } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(void) +noqiflush(void) +{ + NCURSES_SP_NAME(noqiflush) (CURRENT_SCREEN); +} +#endif + /* * This call does the same thing as the qiflush()/noqiflush() pair. We know * for certain that SVr3 intrflush() tweaks the NOFLSH bit; on the other hand, @@ -269,30 +359,82 @@ noqiflush(void) * curs_inopts(3x) is too exact to be coincidence. */ NCURSES_EXPORT(int) -intrflush(WINDOW *win GCC_UNUSED, bool flag) +NCURSES_SP_NAME(intrflush) (NCURSES_SP_DCLx WINDOW *win GCC_UNUSED, bool flag) { int result = ERR; + TERMINAL *termp; - T((T_CALLED("intrflush(%d)"), flag)); + T((T_CALLED("intrflush(%p,%d)"), (void *) SP_PARM, flag)); + if (SP_PARM == 0) + returnCode(ERR); - if (cur_term != 0) { + if ((termp = TerminalOf(SP_PARM)) != 0) { TTY buf; BEFORE("intrflush"); - buf = cur_term->Nttyb; + buf = termp->Nttyb; #ifdef TERMIOS if (flag) - buf.c_lflag &= ~(NOFLSH); + buf.c_lflag &= (unsigned) ~(NOFLSH); else buf.c_lflag |= (NOFLSH); - result = _nc_set_tty_mode(&buf); + result = NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx &buf); #else /* FIXME */ #endif if (result == OK) { - cur_term->Nttyb = buf; + termp->Nttyb = buf; } AFTER("intrflush"); } returnCode(result); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +intrflush(WINDOW *win GCC_UNUSED, bool flag) +{ + return NCURSES_SP_NAME(intrflush) (CURRENT_SCREEN, win, flag); +} +#endif + +#if NCURSES_EXT_FUNCS + +/* + * SCREEN is always opaque, but nl/raw/cbreak/echo set properties in it. + * As an extension, provide a way to query the properties. + * + * There are other properties which could be queried, e.g., filter, keypad, + * use_env, use_meta, but these particular properties are saved/restored within + * the wgetnstr() and wgetn_wstr() functions, which requires that the higher + * level curses library knows about the internal state of the lower level + * terminfo library. + */ + +#define is_TEST(show,what) \ + NCURSES_EXPORT(int) \ + NCURSES_SP_NAME(show) (NCURSES_SP_DCL0) \ + { \ + return ((SP_PARM != NULL) ? (what(SP_PARM) ? 1 : 0) : -1); \ + } + +is_TEST(is_nl, IsNl); +is_TEST(is_raw, IsRaw); +is_TEST(is_cbreak, IsCbreak); +is_TEST(is_echo, IsEcho); + +#if NCURSES_SP_FUNCS +#undef is_TEST +#define is_TEST(show) \ + NCURSES_EXPORT(int) \ + show(void) \ + { \ + return NCURSES_SP_NAME(show) (CURRENT_SCREEN); \ + } +is_TEST(is_nl); +is_TEST(is_raw); +is_TEST(is_cbreak); +is_TEST(is_echo); +#endif + +#endif /* extensions */ diff --git a/lib/libcurses/tinfo/lib_setup.c b/lib/libcurses/tinfo/lib_setup.c index e6552263a44..335b8893626 100644 --- a/lib/libcurses/tinfo/lib_setup.c +++ b/lib/libcurses/tinfo/lib_setup.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_setup.c,v 1.13 2021/03/10 20:16:08 millert Exp $ */ +/* $OpenBSD: lib_setup.c,v 1.14 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,30 +33,25 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* * Terminal setup routines common to termcap and terminfo: * * use_env(bool) + * use_tioctl(bool) * setupterm(char *, int, int *) */ #include #include /* for MAX_NAME_SIZE */ -#include - -#if SVR4_TERMIO && !defined(_POSIX_SOURCE) -#define _POSIX_SOURCE -#endif #if HAVE_LOCALE_H #include #endif -#include /* lines, columns, cur_term */ - -MODULE_ID("$Id: lib_setup.c,v 1.13 2021/03/10 20:16:08 millert Exp $") +MODULE_ID("$Id: lib_setup.c,v 1.14 2023/10/17 09:52:09 nicm Exp $") /**************************************************************************** * @@ -72,7 +68,7 @@ MODULE_ID("$Id: lib_setup.c,v 1.13 2021/03/10 20:16:08 millert Exp $") #endif #if NEED_PTEM_H - /* On SCO, they neglected to define struct winsize in termios.h -- it's only + /* On SCO, they neglected to define struct winsize in termios.h -- it is only * in termio.h and ptem.h (the former conflicts with other definitions). */ # include @@ -105,67 +101,106 @@ MODULE_ID("$Id: lib_setup.c,v 1.13 2021/03/10 20:16:08 millert Exp $") * Reduce explicit use of "cur_term" global variable. */ #undef CUR -#define CUR termp->type. +#define CUR TerminalType(termp). /* * Wrap global variables in this module. */ #if USE_REENTRANT + NCURSES_EXPORT(char *) NCURSES_PUBLIC_VAR(ttytype) (void) { static char empty[] = ""; - return cur_term ? cur_term->type.term_names : empty; + char *result = empty; + +#if NCURSES_SP_FUNCS + if (CURRENT_SCREEN) { + TERMINAL *termp = TerminalOf(CURRENT_SCREEN); + if (termp != 0) { + result = TerminalType(termp).term_names; + } + } +#else + if (cur_term != 0) { + result = TerminalType(cur_term).term_names; + } +#endif + return result; } + NCURSES_EXPORT(int *) -_nc_ptr_Lines(void) +_nc_ptr_Lines(SCREEN *sp) { - return ptrLines(); + return ptrLines(sp); } + NCURSES_EXPORT(int) NCURSES_PUBLIC_VAR(LINES) (void) { - return *_nc_ptr_Lines(); + return *_nc_ptr_Lines(CURRENT_SCREEN); } + NCURSES_EXPORT(int *) -_nc_ptr_Cols(void) +_nc_ptr_Cols(SCREEN *sp) { - return ptrCols(); + return ptrCols(sp); } + NCURSES_EXPORT(int) NCURSES_PUBLIC_VAR(COLS) (void) { - return *_nc_ptr_Cols(); + return *_nc_ptr_Cols(CURRENT_SCREEN); } + +NCURSES_EXPORT(int *) +_nc_ptr_Tabsize(SCREEN *sp) +{ + return ptrTabsize(sp); +} + NCURSES_EXPORT(int) NCURSES_PUBLIC_VAR(TABSIZE) (void) { - return SP ? SP->_TABSIZE : 8; + return *_nc_ptr_Tabsize(CURRENT_SCREEN); } #else NCURSES_EXPORT_VAR(char) ttytype[NAMESIZE] = ""; NCURSES_EXPORT_VAR(int) LINES = 0; NCURSES_EXPORT_VAR(int) COLS = 0; -NCURSES_EXPORT_VAR(int) TABSIZE = 0; +NCURSES_EXPORT_VAR(int) TABSIZE = 8; #endif #if NCURSES_EXT_FUNCS NCURSES_EXPORT(int) -set_tabsize(int value) +NCURSES_SP_NAME(set_tabsize) (NCURSES_SP_DCLx int value) { int code = OK; -#if USE_REENTRANT - if (SP) { - SP->_TABSIZE = value; - } else { + if (value <= 0) { code = ERR; - } + } else { +#if USE_REENTRANT + if (SP_PARM) { + SP_PARM->_TABSIZE = value; + } else { + code = ERR; + } #else - TABSIZE = value; + (void) SP_PARM; + TABSIZE = value; #endif + } return code; } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +set_tabsize(int value) +{ + return NCURSES_SP_NAME(set_tabsize) (CURRENT_SCREEN, value); +} #endif +#endif /* NCURSES_EXT_FUNCS */ #if USE_SIGWINCH /* @@ -189,78 +224,174 @@ _nc_handle_sigwinch(SCREEN *sp) #endif +NCURSES_EXPORT(void) +NCURSES_SP_NAME(use_env) (NCURSES_SP_DCLx bool f) +{ + START_TRACE(); + T((T_CALLED("use_env(%p,%d)"), (void *) SP_PARM, (int) f)); +#if NCURSES_SP_FUNCS + if (IsPreScreen(SP_PARM)) { + SP_PARM->_use_env = f; + } +#else + _nc_prescreen.use_env = f; +#endif + returnVoid; +} + +NCURSES_EXPORT(void) +NCURSES_SP_NAME(use_tioctl) (NCURSES_SP_DCLx bool f) +{ + START_TRACE(); + T((T_CALLED("use_tioctl(%p,%d)"), (void *) SP_PARM, (int) f)); +#if NCURSES_SP_FUNCS + if (IsPreScreen(SP_PARM)) { + SP_PARM->use_tioctl = f; + } +#else + _nc_prescreen.use_tioctl = f; +#endif + returnVoid; +} + +#if NCURSES_SP_FUNCS NCURSES_EXPORT(void) use_env(bool f) { - T((T_CALLED("use_env()"))); + START_TRACE(); + T((T_CALLED("use_env(%d)"), (int) f)); _nc_prescreen.use_env = f; returnVoid; } NCURSES_EXPORT(void) -_nc_get_screensize(SCREEN *sp, int *linep, int *colp) +use_tioctl(bool f) +{ + START_TRACE(); + T((T_CALLED("use_tioctl(%d)"), (int) f)); + _nc_prescreen.use_tioctl = f; + returnVoid; +} +#endif + +NCURSES_EXPORT(void) +_nc_get_screensize(SCREEN *sp, +#ifdef USE_TERM_DRIVER + TERMINAL *termp, +#endif + int *linep, int *colp) /* Obtain lines/columns values from the environment and/or terminfo entry */ { +#ifdef USE_TERM_DRIVER + TERMINAL_CONTROL_BLOCK *TCB; + int my_tabsize; + + assert(termp != 0 && linep != 0 && colp != 0); + TCB = (TERMINAL_CONTROL_BLOCK *) termp; + + my_tabsize = TCB->info.tabsize; + TCB->drv->td_size(TCB, linep, colp); + +#if USE_REENTRANT + if (sp != 0) { + sp->_TABSIZE = my_tabsize; + } +#else + (void) sp; + TABSIZE = my_tabsize; +#endif + T(("TABSIZE = %d", my_tabsize)); +#else /* !USE_TERM_DRIVER */ TERMINAL *termp = cur_term; int my_tabsize; + bool useEnv = _nc_prescreen.use_env; + bool useTioctl = _nc_prescreen.use_tioctl; +#ifdef EXP_WIN32_DRIVER + /* If we are here, then Windows console is used in terminfo mode. + We need to figure out the size using the console API + */ + _nc_console_size(linep, colp); + T(("screen size: winconsole lines = %d columns = %d", *linep, *colp)); +#else /* figure out the size of the screen */ T(("screen size: terminfo lines = %d columns = %d", lines, columns)); - if (!_nc_prescreen.use_env) { - *linep = (int) lines; - *colp = (int) columns; - } else { /* usually want to query LINES and COLUMNS from environment */ - int value; - - *linep = *colp = 0; + *linep = (int) lines; + *colp = (int) columns; +#endif - /* first, look for environment variables */ - if ((value = _nc_getenv_num("LINES")) > 0) { - *linep = value; - } - if ((value = _nc_getenv_num("COLUMNS")) > 0) { - *colp = value; - } - T(("screen size: environment LINES = %d COLUMNS = %d", *linep, *colp)); +#if NCURSES_SP_FUNCS + if (sp) { + useEnv = sp->_use_env; + useTioctl = sp->use_tioctl; + } +#endif + if (useEnv || useTioctl) { #ifdef __EMX__ - if (*linep <= 0 || *colp <= 0) { + { int screendata[2]; _scrsize(screendata); *colp = screendata[0]; - *linep = screendata[1]; + *linep = ((sp != 0 && sp->_filtered) + ? 1 + : screendata[1]); T(("EMX screen size: environment LINES = %d COLUMNS = %d", *linep, *colp)); } #endif #if HAVE_SIZECHANGE - /* if that didn't work, maybe we can try asking the OS */ - if (*linep <= 0 || *colp <= 0) { - if (isatty(cur_term->Filedes)) { - STRUCT_WINSIZE size; - - errno = 0; - do { - if (ioctl(cur_term->Filedes, IOCTL_WINSIZE, &size) < 0 - && errno != EINTR) - goto failure; - } while - (errno == EINTR); + /* try asking the OS */ + if (NC_ISATTY(cur_term->Filedes)) { + STRUCT_WINSIZE size; + + errno = 0; + do { + if (ioctl(cur_term->Filedes, IOCTL_WINSIZE, &size) >= 0) { + *linep = ((sp != 0 && sp->_filtered) + ? 1 + : WINSIZE_ROWS(size)); + *colp = WINSIZE_COLS(size); + T(("SYS screen size: environment LINES = %d COLUMNS = %d", + *linep, *colp)); + break; + } + } while + (errno == EINTR); + } +#endif /* HAVE_SIZECHANGE */ + + if (useEnv) { + int value; + if (useTioctl) { /* - * Solaris lets users override either dimension with an - * environment variable. + * If environment variables are used, update them. */ - if (*linep <= 0) - *linep = (sp != 0 && sp->_filtered) ? 1 : WINSIZE_ROWS(size); - if (*colp <= 0) - *colp = WINSIZE_COLS(size); + if ((sp == 0 || !sp->_filtered) && _nc_getenv_num("LINES") > 0) { + _nc_setenv_num("LINES", *linep); + } + if (_nc_getenv_num("COLUMNS") > 0) { + _nc_setenv_num("COLUMNS", *colp); + } + } + + /* + * Finally, look for environment variables. + * + * Solaris lets users override either dimension with an environment + * variable. + */ + if ((value = _nc_getenv_num("LINES")) > 0) { + *linep = value; + T(("screen size: environment LINES = %d", *linep)); + } + if ((value = _nc_getenv_num("COLUMNS")) > 0) { + *colp = value; + T(("screen size: environment COLUMNS = %d", *colp)); } - /* FALLTHRU */ - failure:; } -#endif /* HAVE_SIZECHANGE */ /* if we can't get dynamic info about the size, use static */ if (*linep <= 0) { @@ -282,8 +413,14 @@ _nc_get_screensize(SCREEN *sp, int *linep, int *colp) * Put the derived values back in the screen-size caps, so * tigetnum() and tgetnum() will do the right thing. */ - lines = (short) (*linep); - columns = (short) (*colp); + lines = (NCURSES_INT2) (*linep); + columns = (NCURSES_INT2) (*colp); +#if NCURSES_EXT_NUMBERS +#define OldNumber(termp,name) \ + (termp)->type.Numbers[(&name - (termp)->type2.Numbers)] + OldNumber(termp, lines) = (short) (*linep); + OldNumber(termp, columns) = (short) (*colp); +#endif } T(("screen size is %dx%d", *linep, *colp)); @@ -300,36 +437,48 @@ _nc_get_screensize(SCREEN *sp, int *linep, int *colp) TABSIZE = my_tabsize; #endif T(("TABSIZE = %d", TABSIZE)); +#endif /* USE_TERM_DRIVER */ } #if USE_SIZECHANGE NCURSES_EXPORT(void) _nc_update_screensize(SCREEN *sp) { - TERMINAL *termp = cur_term; - int old_lines = lines; int new_lines; - int old_cols = columns; int new_cols; - _nc_get_screensize(sp, &new_lines, &new_cols); +#ifdef USE_TERM_DRIVER + int old_lines; + int old_cols; - /* - * See is_term_resized() and resizeterm(). - * We're doing it this way because those functions belong to the upper - * ncurses library, while this resides in the lower terminfo library. - */ - if (sp != 0 - && sp->_resize != 0) { - if ((new_lines != old_lines) || (new_cols != old_cols)) { - sp->_resize(new_lines, new_cols); - } else if (sp->_sig_winch && (sp->_ungetch != 0)) { - sp->_ungetch(SP, KEY_RESIZE); /* so application can know this */ + assert(sp != 0); + + CallDriver_2(sp, td_getsize, &old_lines, &old_cols); + +#else + TERMINAL *termp = cur_term; + int old_lines = lines; + int old_cols = columns; +#endif + + if (sp != 0) { + TINFO_GET_SIZE(sp, sp->_term, &new_lines, &new_cols); + /* + * See is_term_resized() and resizeterm(). + * We're doing it this way because those functions belong to the upper + * ncurses library, while this resides in the lower terminfo library. + */ + if (sp->_resize != 0) { + if ((new_lines != old_lines) || (new_cols != old_cols)) { + sp->_resize(NCURSES_SP_ARGx new_lines, new_cols); + } else if (sp->_sig_winch && (sp->_ungetch != 0)) { + sp->_ungetch(SP_PARM, KEY_RESIZE); /* so application can know this */ + } + sp->_sig_winch = FALSE; } - sp->_sig_winch = FALSE; } } -#endif +#endif /* USE_SIZECHANGE */ /**************************************************************************** * @@ -337,32 +486,16 @@ _nc_update_screensize(SCREEN *sp) * ****************************************************************************/ -#define ret_error(code, fmt, arg) if (errret) {\ - *errret = code;\ - returnCode(ERR);\ - } else {\ - fprintf(stderr, fmt, arg);\ - exit(EXIT_FAILURE);\ - } - -#define ret_error0(code, msg) if (errret) {\ - *errret = code;\ - returnCode(ERR);\ - } else {\ - fprintf(stderr, msg);\ - exit(EXIT_FAILURE);\ - } - -#if USE_DATABASE || USE_TERMCAP +#if NCURSES_USE_DATABASE || NCURSES_USE_TERMCAP /* * Return 1 if entry found, 0 if not found, -1 if database not accessible, * just like tgetent(). */ -static int -grab_entry(const char *const tn, TERMTYPE *const tp) +int +_nc_setup_tinfo(const char *const tn, TERMTYPE2 *const tp) { char filename[PATH_MAX]; - int status = _nc_read_entry(tn, filename, tp); + int status = _nc_read_entry2(tn, filename, tp); /* * If we have an entry, force all of the cancelled strings to null @@ -386,28 +519,27 @@ grab_entry(const char *const tn, TERMTYPE *const tp) #endif /* -** do_prototype() -** ** Take the real command character out of the CC environment variable ** and substitute it in for the prototype given in 'command_character'. */ -static void -do_prototype(TERMINAL * termp) +void +_nc_tinfo_cmdch(TERMINAL *termp, int proto) { - unsigned i; - char CC; - char proto; char *tmp; - if ((tmp = getenv("CC")) != 0) { - if ((CC = *tmp) != 0) { - proto = *command_character; - - for_each_string(i, &(termp->type)) { - for (tmp = termp->type.Strings[i]; *tmp; tmp++) { - if (*tmp == proto) - *tmp = CC; - } + /* + * Only use the character if the string is a single character, + * since it is fairly common for developers to set the C compiler + * name as an environment variable - using the same symbol. + */ + if ((tmp = getenv("CC")) != 0 && strlen(tmp) == 1) { + unsigned i; + char CC = *tmp; + + for_each_string(i, &(termp->type)) { + for (tmp = termp->type.Strings[i]; tmp && *tmp; tmp++) { + if (UChar(*tmp) == proto) + *tmp = CC; } } } @@ -427,9 +559,9 @@ _nc_get_locale(void) */ env = setlocale(LC_CTYPE, 0); #else - if (((env = getenv("LC_ALL")) != 0 && *env != '\0') + if (((env = getenv("LANG")) != 0 && *env != '\0') || ((env = getenv("LC_CTYPE")) != 0 && *env != '\0') - || ((env = getenv("LANG")) != 0 && *env != '\0')) { + || ((env = getenv("LC_ALL")) != 0 && *env != '\0')) { ; } #endif @@ -444,7 +576,9 @@ NCURSES_EXPORT(int) _nc_unicode_locale(void) { int result = 0; -#if HAVE_LANGINFO_CODESET +#if defined(_NC_WINDOWS) && USE_WIDEC_SUPPORT + result = 1; +#elif HAVE_LANGINFO_CODESET char *env = nl_langinfo(CODESET); result = !strcmp(env, "UTF-8"); T(("_nc_unicode_locale(%s) ->%d", env, result)); @@ -468,63 +602,104 @@ _nc_unicode_locale(void) * character set. */ NCURSES_EXPORT(int) -_nc_locale_breaks_acs(TERMINAL * termp) +_nc_locale_breaks_acs(TERMINAL *termp) { - char *env; + const char *env_name = "NCURSES_NO_UTF8_ACS"; + const char *env; + int value; + int result = 0; - if ((env = getenv("NCURSES_NO_UTF8_ACS")) != 0) { - return atoi(env); + T((T_CALLED("_nc_locale_breaks_acs:%d"), result)); + if (getenv(env_name) != 0) { + result = _nc_getenv_num(env_name); + } else if ((value = tigetnum("U8")) >= 0) { + result = value; /* use extension feature */ } else if ((env = getenv("TERM")) != 0) { - if (strstr(env, "linux")) - return 1; /* always broken */ - if (strstr(env, "screen") != 0 - && ((env = getenv("TERMCAP")) != 0 - && strstr(env, "screen") != 0) - && strstr(env, "hhII00") != 0) { + if (strstr(env, "linux")) { + result = 1; /* always broken */ + } else if (strstr(env, "screen") != 0 + && ((env = getenv("TERMCAP")) != 0 + && strstr(env, "screen") != 0) + && strstr(env, "hhII00") != 0) { if (CONTROL_N(enter_alt_charset_mode) || CONTROL_O(enter_alt_charset_mode) || CONTROL_N(set_attributes) || - CONTROL_O(set_attributes)) - return 1; + CONTROL_O(set_attributes)) { + result = 1; + } } } - return 0; + returnCode(result); } -/* - * This entrypoint is called from tgetent() to allow a special case of reusing - * the same TERMINAL data (see comment). - */ NCURSES_EXPORT(int) -_nc_setupterm(NCURSES_CONST char *tname, int Filedes, int *errret, bool reuse) +TINFO_SETUP_TERM(TERMINAL **tp, + const char *tname, + int Filedes, + int *errret, + int reuse) { +#ifdef USE_TERM_DRIVER + TERMINAL_CONTROL_BLOCK *TCB = 0; +#endif TERMINAL *termp; - int status; + SCREEN *sp = 0; + char *myname; + int code = ERR; START_TRACE(); - T((T_CALLED("setupterm(%s,%d,%p)"), _nc_visbuf(tname), Filedes, errret)); + +#ifdef USE_TERM_DRIVER + T((T_CALLED("_nc_setupterm_ex(%p,%s,%d,%p)"), + (void *) tp, _nc_visbuf(tname), Filedes, (void *) errret)); + + if (tp == 0) { + ret_error0(TGETENT_ERR, + "Invalid parameter, internal error.\n"); + } else + termp = *tp; +#else + termp = cur_term; + T((T_CALLED("setupterm(%s,%d,%p)"), _nc_visbuf(tname), Filedes, (void *) errret)); +#endif if (tname == 0) { tname = getenv("TERM"); - if (tname == 0 || *tname == '\0') { +#if defined(EXP_WIN32_DRIVER) + if (!VALID_TERM_ENV(tname, NO_TERMINAL)) { + T(("Failure with TERM=%s", NonNull(tname))); ret_error0(TGETENT_ERR, "TERM environment variable not set.\n"); } +#elif defined(USE_TERM_DRIVER) + if (!NonEmpty(tname)) + tname = "unknown"; +#else + if (!NonEmpty(tname)) { + T(("Failure with TERM=%s", NonNull(tname))); + ret_error0(TGETENT_ERR, "TERM environment variable not set.\n"); + } +#endif } - - if (strlen(tname) > MAX_NAME_SIZE) { + myname = strdup(tname); + if (myname == NULL || strlen(myname) > MAX_NAME_SIZE) { ret_error(TGETENT_ERR, - "TERM environment must be <= %d characters.\n", - MAX_NAME_SIZE); + "TERM environment must be 1..%d characters.\n", + MAX_NAME_SIZE, + free(myname)); } - T(("your terminal name is %s", tname)); + T(("your terminal name is %s", myname)); /* * Allow output redirection. This is what SVr3 does. If stdout is * directed to a file, screen updates go to standard error. */ - if (Filedes == STDOUT_FILENO && !isatty(Filedes)) + if (Filedes == STDOUT_FILENO && !NC_ISATTY(Filedes)) Filedes = STDERR_FILENO; +#if defined(EXP_WIN32_DRIVER) + if (Filedes != STDERR_FILENO && NC_ISATTY(Filedes)) + _setmode(Filedes, _O_BINARY); +#endif /* * Check if we have already initialized to use this terminal. If so, we @@ -543,32 +718,83 @@ _nc_setupterm(NCURSES_CONST char *tname, int Filedes, int *errret, bool reuse) * properly with this feature). */ if (reuse - && (termp = cur_term) != 0 + && (termp != 0) && termp->Filedes == Filedes && termp->_termname != 0 - && !strcmp(termp->_termname, tname) - && _nc_name_match(termp->type.term_names, tname, "|")) { + && !strcmp(termp->_termname, myname) + && _nc_name_match(TerminalType(termp).term_names, myname, "|")) { T(("reusing existing terminal information and mode-settings")); + code = OK; +#ifdef USE_TERM_DRIVER + TCB = (TERMINAL_CONTROL_BLOCK *) termp; +#endif } else { +#ifdef USE_TERM_DRIVER + TERMINAL_CONTROL_BLOCK *my_tcb; + termp = 0; + if ((my_tcb = typeCalloc(TERMINAL_CONTROL_BLOCK, 1)) != 0) + termp = &(my_tcb->term); +#else + int status; termp = typeCalloc(TERMINAL, 1); - +#endif if (termp == 0) { - ret_error0(TGETENT_ERR, - "Not enough memory to create terminal structure.\n"); + ret_error1(TGETENT_ERR, + "Not enough memory to create terminal structure.\n", + myname, free(myname)); } -#if USE_DATABASE || USE_TERMCAP - status = grab_entry(tname, &termp->type); + ++_nc_globals.terminal_count; +#if HAVE_SYSCONF + { + long limit; +#ifdef LINE_MAX + limit = LINE_MAX; #else + limit = _nc_globals.getstr_limit; +#endif +#ifdef _SC_LINE_MAX + if (limit < sysconf(_SC_LINE_MAX)) + limit = sysconf(_SC_LINE_MAX); +#endif + if (_nc_globals.getstr_limit < (int) limit) + _nc_globals.getstr_limit = (int) limit; + } +#endif /* HAVE_SYSCONF */ + T(("using %d for getstr limit", _nc_globals.getstr_limit)); + +#ifdef USE_TERM_DRIVER + INIT_TERM_DRIVER(); + /* + * _nc_get_driver() will call td_CanHandle() for each driver, and win_driver + * needs file descriptor to do the test, so set it before calling. + */ + termp->Filedes = (short) Filedes; + TCB = (TERMINAL_CONTROL_BLOCK *) termp; + code = _nc_globals.term_driver(TCB, myname, errret); + if (code == OK) { + termp->_termname = strdup(myname); + } else { + ret_error1(errret ? *errret : TGETENT_ERR, + "Could not find any driver to handle terminal.\n", + myname, free(myname)); + } +#else +#if NCURSES_USE_DATABASE || NCURSES_USE_TERMCAP + status = _nc_setup_tinfo(myname, &TerminalType(termp)); + T(("_nc_setup_tinfo returns %d", status)); +#else + T(("no database available")); status = TGETENT_NO; #endif /* try fallback list if entry on disk */ if (status != TGETENT_YES) { - const TERMTYPE *fallback = _nc_fallback(tname); + const TERMTYPE2 *fallback = _nc_fallback2(myname); if (fallback) { - termp->type = *fallback; + T(("found fallback entry")); + _nc_copy_termtype2(&(TerminalType(termp)), fallback); status = TGETENT_YES; } } @@ -576,52 +802,215 @@ _nc_setupterm(NCURSES_CONST char *tname, int Filedes, int *errret, bool reuse) if (status != TGETENT_YES) { del_curterm(termp); if (status == TGETENT_ERR) { + free(myname); ret_error0(status, "terminals database is inaccessible\n"); } else if (status == TGETENT_NO) { - ret_error(status, "'%s': unknown terminal type.\n", tname); + ret_error1(status, "unknown terminal type.\n", + myname, free(myname)); + } else { + free(myname); + ret_error0(status, "unexpected return-code\n"); } } +#if NCURSES_EXT_NUMBERS + _nc_export_termtype2(&termp->type, &TerminalType(termp)); +#endif #if !USE_REENTRANT - strncpy(ttytype, termp->type.term_names, NAMESIZE - 1); - ttytype[NAMESIZE - 1] = '\0'; + save_ttytype(termp); #endif - termp->Filedes = Filedes; - termp->_termname = strdup(tname); + termp->Filedes = (short) Filedes; + termp->_termname = strdup(myname); set_curterm(termp); - if (command_character && getenv("CC")) - do_prototype(termp); + if (command_character) + _nc_tinfo_cmdch(termp, UChar(*command_character)); /* * If an application calls setupterm() rather than initscr() or * newterm(), we will not have the def_prog_mode() call in * _nc_setupscreen(). Do it now anyway, so we can initialize the - * baudrate. + * baudrate. Also get the shell-mode so that erasechar() works. */ - if (isatty(Filedes)) { - def_prog_mode(); - baudrate(); + if (NC_ISATTY(Filedes)) { + NCURSES_SP_NAME(def_shell_mode) (NCURSES_SP_ARG); + NCURSES_SP_NAME(def_prog_mode) (NCURSES_SP_ARG); + NCURSES_SP_NAME(baudrate) (NCURSES_SP_ARG); } + code = OK; +#endif } +#ifdef USE_TERM_DRIVER + *tp = termp; + NCURSES_SP_NAME(set_curterm) (sp, termp); + TCB->drv->td_init(TCB); +#else + sp = SP; +#endif + /* * We should always check the screensize, just in case. */ - _nc_get_screensize(SP, ptrLines(), ptrCols()); + TINFO_GET_SIZE(sp, termp, ptrLines(sp), ptrCols(sp)); if (errret) *errret = TGETENT_YES; +#ifndef USE_TERM_DRIVER if (generic_type) { - ret_error(TGETENT_NO, "'%s': I need something more specific.\n", tname); + /* + * BSD 4.3's termcap contains mis-typed "gn" for wy99. Do a sanity + * check before giving up. + */ + if ((VALID_STRING(cursor_address) + || (VALID_STRING(cursor_down) && VALID_STRING(cursor_home))) + && VALID_STRING(clear_screen)) { + ret_error1(TGETENT_YES, "terminal is not really generic.\n", + myname, free(myname)); + } else { + del_curterm(termp); + ret_error1(TGETENT_NO, "I need something more specific.\n", + myname, free(myname)); + } + } else if (hard_copy) { + ret_error1(TGETENT_YES, "I can't handle hardcopy terminals.\n", + myname, free(myname)); + } +#endif + free(myname); + returnCode(code); +} + +#ifdef USE_PTHREADS +/* + * Returns a non-null pointer unless a new screen should be allocated because + * no match was found in the pre-screen cache. + */ +NCURSES_EXPORT(SCREEN *) +_nc_find_prescr(void) +{ + SCREEN *result = 0; + PRESCREEN_LIST *p; + pthread_t id = GetThreadID(); + for (p = _nc_prescreen.allocated; p != 0; p = p->next) { + if (p->id == id) { + result = p->sp; + break; + } + } + return result; +} + +/* + * Tells ncurses to forget that this thread was associated with the pre-screen + * cache. It does not modify the pre-screen cache itself, since that is used + * for creating new screens. + */ +NCURSES_EXPORT(void) +_nc_forget_prescr(void) +{ + PRESCREEN_LIST *p, *q; + pthread_t id = GetThreadID(); + _nc_lock_global(screen); + for (p = _nc_prescreen.allocated, q = 0; p != 0; q = p, p = p->next) { + if (p->id == id) { + if (q) { + q->next = p->next; + } else { + _nc_prescreen.allocated = p->next; + } + free(p); + break; + } + } + _nc_unlock_global(screen); +} +#endif /* USE_PTHREADS */ + +#if NCURSES_SP_FUNCS +/* + * In case of handling multiple screens, we need to have a screen before + * initialization in _nc_setupscreen takes place. This is to extend the + * substitute for some of the stuff in _nc_prescreen, especially for slk and + * ripoff handling which should be done per screen. + */ +NCURSES_EXPORT(SCREEN *) +new_prescr(void) +{ + SCREEN *sp; + + START_TRACE(); + T((T_CALLED("new_prescr()"))); + + _nc_lock_global(screen); + if ((sp = _nc_find_prescr()) == 0) { + sp = _nc_alloc_screen_sp(); + T(("_nc_alloc_screen_sp %p", (void *) sp)); + if (sp != 0) { +#ifdef USE_PTHREADS + PRESCREEN_LIST *p = typeCalloc(PRESCREEN_LIST, 1); + if (p != 0) { + p->id = GetThreadID(); + p->sp = sp; + p->next = _nc_prescreen.allocated; + _nc_prescreen.allocated = p; + } +#else + _nc_prescreen.allocated = sp; +#endif + sp->rsp = sp->rippedoff; + sp->_filtered = _nc_prescreen.filter_mode; + sp->_use_env = _nc_prescreen.use_env; +#if NCURSES_NO_PADDING + sp->_no_padding = _nc_prescreen._no_padding; +#endif + sp->slk_format = 0; + sp->_slk = 0; + sp->_prescreen = TRUE; + SP_PRE_INIT(sp); +#if USE_REENTRANT + sp->_TABSIZE = _nc_prescreen._TABSIZE; + sp->_ESCDELAY = _nc_prescreen._ESCDELAY; +#endif + } + } else { + T(("_nc_alloc_screen_sp %p (reuse)", (void *) sp)); } - if (hard_copy) { - ret_error(TGETENT_YES, "'%s': I can't handle hardcopy terminals.\n", tname); + _nc_unlock_global(screen); + returnSP(sp); +} +#endif + +#ifdef USE_TERM_DRIVER +/* + * This entrypoint is called from tgetent() to allow a special case of reusing + * the same TERMINAL data (see comment). + */ +NCURSES_EXPORT(int) +_nc_setupterm(const char *tname, + int Filedes, + int *errret, + int reuse) +{ + int rc = ERR; + TERMINAL *termp = 0; + + _nc_init_pthreads(); + _nc_lock_global(prescreen); + START_TRACE(); + if (TINFO_SETUP_TERM(&termp, tname, Filedes, errret, reuse) == OK) { + _nc_forget_prescr(); + if (NCURSES_SP_NAME(set_curterm) (CURRENT_SCREEN_PRE, termp) != 0) { + rc = OK; + } } - returnCode(OK); + _nc_unlock_global(prescreen); + + return rc; } +#endif /* * setupterm(termname, Filedes, errret) @@ -630,7 +1019,8 @@ _nc_setupterm(NCURSES_CONST char *tname, int Filedes, int *errret, bool reuse) * Make cur_term point to the structure. */ NCURSES_EXPORT(int) -setupterm(NCURSES_CONST char *tname, int Filedes, int *errret) +setupterm(const char *tname, int Filedes, int *errret) { + START_TRACE(); return _nc_setupterm(tname, Filedes, errret, FALSE); } diff --git a/lib/libcurses/tinfo/lib_termcap.c b/lib/libcurses/tinfo/lib_termcap.c index 66ccb8cf63d..55185fa321c 100644 --- a/lib/libcurses/tinfo/lib_termcap.c +++ b/lib/libcurses/tinfo/lib_termcap.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_termcap.c,v 1.10 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_termcap.c,v 1.11 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2020,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,6 +33,7 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer * * * * some of the code in here was contributed by: * * Magnus Bengtsson, d6mbeng@dtek.chalmers.se (Nov'93) * @@ -45,9 +47,11 @@ #include #include -#include +#ifndef CUR +#define CUR SP_TERMTYPE +#endif -MODULE_ID("$Id: lib_termcap.c,v 1.10 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_termcap.c,v 1.11 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT_VAR(char *) UP = 0; NCURSES_EXPORT_VAR(char *) BC = 0; @@ -62,6 +66,15 @@ NCURSES_EXPORT_VAR(char *) BC = 0; #define LAST_USE MyCache[CacheInx].last_used #define LAST_SEQ MyCache[CacheInx].sequence +/* + * Termcap names are matched only using the first two bytes. + * Ignore any extended names longer than two bytes, to avoid problems + * with legacy code which passes in parameters whose use is long forgotten. + */ +#define ValidCap(cap) (((cap)[0] != '\0') && ((cap)[1] != '\0')) +#define SameCap(a,b) (((a)[0] == (b)[0]) && ((a)[1] == (b)[1])) +#define ValidExt(ext) (ValidCap(ext) && (ext)[2] == '\0') + /*************************************************************************** * * tgetent(bufp, term) @@ -78,16 +91,25 @@ NCURSES_EXPORT_VAR(char *) BC = 0; ***************************************************************************/ NCURSES_EXPORT(int) -tgetent(char *bufp, const char *name) +NCURSES_SP_NAME(tgetent) (NCURSES_SP_DCLx char *bufp, const char *name) { - int errcode; + int rc = ERR; int n; bool found_cache = FALSE; +#ifdef USE_TERM_DRIVER + TERMINAL *termp = 0; +#endif START_TRACE(); T((T_CALLED("tgetent()"))); - _nc_setupterm((NCURSES_CONST char *) name, STDOUT_FILENO, &errcode, TRUE); + TINFO_SETUP_TERM(&termp, name, STDOUT_FILENO, &rc, TRUE); + +#ifdef USE_TERM_DRIVER + if (termp == 0 || + !((TERMINAL_CONTROL_BLOCK *) termp)->drv->isTerminfo) + returnCode(rc); +#endif /* * In general we cannot tell if the fixed sgr0 is still used by the @@ -111,9 +133,9 @@ tgetent(char *bufp, const char *name) /* * Also free the terminfo data that we loaded (much bigger leak). */ - if (LAST_TRM != 0 && LAST_TRM != cur_term) { + if (LAST_TRM != 0 && LAST_TRM != TerminalOf(SP_PARM)) { TERMINAL *trm = LAST_TRM; - del_curterm(LAST_TRM); + NCURSES_SP_NAME(del_curterm) (NCURSES_SP_ARGx LAST_TRM); for (CacheInx = 0; CacheInx < TGETENT_MAX; ++CacheInx) if (LAST_TRM == trm) LAST_TRM = 0; @@ -133,15 +155,19 @@ tgetent(char *bufp, const char *name) } CacheInx = best; } - LAST_TRM = cur_term; - LAST_SEQ = ++CacheSeq; + if (rc == 1) { + LAST_TRM = TerminalOf(SP_PARM); + LAST_SEQ = ++CacheSeq; + } else { + LAST_TRM = 0; + } PC = 0; UP = 0; BC = 0; FIX_SGR0 = 0; /* don't free it - application may still use */ - if (errcode == 1) { + if (rc == 1) { if (cursor_left) if ((backspaces_with_bs = (char) !strcmp(cursor_left, "\b")) == 0) @@ -155,7 +181,8 @@ tgetent(char *bufp, const char *name) if (backspace_if_not_bs != NULL) BC = backspace_if_not_bs; - if ((FIX_SGR0 = _nc_trim_sgr0(&(cur_term->type))) != 0) { + if ((FIX_SGR0 = _nc_trim_sgr0(&TerminalType(TerminalOf(SP_PARM)))) + != 0) { if (!strcmp(FIX_SGR0, exit_attribute_mode)) { if (FIX_SGR0 != exit_attribute_mode) { free(FIX_SGR0); @@ -166,8 +193,8 @@ tgetent(char *bufp, const char *name) LAST_BUF = bufp; LAST_USE = TRUE; - SetNoPadding(SP); - (void) baudrate(); /* sets ospeed as a side-effect */ + SetNoPadding(SP_PARM); + (void) NCURSES_SP_NAME(baudrate) (NCURSES_SP_ARG); /* sets ospeed as a side-effect */ /* LINT_PREPRO #if 0*/ @@ -176,9 +203,30 @@ tgetent(char *bufp, const char *name) #endif*/ } - returnCode(errcode); + returnCode(rc); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +tgetent(char *bufp, const char *name) +{ + return NCURSES_SP_NAME(tgetent) (CURRENT_SCREEN, bufp, name); +} +#endif + +#if 0 +static bool +same_tcname(const char *a, const char *b) +{ + bool code = SameCap(a, b); + fprintf(stderr, "compare(%s,%s) %s\n", a, b, code ? "same" : "diff"); + return code; +} + +#else +#define same_tcname(a,b) SameCap(a,b) +#endif + /*************************************************************************** * * tgetflag(str) @@ -189,23 +237,47 @@ tgetent(char *bufp, const char *name) ***************************************************************************/ NCURSES_EXPORT(int) -tgetflag(NCURSES_CONST char *id) +NCURSES_SP_NAME(tgetflag) (NCURSES_SP_DCLx const char *id) { - unsigned i; - - T((T_CALLED("tgetflag(%s)"), id)); - if (cur_term != 0) { - TERMTYPE *tp = &(cur_term->type); - for_each_boolean(i, tp) { - const char *capname = ExtBoolname(tp, i, boolcodes); - if (!strncmp(id, capname, 2)) { - /* setupterm forces invalid booleans to false */ - returnCode(tp->Booleans[i]); + int result = 0; /* Solaris returns zero for missing flag */ + + T((T_CALLED("tgetflag(%p, %s)"), (void *) SP_PARM, id)); + if (HasTInfoTerminal(SP_PARM) && ValidCap(id)) { + TERMTYPE2 *tp = &TerminalType(TerminalOf(SP_PARM)); + struct name_table_entry const *entry_ptr; + int j = -1; + + entry_ptr = _nc_find_type_entry(id, BOOLEAN, TRUE); + if (entry_ptr != 0) { + j = entry_ptr->nte_index; + } +#if NCURSES_XNAMES + else { + int i; + for_each_ext_boolean(i, tp) { + const char *capname = ExtBoolname(tp, i, boolcodes); + if (same_tcname(id, capname) && ValidExt(capname)) { + j = i; + break; + } } } +#endif + if (j >= 0) { + /* note: setupterm forces invalid booleans to false */ + result = tp->Booleans[j]; + } } - returnCode(0); /* Solaris does this */ + returnCode(result); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +tgetflag(const char *id) +{ + return NCURSES_SP_NAME(tgetflag) (CURRENT_SCREEN, id); } +#endif /*************************************************************************** * @@ -217,25 +289,48 @@ tgetflag(NCURSES_CONST char *id) ***************************************************************************/ NCURSES_EXPORT(int) -tgetnum(NCURSES_CONST char *id) +NCURSES_SP_NAME(tgetnum) (NCURSES_SP_DCLx const char *id) { - unsigned i; - - T((T_CALLED("tgetnum(%s)"), id)); - if (cur_term != 0) { - TERMTYPE *tp = &(cur_term->type); - for_each_number(i, tp) { - const char *capname = ExtNumname(tp, i, numcodes); - if (!strncmp(id, capname, 2)) { - if (!VALID_NUMERIC(tp->Numbers[i])) - returnCode(ABSENT_NUMERIC); - returnCode(tp->Numbers[i]); + int result = ABSENT_NUMERIC; + + T((T_CALLED("tgetnum(%p, %s)"), (void *) SP_PARM, id)); + if (HasTInfoTerminal(SP_PARM) && ValidCap(id)) { + TERMTYPE2 *tp = &TerminalType(TerminalOf(SP_PARM)); + struct name_table_entry const *entry_ptr; + int j = -1; + + entry_ptr = _nc_find_type_entry(id, NUMBER, TRUE); + if (entry_ptr != 0) { + j = entry_ptr->nte_index; + } +#if NCURSES_XNAMES + else { + int i; + for_each_ext_number(i, tp) { + const char *capname = ExtNumname(tp, i, numcodes); + if (same_tcname(id, capname) && ValidExt(capname)) { + j = i; + break; + } } } +#endif + if (j >= 0) { + if (VALID_NUMERIC(tp->Numbers[j])) + result = tp->Numbers[j]; + } } - returnCode(ABSENT_NUMERIC); + returnCode(result); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +tgetnum(const char *id) +{ + return NCURSES_SP_NAME(tgetnum) (CURRENT_SCREEN, id); +} +#endif + /*************************************************************************** * * tgetstr(str, area) @@ -246,49 +341,91 @@ tgetnum(NCURSES_CONST char *id) ***************************************************************************/ NCURSES_EXPORT(char *) -tgetstr(NCURSES_CONST char *id, char **area) +NCURSES_SP_NAME(tgetstr) (NCURSES_SP_DCLx const char *id, char **area) { - unsigned i; - char *result = NULL, *base; - - if (area != 0 && *area != 0) - base = *area; - T((T_CALLED("tgetstr(%s,%p)"), id, area)); - if (cur_term != 0) { - TERMTYPE *tp = &(cur_term->type); - for_each_string(i, tp) { - const char *capname = ExtStrname(tp, i, strcodes); - if (!strncmp(id, capname, 2)) { - result = tp->Strings[i]; - TR(TRACE_DATABASE, ("found match : %s", _nc_visbuf(result))); - /* setupterm forces canceled strings to null */ - if (VALID_STRING(result)) { - if (result == exit_attribute_mode - && FIX_SGR0 != 0) { - result = FIX_SGR0; - TR(TRACE_DATABASE, ("altered to : %s", _nc_visbuf(result))); - } - if (area != 0 && *area != 0) { - (void) strlcpy(*area, result, 1024 - (*area - base)); - result = *area; - *area += strlen(*area) + 1; - } + char *result = NULL; + + T((T_CALLED("tgetstr(%s,%p)"), id, (void *) area)); + if (HasTInfoTerminal(SP_PARM) && ValidCap(id)) { + TERMTYPE2 *tp = &TerminalType(TerminalOf(SP_PARM)); + struct name_table_entry const *entry_ptr; + int j = -1; + + entry_ptr = _nc_find_type_entry(id, STRING, TRUE); + if (entry_ptr != 0) { + j = entry_ptr->nte_index; + } +#if NCURSES_XNAMES + else { + int i; + for_each_ext_string(i, tp) { + const char *capname = ExtStrname(tp, i, strcodes); + if (same_tcname(id, capname) && ValidExt(capname)) { + j = i; + break; + } + } + } +#endif + if (j >= 0) { + result = tp->Strings[j]; + TR(TRACE_DATABASE, ("found match %d: %s", j, _nc_visbuf(result))); + /* setupterm forces canceled strings to null */ + if (VALID_STRING(result)) { + if (result == exit_attribute_mode + && FIX_SGR0 != 0) { + result = FIX_SGR0; + TR(TRACE_DATABASE, ("altered to : %s", _nc_visbuf(result))); + } + if (area != 0 + && *area != 0) { + _nc_STRCPY(*area, result, 1024); + result = *area; + *area += strlen(*area) + 1; } - break; } } } returnPtr(result); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(char *) +tgetstr(const char *id, char **area) +{ + return NCURSES_SP_NAME(tgetstr) (CURRENT_SCREEN, id, area); +} +#endif + #if NO_LEAKS +#undef CacheInx +#define CacheInx num +NCURSES_EXPORT(void) +_nc_tgetent_leak(const TERMINAL *const termp) +{ + if (termp != 0) { + int num; + for (CacheInx = 0; CacheInx < TGETENT_MAX; ++CacheInx) { + if (LAST_TRM == termp) { + FreeAndNull(FIX_SGR0); + if (LAST_TRM != 0) { + LAST_TRM = 0; + } + break; + } + } + } +} + NCURSES_EXPORT(void) _nc_tgetent_leaks(void) { + int num; for (CacheInx = 0; CacheInx < TGETENT_MAX; ++CacheInx) { - FreeIfNeeded(FIX_SGR0); - if (LAST_TRM != 0) + if (LAST_TRM != 0) { del_curterm(LAST_TRM); + _nc_tgetent_leak(LAST_TRM); + } } } #endif diff --git a/lib/libcurses/tinfo/lib_termname.c b/lib/libcurses/tinfo/lib_termname.c index f4ddf8b334b..04ea19e96ba 100644 --- a/lib/libcurses/tinfo/lib_termname.c +++ b/lib/libcurses/tinfo/lib_termname.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_termname.c,v 1.5 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_termname.c,v 1.6 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2001,2003 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2003,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -30,17 +31,31 @@ #include -MODULE_ID("$Id: lib_termname.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_termname.c,v 1.6 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(char *) -termname(void) +NCURSES_SP_NAME(termname) (NCURSES_SP_DCL0) { char *name = 0; - T((T_CALLED("termname()"))); + T((T_CALLED("termname(%p)"), (void *) SP_PARM)); +#if NCURSES_SP_FUNCS + if (TerminalOf(SP_PARM) != 0) { + name = TerminalOf(SP_PARM)->_termname; + } +#else if (cur_term != 0) name = cur_term->_termname; +#endif returnPtr(name); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(char *) +termname(void) +{ + return NCURSES_SP_NAME(termname) (CURRENT_SCREEN); +} +#endif diff --git a/lib/libcurses/tinfo/lib_tgoto.c b/lib/libcurses/tinfo/lib_tgoto.c index 887cb8f5f5b..d16f092656a 100644 --- a/lib/libcurses/tinfo/lib_tgoto.c +++ b/lib/libcurses/tinfo/lib_tgoto.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_tgoto.c,v 1.6 2010/01/14 22:53:22 nicm Exp $ */ +/* $OpenBSD: lib_tgoto.c,v 1.7 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2000-2006,2008 Free Software Foundation, Inc. * + * Copyright 2018-2020,2023 Thomas E. Dickey * + * Copyright 2000-2008,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -37,7 +38,7 @@ #include #include -MODULE_ID("$Id: lib_tgoto.c,v 1.6 2010/01/14 22:53:22 nicm Exp $") +MODULE_ID("$Id: lib_tgoto.c,v 1.7 2023/10/17 09:52:09 nicm Exp $") #if !PURE_TERMINFO static bool @@ -77,7 +78,6 @@ tgoto_internal(const char *string, int x, int y) int param[3]; size_t used = 0; size_t need = 10; - size_t copied; int *value = param; bool need_BC = FALSE; @@ -128,7 +128,14 @@ tgoto_internal(const char *string, int x, int y) *value += 1; need_BC = TRUE; } else { - *value = 0200; /* tputs will treat this as \0 */ + /* tputs will pretend this is \0, which will almost + * always work since ANSI-compatible terminals ignore + * the character. ECMA-48 does not document a C1 + * control for this value. A few (obsolete) terminals + * can use this value in special cases, such as cursor + * addressing using single-byte coordinates. + */ + *value = 0200; } } result[used++] = (char) *value++; @@ -162,7 +169,8 @@ tgoto_internal(const char *string, int x, int y) break; } if (fmt != 0) { - snprintf(result + used, length - used, fmt, *value++); + _nc_SPRINTF(result + used, _nc_SLIMIT(length - used) + fmt, *value++); used += strlen(result + used); fmt = 0; } @@ -177,11 +185,8 @@ tgoto_internal(const char *string, int x, int y) } if (result != 0) { if (need_BC) { - copied = strlcpy(result + used, BC, length - used); - if (copied < length - used) - used += copied; - else - used += length - used - 1; + _nc_STRCPY(result + used, BC, length - used); + used += strlen(BC); } result[used] = '\0'; } @@ -204,6 +209,16 @@ tgoto(const char *string, int x, int y) result = tgoto_internal(string, x, y); else #endif - result = TPARM_2((NCURSES_CONST char *) string, y, x); + if ((result = TIPARM_2(string, y, x)) == NULL) { + /* + * Because termcap did not provide a more general solution such as + * tparm(), it was necessary to handle single-parameter capabilities + * using tgoto(). The internal _nc_tiparm() function returns a NULL + * for that case; retry for the single-parameter case. + */ + if ((result = TIPARM_1(string, y)) == NULL) { + result = TIPARM_0(string); + } + } returnPtr(result); } diff --git a/lib/libcurses/tinfo/lib_ti.c b/lib/libcurses/tinfo/lib_ti.c index 9416c56cca9..ec1dec50bab 100644 --- a/lib/libcurses/tinfo/lib_ti.c +++ b/lib/libcurses/tinfo/lib_ti.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_ti.c,v 1.7 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_ti.c,v 1.8 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2003 Free Software Foundation, Inc. * + * Copyright 2018,2020 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,75 +32,159 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-on * ****************************************************************************/ #include -#include #include -MODULE_ID("$Id: lib_ti.c,v 1.7 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_ti.c,v 1.8 2023/10/17 09:52:09 nicm Exp $") + +#if 0 +static bool +same_name(const char *a, const char *b) +{ + fprintf(stderr, "compare(%s,%s)\n", a, b); + return !strcmp(a, b); +} +#else +#define same_name(a,b) !strcmp(a,b) +#endif NCURSES_EXPORT(int) -tigetflag(NCURSES_CONST char *str) +NCURSES_SP_NAME(tigetflag) (NCURSES_SP_DCLx const char *str) { - unsigned i; + int result = ABSENT_BOOLEAN; + + T((T_CALLED("tigetflag(%p, %s)"), (void *) SP_PARM, str)); - T((T_CALLED("tigetflag(%s)"), str)); + if (HasTInfoTerminal(SP_PARM)) { + TERMTYPE2 *tp = &TerminalType(TerminalOf(SP_PARM)); + struct name_table_entry const *entry_ptr; + int j = -1; - if (cur_term != 0) { - TERMTYPE *tp = &(cur_term->type); - for_each_boolean(i, tp) { - const char *capname = ExtBoolname(tp, i, boolnames); - if (!strcmp(str, capname)) { - /* setupterm forces invalid booleans to false */ - returnCode(tp->Booleans[i]); + entry_ptr = _nc_find_type_entry(str, BOOLEAN, FALSE); + if (entry_ptr != 0) { + j = entry_ptr->nte_index; + } +#if NCURSES_XNAMES + else { + int i; + for_each_ext_boolean(i, tp) { + const char *capname = ExtBoolname(tp, i, boolnames); + if (same_name(str, capname)) { + j = i; + break; + } } } +#endif + if (j >= 0) { + /* note: setupterm forces invalid booleans to false */ + result = tp->Booleans[j]; + } } - returnCode(ABSENT_BOOLEAN); + returnCode(result); } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) -tigetnum(NCURSES_CONST char *str) +tigetflag(const char *str) { - unsigned i; - - T((T_CALLED("tigetnum(%s)"), str)); - - if (cur_term != 0) { - TERMTYPE *tp = &(cur_term->type); - for_each_number(i, tp) { - const char *capname = ExtNumname(tp, i, numnames); - if (!strcmp(str, capname)) { - if (!VALID_NUMERIC(tp->Numbers[i])) - returnCode(ABSENT_NUMERIC); - returnCode(tp->Numbers[i]); + return NCURSES_SP_NAME(tigetflag) (CURRENT_SCREEN, str); +} +#endif + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(tigetnum) (NCURSES_SP_DCLx const char *str) +{ + int result = CANCELLED_NUMERIC; /* Solaris returns a -1 on error */ + + T((T_CALLED("tigetnum(%p, %s)"), (void *) SP_PARM, str)); + + if (HasTInfoTerminal(SP_PARM)) { + TERMTYPE2 *tp = &TerminalType(TerminalOf(SP_PARM)); + struct name_table_entry const *entry_ptr; + int j = -1; + + entry_ptr = _nc_find_type_entry(str, NUMBER, FALSE); + if (entry_ptr != 0) { + j = entry_ptr->nte_index; + } +#if NCURSES_XNAMES + else { + int i; + for_each_ext_number(i, tp) { + const char *capname = ExtNumname(tp, i, numnames); + if (same_name(str, capname)) { + j = i; + break; + } } } +#endif + if (j >= 0) { + if (VALID_NUMERIC(tp->Numbers[j])) + result = tp->Numbers[j]; + else + result = ABSENT_NUMERIC; + } } - returnCode(CANCELLED_NUMERIC); /* Solaris returns a -1 instead */ + returnCode(result); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +tigetnum(const char *str) +{ + return NCURSES_SP_NAME(tigetnum) (CURRENT_SCREEN, str); +} +#endif + NCURSES_EXPORT(char *) -tigetstr(NCURSES_CONST char *str) +NCURSES_SP_NAME(tigetstr) (NCURSES_SP_DCLx const char *str) { - unsigned i; + char *result = CANCELLED_STRING; + + T((T_CALLED("tigetstr(%p, %s)"), (void *) SP_PARM, str)); - T((T_CALLED("tigetstr(%s)"), str)); + if (HasTInfoTerminal(SP_PARM)) { + TERMTYPE2 *tp = &TerminalType(TerminalOf(SP_PARM)); + struct name_table_entry const *entry_ptr; + int j = -1; - if (cur_term != 0) { - TERMTYPE *tp = &(cur_term->type); - for_each_string(i, tp) { - const char *capname = ExtStrname(tp, i, strnames); - if (!strcmp(str, capname)) { - /* setupterm forces cancelled strings to null */ - returnPtr(tp->Strings[i]); + entry_ptr = _nc_find_type_entry(str, STRING, FALSE); + if (entry_ptr != 0) { + j = entry_ptr->nte_index; + } +#if NCURSES_XNAMES + else { + int i; + for_each_ext_string(i, tp) { + const char *capname = ExtStrname(tp, i, strnames); + if (same_name(str, capname)) { + j = i; + break; + } } } +#endif + if (j >= 0) { + /* note: setupterm forces cancelled strings to null */ + result = tp->Strings[j]; + } } - returnPtr(CANCELLED_STRING); + returnPtr(result); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(char *) +tigetstr(const char *str) +{ + return NCURSES_SP_NAME(tigetstr) (CURRENT_SCREEN, str); } +#endif diff --git a/lib/libcurses/tinfo/lib_tparm.c b/lib/libcurses/tinfo/lib_tparm.c index 2e54a43aba5..81ac5a45525 100644 --- a/lib/libcurses/tinfo/lib_tparm.c +++ b/lib/libcurses/tinfo/lib_tparm.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_tparm.c,v 1.10 2022/06/28 07:36:52 nicm Exp $ */ +/* $OpenBSD: lib_tparm.c,v 1.11 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2021,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,13 +40,22 @@ * */ +#define entry _ncu_entry +#define ENTRY _ncu_ENTRY + #include +#undef entry +#undef ENTRY + +#if HAVE_TSEARCH +#include +#endif + #include -#include #include -MODULE_ID("$Id: lib_tparm.c,v 1.10 2022/06/28 07:36:52 nicm Exp $") +MODULE_ID("$Id: lib_tparm.c,v 1.11 2023/10/17 09:52:09 nicm Exp $") /* * char * @@ -56,7 +66,7 @@ MODULE_ID("$Id: lib_tparm.c,v 1.10 2022/06/28 07:36:52 nicm Exp $") * * Cursor addressing and other strings requiring parame- * ters in the terminal are described by a parameterized string - * capability, with like escapes %x in it. For example, to + * capability, with escapes like %x in it. For example, to * address the cursor, the cup capability is given, using two * parameters: the row and column to address to. (Rows and * columns are numbered from zero and refer to the physical @@ -109,125 +119,245 @@ MODULE_ID("$Id: lib_tparm.c,v 1.10 2022/06/28 07:36:52 nicm Exp $") NCURSES_EXPORT_VAR(int) _nc_tparm_err = 0; -#define TPS(var) _nc_prescreen.tparm_state.var +#define TPS(var) tps->var +#define popcount _nc_popcount /* workaround for NetBSD 6.0 defect */ -#if NO_LEAKS -NCURSES_EXPORT(void) -_nc_free_tparm(void) +#define get_tparm_state(term) \ + (term != NULL \ + ? &(term->tparm_state) \ + : &(_nc_prescreen.tparm_state)) + +#define isUPPER(c) ((c) >= 'A' && (c) <= 'Z') +#define isLOWER(c) ((c) >= 'a' && (c) <= 'z') +#define tc_BUMP() if (level < 0 && number < 2) number++ + +typedef struct { + const char *format; /* format-string can be used as cache-key */ + int tparm_type; /* bit-set for each string-parameter */ + int num_actual; + int num_parsed; + int num_popped; + TPARM_ARG param[NUM_PARM]; + char *p_is_s[NUM_PARM]; +} TPARM_DATA; + +#if HAVE_TSEARCH +#define MyCache _nc_globals.cached_tparm +#define MyCount _nc_globals.count_tparm +static int which_tparm; +static TPARM_DATA **delete_tparm; +#endif /* HAVE_TSEARCH */ + +static char dummy[] = ""; /* avoid const-cast */ + +#if HAVE_TSEARCH +static int +cmp_format(const void *p, const void *q) { - if (TPS(out_buff) != 0) { - FreeAndNull(TPS(out_buff)); - TPS(out_size) = 0; - TPS(out_used) = 0; - FreeAndNull(TPS(fmt_buff)); - TPS(fmt_size) = 0; + const char *a = *(char *const *) p; + const char *b = *(char *const *) q; + return strcmp(a, b); +} +#endif + +#if HAVE_TSEARCH +static void +visit_nodes(const void *nodep, VISIT which, int depth) +{ + (void) depth; + if (which == preorder || which == leaf) { + delete_tparm[which_tparm] = *(TPARM_DATA **) nodep; + which_tparm++; } } #endif -static NCURSES_INLINE void -get_space(size_t need) +NCURSES_EXPORT(void) +_nc_free_tparm(TERMINAL *termp) { - need += TPS(out_used); - if (need > TPS(out_size)) { - TPS(out_size) = need * 2; - TPS(out_buff) = typeRealloc(char, TPS(out_size), TPS(out_buff)); - if (TPS(out_buff) == 0) - _nc_err_abort(MSG_NO_MEMORY); + TPARM_STATE *tps = get_tparm_state(termp); +#if HAVE_TSEARCH + if (MyCount != 0) { + delete_tparm = typeCalloc(TPARM_DATA *, MyCount); + if (delete_tparm != NULL) { + which_tparm = 0; + twalk(MyCache, visit_nodes); + for (which_tparm = 0; which_tparm < MyCount; ++which_tparm) { + TPARM_DATA *ptr = delete_tparm[which_tparm]; + if (ptr != NULL) { + tdelete(ptr, &MyCache, cmp_format); + free((char *) ptr->format); + free(ptr); + } + } + which_tparm = 0; + twalk(MyCache, visit_nodes); + FreeAndNull(delete_tparm); + } + MyCount = 0; + which_tparm = 0; } +#endif + FreeAndNull(TPS(out_buff)); + TPS(out_size) = 0; + TPS(out_used) = 0; + + FreeAndNull(TPS(fmt_buff)); + TPS(fmt_size) = 0; } -static NCURSES_INLINE void -save_text(const char *fmt, const char *s, int len) +static int +tparm_error(TPARM_STATE *tps, const char *message) { - size_t s_len = strlen(s); - if (len > (int) s_len) - s_len = len; + (void) tps; + (void) message; + DEBUG(2, ("%s: %s", message, _nc_visbuf(TPS(tparam_base)))); + return ++_nc_tparm_err; +} + +#define get_space(tps, need) \ +{ \ + size_t need2get = need + TPS(out_used); \ + if (need2get > TPS(out_size)) { \ + TPS(out_size) = need2get * 2; \ + TYPE_REALLOC(char, TPS(out_size), TPS(out_buff)); \ + } \ +} + +#if NCURSES_EXPANDED +static NCURSES_INLINE void + (get_space) (TPARM_STATE *tps, size_t need) { + get_space(tps, need); +} - get_space(s_len + 1); +#undef get_space +#endif - (void) snprintf(TPS(out_buff) + TPS(out_used), TPS(out_size) - TPS(out_used), fmt, s); - TPS(out_used) += strlen(TPS(out_buff) + TPS(out_used)); +#define save_text(tps, fmt, s, len) \ +{ \ + size_t s_len = (size_t) len + strlen(s) + strlen(fmt); \ + get_space(tps, s_len + 1); \ + _nc_SPRINTF(TPS(out_buff) + TPS(out_used), \ + _nc_SLIMIT(TPS(out_size) - TPS(out_used)) \ + fmt, s); \ + TPS(out_used) += strlen(TPS(out_buff) + TPS(out_used)); \ } +#if NCURSES_EXPANDED static NCURSES_INLINE void -save_number(const char *fmt, int number, int len) -{ - if (len < 30) - len = 30; /* actually log10(MAX_INT)+1 */ + (save_text) (TPARM_STATE *tps, const char *fmt, const char *s, int len) { + save_text(tps, fmt, s, len); +} - get_space((unsigned) len + 1); +#undef save_text +#endif - (void) snprintf(TPS(out_buff) + TPS(out_used), TPS(out_size) - TPS(out_used), fmt, number); - TPS(out_used) += strlen(TPS(out_buff) + TPS(out_used)); +#define save_number(tps, fmt, number, len) \ +{ \ + size_t s_len = (size_t) len + 30 + strlen(fmt); \ + get_space(tps, s_len + 1); \ + _nc_SPRINTF(TPS(out_buff) + TPS(out_used), \ + _nc_SLIMIT(TPS(out_size) - TPS(out_used)) \ + fmt, number); \ + TPS(out_used) += strlen(TPS(out_buff) + TPS(out_used)); \ } +#if NCURSES_EXPANDED static NCURSES_INLINE void -save_char(int c) -{ - if (c == 0) - c = 0200; - get_space(1); - TPS(out_buff)[TPS(out_used)++] = (char) c; + (save_number) (TPARM_STATE *tps, const char *fmt, int number, int len) { + save_number(tps, fmt, number, len); } +#undef save_number +#endif + +#define save_char(tps, c) \ +{ \ + get_space(tps, (size_t) 1); \ + TPS(out_buff)[TPS(out_used)++] = (char) ((c == 0) ? 0200 : c); \ +} + +#if NCURSES_EXPANDED static NCURSES_INLINE void -npush(int x) -{ - if (TPS(stack_ptr) < STACKSIZE) { - TPS(stack)[TPS(stack_ptr)].num_type = TRUE; - TPS(stack)[TPS(stack_ptr)].data.num = x; - TPS(stack_ptr)++; - } else { - DEBUG(2, ("npush: stack overflow: %s", _nc_visbuf(TPS(tparam_base)))); - _nc_tparm_err++; - } + (save_char) (TPARM_STATE *tps, int c) { + save_char(tps, c); } -static NCURSES_INLINE int -npop(void) -{ - int result = 0; - if (TPS(stack_ptr) > 0) { - TPS(stack_ptr)--; - if (TPS(stack)[TPS(stack_ptr)].num_type) - result = TPS(stack)[TPS(stack_ptr)].data.num; - } else { - DEBUG(2, ("npop: stack underflow: %s", _nc_visbuf(TPS(tparam_base)))); - _nc_tparm_err++; - } - return result; +#undef save_char +#endif + +#define npush(tps, x) \ +{ \ + if (TPS(stack_ptr) < STACKSIZE) { \ + TPS(stack)[TPS(stack_ptr)].num_type = TRUE; \ + TPS(stack)[TPS(stack_ptr)].data.num = x; \ + TPS(stack_ptr)++; \ + } else { \ + (void) tparm_error(tps, "npush: stack overflow"); \ + } \ } +#if NCURSES_EXPANDED static NCURSES_INLINE void -spush(char *x) -{ - if (TPS(stack_ptr) < STACKSIZE) { - TPS(stack)[TPS(stack_ptr)].num_type = FALSE; - TPS(stack)[TPS(stack_ptr)].data.str = x; - TPS(stack_ptr)++; - } else { - DEBUG(2, ("spush: stack overflow: %s", _nc_visbuf(TPS(tparam_base)))); - _nc_tparm_err++; - } + (npush) (TPARM_STATE *tps, int x) { + npush(tps, x); +} + +#undef npush +#endif + +#define spush(tps, x) \ +{ \ + if (TPS(stack_ptr) < STACKSIZE) { \ + TPS(stack)[TPS(stack_ptr)].num_type = FALSE; \ + TPS(stack)[TPS(stack_ptr)].data.str = x; \ + TPS(stack_ptr)++; \ + } else { \ + (void) tparm_error(tps, "spush: stack overflow"); \ + } \ } +#if NCURSES_EXPANDED +static NCURSES_INLINE void + (spush) (TPARM_STATE *tps, char *x) { + spush(tps, x); +} + +#undef spush +#endif + +#define npop(tps) \ + ((TPS(stack_ptr)-- > 0) \ + ? ((TPS(stack)[TPS(stack_ptr)].num_type) \ + ? TPS(stack)[TPS(stack_ptr)].data.num \ + : 0) \ + : (tparm_error(tps, "npop: stack underflow"), \ + TPS(stack_ptr) = 0)) + +#if NCURSES_EXPANDED +static NCURSES_INLINE int + (npop) (TPARM_STATE *tps) { + return npop(tps); +} +#undef npop +#endif + +#define spop(tps) \ + ((TPS(stack_ptr)-- > 0) \ + ? ((!TPS(stack)[TPS(stack_ptr)].num_type \ + && TPS(stack)[TPS(stack_ptr)].data.str != 0) \ + ? TPS(stack)[TPS(stack_ptr)].data.str \ + : dummy) \ + : (tparm_error(tps, "spop: stack underflow"), \ + dummy)) + +#if NCURSES_EXPANDED static NCURSES_INLINE char * -spop(void) -{ - static char dummy[] = ""; /* avoid const-cast */ - char *result = dummy; - if (TPS(stack_ptr) > 0) { - TPS(stack_ptr)--; - if (!TPS(stack)[TPS(stack_ptr)].num_type - && TPS(stack)[TPS(stack_ptr)].data.str != 0) - result = TPS(stack)[TPS(stack_ptr)].data.str; - } else { - DEBUG(2, ("spop: stack underflow: %s", _nc_visbuf(TPS(tparam_base)))); - _nc_tparm_err++; - } - return result; + (spop) (TPARM_STATE *tps) { + return spop(tps); } +#undef spop +#endif static NCURSES_INLINE const char * parse_format(const char *s, char *format, int *len) @@ -253,6 +383,9 @@ parse_format(const char *s, char *format, int *len) case 'x': /* FALLTHRU */ case 'X': /* FALLTHRU */ case 's': +#ifdef EXP_XTERM_1005 + case 'u': +#endif *format++ = *s; done = TRUE; break; @@ -321,9 +454,6 @@ parse_format(const char *s, char *format, int *len) return s; } -#define isUPPER(c) ((c) >= 'A' && (c) <= 'Z') -#define isLOWER(c) ((c) >= 'a' && (c) <= 'z') - /* * Analyze the string to see how many parameters we need from the varargs list, * and what their types are. We will only accept string parameters if they @@ -336,21 +466,22 @@ parse_format(const char *s, char *format, int *len) * may be cases that we cannot see the explicit parameter numbers. */ NCURSES_EXPORT(int) -_nc_tparm_analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount) +_nc_tparm_analyze(TERMINAL *term, const char *string, char **p_is_s, int *popcount) { + TPARM_STATE *tps = get_tparm_state(term); size_t len2; int i; int lastpop = -1; int len; int number = 0; + int level = -1; const char *cp = string; - static char dummy[] = ""; if (cp == 0) return 0; - if ((len2 = strlen(cp)) > TPS(fmt_size)) { - TPS(fmt_size) = len2 + TPS(fmt_size) + 2; + if ((len2 = strlen(cp)) + 2 > TPS(fmt_size)) { + TPS(fmt_size) += len2 + 2; TPS(fmt_buff) = typeRealloc(char, TPS(fmt_size), TPS(fmt_buff)); if (TPS(fmt_buff) == 0) return 0; @@ -372,22 +503,30 @@ _nc_tparm_analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount) case 'x': /* FALLTHRU */ case 'X': /* FALLTHRU */ case 'c': /* FALLTHRU */ - if (lastpop <= 0) - number++; +#ifdef EXP_XTERM_1005 + case 'u': +#endif + if (lastpop <= 0) { + tc_BUMP(); + } + level -= 1; lastpop = -1; break; case 'l': case 's': - if (lastpop > 0) + if (lastpop > 0) { + level -= 1; p_is_s[lastpop - 1] = dummy; - ++number; + } + tc_BUMP(); break; case 'p': cp++; i = (UChar(*cp) - '0'); if (i >= 0 && i <= NUM_PARM) { + ++level; lastpop = i; if (lastpop > *popcount) *popcount = lastpop; @@ -395,20 +534,22 @@ _nc_tparm_analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount) break; case 'P': - ++number; ++cp; break; case 'g': + ++level; cp++; break; case S_QUOTE: + ++level; cp += 2; lastpop = -1; break; case L_BRACE: + ++level; cp++; while (isdigit(UChar(*cp))) { cp++; @@ -428,14 +569,15 @@ _nc_tparm_analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount) case '=': case '<': case '>': + tc_BUMP(); + level -= 1; /* pop 2, operate, push 1 */ lastpop = -1; - number += 2; break; case '!': case '~': + tc_BUMP(); lastpop = -1; - ++number; break; case 'i': @@ -452,84 +594,220 @@ _nc_tparm_analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount) return number; } -static NCURSES_INLINE char * -tparam_internal(const char *string, va_list ap) +/* + * Analyze the capability string, finding the number of parameters and their + * types. + * + * TODO: cache the result so that this is done once per capability per term. + */ +static int +tparm_setup(TERMINAL *term, const char *string, TPARM_DATA *result) { - char *p_is_s[NUM_PARM]; - TPARM_ARG param[NUM_PARM]; - int popcount; - int number; - int len; - int level; - int x, y; - int i; - const char *cp = string; - size_t len2; - - if (cp == NULL) - return NULL; + TPARM_STATE *tps = get_tparm_state(term); + int rc = OK; TPS(out_used) = 0; - len2 = strlen(cp); + memset(result, 0, sizeof(*result)); - /* - * Find the highest parameter-number referred to in the format string. - * Use this value to limit the number of arguments copied from the - * variable-length argument list. - */ - number = _nc_tparm_analyze(cp, p_is_s, &popcount); - if (TPS(fmt_buff) == 0) - return NULL; + if (!VALID_STRING(string)) { + TR(TRACE_CALLS, ("%s: format is invalid", TPS(tname))); + rc = ERR; + } else { +#if HAVE_TSEARCH + TPARM_DATA *fs; + void *ft; + + result->format = string; + if ((ft = tfind(result, &MyCache, cmp_format)) != 0) { + size_t len2; + fs = *(TPARM_DATA **) ft; + *result = *fs; + if ((len2 = strlen(string)) + 2 > TPS(fmt_size)) { + TPS(fmt_size) += len2 + 2; + TPS(fmt_buff) = typeRealloc(char, TPS(fmt_size), TPS(fmt_buff)); + if (TPS(fmt_buff) == 0) + return ERR; + } + } else +#endif + { + /* + * Find the highest parameter-number referred to in the format + * string. Use this value to limit the number of arguments copied + * from the variable-length argument list. + */ + result->num_parsed = _nc_tparm_analyze(term, string, + result->p_is_s, + &(result->num_popped)); + if (TPS(fmt_buff) == 0) { + TR(TRACE_CALLS, ("%s: error in analysis", TPS(tname))); + rc = ERR; + } else { + int n; + + if (result->num_parsed > NUM_PARM) + result->num_parsed = NUM_PARM; + if (result->num_popped > NUM_PARM) + result->num_popped = NUM_PARM; + result->num_actual = max(result->num_popped, result->num_parsed); + + for (n = 0; n < result->num_actual; ++n) { + if (result->p_is_s[n]) + result->tparm_type |= (1 << n); + } +#if HAVE_TSEARCH + if ((fs = typeCalloc(TPARM_DATA, 1)) != 0) { + *fs = *result; + if ((fs->format = strdup(string)) != 0) { + if (tsearch(fs, &MyCache, cmp_format) != 0) { + ++MyCount; + } else { + free(fs); + rc = ERR; + } + } else { + free(fs); + rc = ERR; + } + } else { + rc = ERR; + } +#endif + } + } + } - for (i = 0; i < max(popcount, number); i++) { - /* - * A few caps (such as plab_norm) have string-valued parms. - * We'll have to assume that the caller knows the difference, since - * a char* and an int may not be the same size on the stack. The - * normal prototype for this uses 9 long's, which is consistent with - * our va_arg() usage. - */ - if (p_is_s[i] != 0) { - p_is_s[i] = va_arg(ap, char *); + return rc; +} + +/* + * A few caps (such as plab_norm) have string-valued parms. We'll have to + * assume that the caller knows the difference, since a char* and an int may + * not be the same size on the stack. The normal prototype for tparm uses 9 + * long's, which is consistent with our va_arg() usage. + */ +static void +tparm_copy_valist(TPARM_DATA *data, int use_TPARM_ARG, va_list ap) +{ + int i; + + for (i = 0; i < data->num_actual; i++) { + if (data->p_is_s[i] != 0) { + char *value = va_arg(ap, char *); + if (value == 0) + value = dummy; + data->p_is_s[i] = value; + data->param[i] = 0; + } else if (use_TPARM_ARG) { + data->param[i] = va_arg(ap, TPARM_ARG); } else { - param[i] = va_arg(ap, TPARM_ARG); + data->param[i] = (TPARM_ARG) va_arg(ap, int); } } +} + +/* + * This is a termcap compatibility hack. If there are no explicit pop + * operations in the string, load the stack in such a way that successive pops + * will grab successive parameters. That will make the expansion of (for + * example) \E[%d;%dH work correctly in termcap style, which means tparam() + * will expand termcap strings OK. + */ +static bool +tparm_tc_compat(TPARM_STATE *tps, TPARM_DATA *data) +{ + bool termcap_hack = FALSE; - /* - * This is a termcap compatibility hack. If there are no explicit pop - * operations in the string, load the stack in such a way that - * successive pops will grab successive parameters. That will make - * the expansion of (for example) \E[%d;%dH work correctly in termcap - * style, which means tparam() will expand termcap strings OK. - */ TPS(stack_ptr) = 0; - if (popcount == 0) { - popcount = number; - for (i = number - 1; i >= 0; i--) { - if (p_is_s[i]) - spush(p_is_s[i]); - else - npush(param[i]); + + if (data->num_popped == 0) { + int i; + + termcap_hack = TRUE; + for (i = data->num_parsed - 1; i >= 0; i--) { + if (data->p_is_s[i]) { + spush(tps, data->p_is_s[i]); + } else { + npush(tps, (int) data->param[i]); + } } } + return termcap_hack; +} + #ifdef TRACE +static void +tparm_trace_call(TPARM_STATE *tps, const char *string, TPARM_DATA *data) +{ if (USE_TRACEF(TRACE_CALLS)) { - for (i = 0; i < popcount; i++) { - if (p_is_s[i] != 0) - save_text(", %s", _nc_visbuf(p_is_s[i]), 0); - else - save_number(", %d", param[i], 0); + int i; + for (i = 0; i < data->num_actual; i++) { + if (data->p_is_s[i] != 0) { + save_text(tps, ", %s", _nc_visbuf(data->p_is_s[i]), 0); + } else if ((long) data->param[i] > MAX_OF_TYPE(NCURSES_INT2) || + (long) data->param[i] < 0) { + _tracef("BUG: problem with tparm parameter #%d of %d", + i + 1, data->num_actual); + break; + } else { + save_number(tps, ", %d", (int) data->param[i], 0); + } } - _tracef(T_CALLED("%s(%s%s)"), TPS(tname), _nc_visbuf(cp), TPS(out_buff)); + _tracef(T_CALLED("%s(%s%s)"), TPS(tname), _nc_visbuf(string), TPS(out_buff)); TPS(out_used) = 0; _nc_unlock_global(tracef); } +} + +#else +#define tparm_trace_call(tps, string, data) /* nothing */ #endif /* TRACE */ +#define init_vars(name) \ + if (!name##_used) { \ + name##_used = TRUE; \ + memset(name##_vars, 0, sizeof(name##_vars)); \ + } + +static NCURSES_INLINE char * +tparam_internal(TPARM_STATE *tps, const char *string, TPARM_DATA *data) +{ + int number; + int len; + int level; + int x, y; + int i; + const char *s; + const char *cp = string; + size_t len2 = strlen(cp); + bool incremented_two = FALSE; + bool termcap_hack = tparm_tc_compat(tps, data); + /* + * SVr4 curses stores variables 'A' to 'Z' in the TERMINAL structure (so + * they are initialized once to zero), and variables 'a' to 'z' on the + * stack in tparm, referring to the former as "static" and the latter as + * "dynamic". However, it makes no check to ensure that the "dynamic" + * variables are initialized. + * + * Solaris xpg4 curses makes no distinction between the upper/lower, and + * stores the common set of 26 variables on the stack, without initializing + * them. + * + * In ncurses, both sets of variables are initialized on the first use. + */ + bool dynamic_used = FALSE; + int dynamic_vars[NUM_VARS]; + + tparm_trace_call(tps, string, data); + + if (TPS(fmt_buff) == NULL) { + T((T_RETURN(""))); + return NULL; + } + while ((cp - string) < (int) len2) { if (*cp != '%') { - save_char(UChar(*cp)); + save_char(tps, UChar(*cp)); } else { TPS(tparam_base) = cp++; cp = parse_format(cp, TPS(fmt_buff), &len); @@ -537,36 +815,55 @@ tparam_internal(const char *string, va_list ap) default: break; case '%': - save_char('%'); + save_char(tps, '%'); break; case 'd': /* FALLTHRU */ case 'o': /* FALLTHRU */ case 'x': /* FALLTHRU */ case 'X': /* FALLTHRU */ - save_number(TPS(fmt_buff), npop(), len); + x = npop(tps); + save_number(tps, TPS(fmt_buff), x, len); break; case 'c': /* FALLTHRU */ - save_char(npop()); + x = npop(tps); + save_char(tps, x); break; +#ifdef EXP_XTERM_1005 + case 'u': + { + unsigned char target[10]; + unsigned source = (unsigned) npop(tps); + int rc = _nc_conv_to_utf8(target, source, (unsigned) + sizeof(target)); + int n; + for (n = 0; n < rc; ++n) { + save_char(tps, target[n]); + } + } + break; +#endif case 'l': - npush((int) strlen(spop())); + s = spop(tps); + npush(tps, (int) strlen(s)); break; case 's': - save_text(TPS(fmt_buff), spop(), len); + s = spop(tps); + save_text(tps, TPS(fmt_buff), s, len); break; case 'p': cp++; i = (UChar(*cp) - '1'); if (i >= 0 && i < NUM_PARM) { - if (p_is_s[i]) - spush(p_is_s[i]); - else - npush(param[i]); + if (data->p_is_s[i]) { + spush(tps, data->p_is_s[i]); + } else { + npush(tps, (int) data->param[i]); + } } break; @@ -574,10 +871,11 @@ tparam_internal(const char *string, va_list ap) cp++; if (isUPPER(*cp)) { i = (UChar(*cp) - 'A'); - TPS(static_vars)[i] = npop(); + TPS(static_vars)[i] = npop(tps); } else if (isLOWER(*cp)) { i = (UChar(*cp) - 'a'); - TPS(dynamic_var)[i] = npop(); + init_vars(dynamic); + dynamic_vars[i] = npop(tps); } break; @@ -585,16 +883,17 @@ tparam_internal(const char *string, va_list ap) cp++; if (isUPPER(*cp)) { i = (UChar(*cp) - 'A'); - npush(TPS(static_vars)[i]); + npush(tps, TPS(static_vars)[i]); } else if (isLOWER(*cp)) { i = (UChar(*cp) - 'a'); - npush(TPS(dynamic_var)[i]); + init_vars(dynamic); + npush(tps, dynamic_vars[i]); } break; case S_QUOTE: cp++; - npush(UChar(*cp)); + npush(tps, UChar(*cp)); cp++; break; @@ -605,93 +904,125 @@ tparam_internal(const char *string, va_list ap) number = (number * 10) + (UChar(*cp) - '0'); cp++; } - npush(number); + npush(tps, number); break; case '+': - npush(npop() + npop()); + y = npop(tps); + x = npop(tps); + npush(tps, x + y); break; case '-': - y = npop(); - x = npop(); - npush(x - y); + y = npop(tps); + x = npop(tps); + npush(tps, x - y); break; case '*': - npush(npop() * npop()); + y = npop(tps); + x = npop(tps); + npush(tps, x * y); break; case '/': - y = npop(); - x = npop(); - npush(y ? (x / y) : 0); + y = npop(tps); + x = npop(tps); + npush(tps, y ? (x / y) : 0); break; case 'm': - y = npop(); - x = npop(); - npush(y ? (x % y) : 0); + y = npop(tps); + x = npop(tps); + npush(tps, y ? (x % y) : 0); break; case 'A': - npush(npop() && npop()); + y = npop(tps); + x = npop(tps); + npush(tps, y && x); break; case 'O': - npush(npop() || npop()); + y = npop(tps); + x = npop(tps); + npush(tps, y || x); break; case '&': - npush(npop() & npop()); + y = npop(tps); + x = npop(tps); + npush(tps, x & y); break; case '|': - npush(npop() | npop()); + y = npop(tps); + x = npop(tps); + npush(tps, x | y); break; case '^': - npush(npop() ^ npop()); + y = npop(tps); + x = npop(tps); + npush(tps, x ^ y); break; case '=': - y = npop(); - x = npop(); - npush(x == y); + y = npop(tps); + x = npop(tps); + npush(tps, x == y); break; case '<': - y = npop(); - x = npop(); - npush(x < y); + y = npop(tps); + x = npop(tps); + npush(tps, x < y); break; case '>': - y = npop(); - x = npop(); - npush(x > y); + y = npop(tps); + x = npop(tps); + npush(tps, x > y); break; case '!': - npush(!npop()); + x = npop(tps); + npush(tps, !x); break; case '~': - npush(~npop()); + x = npop(tps); + npush(tps, ~x); break; case 'i': - if (p_is_s[0] == 0) - param[0]++; - if (p_is_s[1] == 0) - param[1]++; + /* + * Increment the first two parameters -- if they are numbers + * rather than strings. As a side effect, assign into the + * stack; if this is termcap, then the stack was populated + * using the termcap hack above rather than via the terminfo + * 'p' case. + */ + if (!incremented_two) { + incremented_two = TRUE; + if (data->p_is_s[0] == 0) { + data->param[0]++; + if (termcap_hack) + TPS(stack)[0].data.num = (int) data->param[0]; + } + if (data->p_is_s[1] == 0) { + data->param[1]++; + if (termcap_hack) + TPS(stack)[1].data.num = (int) data->param[1]; + } + } break; case '?': break; case 't': - x = npop(); + x = npop(tps); if (!x) { /* scan forward for %e or %; at level zero */ cp++; @@ -750,48 +1081,328 @@ tparam_internal(const char *string, va_list ap) cp++; } /* endwhile (*cp) */ - get_space(1); + get_space(tps, (size_t) 1); TPS(out_buff)[TPS(out_used)] = '\0'; + if (TPS(stack_ptr) && !_nc_tparm_err) { + DEBUG(2, ("tparm: stack has %d item%s on return", + TPS(stack_ptr), + TPS(stack_ptr) == 1 ? "" : "s")); + _nc_tparm_err++; + } + T((T_RETURN("%s"), _nc_visbuf(TPS(out_buff)))); return (TPS(out_buff)); } -#if NCURSES_TPARM_VARARGS -#define tparm_varargs tparm +#ifdef CUR +/* + * Only a few standard capabilities accept string parameters. The others that + * are parameterized accept only numeric parameters. + */ +static bool +check_string_caps(TPARM_DATA *data, const char *string) +{ + bool result = FALSE; + +#define CHECK_CAP(name) (VALID_STRING(name) && !strcmp(name, string)) + + /* + * Disallow string parameters unless we can check them against a terminal + * description. + */ + if (cur_term != NULL) { + int want_type = 0; + + if (CHECK_CAP(pkey_key)) + want_type = 2; /* function key #1, type string #2 */ + else if (CHECK_CAP(pkey_local)) + want_type = 2; /* function key #1, execute string #2 */ + else if (CHECK_CAP(pkey_xmit)) + want_type = 2; /* function key #1, transmit string #2 */ + else if (CHECK_CAP(plab_norm)) + want_type = 2; /* label #1, show string #2 */ + else if (CHECK_CAP(pkey_plab)) + want_type = 6; /* function key #1, type string #2, show string #3 */ +#if NCURSES_XNAMES + else { + char *check; + + check = tigetstr("Cs"); + if (CHECK_CAP(check)) + want_type = 1; /* style #1 */ + + check = tigetstr("Ms"); + if (CHECK_CAP(check)) + want_type = 3; /* storage unit #1, content #2 */ + } +#endif + + if (want_type == data->tparm_type) { + result = TRUE; + } else { + T(("unexpected string-parameter")); + } + } + return result; +} + +#define ValidCap(allow_strings) (myData.tparm_type == 0 || \ + (allow_strings && \ + check_string_caps(&myData, string))) #else -#define tparm_proto tparm +#define ValidCap(allow_strings) 1 #endif +#if NCURSES_TPARM_VARARGS + NCURSES_EXPORT(char *) -tparm_varargs(NCURSES_CONST char *string,...) +tparm(const char *string, ...) { - va_list ap; - char *result; + TPARM_STATE *tps = get_tparm_state(cur_term); + TPARM_DATA myData; + char *result = NULL; _nc_tparm_err = 0; - va_start(ap, string); #ifdef TRACE - TPS(tname) = "tparm"; + tps->tname = "tparm"; #endif /* TRACE */ - result = tparam_internal(string, ap); - va_end(ap); + + if (tparm_setup(cur_term, string, &myData) == OK && ValidCap(TRUE)) { + va_list ap; + + va_start(ap, string); + tparm_copy_valist(&myData, TRUE, ap); + va_end(ap); + + result = tparam_internal(tps, string, &myData); + } return result; } -#if !NCURSES_TPARM_VARARGS +#else /* !NCURSES_TPARM_VARARGS */ + NCURSES_EXPORT(char *) -tparm_proto(NCURSES_CONST char *string, - TPARM_ARG a1, - TPARM_ARG a2, - TPARM_ARG a3, - TPARM_ARG a4, - TPARM_ARG a5, - TPARM_ARG a6, - TPARM_ARG a7, - TPARM_ARG a8, - TPARM_ARG a9) +tparm(const char *string, + TPARM_ARG a1, + TPARM_ARG a2, + TPARM_ARG a3, + TPARM_ARG a4, + TPARM_ARG a5, + TPARM_ARG a6, + TPARM_ARG a7, + TPARM_ARG a8, + TPARM_ARG a9) { - return tparm_varargs(string, a1, a2, a3, a4, a5, a6, a7, a8, a9); + TPARM_STATE *tps = get_tparm_state(cur_term); + TPARM_DATA myData; + char *result = NULL; + + _nc_tparm_err = 0; +#ifdef TRACE + tps->tname = "tparm"; +#endif /* TRACE */ + +#define string_ok (sizeof(char*) <= sizeof(TPARM_ARG)) + + if (tparm_setup(cur_term, string, &myData) == OK && ValidCap(string_ok)) { + + myData.param[0] = a1; + myData.param[1] = a2; + myData.param[2] = a3; + myData.param[3] = a4; + myData.param[4] = a5; + myData.param[5] = a6; + myData.param[6] = a7; + myData.param[7] = a8; + myData.param[8] = a9; + + result = tparam_internal(tps, string, &myData); + } + return result; } + #endif /* NCURSES_TPARM_VARARGS */ + +NCURSES_EXPORT(char *) +tiparm(const char *string, ...) +{ + TPARM_STATE *tps = get_tparm_state(cur_term); + TPARM_DATA myData; + char *result = NULL; + + _nc_tparm_err = 0; +#ifdef TRACE + tps->tname = "tiparm"; +#endif /* TRACE */ + + if (tparm_setup(cur_term, string, &myData) == OK && ValidCap(TRUE)) { + va_list ap; + + va_start(ap, string); + tparm_copy_valist(&myData, FALSE, ap); + va_end(ap); + + result = tparam_internal(tps, string, &myData); + } + return result; +} + +/* + * Use tparm if the formatting string matches the expected number of parameters + * counting string-parameters. + */ +NCURSES_EXPORT(char *) +tiparm_s(int num_expected, int tparm_type, const char *string, ...) +{ + TPARM_STATE *tps = get_tparm_state(cur_term); + TPARM_DATA myData; + char *result = NULL; + + _nc_tparm_err = 0; +#ifdef TRACE + tps->tname = "tiparm_s"; +#endif /* TRACE */ + if (num_expected >= 0 && + num_expected <= 9 && + tparm_type >= 0 && + tparm_type < 7 && /* limit to 2 string parameters */ + tparm_setup(cur_term, string, &myData) == OK && + myData.tparm_type == tparm_type && + myData.num_actual == num_expected) { + va_list ap; + + va_start(ap, string); + tparm_copy_valist(&myData, FALSE, ap); + va_end(ap); + + result = tparam_internal(tps, string, &myData); + } + return result; +} + +/* + * Analyze the formatting string, return the analysis. + */ +NCURSES_EXPORT(int) +tiscan_s(int *num_expected, int *tparm_type, const char *string) +{ + TPARM_DATA myData; + int result = ERR; + +#ifdef TRACE + TPARM_STATE *tps = get_tparm_state(cur_term); + tps->tname = "tiscan_s"; +#endif /* TRACE */ + + if (tparm_setup(cur_term, string, &myData) == OK) { + *num_expected = myData.num_actual; + *tparm_type = myData.tparm_type; + result = OK; + } + return result; +} + +/* + * The internal-use flavor ensures that parameters are numbers, not strings. + * In addition to ensuring that they are numbers, it ensures that the parameter + * count is consistent with intended usage. + * + * Unlike the general-purpose tparm/tiparm, these internal calls are fairly + * well defined: + * + * expected == 0 - not applicable + * expected == 1 - set color, or vertical/horizontal addressing + * expected == 2 - cursor addressing + * expected == 4 - initialize color or color pair + * expected == 9 - set attributes + * + * Only for the last case (set attributes) should a parameter be optional. + * Also, a capability which calls for more parameters than expected should be + * ignored. + * + * Return a null if the parameter-checks fail. Otherwise, return a pointer to + * the formatted capability string. + */ +NCURSES_EXPORT(char *) +_nc_tiparm(int expected, const char *string, ...) +{ + TPARM_STATE *tps = get_tparm_state(cur_term); + TPARM_DATA myData; + char *result = NULL; + + _nc_tparm_err = 0; + T((T_CALLED("_nc_tiparm(%d, %s, ...)"), expected, _nc_visbuf(string))); +#ifdef TRACE + tps->tname = "_nc_tiparm"; +#endif /* TRACE */ + + if (tparm_setup(cur_term, string, &myData) == OK && ValidCap(FALSE)) { +#ifdef CUR + if (myData.num_actual != expected && cur_term != NULL) { + int needed = expected; + if (CHECK_CAP(to_status_line)) { + needed = 0; /* allow for xterm's status line */ + } else if (CHECK_CAP(set_a_background)) { + needed = 0; /* allow for monochrome fakers */ + } else if (CHECK_CAP(set_a_foreground)) { + needed = 0; + } else if (CHECK_CAP(set_background)) { + needed = 0; + } else if (CHECK_CAP(set_foreground)) { + needed = 0; + } +#if NCURSES_XNAMES + else { + char *check; + + check = tigetstr("xm"); + if (CHECK_CAP(check)) { + needed = 3; + } + check = tigetstr("S0"); + if (CHECK_CAP(check)) { + needed = 0; /* used in screen-base */ + } + } +#endif + if (myData.num_actual >= needed && myData.num_actual <= expected) + expected = myData.num_actual; + } +#endif + if (myData.num_actual == 0 && expected) { + T(("missing parameter%s, expected %s%d", + expected > 1 ? "s" : "", + expected == 9 ? "up to " : "", + expected)); + } else if (myData.num_actual > expected) { + T(("too many parameters, have %d, expected %d", + myData.num_actual, + expected)); + } else if (expected != 9 && myData.num_actual != expected) { + T(("expected %d parameters, have %d", + myData.num_actual, + expected)); + } else { + va_list ap; + + va_start(ap, string); + tparm_copy_valist(&myData, FALSE, ap); + va_end(ap); + + result = tparam_internal(tps, string, &myData); + } + } + returnPtr(result); +} + +/* + * Improve tic's checks by resetting the terminfo "static variables" before + * calling functions which may update them. + */ +NCURSES_EXPORT(void) +_nc_reset_tparm(TERMINAL *term) +{ + TPARM_STATE *tps = get_tparm_state(term); + memset(TPS(static_vars), 0, sizeof(TPS(static_vars))); +} diff --git a/lib/libcurses/tinfo/lib_tputs.c b/lib/libcurses/tinfo/lib_tputs.c index c085ecfb77f..9fdcc137434 100644 --- a/lib/libcurses/tinfo/lib_tputs.c +++ b/lib/libcurses/tinfo/lib_tputs.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_tputs.c,v 1.12 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_tputs.c,v 1.13 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,6 +33,7 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -43,17 +45,21 @@ */ #include + +#ifndef CUR +#define CUR SP_TERMTYPE +#endif + #include -#include /* padding_baud_rate, xon_xoff */ #include /* ospeed */ #include -MODULE_ID("$Id: lib_tputs.c,v 1.12 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_tputs.c,v 1.13 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT_VAR(char) PC = 0; /* used by termcap library */ NCURSES_EXPORT_VAR(NCURSES_OSPEED) ospeed = 0; /* used by termcap library */ -NCURSES_EXPORT_VAR(int) _nc_nulls_sent = 0; /* used by 'tack' program */ +NCURSES_EXPORT_VAR(int) _nc_nulls_sent = 0; #if NCURSES_NO_PADDING NCURSES_EXPORT(void) @@ -71,78 +77,226 @@ _nc_set_no_padding(SCREEN *sp) } #endif -static int (*my_outch) (int c) = _nc_outch; +#if NCURSES_SP_FUNCS +#define SetOutCh(func) if (SP_PARM) SP_PARM->_outch = func; else _nc_prescreen._outch = func +#define GetOutCh() (SP_PARM ? SP_PARM->_outch : _nc_prescreen._outch) +#else +#define SetOutCh(func) static_outch = func +#define GetOutCh() static_outch +static NCURSES_SP_OUTC static_outch = NCURSES_SP_NAME(_nc_outch); +#endif NCURSES_EXPORT(int) -delay_output(int ms) +NCURSES_SP_NAME(delay_output) (NCURSES_SP_DCLx int ms) { - T((T_CALLED("delay_output(%d)"), ms)); + T((T_CALLED("delay_output(%p,%d)"), (void *) SP_PARM, ms)); + + if (!HasTInfoTerminal(SP_PARM)) + returnCode(ERR); if (no_pad_char) { - _nc_flush(); + NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG); napms(ms); } else { + NCURSES_SP_OUTC my_outch = GetOutCh(); register int nullcount; nullcount = (ms * _nc_baudrate(ospeed)) / (BAUDBYTE * 1000); for (_nc_nulls_sent += nullcount; nullcount > 0; nullcount--) - my_outch(PC); - if (my_outch == _nc_outch) - _nc_flush(); + my_outch(NCURSES_SP_ARGx PC); + if (my_outch == NCURSES_SP_NAME(_nc_outch)) + NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG); } returnCode(OK); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +delay_output(int ms) +{ + return NCURSES_SP_NAME(delay_output) (CURRENT_SCREEN, ms); +} +#endif + +NCURSES_EXPORT(void) +NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_DCL0) +{ + T((T_CALLED("_nc_flush(%p)"), (void *) SP_PARM)); + if (SP_PARM != 0 && SP_PARM->_ofd >= 0) { + TR(TRACE_CHARPUT, ("ofd:%d inuse:%lu buffer:%p", + SP_PARM->_ofd, + (unsigned long) SP_PARM->out_inuse, + SP_PARM->out_buffer)); + if (SP_PARM->out_inuse) { + char *buf = SP_PARM->out_buffer; + size_t amount = SP_PARM->out_inuse; + + TR(TRACE_CHARPUT, ("flushing %ld/%ld bytes", + (unsigned long) amount, _nc_outchars)); + while (amount) { + ssize_t res = write(SP_PARM->_ofd, buf, amount); + if (res > 0) { + /* if the write was incomplete, try again */ + amount -= (size_t) res; + buf += res; + } else if (errno == EAGAIN) { + continue; + } else if (errno == EINTR) { + continue; + } else { + break; /* an error we can not recover from */ + } + } + } else if (SP_PARM->out_buffer == 0) { + TR(TRACE_CHARPUT, ("flushing stdout")); + fflush(stdout); + } + } else { + TR(TRACE_CHARPUT, ("flushing stdout")); + fflush(stdout); + } + if (SP_PARM != 0) + SP_PARM->out_inuse = 0; + returnVoid; +} + +#if NCURSES_SP_FUNCS NCURSES_EXPORT(void) _nc_flush(void) { - (void) fflush(NC_OUTPUT); + NCURSES_SP_NAME(_nc_flush) (CURRENT_SCREEN); } +#endif NCURSES_EXPORT(int) -_nc_outch(int ch) +NCURSES_SP_NAME(_nc_outch) (NCURSES_SP_DCLx int ch) { + int rc = OK; + COUNT_OUTCHARS(1); - if (SP != 0 - && SP->_cleanup) { - char tmp = ch; - /* - * POSIX says write() is safe in a signal handler, but the - * buffered I/O is not. - */ - write(fileno(NC_OUTPUT), &tmp, 1); + if (HasTInfoTerminal(SP_PARM) + && SP_PARM != 0) { + if (SP_PARM->out_buffer != 0) { + if (SP_PARM->out_inuse + 1 >= SP_PARM->out_limit) + NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG); + SP_PARM->out_buffer[SP_PARM->out_inuse++] = (char) ch; + } else { + char tmp = (char) ch; + /* + * POSIX says write() is safe in a signal handler, but the + * buffered I/O is not. + */ + if (write(fileno(NC_OUTPUT(SP_PARM)), &tmp, (size_t) 1) == -1) + rc = ERR; + } } else { - putc(ch, NC_OUTPUT); + char tmp = (char) ch; + if (write(fileno(stdout), &tmp, (size_t) 1) == -1) + rc = ERR; } - return OK; + return rc; +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +_nc_outch(int ch) +{ + return NCURSES_SP_NAME(_nc_outch) (CURRENT_SCREEN, ch); +} +#endif + +/* + * This is used for the putp special case. + */ +NCURSES_EXPORT(int) +NCURSES_SP_NAME(_nc_putchar) (NCURSES_SP_DCLx int ch) +{ + (void) SP_PARM; + return putchar(ch); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +_nc_putchar(int ch) +{ + return putchar(ch); } +#endif +/* + * putp is special - per documentation it calls tputs with putchar as the + * parameter for outputting characters. This means that it uses stdio, which + * is not signal-safe. Applications call this entrypoint; we do not call it + * from within the library. + */ +NCURSES_EXPORT(int) +NCURSES_SP_NAME(putp) (NCURSES_SP_DCLx const char *string) +{ + return NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + string, 1, NCURSES_SP_NAME(_nc_putchar)); +} + +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) putp(const char *string) { - return tputs(string, 1, _nc_outch); + return NCURSES_SP_NAME(putp) (CURRENT_SCREEN, string); +} +#endif + +/* + * Use these entrypoints rather than "putp" within the library. + */ +NCURSES_EXPORT(int) +NCURSES_SP_NAME(_nc_putp) (NCURSES_SP_DCLx + const char *name GCC_UNUSED, + const char *string) +{ + int rc = ERR; + + if (string != 0) { + TPUTS_TRACE(name); + rc = NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + string, 1, NCURSES_SP_NAME(_nc_outch)); + } + return rc; } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) -tputs(const char *string, int affcnt, int (*outc) (int)) +_nc_putp(const char *name, const char *string) +{ + return NCURSES_SP_NAME(_nc_putp) (CURRENT_SCREEN, name, string); +} +#endif + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(tputs) (NCURSES_SP_DCLx + const char *string, + int affcnt, + NCURSES_SP_OUTC outc) { - bool always_delay; - bool normal_delay; + NCURSES_SP_OUTC my_outch = GetOutCh(); + bool always_delay = FALSE; + bool normal_delay = FALSE; int number; #if BSD_TPUTS int trailpad; #endif /* BSD_TPUTS */ #ifdef TRACE - char addrbuf[32]; - if (USE_TRACEF(TRACE_TPUTS)) { - if (outc == _nc_outch) - (void) strlcpy(addrbuf, "_nc_outch", sizeof(addrbuf)); - else - (void) snprintf(addrbuf, sizeof(addrbuf), "%p", outc); + char addrbuf[32]; + TR_FUNC_BFR(1); + + if (outc == NCURSES_SP_NAME(_nc_outch)) { + _nc_STRCPY(addrbuf, "_nc_outch", sizeof(addrbuf)); + } else { + _nc_SPRINTF(addrbuf, _nc_SLIMIT(sizeof(addrbuf)) "%s", + TR_FUNC_ARG(0, outc)); + } if (_nc_tputs_trace) { _tracef("tputs(%s = %s, %d, %s) called", _nc_tputs_trace, _nc_visbuf(string), affcnt, addrbuf); @@ -157,20 +311,27 @@ tputs(const char *string, int affcnt, int (*outc) (int)) if (!VALID_STRING(string)) return ERR; - if (cur_term == 0) { - always_delay = FALSE; - normal_delay = TRUE; - } else { - always_delay = (string == bell) || (string == flash_screen); - normal_delay = - !xon_xoff - && padding_baud_rate + if (SP_PARM != 0 && HasTInfoTerminal(SP_PARM)) { + if ( +#if NCURSES_SP_FUNCS + (SP_PARM != 0 && SP_PARM->_term == 0) +#else + cur_term == 0 +#endif + ) { + always_delay = FALSE; + normal_delay = TRUE; + } else { + always_delay = (string == bell) || (string == flash_screen); + normal_delay = + !xon_xoff + && padding_baud_rate #if NCURSES_NO_PADDING - && !GetNoPadding(SP) + && !GetNoPadding(SP_PARM) #endif - && (_nc_baudrate(ospeed) >= padding_baud_rate); + && (_nc_baudrate(ospeed) >= padding_baud_rate); + } } - #if BSD_TPUTS /* * This ugly kluge deals with the fact that some ancient BSD programs @@ -200,24 +361,24 @@ tputs(const char *string, int affcnt, int (*outc) (int)) } #endif /* BSD_TPUTS */ - my_outch = outc; /* redirect delay_output() */ + SetOutCh(outc); /* redirect delay_output() */ while (*string) { if (*string != '$') - (*outc) (*string); + (*outc) (NCURSES_SP_ARGx *string); else { string++; if (*string != '<') { - (*outc) ('$'); + (*outc) (NCURSES_SP_ARGx '$'); if (*string) - (*outc) (*string); + (*outc) (NCURSES_SP_ARGx *string); } else { bool mandatory; string++; if ((!isdigit(UChar(*string)) && *string != '.') || !strchr(string, '>')) { - (*outc) ('$'); - (*outc) ('<'); + (*outc) (NCURSES_SP_ARGx '$'); + (*outc) (NCURSES_SP_ARGx '<'); continue; } @@ -252,7 +413,7 @@ tputs(const char *string, int affcnt, int (*outc) (int)) && (always_delay || normal_delay || mandatory)) - delay_output(number / 10); + NCURSES_SP_NAME(delay_output) (NCURSES_SP_ARGx number / 10); } /* endelse (*string == '<') */ } /* endelse (*string == '$') */ @@ -269,9 +430,28 @@ tputs(const char *string, int affcnt, int (*outc) (int)) */ if (trailpad > 0 && (always_delay || normal_delay)) - delay_output(trailpad / 10); + NCURSES_SP_NAME(delay_output) (NCURSES_SP_ARGx trailpad / 10); #endif /* BSD_TPUTS */ - my_outch = _nc_outch; + SetOutCh(my_outch); return OK; } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +_nc_outc_wrapper(SCREEN *sp, int c) +{ + if (0 == sp) { + return fputc(c, stdout); + } else { + return sp->jump(c); + } +} + +NCURSES_EXPORT(int) +tputs(const char *string, int affcnt, int (*outc) (int)) +{ + SetSafeOutcWrapper(outc); + return NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx string, affcnt, _nc_outc_wrapper); +} +#endif diff --git a/lib/libcurses/tinfo/lib_ttyflags.c b/lib/libcurses/tinfo/lib_ttyflags.c index ec604dcaa53..293eefebff7 100644 --- a/lib/libcurses/tinfo/lib_ttyflags.c +++ b/lib/libcurses/tinfo/lib_ttyflags.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_ttyflags.c,v 1.5 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_ttyflags.c,v 1.6 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -38,159 +39,254 @@ */ #include -#include /* cur_term */ -MODULE_ID("$Id: lib_ttyflags.c,v 1.5 2010/01/12 23:22:06 nicm Exp $") +#ifndef CUR +#define CUR SP_TERMTYPE +#endif + +MODULE_ID("$Id: lib_ttyflags.c,v 1.6 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) -_nc_get_tty_mode(TTY * buf) +NCURSES_SP_NAME(_nc_get_tty_mode) (NCURSES_SP_DCLx TTY * buf) { + TERMINAL *termp = TerminalOf(SP_PARM); int result = OK; - if (buf == 0) { + if (buf == 0 || termp == 0) { result = ERR; } else { - if (cur_term == 0) { - result = ERR; + +#ifdef USE_TERM_DRIVER + if (SP_PARM != 0) { + result = CallDriver_2(SP_PARM, td_sgmode, FALSE, buf); } else { - for (;;) { - if (GET_TTY(cur_term->Filedes, buf) != 0) { - if (errno == EINTR) - continue; - result = ERR; - } - break; + result = ERR; + } +#else + for (;;) { + if (GET_TTY(termp->Filedes, buf) != 0) { + if (errno == EINTR) + continue; + result = ERR; } + break; } - - if (result == ERR) - memset(buf, 0, sizeof(*buf)); +#endif TR(TRACE_BITS, ("_nc_get_tty_mode(%d): %s", - cur_term ? cur_term->Filedes : -1, + termp ? termp->Filedes : -1, _nc_trace_ttymode(buf))); } + if (result == ERR && buf != 0) + memset(buf, 0, sizeof(*buf)); + return (result); } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) -_nc_set_tty_mode(TTY * buf) +_nc_get_tty_mode(TTY * buf) +{ + return NCURSES_SP_NAME(_nc_get_tty_mode) (CURRENT_SCREEN, buf); +} +#endif + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_DCLx TTY * buf) { int result = OK; - if (buf == 0) { + if (buf == 0 || SP_PARM == 0) { result = ERR; } else { - if (cur_term == 0) { + TERMINAL *termp = TerminalOf(SP_PARM); + + if (0 == termp) { result = ERR; } else { +#ifdef USE_TERM_DRIVER + result = CallDriver_2(SP_PARM, td_sgmode, TRUE, buf); +#else for (;;) { - if (SET_TTY(cur_term->Filedes, buf) != 0) { + if ((SET_TTY(termp->Filedes, buf) != 0) +#if USE_KLIBC_KBD + && !NC_ISATTY(termp->Filedes) +#endif + ) { if (errno == EINTR) continue; - if ((errno == ENOTTY) && (SP != 0)) - SP->_notty = TRUE; + if ((errno == ENOTTY) && (SP_PARM != 0)) + SP_PARM->_notty = TRUE; result = ERR; } break; } +#endif } TR(TRACE_BITS, ("_nc_set_tty_mode(%d): %s", - cur_term ? cur_term->Filedes : -1, + termp ? termp->Filedes : -1, _nc_trace_ttymode(buf))); } return (result); } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) -def_shell_mode(void) +_nc_set_tty_mode(TTY * buf) +{ + return NCURSES_SP_NAME(_nc_set_tty_mode) (CURRENT_SCREEN, buf); +} +#endif + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(def_shell_mode) (NCURSES_SP_DCL0) { int rc = ERR; + TERMINAL *termp = TerminalOf(SP_PARM); - T((T_CALLED("def_shell_mode()"))); + T((T_CALLED("def_shell_mode(%p) ->term %p"), + (void *) SP_PARM, (void *) termp)); - if (cur_term != 0) { + if (termp != 0) { +#ifdef USE_TERM_DRIVER + rc = CallDriver_2(SP_PARM, td_mode, FALSE, TRUE); +#else /* * If XTABS was on, remove the tab and backtab capabilities. */ - if (_nc_get_tty_mode(&cur_term->Ottyb) == OK) { + if (_nc_get_tty_mode(&termp->Ottyb) == OK) { #ifdef TERMIOS - if (cur_term->Ottyb.c_oflag & OFLAGS_TABS) + if (termp->Ottyb.c_oflag & OFLAGS_TABS) tab = back_tab = NULL; +#elif defined(EXP_WIN32_DRIVER) + /* noop */ #else - if (cur_term->Ottyb.sg_flags & XTABS) + if (termp->Ottyb.sg_flags & XTABS) tab = back_tab = NULL; #endif rc = OK; } +#endif } returnCode(rc); } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) -def_prog_mode(void) +def_shell_mode(void) +{ + return NCURSES_SP_NAME(def_shell_mode) (CURRENT_SCREEN); +} +#endif + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(def_prog_mode) (NCURSES_SP_DCL0) { int rc = ERR; + TERMINAL *termp = TerminalOf(SP_PARM); - T((T_CALLED("def_prog_mode()"))); + T((T_CALLED("def_prog_mode(%p) ->term %p"), (void *) SP_PARM, (void *) termp)); - if (cur_term != 0) { + if (termp != 0) { +#ifdef USE_TERM_DRIVER + rc = CallDriver_2(SP_PARM, td_mode, TRUE, TRUE); +#else /* * Turn off the XTABS bit in the tty structure if it was on. */ - if (_nc_get_tty_mode(&cur_term->Nttyb) == OK) { + if (_nc_get_tty_mode(&termp->Nttyb) == OK) { #ifdef TERMIOS - cur_term->Nttyb.c_oflag &= ~OFLAGS_TABS; + termp->Nttyb.c_oflag &= (unsigned) (~OFLAGS_TABS); +#elif defined(EXP_WIN32_DRIVER) + /* noop */ #else - cur_term->Nttyb.sg_flags &= ~XTABS; + termp->Nttyb.sg_flags &= (unsigned) (~XTABS); #endif rc = OK; } +#endif } returnCode(rc); } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) -reset_prog_mode(void) +def_prog_mode(void) { - T((T_CALLED("reset_prog_mode()"))); + return NCURSES_SP_NAME(def_prog_mode) (CURRENT_SCREEN); +} +#endif + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(reset_prog_mode) (NCURSES_SP_DCL0) +{ + int rc = ERR; + TERMINAL *termp = TerminalOf(SP_PARM); + + T((T_CALLED("reset_prog_mode(%p) ->term %p"), (void *) SP_PARM, (void *) termp)); - if (cur_term != 0) { - if (_nc_set_tty_mode(&cur_term->Nttyb) == OK) { - if (SP) { - if (SP->_keypad_on) - _nc_keypad(SP, TRUE); - NC_BUFFERED(TRUE); + if (termp != 0) { +#ifdef USE_TERM_DRIVER + rc = CallDriver_2(SP_PARM, td_mode, TRUE, FALSE); +#else + if (_nc_set_tty_mode(&termp->Nttyb) == OK) { + if (SP_PARM) { + if (SP_PARM->_keypad_on) + _nc_keypad(SP_PARM, TRUE); } - returnCode(OK); + rc = OK; } +#endif } - returnCode(ERR); + returnCode(rc); } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) -reset_shell_mode(void) +reset_prog_mode(void) { - T((T_CALLED("reset_shell_mode()"))); + return NCURSES_SP_NAME(reset_prog_mode) (CURRENT_SCREEN); +} +#endif - if (cur_term != 0) { - if (SP) { - _nc_keypad(SP, FALSE); +NCURSES_EXPORT(int) +NCURSES_SP_NAME(reset_shell_mode) (NCURSES_SP_DCL0) +{ + int rc = ERR; + TERMINAL *termp = TerminalOf(SP_PARM); + + T((T_CALLED("reset_shell_mode(%p) ->term %p"), + (void *) SP_PARM, (void *) termp)); + + if (termp != 0) { +#ifdef USE_TERM_DRIVER + rc = CallDriver_2(SP_PARM, td_mode, FALSE, FALSE); +#else + if (SP_PARM) { + _nc_keypad(SP_PARM, FALSE); _nc_flush(); - NC_BUFFERED(FALSE); } - returnCode(_nc_set_tty_mode(&cur_term->Ottyb)); + rc = _nc_set_tty_mode(&termp->Ottyb); +#endif } - returnCode(ERR); + returnCode(rc); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +reset_shell_mode(void) +{ + return NCURSES_SP_NAME(reset_shell_mode) (CURRENT_SCREEN); +} +#endif + static TTY * -saved_tty(void) +saved_tty(NCURSES_SP_DCL0) { TTY *result = 0; - if (SP != 0) { - result = &(SP->_saved_tty); + if (SP_PARM != 0) { + result = (TTY *) & (SP_PARM->_saved_tty); } else { if (_nc_prescreen.saved_tty == 0) { _nc_prescreen.saved_tty = typeCalloc(TTY, 1); @@ -205,18 +301,32 @@ saved_tty(void) ** */ +NCURSES_EXPORT(int) +NCURSES_SP_NAME(savetty) (NCURSES_SP_DCL0) +{ + T((T_CALLED("savetty(%p)"), (void *) SP_PARM)); + returnCode(NCURSES_SP_NAME(_nc_get_tty_mode) (NCURSES_SP_ARGx saved_tty(NCURSES_SP_ARG))); +} + +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) savetty(void) { - T((T_CALLED("savetty()"))); + return NCURSES_SP_NAME(savetty) (CURRENT_SCREEN); +} +#endif - returnCode(_nc_get_tty_mode(saved_tty())); +NCURSES_EXPORT(int) +NCURSES_SP_NAME(resetty) (NCURSES_SP_DCL0) +{ + T((T_CALLED("resetty(%p)"), (void *) SP_PARM)); + returnCode(NCURSES_SP_NAME(_nc_set_tty_mode) (NCURSES_SP_ARGx saved_tty(NCURSES_SP_ARG))); } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) resetty(void) { - T((T_CALLED("resetty()"))); - - returnCode(_nc_set_tty_mode(saved_tty())); + return NCURSES_SP_NAME(resetty) (CURRENT_SCREEN); } +#endif diff --git a/lib/libcurses/tinfo/lib_win32con.c b/lib/libcurses/tinfo/lib_win32con.c new file mode 100644 index 00000000000..c3df420bfa0 --- /dev/null +++ b/lib/libcurses/tinfo/lib_win32con.c @@ -0,0 +1,1252 @@ +/**************************************************************************** + * Copyright 2020-2021,2023 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Juergen Pfeifer * + * and: Thomas E. Dickey * + ****************************************************************************/ + +/* + * TODO - GetMousePos(POINT * result) from ntconio.c + */ + +#include + +MODULE_ID("$Id: lib_win32con.c,v 1.1 2023/10/17 09:52:09 nicm Exp $") + +#ifdef _NC_WINDOWS + +#ifdef _NC_MINGW +#include +#else +#include +#endif + +#include + +#if USE_WIDEC_SUPPORT +#define write_screen WriteConsoleOutputW +#define read_screen ReadConsoleOutputW +#else +#define write_screen WriteConsoleOutput +#define read_screen ReadConsoleOutput +#endif + +static bool read_screen_data(void); + +#define GenMap(vKey,key) MAKELONG(key, vKey) +static const LONG keylist[] = +{ + GenMap(VK_PRIOR, KEY_PPAGE), + GenMap(VK_NEXT, KEY_NPAGE), + GenMap(VK_END, KEY_END), + GenMap(VK_HOME, KEY_HOME), + GenMap(VK_LEFT, KEY_LEFT), + GenMap(VK_UP, KEY_UP), + GenMap(VK_RIGHT, KEY_RIGHT), + GenMap(VK_DOWN, KEY_DOWN), + GenMap(VK_DELETE, KEY_DC), + GenMap(VK_INSERT, KEY_IC) +}; +static const LONG ansi_keys[] = +{ + GenMap(VK_PRIOR, 'I'), + GenMap(VK_NEXT, 'Q'), + GenMap(VK_END, 'O'), + GenMap(VK_HOME, 'H'), + GenMap(VK_LEFT, 'K'), + GenMap(VK_UP, 'H'), + GenMap(VK_RIGHT, 'M'), + GenMap(VK_DOWN, 'P'), + GenMap(VK_DELETE, 'S'), + GenMap(VK_INSERT, 'R') +}; +#define array_length(a) (sizeof(a)/sizeof(a[0])) +#define N_INI ((int)array_length(keylist)) +#define FKEYS 24 +#define MAPSIZE (FKEYS + N_INI) + +/* A process can only have a single console, so it is safe + to maintain all the information about it in a single + static structure. + */ +NCURSES_EXPORT_VAR(ConsoleInfo) _nc_CONSOLE; +static bool console_initialized = FALSE; + +#define EnsureInit() (void)(console_initialized ? TRUE : _nc_console_checkinit(TRUE, TRUE)) + +#define REQUIRED_MAX_V (DWORD)10 +#define REQUIRED_MIN_V (DWORD)0 +#define REQUIRED_BUILD (DWORD)17763 +/* + This function returns 0 if the Windows version has no support for + the modern Console interface, otherwise it returns 1 + */ +NCURSES_EXPORT(int) +_nc_console_vt_supported(void) +{ + OSVERSIONINFO osvi; + int res = 0; + + T((T_CALLED("lib_win32con::_nc_console_vt_supported"))); + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + GetVersionEx(&osvi); + T(("GetVersionEx returnedMajor=%ld, Minor=%ld, Build=%ld", + osvi.dwMajorVersion, + osvi.dwMinorVersion, + osvi.dwBuildNumber)); + if (osvi.dwMajorVersion >= REQUIRED_MAX_V) { + if (osvi.dwMajorVersion == REQUIRED_MAX_V) { + if (((osvi.dwMinorVersion == REQUIRED_MIN_V) && + (osvi.dwBuildNumber >= REQUIRED_BUILD)) || + ((osvi.dwMinorVersion > REQUIRED_MIN_V))) + res = 1; + } else + res = 1; + } + returnCode(res); +} + +NCURSES_EXPORT(void) +_nc_console_size(int *Lines, int *Cols) +{ + EnsureInit(); + if (Lines != NULL && Cols != NULL) { + if (WINCONSOLE.buffered) { + *Lines = (int) (WINCONSOLE.SBI.dwSize.Y); + *Cols = (int) (WINCONSOLE.SBI.dwSize.X); + } else { + *Lines = (int) (WINCONSOLE.SBI.srWindow.Bottom + 1 - + WINCONSOLE.SBI.srWindow.Top); + *Cols = (int) (WINCONSOLE.SBI.srWindow.Right + 1 - + WINCONSOLE.SBI.srWindow.Left); + } + } +} + +/* Convert a file descriptor into a HANDLE + That's not necessarily a console HANDLE +*/ +NCURSES_EXPORT(HANDLE) +_nc_console_handle(int fd) +{ + intptr_t value = _get_osfhandle(fd); + return (HANDLE) value; +} + +/* Validate that a HANDLE is actually a + console HANDLE +*/ +static BOOL +IsConsoleHandle(HANDLE hdl) +{ + DWORD dwFlag = 0; + BOOL result = FALSE; + + T((T_CALLED("lib_win32con::IsConsoleHandle(HANDLE=%p"), hdl)); + + EnsureInit(); + + if (!GetConsoleMode(hdl, &dwFlag)) { + T(("GetConsoleMode failed")); + } else { + result = TRUE; + } + + returnBool(result); +} + +/* This is used when running in terminfo mode to discover, + whether or not the "terminal" is actually a Windows + Console. It is the responsibility of the console to deal + with the terminal escape sequences that are sent by + terminfo. + */ +NCURSES_EXPORT(int) +_nc_console_test(int fd) +{ + int code = 0; + HANDLE hdl = INVALID_HANDLE_VALUE; + T((T_CALLED("lib_win32con::_nc_console_test(%d)"), fd)); + hdl = _nc_console_handle(fd); + code = (int) IsConsoleHandle(hdl); + returnCode(code); +} + +#define OutHandle() ((WINCONSOLE.isTermInfoConsole || WINCONSOLE.progMode) ? WINCONSOLE.hdl : WINCONSOLE.out) + +NCURSES_EXPORT(void) +_nc_console_selectActiveHandle(void) +{ + if (WINCONSOLE.lastOut != WINCONSOLE.hdl) { + WINCONSOLE.lastOut = WINCONSOLE.hdl; + SetConsoleActiveScreenBuffer(WINCONSOLE.lastOut); + } +} + +NCURSES_EXPORT(HANDLE) +_nc_console_fd2handle(int fd) +{ + HANDLE hdl = _nc_console_handle(fd); + if (hdl == WINCONSOLE.inp) { + T(("lib_win32con:validateHandle %d -> WINCONSOLE.inp", fd)); + } else if (hdl == WINCONSOLE.hdl) { + T(("lib_win32con:validateHandle %d -> WINCONSOLE.hdl", fd)); + } else if (hdl == WINCONSOLE.out) { + T(("lib_win32con:validateHandle %d -> WINCONSOLE.out", fd)); + } else { + T(("lib_win32con:validateHandle %d maps to unknown HANDLE", fd)); + hdl = INVALID_HANDLE_VALUE; + } +#if 1 + assert(hdl != INVALID_HANDLE_VALUE); +#endif + if (hdl != INVALID_HANDLE_VALUE) { + if (hdl != WINCONSOLE.inp && (!WINCONSOLE.isTermInfoConsole && WINCONSOLE.progMode)) { + if (hdl == WINCONSOLE.out && hdl != WINCONSOLE.hdl) { + T(("lib_win32con:validateHandle forcing WINCONSOLE.out -> WINCONSOLE.hdl")); + hdl = WINCONSOLE.hdl; + } + } + } + return hdl; +} + +NCURSES_EXPORT(int) +_nc_console_setmode(HANDLE hdl, const TTY * arg) +{ + DWORD dwFlag = 0; + int code = ERR; + HANDLE alt; + + if (arg) { +#ifdef TRACE + TTY TRCTTY; +#define TRCTTYOUT(flag) TRCTTY.dwFlagOut = flag +#define TRCTTYIN(flag) TRCTTY.dwFlagIn = flag +#else +#define TRCTTYOUT(flag) +#define TRCTTYIN(flag) +#endif + T(("lib_win32con:_nc_console_setmode %s", _nc_trace_ttymode(arg))); + if (hdl == WINCONSOLE.inp) { + dwFlag = arg->dwFlagIn | ENABLE_MOUSE_INPUT | VT_FLAG_IN; + if (WINCONSOLE.isTermInfoConsole) + dwFlag |= (VT_FLAG_IN); + else + dwFlag &= (DWORD) ~ (VT_FLAG_IN); + TRCTTYIN(dwFlag); + SetConsoleMode(hdl, dwFlag); + + alt = OutHandle(); + dwFlag = arg->dwFlagOut; + if (WINCONSOLE.isTermInfoConsole) + dwFlag |= (VT_FLAG_OUT); + else + dwFlag |= (VT_FLAG_OUT); + TRCTTYOUT(dwFlag); + SetConsoleMode(alt, dwFlag); + } else { + dwFlag = arg->dwFlagOut; + if (WINCONSOLE.isTermInfoConsole) + dwFlag |= (VT_FLAG_OUT); + else + dwFlag |= (VT_FLAG_OUT); + TRCTTYOUT(dwFlag); + SetConsoleMode(hdl, dwFlag); + + alt = WINCONSOLE.inp; + dwFlag = arg->dwFlagIn | ENABLE_MOUSE_INPUT; + if (WINCONSOLE.isTermInfoConsole) + dwFlag |= (VT_FLAG_IN); + else + dwFlag &= (DWORD) ~ (VT_FLAG_IN); + TRCTTYIN(dwFlag); + SetConsoleMode(alt, dwFlag); + T(("effective mode set %s", _nc_trace_ttymode(&TRCTTY))); + } + code = OK; + } + return (code); +} + +NCURSES_EXPORT(int) +_nc_console_getmode(HANDLE hdl, TTY * arg) +{ + int code = ERR; + + if (arg) { + DWORD dwFlag = 0; + HANDLE alt; + + if (hdl == WINCONSOLE.inp) { + if (GetConsoleMode(hdl, &dwFlag)) { + arg->dwFlagIn = dwFlag; + alt = OutHandle(); + if (GetConsoleMode(alt, &dwFlag)) { + arg->dwFlagOut = dwFlag; + code = OK; + } + } + } else { + if (GetConsoleMode(hdl, &dwFlag)) { + arg->dwFlagOut = dwFlag; + alt = WINCONSOLE.inp; + if (GetConsoleMode(alt, &dwFlag)) { + arg->dwFlagIn = dwFlag; + code = OK; + } + } + } + } + T(("lib_win32con:_nc_console_getmode %s", _nc_trace_ttymode(arg))); + return (code); +} + +NCURSES_EXPORT(int) +_nc_console_flush(HANDLE hdl) +{ + int code = OK; + + T((T_CALLED("lib_win32con::_nc_console_flush(hdl=%p"), hdl)); + + if (hdl != INVALID_HANDLE_VALUE) { + if (hdl == WINCONSOLE.hdl || + hdl == WINCONSOLE.inp || + hdl == WINCONSOLE.out) { + if (!FlushConsoleInputBuffer(WINCONSOLE.inp)) + code = ERR; + } else { + code = ERR; + T(("_nc_console_flush not requesting a handle owned by console.")); + } + } + returnCode(code); +} + +NCURSES_EXPORT(WORD) +_nc_console_MapColor(bool fore, int color) +{ + static const int _cmap[] = + {0, 4, 2, 6, 1, 5, 3, 7}; + int a; + if (color < 0 || color > 7) + a = fore ? 7 : 0; + else + a = _cmap[color]; + if (!fore) + a = a << 4; + return (WORD) a; +} + +/* + * Attempt to save the screen contents. PDCurses does this if + * PDC_RESTORE_SCREEN is set, giving the same visual appearance on + * restoration as if the library had allocated a console buffer. MSDN + * says that the data which can be read is limited to 64Kb (and may be + * less). + */ +static bool +save_original_screen(void) +{ + bool result = FALSE; + + WINCONSOLE.save_region.Top = 0; + WINCONSOLE.save_region.Left = 0; + WINCONSOLE.save_region.Bottom = (SHORT) (WINCONSOLE.SBI.dwSize.Y - 1); + WINCONSOLE.save_region.Right = (SHORT) (WINCONSOLE.SBI.dwSize.X - 1); + + if (read_screen_data()) { + result = TRUE; + } else { + + WINCONSOLE.save_region.Top = WINCONSOLE.SBI.srWindow.Top; + WINCONSOLE.save_region.Left = WINCONSOLE.SBI.srWindow.Left; + WINCONSOLE.save_region.Bottom = WINCONSOLE.SBI.srWindow.Bottom; + WINCONSOLE.save_region.Right = WINCONSOLE.SBI.srWindow.Right; + + WINCONSOLE.window_only = TRUE; + + if (read_screen_data()) { + result = TRUE; + } + } + + T(("... save original screen contents %s", result ? "ok" : "err")); + return result; +} + +#if 0 +static bool +restore_original_screen(void) +{ + COORD bufferCoord; + bool result = FALSE; + SMALL_RECT save_region = WINCONSOLE.save_region; + + T(("... restoring %s", + WINCONSOLE.window_only ? "window" : "entire buffer")); + + bufferCoord.X = (SHORT) (WINCONSOLE.window_only ? + WINCONSOLE.SBI.srWindow.Left : 0); + bufferCoord.Y = (SHORT) (WINCONSOLE.window_only ? + WINCONSOLE.SBI.srWindow.Top : 0); + + if (write_screen(WINCONSOLE.hdl, + WINCONSOLE.save_screen, + WINCONSOLE.save_size, + bufferCoord, + &save_region)) { + result = TRUE; + mvcur(-1, -1, LINES - 2, 0); + T(("... restore original screen contents ok %dx%d (%d,%d - %d,%d)", + WINCONSOLE.save_size.Y, + WINCONSOLE.save_size.X, + save_region.Top, + save_region.Left, + save_region.Bottom, + save_region.Right)); + } else { + T(("... restore original screen contents err")); + } + return result; +} +#endif + +static bool +read_screen_data(void) +{ + bool result = FALSE; + COORD bufferCoord; + size_t want; + + WINCONSOLE.save_size.X = (SHORT) (WINCONSOLE.save_region.Right + - WINCONSOLE.save_region.Left + 1); + WINCONSOLE.save_size.Y = (SHORT) (WINCONSOLE.save_region.Bottom + - WINCONSOLE.save_region.Top + 1); + + want = (size_t) (WINCONSOLE.save_size.X * WINCONSOLE.save_size.Y); + + if ((WINCONSOLE.save_screen = malloc(want * sizeof(CHAR_INFO))) != 0) { + bufferCoord.X = (SHORT) (WINCONSOLE.window_only ? + WINCONSOLE.SBI.srWindow.Left : 0); + bufferCoord.Y = (SHORT) (WINCONSOLE.window_only ? + WINCONSOLE.SBI.srWindow.Top : 0); + + T(("... reading console %s %dx%d into %d,%d - %d,%d at %d,%d", + WINCONSOLE.window_only ? "window" : "buffer", + WINCONSOLE.save_size.Y, WINCONSOLE.save_size.X, + WINCONSOLE.save_region.Top, + WINCONSOLE.save_region.Left, + WINCONSOLE.save_region.Bottom, + WINCONSOLE.save_region.Right, + bufferCoord.Y, + bufferCoord.X)); + + if (read_screen(WINCONSOLE.hdl, + WINCONSOLE.save_screen, + WINCONSOLE.save_size, + bufferCoord, + &WINCONSOLE.save_region)) { + result = TRUE; + } else { + T((" error %#lx", (unsigned long) GetLastError())); + FreeAndNull(WINCONSOLE.save_screen); + } + } + + return result; +} + +NCURSES_EXPORT(bool) +_nc_console_get_SBI(void) +{ + bool rc = FALSE; + if (GetConsoleScreenBufferInfo(WINCONSOLE.hdl, &(WINCONSOLE.SBI))) { + T(("GetConsoleScreenBufferInfo")); + T(("... buffer(X:%d Y:%d)", + WINCONSOLE.SBI.dwSize.X, + WINCONSOLE.SBI.dwSize.Y)); + T(("... window(X:%d Y:%d)", + WINCONSOLE.SBI.dwMaximumWindowSize.X, + WINCONSOLE.SBI.dwMaximumWindowSize.Y)); + T(("... cursor(X:%d Y:%d)", + WINCONSOLE.SBI.dwCursorPosition.X, + WINCONSOLE.SBI.dwCursorPosition.Y)); + T(("... display(Top:%d Bottom:%d Left:%d Right:%d)", + WINCONSOLE.SBI.srWindow.Top, + WINCONSOLE.SBI.srWindow.Bottom, + WINCONSOLE.SBI.srWindow.Left, + WINCONSOLE.SBI.srWindow.Right)); + if (WINCONSOLE.buffered) { + WINCONSOLE.origin.X = 0; + WINCONSOLE.origin.Y = 0; + } else { + WINCONSOLE.origin.X = WINCONSOLE.SBI.srWindow.Left; + WINCONSOLE.origin.Y = WINCONSOLE.SBI.srWindow.Top; + } + rc = TRUE; + } else { + T(("GetConsoleScreenBufferInfo ERR")); + } + return rc; +} + +#define MIN_WIDE 80 +#define MIN_HIGH 24 + +/* + * In "normal" mode, reset the buffer- and window-sizes back to their original values. + */ +NCURSES_EXPORT(void) +_nc_console_set_scrollback(bool normal, CONSOLE_SCREEN_BUFFER_INFO * info) +{ + SMALL_RECT rect; + COORD coord; + bool changed = FALSE; + + T((T_CALLED("lib_win32con::_nc_console_set_scrollback(%s)"), + (normal + ? "normal" + : "application"))); + + T(("... SBI.srWindow %d,%d .. %d,%d", + info->srWindow.Top, + info->srWindow.Left, + info->srWindow.Bottom, + info->srWindow.Right)); + T(("... SBI.dwSize %dx%d", + info->dwSize.Y, + info->dwSize.X)); + + if (normal) { + rect = info->srWindow; + coord = info->dwSize; + if (memcmp(info, &WINCONSOLE.SBI, sizeof(*info)) != 0) { + changed = TRUE; + WINCONSOLE.SBI = *info; + } + } else { + int high = info->srWindow.Bottom - info->srWindow.Top + 1; + int wide = info->srWindow.Right - info->srWindow.Left + 1; + + if (high < MIN_HIGH) { + T(("... height %d < %d", high, MIN_HIGH)); + high = MIN_HIGH; + changed = TRUE; + } + if (wide < MIN_WIDE) { + T(("... width %d < %d", wide, MIN_WIDE)); + wide = MIN_WIDE; + changed = TRUE; + } + + rect.Left = + rect.Top = 0; + rect.Right = (SHORT) (wide - 1); + rect.Bottom = (SHORT) (high - 1); + + coord.X = (SHORT) wide; + coord.Y = (SHORT) high; + + if (info->dwSize.Y != high || + info->dwSize.X != wide || + info->srWindow.Top != 0 || + info->srWindow.Left != 0) { + changed = TRUE; + } + + } + + if (changed) { + T(("... coord %d,%d", coord.Y, coord.X)); + T(("... rect %d,%d - %d,%d", + rect.Top, rect.Left, + rect.Bottom, rect.Right)); + SetConsoleScreenBufferSize(WINCONSOLE.hdl, coord); /* dwSize */ + SetConsoleWindowInfo(WINCONSOLE.hdl, TRUE, &rect); /* srWindow */ + _nc_console_get_SBI(); + } + returnVoid; +} + +static ULONGLONG +tdiff(FILETIME fstart, FILETIME fend) +{ + ULARGE_INTEGER ustart; + ULARGE_INTEGER uend; + ULONGLONG diff; + + ustart.LowPart = fstart.dwLowDateTime; + ustart.HighPart = fstart.dwHighDateTime; + uend.LowPart = fend.dwLowDateTime; + uend.HighPart = fend.dwHighDateTime; + + diff = (uend.QuadPart - ustart.QuadPart) / 10000; + return diff; +} + +static int +Adjust(int milliseconds, int diff) +{ + if (milliseconds != INFINITY) { + milliseconds -= diff; + if (milliseconds < 0) + milliseconds = 0; + } + return milliseconds; +} + +#define BUTTON_MASK (FROM_LEFT_1ST_BUTTON_PRESSED | \ + FROM_LEFT_2ND_BUTTON_PRESSED | \ + FROM_LEFT_3RD_BUTTON_PRESSED | \ + FROM_LEFT_4TH_BUTTON_PRESSED | \ + RIGHTMOST_BUTTON_PRESSED) + +static mmask_t +decode_mouse(SCREEN *sp, int mask) +{ + mmask_t result = 0; + + (void) sp; + assert(sp && console_initialized); + + if (mask & FROM_LEFT_1ST_BUTTON_PRESSED) + result |= BUTTON1_PRESSED; + if (mask & FROM_LEFT_2ND_BUTTON_PRESSED) + result |= BUTTON2_PRESSED; + if (mask & FROM_LEFT_3RD_BUTTON_PRESSED) + result |= BUTTON3_PRESSED; + if (mask & FROM_LEFT_4TH_BUTTON_PRESSED) + result |= BUTTON4_PRESSED; + + if (mask & RIGHTMOST_BUTTON_PRESSED) { + switch (WINCONSOLE.numButtons) { + case 1: + result |= BUTTON1_PRESSED; + break; + case 2: + result |= BUTTON2_PRESSED; + break; + case 3: + result |= BUTTON3_PRESSED; + break; + case 4: + result |= BUTTON4_PRESSED; + break; + } + } + + return result; +} + +#define AdjustY() (WINCONSOLE.buffered ? 0 : (int) WINCONSOLE.SBI.srWindow.Top) + +static bool +handle_mouse(SCREEN *sp, MOUSE_EVENT_RECORD mer) +{ + MEVENT work; + bool result = FALSE; + + assert(sp); + + sp->_drv_mouse_old_buttons = sp->_drv_mouse_new_buttons; + sp->_drv_mouse_new_buttons = mer.dwButtonState & BUTTON_MASK; + + /* + * We're only interested if the button is pressed or released. + * FIXME: implement continuous event-tracking. + */ + if (sp->_drv_mouse_new_buttons != sp->_drv_mouse_old_buttons) { + memset(&work, 0, sizeof(work)); + + if (sp->_drv_mouse_new_buttons) { + work.bstate |= decode_mouse(sp, sp->_drv_mouse_new_buttons); + } else { + /* cf: BUTTON_PRESSED, BUTTON_RELEASED */ + work.bstate |= (decode_mouse(sp, sp->_drv_mouse_old_buttons) + >> 1); + result = TRUE; + } + + work.x = mer.dwMousePosition.X; + work.y = mer.dwMousePosition.Y - AdjustY(); + + sp->_drv_mouse_fifo[sp->_drv_mouse_tail] = work; + sp->_drv_mouse_tail += 1; + } + return result; +} + +static int +rkeycompare(const void *el1, const void *el2) +{ + WORD key1 = (LOWORD((*((const LONG *) el1)))) & 0x7fff; + WORD key2 = (LOWORD((*((const LONG *) el2)))) & 0x7fff; + + return ((key1 < key2) ? -1 : ((key1 == key2) ? 0 : 1)); +} + +static int +keycompare(const void *el1, const void *el2) +{ + WORD key1 = HIWORD((*((const LONG *) el1))); + WORD key2 = HIWORD((*((const LONG *) el2))); + + return ((key1 < key2) ? -1 : ((key1 == key2) ? 0 : 1)); +} + +static int +MapKey(WORD vKey) +{ + int code = -1; + + if (!WINCONSOLE.isTermInfoConsole) { + WORD nKey = 0; + void *res; + LONG key = GenMap(vKey, 0); + + res = bsearch(&key, + WINCONSOLE.map, + (size_t) (N_INI + FKEYS), + sizeof(keylist[0]), + keycompare); + if (res) { + key = *((LONG *) res); + nKey = LOWORD(key); + code = (int) (nKey & 0x7fff); + if (nKey & 0x8000) + code = -code; + } + } + return code; +} + +static int +AnsiKey(WORD vKey) +{ + int code = -1; + + if (!WINCONSOLE.isTermInfoConsole) { + WORD nKey = 0; + void *res; + LONG key = GenMap(vKey, 0); + + res = bsearch(&key, + WINCONSOLE.ansi_map, + (size_t) (N_INI + FKEYS), + sizeof(keylist[0]), + keycompare); + if (res) { + key = *((LONG *) res); + nKey = LOWORD(key); + code = (int) (nKey & 0x7fff); + if (nKey & 0x8000) + code = -code; + } + } + return code; +} + +NCURSES_EXPORT(int) +_nc_console_keyok(int keycode, int flag) +{ + int code = ERR; + WORD nKey; + WORD vKey; + void *res; + LONG key = GenMap(0, (WORD) keycode); + + T((T_CALLED("lib_win32con::_nc_console_keyok(%d, %d)"), keycode, flag)); + + res = bsearch(&key, + WINCONSOLE.rmap, + (size_t) (N_INI + FKEYS), + sizeof(keylist[0]), + rkeycompare); + if (res) { + key = *((LONG *) res); + vKey = HIWORD(key); + nKey = (LOWORD(key)) & 0x7fff; + if (!flag) + nKey |= 0x8000; + *(LONG *) res = GenMap(vKey, nKey); + } + returnCode(code); +} + +NCURSES_EXPORT(bool) +_nc_console_keyExist(int keycode) +{ + WORD nKey; + void *res; + bool found = FALSE; + LONG key = GenMap(0, (WORD) keycode); + + T((T_CALLED("lib_win32con::_nc_console_keyExist(%d)"), keycode)); + res = bsearch(&key, + WINCONSOLE.rmap, + (size_t) (N_INI + FKEYS), + sizeof(keylist[0]), + rkeycompare); + if (res) { + key = *((LONG *) res); + nKey = LOWORD(key); + if (!(nKey & 0x8000)) + found = TRUE; + } + returnCode(found); +} + +NCURSES_EXPORT(int) +_nc_console_twait( + SCREEN *sp, + HANDLE hdl, + int mode, + int milliseconds, + int *timeleft + EVENTLIST_2nd(_nc_eventlist * evl)) +{ + INPUT_RECORD inp_rec; + BOOL b; + DWORD nRead = 0, rc = (DWORD) (-1); + int code = 0; + FILETIME fstart; + FILETIME fend; + int diff; + bool isNoDelay = (milliseconds == 0); + +#ifdef NCURSES_WGETCH_EVENTS + (void) evl; /* TODO: implement wgetch-events */ +#endif + +#define IGNORE_CTRL_KEYS (SHIFT_PRESSED|LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED| \ + LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED) +#define CONSUME() ReadConsoleInput(hdl, &inp_rec, 1, &nRead) + + assert(sp); + + TR(TRACE_IEVENT, ("start twait: hdl=%p, %d milliseconds, mode: %d", + hdl, milliseconds, mode)); + + if (milliseconds < 0) + milliseconds = INFINITY; + + memset(&inp_rec, 0, sizeof(inp_rec)); + + while (true) { + if (!isNoDelay) { + GetSystemTimeAsFileTime(&fstart); + rc = WaitForSingleObject(hdl, (DWORD) milliseconds); + GetSystemTimeAsFileTime(&fend); + diff = (int) tdiff(fstart, fend); + milliseconds = Adjust(milliseconds, diff); + if (milliseconds < 0) + break; + } + + if (isNoDelay || (rc == WAIT_OBJECT_0)) { + if (mode) { + nRead = 0; + b = GetNumberOfConsoleInputEvents(hdl, &nRead); + if (!b) { + T(("twait:err GetNumberOfConsoleInputEvents")); + } + if (isNoDelay && b) { + T(("twait: Events Available: %ld", nRead)); + if (nRead == 0) { + code = 0; + goto end; + } else { + DWORD n = 0; + INPUT_RECORD *pInpRec = + TypeAlloca(INPUT_RECORD, nRead); + if (pInpRec != NULL) { + DWORD i; + BOOL f; + memset(pInpRec, 0, sizeof(INPUT_RECORD) * nRead); + f = PeekConsoleInput(hdl, pInpRec, nRead, &n); + if (f) { + for (i = 0; i < n; i++) { + if (pInpRec[i].EventType == KEY_EVENT) { + if (pInpRec[i].Event.KeyEvent.bKeyDown) { + DWORD ctrlMask = + (pInpRec[i].Event.KeyEvent.dwControlKeyState & + IGNORE_CTRL_KEYS); + if (!ctrlMask) { + code = TW_INPUT; + goto end; + } + } + } + } + } else { + T(("twait:err PeekConsoleInput")); + } + code = 0; + goto end; + } else { + T(("twait:err could not alloca input records")); + } + } + } + if (b && nRead > 0) { + b = PeekConsoleInput(hdl, &inp_rec, 1, &nRead); + if (!b) { + T(("twait:err PeekConsoleInput")); + } + if (b && nRead > 0) { + switch (inp_rec.EventType) { + case KEY_EVENT: + if (mode & TW_INPUT) { + WORD vk = + inp_rec.Event.KeyEvent.wVirtualKeyCode; + char ch = + inp_rec.Event.KeyEvent.uChar.AsciiChar; + T(("twait:event KEY_EVENT")); + T(("twait vk=%d, ch=%d, keydown=%d", + vk, ch, inp_rec.Event.KeyEvent.bKeyDown)); + if (inp_rec.Event.KeyEvent.bKeyDown) { + T(("twait:event KeyDown")); + if (!WINCONSOLE.isTermInfoConsole && + (0 == ch)) { + int nKey = MapKey(vk); + if (nKey < 0) { + CONSUME(); + continue; + } + } + code = TW_INPUT; + goto end; + } else { + CONSUME(); + } + } + continue; + case MOUSE_EVENT: + T(("twait:event MOUSE_EVENT")); + if (decode_mouse(sp, + (inp_rec.Event.MouseEvent.dwButtonState + & BUTTON_MASK)) == 0) { + CONSUME(); + } else if (mode & TW_MOUSE) { + code = TW_MOUSE; + goto end; + } + continue; + /* e.g., FOCUS_EVENT */ + default: + T(("twait:event Tyoe %d", inp_rec.EventType)); + CONSUME(); + _nc_console_selectActiveHandle(); + continue; + } + } + } + } + continue; + } else { + if (rc != WAIT_TIMEOUT) { + code = -1; + break; + } else { + code = 0; + break; + } + } + } + end: + + TR(TRACE_IEVENT, ("end twait: returned %d (%lu), remaining time %d msec", + code, GetLastError(), milliseconds)); + + if (timeleft) + *timeleft = milliseconds; + + return code; +} + +NCURSES_EXPORT(int) +_nc_console_testmouse( + SCREEN *sp, + HANDLE hdl, + int delay + EVENTLIST_2nd(_nc_eventlist * evl)) +{ + int rc = 0; + + assert(sp); + + if (sp->_drv_mouse_head < sp->_drv_mouse_tail) { + rc = TW_MOUSE; + } else { + rc = _nc_console_twait(sp, + hdl, + TWAIT_MASK, + delay, + (int *) 0 + EVENTLIST_2nd(evl)); + } + return rc; +} + +NCURSES_EXPORT(int) +_nc_console_read( + SCREEN *sp, + HANDLE hdl, + int *buf) +{ + int rc = -1; + INPUT_RECORD inp_rec; + BOOL b; + DWORD nRead; + WORD vk; + + assert(sp); + assert(buf); + + memset(&inp_rec, 0, sizeof(inp_rec)); + + T((T_CALLED("lib_win32con::_nc_console_read(%p)"), sp)); + + while ((b = ReadConsoleInput(hdl, &inp_rec, 1, &nRead))) { + if (b && nRead > 0) { + if (rc < 0) + rc = 0; + rc = rc + (int) nRead; + if (inp_rec.EventType == KEY_EVENT) { + if (!inp_rec.Event.KeyEvent.bKeyDown) + continue; + *buf = (int) inp_rec.Event.KeyEvent.uChar.AsciiChar; + vk = inp_rec.Event.KeyEvent.wVirtualKeyCode; + /* + * There are 24 virtual function-keys, and typically + * 12 function-keys on a keyboard. Use the shift-modifier + * to provide the remaining 12 keys. + */ + if (vk >= VK_F1 && vk <= VK_F12) { + if (inp_rec.Event.KeyEvent.dwControlKeyState & + SHIFT_PRESSED) { + vk = (WORD) (vk + 12); + } + } + if (*buf == 0) { + int key = MapKey(vk); + if (key < 0) + continue; + if (sp->_keypad_on) { + *buf = key; + } else { + ungetch('\0'); + *buf = AnsiKey(vk); + } + } + break; + } else if (inp_rec.EventType == MOUSE_EVENT) { + if (handle_mouse(sp, + inp_rec.Event.MouseEvent)) { + *buf = KEY_MOUSE; + break; + } + } + continue; + } + } + returnCode(rc); +} + +/* Our replacement for the systems _isatty to include also + a test for mintty. This is called from the NC_ISATTY macro + defined in curses.priv.h + + Return codes: + - 0 : Not a TTY + - 1 : A Windows character device detected by _isatty + - 2 : A future implementation may return 2 for mintty + */ +NCURSES_EXPORT(int) +_nc_console_isatty(int fd) +{ + int result = 0; + T((T_CALLED("lib_win32con::_nc_console_isatty(%d"), fd)); + + if (_isatty(fd)) + result = 1; +#ifdef _NC_CHECK_MINTTY + else { + if (_nc_console_checkmintty(fd, NULL)) { + result = 2; + fprintf(stderr, + "ncurses on Windows must run in a Windows console.\n" + "On newer versions of Windows, the calling program should create a PTY-like.\n" + "device using the CreatePseudoConsole Windows API call.\n"); + exit(EXIT_FAILURE); + } + } +#endif + returnCode(result); +} + +NCURSES_EXPORT(bool) +_nc_console_checkinit(bool initFlag, bool assumeTermInfo) +{ + bool res = FALSE; + + T((T_CALLED("lib_win32con::_nc_console_checkinit(initFlag=%d, assumeTermInfo=%d)"), + initFlag, assumeTermInfo)); + + if (!initFlag) { + res = console_initialized; + } else { + /* initialize once, or not at all */ + if (!console_initialized) { + int i; + DWORD num_buttons; + WORD a; + BOOL buffered = FALSE; + BOOL b; + + START_TRACE(); + WINCONSOLE.isTermInfoConsole = assumeTermInfo; + + WINCONSOLE.map = (LPDWORD) malloc(sizeof(DWORD) * MAPSIZE); + WINCONSOLE.rmap = (LPDWORD) malloc(sizeof(DWORD) * MAPSIZE); + WINCONSOLE.ansi_map = (LPDWORD) malloc(sizeof(DWORD) * MAPSIZE); + + for (i = 0; i < (N_INI + FKEYS); i++) { + if (i < N_INI) { + WINCONSOLE.rmap[i] = WINCONSOLE.map[i] = + (DWORD) keylist[i]; + WINCONSOLE.ansi_map[i] = (DWORD) ansi_keys[i]; + } else { + WINCONSOLE.rmap[i] = WINCONSOLE.map[i] = + (DWORD) GenMap((VK_F1 + (i - N_INI)), + (KEY_F(1) + (i - N_INI))); + WINCONSOLE.ansi_map[i] = + (DWORD) GenMap((VK_F1 + (i - N_INI)), + (';' + (i - N_INI))); + } + } + qsort(WINCONSOLE.ansi_map, + (size_t) (MAPSIZE), + sizeof(keylist[0]), + keycompare); + qsort(WINCONSOLE.map, + (size_t) (MAPSIZE), + sizeof(keylist[0]), + keycompare); + qsort(WINCONSOLE.rmap, + (size_t) (MAPSIZE), + sizeof(keylist[0]), + rkeycompare); + + if (GetNumberOfConsoleMouseButtons(&num_buttons)) { + WINCONSOLE.numButtons = (int) num_buttons; + } else { + WINCONSOLE.numButtons = 1; + } + + a = _nc_console_MapColor(true, COLOR_WHITE) | + _nc_console_MapColor(false, COLOR_BLACK); + for (i = 0; i < CON_NUMPAIRS; i++) + WINCONSOLE.pairs[i] = a; + +#define SaveConsoleMode(handle, value) \ + GetConsoleMode(WINCONSOLE.handle, &WINCONSOLE.originalMode.value) + + if (WINCONSOLE.isTermInfoConsole) { + WINCONSOLE.inp = GetStdHandle(STD_INPUT_HANDLE); + WINCONSOLE.out = GetStdHandle(STD_OUTPUT_HANDLE); + WINCONSOLE.hdl = WINCONSOLE.out; + + SaveConsoleMode(inp, dwFlagIn); + SaveConsoleMode(out, dwFlagOut); + + } else { + b = AllocConsole(); + + if (!b) + b = AttachConsole(ATTACH_PARENT_PROCESS); + + WINCONSOLE.inp = GetDirectHandle("CONIN$", FILE_SHARE_READ); + WINCONSOLE.out = GetDirectHandle("CONOUT$", FILE_SHARE_WRITE); + + SaveConsoleMode(inp, dwFlagIn); + SaveConsoleMode(out, dwFlagOut); + + if (getenv("NCGDB") || getenv("NCURSES_CONSOLE2")) { + WINCONSOLE.hdl = WINCONSOLE.out; + T(("... will not buffer console")); + } else { + T(("... creating console buffer")); + WINCONSOLE.hdl = + CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CONSOLE_TEXTMODE_BUFFER, + NULL); + buffered = TRUE; + } + } + + /* We set binary I/O even when using the console + driver to cover the situation, that the + TERM variable is set to #win32con, but actually + Windows supports virtual terminal processing. + So if terminfo functions are used in this setup, + they actually may work. + */ + _setmode(fileno(stdin), _O_BINARY); + _setmode(fileno(stdout), _O_BINARY); + + if (WINCONSOLE.hdl != INVALID_HANDLE_VALUE) { + WINCONSOLE.buffered = buffered; + _nc_console_get_SBI(); + WINCONSOLE.save_SBI = WINCONSOLE.SBI; + if (!buffered) { + save_original_screen(); + _nc_console_set_scrollback(FALSE, &WINCONSOLE.SBI); + } + GetConsoleCursorInfo(WINCONSOLE.hdl, &WINCONSOLE.save_CI); + T(("... initial cursor is %svisible, %d%%", + (WINCONSOLE.save_CI.bVisible ? "" : "not-"), + (int) WINCONSOLE.save_CI.dwSize)); + } + + WINCONSOLE.initialized = TRUE; + console_initialized = TRUE; + } + res = (WINCONSOLE.hdl != INVALID_HANDLE_VALUE); + } + returnBool(res); +} + +#endif // _NC_WINDOWS diff --git a/lib/libcurses/tinfo/lib_win32util.c b/lib/libcurses/tinfo/lib_win32util.c new file mode 100644 index 00000000000..d0e72eacf86 --- /dev/null +++ b/lib/libcurses/tinfo/lib_win32util.c @@ -0,0 +1,134 @@ +/**************************************************************************** + * Copyright 2020-2021,2023 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Juergen Pfeifer * + * and: Thomas E. Dickey * + ****************************************************************************/ + +#include + +MODULE_ID("$Id: lib_win32util.c,v 1.1 2023/10/17 09:52:09 nicm Exp $") + +#ifdef _NC_WINDOWS +#include + +#ifdef _NC_CHECK_MINTTY +#define PSAPI_VERSION 2 +#include +#include + +#define array_length(a) (sizeof(a)/sizeof(a[0])) + +/* This function tests, whether or not the ncurses application + is running as a descendant of MSYS2/cygwin mintty terminal + application. mintty doesn't use Windows Console for its screen + I/O, so the native Windows _isatty doesn't recognize it as + character device. But we can discover we are at the end of an + Pipe and can query the server side of the pipe, looking whether + or not this is mintty. + For now we terminate the program if we discover that situation. + Although in theory it would be possible, to remotely manipulate + the terminal state of mintty, this is out of scope for now and + not worth the significant effort. + */ +NCURSES_EXPORT(int) +_nc_console_checkmintty(int fd, LPHANDLE pMinTTY) +{ + HANDLE handle = _nc_console_handle(fd); + DWORD dw; + int code = 0; + + T((T_CALLED("lib_winhelper::_nc_console_checkmintty(%d, %p)"), fd, pMinTTY)); + + if (handle != INVALID_HANDLE_VALUE) { + dw = GetFileType(handle); + if (dw == FILE_TYPE_PIPE) { + if (GetNamedPipeInfo(handle, 0, 0, 0, 0)) { + ULONG pPid; + /* Requires NT6 */ + if (GetNamedPipeServerProcessId(handle, &pPid)) { + TCHAR buf[MAX_PATH]; + DWORD len = 0; + /* These security attributes may allow us to + create a remote thread in mintty to manipulate + the terminal state remotely */ + HANDLE pHandle = OpenProcess(PROCESS_CREATE_THREAD + | PROCESS_QUERY_INFORMATION + | PROCESS_VM_OPERATION + | PROCESS_VM_WRITE + | PROCESS_VM_READ, + FALSE, + pPid); + if (pMinTTY) + *pMinTTY = INVALID_HANDLE_VALUE; + if (pHandle != INVALID_HANDLE_VALUE) { + if ((len = GetProcessImageFileName(pHandle, + buf, + (DWORD) + array_length(buf)))) { + TCHAR *pos = _tcsrchr(buf, _T('\\')); + if (pos) { + pos++; + if (_tcsnicmp(pos, _TEXT("mintty.exe"), 10) + == 0) { + if (pMinTTY) + *pMinTTY = pHandle; + code = 1; + } + } + } + } + } + } + } + } + returnCode(code); +} +#endif /* _NC_CHECK_MINTTY */ + +#if HAVE_GETTIMEOFDAY == 2 +#define JAN1970 116444736000000000LL /* the value for 01/01/1970 00:00 */ + +NCURSES_EXPORT(int) +_nc_gettimeofday(struct timeval *tv, void *tz GCC_UNUSED) +{ + union { + FILETIME ft; + long long since1601; /* time since 1 Jan 1601 in 100ns units */ + } data; + + GetSystemTimeAsFileTime(&data.ft); + tv->tv_usec = (long) ((data.since1601 / 10LL) % 1000000LL); + tv->tv_sec = (long) ((data.since1601 - JAN1970) / 10000000LL); + return (0); +} +#endif // HAVE_GETTIMEOFDAY == 2 + +#endif // _NC_WINDOWS diff --git a/lib/libcurses/tinfo/make_hash.c b/lib/libcurses/tinfo/make_hash.c new file mode 100644 index 00000000000..7da174f9cc4 --- /dev/null +++ b/lib/libcurses/tinfo/make_hash.c @@ -0,0 +1,445 @@ +/**************************************************************************** + * Copyright 2018-2019,2020 Thomas E. Dickey * + * Copyright 2009-2013,2017 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Zeyd M. Ben-Halim 1992,1995 * + * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-on * + ****************************************************************************/ + +/* + * make_hash.c --- build-time program for constructing comp_captab.c + */ + +#include + +#include +#include + +#include + +MODULE_ID("$Id: make_hash.c,v 1.1 2023/10/17 09:52:09 nicm Exp $") + +/* + * _nc_make_hash_table() + * + * Takes the entries in table[] and hashes them into hash_table[] + * by name. There are CAPTABSIZE entries in the predefined table[] + * and HASHTABSIZE slots in hash_table[]. + * + */ + +#undef MODULE_ID +#define MODULE_ID(id) /*nothing */ +#include + +#define L_PAREN "(" +#define R_PAREN ")" +#define L_BRACE "{" +#define R_BRACE "}" + +static const char *typenames[] = +{"BOOLEAN", "NUMBER", "STRING"}; + +static void +failed(const char *s) +{ + perror(s); + exit(EXIT_FAILURE); +} + +static char * +strmalloc(char *s) +{ + size_t need = strlen(s) + 1; + char *result = malloc(need); + if (result == 0) + failed("strmalloc"); + _nc_STRCPY(result, s, need); + return result; +} + +/* + * int hash_function(string) + * + * Computes the hashing function on the given string. + * + * The current hash function is the sum of each consecutive pair + * of characters, taken as two-byte integers, mod HASHTABSIZE. + * + */ + +static int +hash_function(const char *string) +{ + long sum = 0; + + while (*string) { + sum += (long) (UChar(*string) + (UChar(*(string + 1)) << 8)); + string++; + } + + return (int) (sum % HASHTABSIZE); +} + +#define UNUSED -1 + +static void +_nc_make_hash_table(struct user_table_entry *table, + HashValue * hash_table, + unsigned tablesize) +{ + unsigned i; + int hashvalue; + int collisions = 0; + + for (i = 0; i < HASHTABSIZE; i++) { + hash_table[i] = UNUSED; + } + for (i = 0; i < tablesize; i++) { + hashvalue = hash_function(table[i].ute_name); + + if (hash_table[hashvalue] >= 0) + collisions++; + + if (hash_table[hashvalue] != UNUSED) { + table[i].ute_link = hash_table[hashvalue]; + } + hash_table[hashvalue] = (HashValue) i; + } + + printf("/* %d collisions out of %d entries */\n", collisions, tablesize); +} + +/* + * This filter reads from standard input a list of tab-delimited columns, + * (e.g., from Caps.filtered) computes the hash-value of a specified column and + * writes the hashed tables to standard output. + * + * By compiling the hash table at build time, we're able to make the entire + * set of terminfo and termcap tables readonly (and also provide some runtime + * performance enhancement). + */ + +#define MAX_COLUMNS BUFSIZ /* this _has_ to be worst-case */ + +static int +count_columns(char **list) +{ + int result = 0; + if (list != 0) { + while (*list++) { + ++result; + } + } + return result; +} + +static char ** +parse_columns(char *buffer) +{ + static char **list; + + int col = 0; + + if (buffer == 0) { + free(list); + list = 0; + return 0; + } + + if (*buffer != '#') { + if (list == 0) { + list = typeCalloc(char *, (MAX_COLUMNS + 1)); + if (list == 0) + return (0); + } + while (*buffer != '\0') { + char *s; + for (s = buffer; (*s != '\0') && !isspace(UChar(*s)); s++) + /*EMPTY */ ; + if (s != buffer) { + char mark = *s; + *s = '\0'; + if ((s - buffer) > 1 + && (*buffer == '"') + && (s[-1] == '"')) { /* strip the quotes */ + assert(s > buffer + 1); + s[-1] = '\0'; + buffer++; + } + list[col] = buffer; + col++; + if (mark == '\0') + break; + while (*++s && isspace(UChar(*s))) + /*EMPTY */ ; + buffer = s; + } else + break; + } + } + return col ? list : 0; +} + +#define SetType(n,t) \ + if (is_user) \ + name_table[n].ute_type |= (int)(1 << (t)); \ + else \ + name_table[n].ute_type = (t) + +#define GetType(n) \ + (is_user \ + ? get_type(name_table[n].ute_type) \ + : typenames[name_table[n].ute_type]) + +static char * +get_type(int type_mask) +{ + static char result[80]; + unsigned n; + _nc_STRCPY(result, L_PAREN, sizeof(result)); + for (n = 0; n < 3; ++n) { + if ((1 << n) & type_mask) { + size_t want = 5 + strlen(typenames[n]); + if (want > sizeof(result)) { + fprintf(stderr, "Buffer is not large enough for %s + %s\n", + result, typenames[n]); + exit(EXIT_FAILURE); + } + if (result[1]) + _nc_STRCAT(result, "|", sizeof(result)); + _nc_STRCAT(result, "1<<", sizeof(result)); + _nc_STRCAT(result, typenames[n], sizeof(result)); + } + } + _nc_STRCAT(result, R_PAREN, sizeof(result)); + return result; +} + +int +main(int argc, char **argv) +{ + unsigned tablesize = CAPTABSIZE; + struct user_table_entry *name_table = typeCalloc(struct + user_table_entry, tablesize); + HashValue *hash_table = typeCalloc(HashValue, HASHTABSIZE); + const char *root_name = ""; + int column = 0; + int bigstring = 0; + unsigned n; + unsigned nn; + unsigned tableused = 0; + bool is_user; + const char *table_name; + char buffer[BUFSIZ]; + + short BoolCount = 0; + short NumCount = 0; + short StrCount = 0; + + /* The first argument is the column-number (starting with 0). + * The second is the root name of the tables to generate. + */ + if (argc <= 3 + || (column = atoi(argv[1])) <= 0 + || (column >= MAX_COLUMNS) + || *(root_name = argv[2]) == 0 + || (bigstring = atoi(argv[3])) < 0 + || name_table == 0 + || hash_table == 0) { + fprintf(stderr, "usage: make_hash column root_name bigstring\n"); + exit(EXIT_FAILURE); + } + is_user = (*root_name == 'u'); + table_name = (is_user ? "user" : "name"); + + /* + * Read the table into our arrays. + */ + for (n = 0; (n < tablesize) && fgets(buffer, BUFSIZ, stdin);) { + char **list; + char *nlp = strchr(buffer, '\n'); + if (nlp) + *nlp = '\0'; + else + buffer[sizeof(buffer) - 2] = '\0'; + list = parse_columns(buffer); + if (list == 0) /* blank or comment */ + continue; + if (is_user) { + if (strcmp(list[0], "userdef")) + continue; + } else if (!strcmp(list[0], "userdef")) { + continue; + } + if (column < 0 || column > count_columns(list)) { + fprintf(stderr, "expected %d columns, have %d:\n%s\n", + column, + count_columns(list), + buffer); + exit(EXIT_FAILURE); + } + nn = tableused; + if (is_user) { + unsigned j; + for (j = 0; j < tableused; ++j) { + if (!strcmp(list[column], name_table[j].ute_name)) { + nn = j; + break; + } + } + } + if (nn == tableused) { + name_table[nn].ute_link = -1; /* end-of-hash */ + name_table[nn].ute_name = strmalloc(list[column]); + ++tableused; + } + + if (!strcmp(list[2], "bool")) { + SetType(nn, BOOLEAN); + name_table[nn].ute_index = BoolCount++; + } else if (!strcmp(list[2], "num")) { + SetType(nn, NUMBER); + name_table[nn].ute_index = NumCount++; + } else if (!strcmp(list[2], "str")) { + SetType(nn, STRING); + name_table[nn].ute_index = StrCount++; + if (is_user) { + if (*list[3] != '-') { + unsigned j; + name_table[nn].ute_argc = (unsigned) strlen(list[3]); + for (j = 0; j < name_table[nn].ute_argc; ++j) { + if (list[3][j] == 's') { + name_table[nn].ute_args |= (1U << j); + } + } + } + } + } else { + fprintf(stderr, "Unknown type: %s\n", list[2]); + exit(EXIT_FAILURE); + } + n++; + } + if (tablesize > tableused) + tablesize = tableused; + _nc_make_hash_table(name_table, hash_table, tablesize); + + /* + * Write the compiled tables to standard output + */ + if (bigstring) { + int len = 0; + int nxt; + + printf("static const char %s_names_text[] = \\\n", root_name); + for (n = 0; n < tablesize; n++) { + nxt = (int) strlen(name_table[n].ute_name) + 5; + if (nxt + len > 72) { + printf("\\\n"); + len = 0; + } + printf("\"%s\\0\" ", name_table[n].ute_name); + len += nxt; + } + printf(";\n\n"); + + len = 0; + printf("static %s_table_data const %s_names_data[] =\n", + table_name, + root_name); + printf("%s\n", L_BRACE); + for (n = 0; n < tablesize; n++) { + printf("\t%s %15d,\t%10s,", L_BRACE, len, GetType(n)); + if (is_user) + printf("\t%d,%d,", + name_table[n].ute_argc, + name_table[n].ute_args); + printf("\t%3d, %3d %s%c\n", + name_table[n].ute_index, + name_table[n].ute_link, + R_BRACE, + n < tablesize - 1 ? ',' : ' '); + len += (int) strlen(name_table[n].ute_name) + 1; + } + printf("%s;\n\n", R_BRACE); + printf("static struct %s_table_entry *_nc_%s_table = 0;\n\n", + table_name, + root_name); + } else { + + printf("static struct %s_table_entry const _nc_%s_table[] =\n", + table_name, + root_name); + printf("%s\n", L_BRACE); + for (n = 0; n < tablesize; n++) { + _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) "\"%s\"", + name_table[n].ute_name); + printf("\t%s %15s,\t%10s,", L_BRACE, buffer, GetType(n)); + if (is_user) + printf("\t%d,%d,", + name_table[n].ute_argc, + name_table[n].ute_args); + printf("\t%3d, %3d %s%c\n", + name_table[n].ute_index, + name_table[n].ute_link, + R_BRACE, + n < tablesize - 1 ? ',' : ' '); + } + printf("%s;\n\n", R_BRACE); + } + + printf("static const HashValue _nc_%s_hash_table[%d] =\n", + root_name, + HASHTABSIZE + 1); + printf("%s\n", L_BRACE); + for (n = 0; n < HASHTABSIZE; n++) { + printf("\t%3d,\n", hash_table[n]); + } + printf("\t0\t/* base-of-table */\n"); + printf("%s;\n\n", R_BRACE); + + if (!is_user) { + printf("#if (BOOLCOUNT!=%d)||(NUMCOUNT!=%d)||(STRCOUNT!=%d)\n", + BoolCount, NumCount, StrCount); + printf("#error\t--> term.h and comp_captab.c disagree about the <--\n"); + printf("#error\t--> numbers of booleans, numbers and/or strings <--\n"); + printf("#endif\n\n"); + } + + free(hash_table); + for (n = 0; (n < tablesize); ++n) { + free((void *) name_table[n].ute_name); + } + free(name_table); + parse_columns(0); + + return EXIT_SUCCESS; +} diff --git a/lib/libcurses/tinfo/make_keys.c b/lib/libcurses/tinfo/make_keys.c index caec31c9ffc..e9364b31bff 100644 --- a/lib/libcurses/tinfo/make_keys.c +++ b/lib/libcurses/tinfo/make_keys.c @@ -1,7 +1,8 @@ -/* $OpenBSD: make_keys.c,v 1.9 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: make_keys.c,v 1.10 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2011,2015 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,18 +40,33 @@ */ #define USE_TERMLIB 1 -#include +#include -MODULE_ID("$Id: make_keys.c,v 1.9 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: make_keys.c,v 1.10 2023/10/17 09:52:09 nicm Exp $") #include -#define UNKNOWN (SIZEOF(strnames) + SIZEOF(strfnames)) +static unsigned +unknown(void) +{ + static unsigned result = 0; + + if (result == 0) { + unsigned n; + for (n = 0; strnames[n] != 0; n++) { + ++result; + } + for (n = 0; strfnames[n] != 0; n++) { + ++result; + } + } + return result; +} -static size_t +static unsigned lookup(const char *name) { - size_t n; + unsigned n; bool found = FALSE; for (n = 0; strnames[n] != 0; n++) { if (!strcmp(name, strnames[n])) { @@ -66,7 +82,7 @@ lookup(const char *name) } } } - return found ? n : UNKNOWN; + return found ? n : unknown(); } static void @@ -75,10 +91,11 @@ make_keys(FILE *ifp, FILE *ofp) char buffer[BUFSIZ]; char from[256]; char to[256]; - int maxlen = 16; + unsigned ignore = unknown(); + unsigned maxlen = 16; int scanned; - while (fgets(buffer, sizeof(buffer), ifp) != NULL) { + while (fgets(buffer, (int) sizeof(buffer), ifp) != 0) { if (*buffer == '#') continue; @@ -87,14 +104,14 @@ make_keys(FILE *ifp, FILE *ofp) scanned = sscanf(buffer, "%255s %255s", to, from); if (scanned == 2) { - int code = lookup(from); - if (code == UNKNOWN) + unsigned code = lookup(from); + if (code == ignore) continue; - if ((int) strlen(from) > maxlen) - maxlen = strlen(from); - fprintf(ofp, "\t{ %4d, %-*.*s },\t/* %s */\n", + if (strlen(from) > maxlen) + maxlen = (unsigned) strlen(from); + fprintf(ofp, "\t{ %4u, %-*.*s },\t/* %s */\n", code, - maxlen, maxlen, + (int) maxlen, (int) maxlen, to, from); } @@ -113,11 +130,13 @@ main(int argc, char *argv[]) { static const char *prefix[] = { - "#ifndef NCU_KEYS_H", - "#define NCU_KEYS_H 1", + "#ifndef _INIT_KEYTRY_H", + "#define _INIT_KEYTRY_H 1", "", "/* This file was generated by MAKE_KEYS */", "", + "#include ", + "", "#if BROKEN_LINKER", "static", "#endif", @@ -128,7 +147,7 @@ main(int argc, char *argv[]) { "\t{ 0, 0} };", "", - "#endif /* NCU_KEYS_H */", + "#endif /* _INIT_KEYTRY_H */", 0 }; diff --git a/lib/libcurses/tinfo/name_match.c b/lib/libcurses/tinfo/name_match.c index 1162430ee2f..7a5945849cb 100644 --- a/lib/libcurses/tinfo/name_match.c +++ b/lib/libcurses/tinfo/name_match.c @@ -1,7 +1,8 @@ -/* $OpenBSD: name_match.c,v 1.4 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: name_match.c,v 1.5 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1999-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2013,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,28 +34,38 @@ ****************************************************************************/ #include -#include #include -MODULE_ID("$Id: name_match.c,v 1.4 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: name_match.c,v 1.5 2023/10/17 09:52:09 nicm Exp $") -/* - * _nc_first_name(char *names) - * - * Extract the primary name from a compiled entry. - */ #define FirstName _nc_globals.first_name +#if NCURSES_USE_TERMCAP && NCURSES_XNAMES +static const char * +skip_index(const char *name) +{ + if ((_nc_syntax == SYN_TERMCAP) && _nc_user_definable) { + const char *bar = strchr(name, '|'); + if (bar != 0 && (bar - name) == 2) + name = bar + 1; + } + return name; +} +#endif + +/* + * Get the primary name from the given name list. For terminfo, this is the + * first name. For termcap, this may be the second name, if the first one + * happens to be two characters. + */ NCURSES_EXPORT(char *) _nc_first_name(const char *const sp) -/* get the first name from the given name list */ { - unsigned n; - #if NO_LEAKS if (sp == 0) { - if (FirstName != 0) + if (FirstName != 0) { FreeAndNull(FirstName); + } } else #endif { @@ -62,8 +73,13 @@ _nc_first_name(const char *const sp) FirstName = typeMalloc(char, MAX_NAME_SIZE + 1); if (FirstName != 0) { + unsigned n; + const char *src = sp; +#if NCURSES_USE_TERMCAP && NCURSES_XNAMES + src = skip_index(sp); +#endif for (n = 0; n < MAX_NAME_SIZE; n++) { - if ((FirstName[n] = sp[n]) == '\0' + if ((FirstName[n] = src[n]) == '\0' || (FirstName[n] == '|')) break; } @@ -74,19 +90,18 @@ _nc_first_name(const char *const sp) } /* - * int _nc_name_match(namelist, name, delim) - * - * Is the given name matched in namelist? + * Is the given name matched in namelist? */ - NCURSES_EXPORT(int) _nc_name_match(const char *const namelst, const char *const name, const char *const delim) { - const char *s, *d, *t; - int code, found; + const char *s; if ((s = namelst) != 0) { while (*s != '\0') { + const char *d, *t; + int code, found; + for (d = name; *d != '\0'; d++) { if (*s != *d) break; diff --git a/lib/libcurses/tinfo/obsolete.c b/lib/libcurses/tinfo/obsolete.c new file mode 100644 index 00000000000..955d8d62de1 --- /dev/null +++ b/lib/libcurses/tinfo/obsolete.c @@ -0,0 +1,335 @@ +/**************************************************************************** + * Copyright 2020,2023 Thomas E. Dickey * + * Copyright 2013-2014,2016 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey 2013-on * + ****************************************************************************/ + +/* +** Support for obsolete/unusual features. +*/ + +#include + +MODULE_ID("$Id: obsolete.c,v 1.1 2023/10/17 09:52:09 nicm Exp $") + +/* + * Obsolete entrypoint retained for binary compatibility. + */ +NCURSES_EXPORT(void) +NCURSES_SP_NAME(_nc_set_buffer) (NCURSES_SP_DCLx FILE *ofp, int buffered) +{ +#if NCURSES_SP_FUNCS + (void) SP_PARM; +#endif + (void) ofp; + (void) buffered; +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(void) +_nc_set_buffer(FILE *ofp, int buffered) +{ + NCURSES_SP_NAME(_nc_set_buffer) (CURRENT_SCREEN, ofp, buffered); +} +#endif + +#if !HAVE_STRDUP +NCURSES_EXPORT(char *) +_nc_strdup(const char *s) +{ + char *result = 0; + if (s != 0) { + size_t need = strlen(s); + result = malloc(need + 1); + if (result != 0) { + _nc_STRCPY(result, s, need); + } + } + return result; +} +#endif + +#if USE_MY_MEMMOVE +#define DST ((char *)s1) +#define SRC ((const char *)s2) +NCURSES_EXPORT(void *) +_nc_memmove(void *s1, const void *s2, size_t n) +{ + if (n != 0) { + if ((DST + n > SRC) && (SRC + n > DST)) { + static char *bfr; + static size_t length; + register size_t j; + if (length < n) { + length = (n * 3) / 2; + bfr = typeRealloc(char, length, bfr); + } + for (j = 0; j < n; j++) + bfr[j] = SRC[j]; + s2 = bfr; + } + while (n-- != 0) + DST[n] = SRC[n]; + } + return s1; +} +#endif /* USE_MY_MEMMOVE */ + +#ifdef EXP_XTERM_1005 +NCURSES_EXPORT(int) +_nc_conv_to_utf8(unsigned char *target, unsigned source, unsigned limit) +{ +#define CH(n) UChar((source) >> ((n) * 8)) + int rc = 0; + + if (source <= 0x0000007f) + rc = 1; + else if (source <= 0x000007ff) + rc = 2; + else if (source <= 0x0000ffff) + rc = 3; + else if (source <= 0x001fffff) + rc = 4; + else if (source <= 0x03ffffff) + rc = 5; + else /* (source <= 0x7fffffff) */ + rc = 6; + + if ((unsigned) rc > limit) { /* whatever it is, we cannot decode it */ + rc = 0; + } + + if (target != 0) { + switch (rc) { + case 1: + target[0] = CH(0); + break; + + case 2: + target[1] = UChar(0x80 | (CH(0) & 0x3f)); + target[0] = UChar(0xc0 | (CH(0) >> 6) | ((CH(1) & 0x07) << 2)); + break; + + case 3: + target[2] = UChar(0x80 | (CH(0) & 0x3f)); + target[1] = UChar(0x80 | (CH(0) >> 6) | ((CH(1) & 0x0f) << 2)); + target[0] = UChar(0xe0 | ((int) (CH(1) & 0xf0) >> 4)); + break; + + case 4: + target[3] = UChar(0x80 | (CH(0) & 0x3f)); + target[2] = UChar(0x80 | (CH(0) >> 6) | ((CH(1) & 0x0f) << 2)); + target[1] = UChar(0x80 | + ((int) (CH(1) & 0xf0) >> 4) | + ((int) (CH(2) & 0x03) << 4)); + target[0] = UChar(0xf0 | ((int) (CH(2) & 0x1f) >> 2)); + break; + + case 5: + target[4] = UChar(0x80 | (CH(0) & 0x3f)); + target[3] = UChar(0x80 | (CH(0) >> 6) | ((CH(1) & 0x0f) << 2)); + target[2] = UChar(0x80 | + ((int) (CH(1) & 0xf0) >> 4) | + ((int) (CH(2) & 0x03) << 4)); + target[1] = UChar(0x80 | (CH(2) >> 2)); + target[0] = UChar(0xf8 | (CH(3) & 0x03)); + break; + + case 6: + target[5] = UChar(0x80 | (CH(0) & 0x3f)); + target[4] = UChar(0x80 | (CH(0) >> 6) | ((CH(1) & 0x0f) << 2)); + target[3] = UChar(0x80 | (CH(1) >> 4) | ((CH(2) & 0x03) << 4)); + target[2] = UChar(0x80 | (CH(2) >> 2)); + target[1] = UChar(0x80 | (CH(3) & 0x3f)); + target[0] = UChar(0xfc | ((int) (CH(3) & 0x40) >> 6)); + break; + } + } + + return rc; /* number of bytes needed in target */ +#undef CH +} + +NCURSES_EXPORT(int) +_nc_conv_to_utf32(unsigned *target, const char *source, unsigned limit) +{ +#define CH(n) UChar((*target) >> ((n) * 8)) + int rc = 0; + int j; + unsigned mask = 0; + + /* + * Find the number of bytes we will need from the source. + */ + if ((*source & 0x80) == 0) { + rc = 1; + mask = (unsigned) *source; + } else if ((*source & 0xe0) == 0xc0) { + rc = 2; + mask = (unsigned) (*source & 0x1f); + } else if ((*source & 0xf0) == 0xe0) { + rc = 3; + mask = (unsigned) (*source & 0x0f); + } else if ((*source & 0xf8) == 0xf0) { + rc = 4; + mask = (unsigned) (*source & 0x07); + } else if ((*source & 0xfc) == 0xf8) { + rc = 5; + mask = (unsigned) (*source & 0x03); + } else if ((*source & 0xfe) == 0xfc) { + rc = 6; + mask = (unsigned) (*source & 0x01); + } + + if ((unsigned) rc > limit) { /* whatever it is, we cannot decode it */ + rc = 0; + } + + /* + * sanity-check. + */ + if (rc > 1) { + for (j = 1; j < rc; j++) { + if ((source[j] & 0xc0) != 0x80) + break; + } + if (j != rc) { + rc = 0; + } + } + + if (target != 0) { + int shift = 0; + *target = 0; + for (j = 1; j < rc; j++) { + *target |= (unsigned) (source[rc - j] & 0x3f) << shift; + shift += 6; + } + *target |= mask << shift; + } + return rc; +#undef CH +} +#endif /* EXP_XTERM_1005 */ + +#ifdef EXP_OOM_TESTING +/* + * Out-of-memory testing, suitable for checking if initialization (and limited + * running) recovers from errors due to insufficient memory. In practice, this + * is unlikely except with artifically constructed tests (or poorly behaved + * applications). + */ +#undef malloc +#undef calloc +#undef realloc +#undef free +#undef strdup + +#define TR_OOM(stmt) T(stmt) + +static long oom_limit = -1; +static long oom_count = 0; + +static bool +oom_check(void) +{ + static bool initialized = FALSE; + static bool triggered = FALSE; + bool result = FALSE; + + if (!initialized) { + char *env = getenv("NCURSES_OOM_TESTING"); + initialized = TRUE; + if (env != NULL) { + char *check; + oom_limit = strtol(env, &check, 0); + if (check != NULL && *check != '\0') + oom_limit = 0; + } + } + ++oom_count; + if (oom_limit >= 0) { + result = (oom_count > oom_limit); + if (result && !triggered) { + triggered = TRUE; + TR_OOM(("out-of-memory")); + } + } + return result; +} + +NCURSES_EXPORT(void *) +_nc_oom_malloc(size_t size) +{ + char *result = (oom_check() + ? NULL + : malloc(size)); + TR_OOM(("oom #%ld malloc(%ld) %p", oom_count, size, result)); + return result; +} + +NCURSES_EXPORT(void *) +_nc_oom_calloc(size_t nmemb, size_t size) +{ + char *result = (oom_check() + ? NULL + : calloc(nmemb, size)); + TR_OOM(("oom #%ld calloc(%ld, %ld) %p", oom_count, nmemb, size, result)); + return result; +} + +NCURSES_EXPORT(void *) +_nc_oom_realloc(void *ptr, size_t size) +{ + char *result = (oom_check() + ? NULL + : realloc(ptr, size)); + TR_OOM(("oom #%ld realloc(%p, %ld) %p", oom_count, ptr, size, result)); + return result; +} + +NCURSES_EXPORT(void) +_nc_oom_free(void *ptr) +{ + ++oom_count; + TR_OOM(("oom #%ld free(%p)", oom_count, ptr)); + free(ptr); +} + +NCURSES_EXPORT(char *) +_nc_oom_strdup(const char *ptr) +{ + char *result = (oom_check() + ? NULL + : strdup(ptr)); + TR_OOM(("oom #%ld strdup(%p) %p", oom_count, ptr, result)); + return result; +} +#endif /* EXP_OOM_TESTING */ diff --git a/lib/libcurses/tinfo/parse_entry.c b/lib/libcurses/tinfo/parse_entry.c index 2270ad90c07..e9d4a7b7ca7 100644 --- a/lib/libcurses/tinfo/parse_entry.c +++ b/lib/libcurses/tinfo/parse_entry.c @@ -1,7 +1,8 @@ -/* $OpenBSD: parse_entry.c,v 1.13 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: parse_entry.c,v 1.14 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -48,9 +49,8 @@ #include #include -#include -MODULE_ID("$Id: parse_entry.c,v 1.13 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: parse_entry.c,v 1.14 2023/10/17 09:52:09 nicm Exp $") #ifdef LINT static short const parametrized[] = @@ -59,17 +59,17 @@ static short const parametrized[] = #include #endif -static void postprocess_termcap(TERMTYPE *, bool); -static void postprocess_terminfo(TERMTYPE *); +static void postprocess_termcap(TERMTYPE2 *, bool); +static void postprocess_terminfo(TERMTYPE2 *); static struct name_table_entry const *lookup_fullname(const char *name); #if NCURSES_XNAMES static struct name_table_entry const * -_nc_extend_names(ENTRY * entryp, char *name, int token_type) +_nc_extend_names(ENTRY * entryp, const char *name, int token_type) { static struct name_table_entry temp; - TERMTYPE *tp = &(entryp->tterm); + TERMTYPE2 *tp = &(entryp->tterm); unsigned offset = 0; unsigned actual; unsigned tindex; @@ -86,13 +86,13 @@ _nc_extend_names(ENTRY * entryp, char *name, int token_type) case NUMBER: first = tp->ext_Booleans; last = tp->ext_Numbers + first; - offset = tp->ext_Booleans + tp->ext_Numbers; + offset = (unsigned) (tp->ext_Booleans + tp->ext_Numbers); tindex = tp->num_Numbers; break; case STRING: - first = tp->ext_Booleans + tp->ext_Numbers; + first = (unsigned) (tp->ext_Booleans + tp->ext_Numbers); last = tp->ext_Strings + first; - offset = tp->ext_Booleans + tp->ext_Numbers + tp->ext_Strings; + offset = (unsigned) (tp->ext_Booleans + tp->ext_Numbers + tp->ext_Strings); tindex = tp->num_Strings; break; case CANCEL: @@ -112,7 +112,7 @@ _nc_extend_names(ENTRY * entryp, char *name, int token_type) /* Well, we are given a cancel for a name that we don't recognize */ return _nc_extend_names(entryp, name, STRING); default: - return 0; + return NULL; } /* Adjust the 'offset' (insertion-point) to keep the lists of extended @@ -139,46 +139,125 @@ _nc_extend_names(ENTRY * entryp, char *name, int token_type) break; } } + +#define for_each_value(max) \ + for (last = (unsigned) (max - 1); last > tindex; last--) + if (!found) { + char *saved; + + if ((saved = _nc_save_str(name)) == NULL) + return NULL; + switch (token_type) { case BOOLEAN: - tp->ext_Booleans += 1; - tp->num_Booleans += 1; - tp->Booleans = typeRealloc(NCURSES_SBOOL, tp->num_Booleans, tp->Booleans); - for (last = tp->num_Booleans - 1; last > tindex; last--) + tp->ext_Booleans++; + tp->num_Booleans++; + TYPE_REALLOC(NCURSES_SBOOL, tp->num_Booleans, tp->Booleans); + for_each_value(tp->num_Booleans) tp->Booleans[last] = tp->Booleans[last - 1]; break; case NUMBER: - tp->ext_Numbers += 1; - tp->num_Numbers += 1; - tp->Numbers = typeRealloc(short, tp->num_Numbers, tp->Numbers); - for (last = tp->num_Numbers - 1; last > tindex; last--) + tp->ext_Numbers++; + tp->num_Numbers++; + TYPE_REALLOC(NCURSES_INT2, tp->num_Numbers, tp->Numbers); + for_each_value(tp->num_Numbers) tp->Numbers[last] = tp->Numbers[last - 1]; break; case STRING: - tp->ext_Strings += 1; - tp->num_Strings += 1; - tp->Strings = typeRealloc(char *, tp->num_Strings, tp->Strings); - for (last = tp->num_Strings - 1; last > tindex; last--) + tp->ext_Strings++; + tp->num_Strings++; + TYPE_REALLOC(char *, tp->num_Strings, tp->Strings); + for_each_value(tp->num_Strings) tp->Strings[last] = tp->Strings[last - 1]; break; } actual = NUM_EXT_NAMES(tp); - tp->ext_Names = typeRealloc(char *, actual, tp->ext_Names); + TYPE_REALLOC(char *, actual, tp->ext_Names); while (--actual > offset) tp->ext_Names[actual] = tp->ext_Names[actual - 1]; - tp->ext_Names[offset] = _nc_save_str(name); + tp->ext_Names[offset] = saved; } temp.nte_name = tp->ext_Names[offset]; temp.nte_type = token_type; - temp.nte_index = tindex; + temp.nte_index = (short) tindex; temp.nte_link = -1; return &temp; } + +static const char * +usertype2s(int mask) +{ + const char *result = "unknown"; + if (mask & (1 << BOOLEAN)) { + result = "boolean"; + } else if (mask & (1 << NUMBER)) { + result = "number"; + } else if (mask & (1 << STRING)) { + result = "string"; + } + return result; +} + +static bool +expected_type(const char *name, int token_type, bool silent) +{ + struct user_table_entry const *entry = _nc_find_user_entry(name); + bool result = TRUE; + if ((entry != 0) && (token_type != CANCEL)) { + int have_type = (1 << token_type); + if (!(entry->ute_type & have_type)) { + if (!silent) + _nc_warning("expected %s-type for %s, have %s", + usertype2s(entry->ute_type), + name, + usertype2s(have_type)); + result = FALSE; + } + } + return result; +} #endif /* NCURSES_XNAMES */ +/* + * A valid entry name uses characters from the "portable character set" + * (more commonly referred to as US-ASCII), and disallows some of the + * punctuation characters: + * + * '/' is a pathname separator + * '\' may be a pathname separator, but more important, is an escape + * '|' delimits names and description + * '#' denotes a numeric value + * '=' denotes a string value + * '@' denotes a cancelled symbol + * ',' separates terminfo capabilities + * ':' separates termcap capabilities + * + * Termcap capability names may begin with a '#' or '@' (since they have + * exactly two characters). + */ +static bool +valid_entryname(const char *name) +{ + bool result = TRUE; + bool first = TRUE; + int ch; + while ((ch = UChar(*name++)) != '\0') { + if (ch <= ' ' || ch > '~' || strchr("/\\|=,:", ch) != NULL) { + result = FALSE; + break; + } + if (!first && strchr("#@", ch) != NULL) { + result = FALSE; + break; + } + first = FALSE; + } + return result; +} + /* * int * _nc_parse_entry(entry, literal, silent) @@ -202,22 +281,29 @@ _nc_extend_names(ENTRY * entryp, char *name, int token_type) { bad_tc_usage = TRUE; \ _nc_warning("Legacy termcap allows only a trailing tc= clause"); } +#define MAX_NUMBER MAX_OF_TYPE(NCURSES_INT2) + NCURSES_EXPORT(int) -_nc_parse_entry(struct entry *entryp, int literal, bool silent) +_nc_parse_entry(ENTRY * entryp, int literal, bool silent) { int token_type; struct name_table_entry const *entry_ptr; char *ptr, *base; + const char *name; bool bad_tc_usage = FALSE; + TR(TRACE_DATABASE, + (T_CALLED("_nc_parse_entry(entry=%p, literal=%d, silent=%d)"), + (void *) entryp, literal, silent)); + token_type = _nc_get_token(silent); if (token_type == EOF) - return (EOF); + returnDB(EOF); if (token_type != NAMES) _nc_err_abort("Entry does not start with terminal names in column one"); - _nc_init_entry(&entryp->tterm); + _nc_init_entry(entryp); entryp->cstart = _nc_comment_start; entryp->cend = _nc_comment_end; @@ -233,13 +319,14 @@ _nc_parse_entry(struct entry *entryp, int literal, bool silent) * implemented it. Note that the resulting terminal type was never the * 2-character name, but was instead the first alias after that. */ +#define ok_TC2(s) (isgraph(UChar(s)) && (s) != '|') ptr = _nc_curr_token.tk_name; if (_nc_syntax == SYN_TERMCAP #if NCURSES_XNAMES && !_nc_user_definable #endif ) { - if (ptr[2] == '|') { + if (ok_TC2(ptr[0]) && ok_TC2(ptr[1]) && (ptr[2] == '|')) { ptr += 3; _nc_curr_token.tk_name[2] = '\0'; } @@ -248,16 +335,21 @@ _nc_parse_entry(struct entry *entryp, int literal, bool silent) entryp->tterm.str_table = entryp->tterm.term_names = _nc_save_str(ptr); if (entryp->tterm.str_table == 0) - return (ERR); + returnDB(ERR); - DEBUG(1, ("Starting '%s'", ptr)); + DEBUG(2, ("Starting '%s'", ptr)); /* * We do this because the one-token lookahead in the parse loop * results in the terminal type getting prematurely set to correspond * to that of the next entry. */ - _nc_set_type(_nc_first_name(entryp->tterm.term_names)); + name = _nc_first_name(entryp->tterm.term_names); + if (!valid_entryname(name)) { + _nc_warning("invalid entry name \"%s\"", name); + name = "invalid"; + } + _nc_set_type(name); /* check for overly-long names and aliases */ for (base = entryp->tterm.term_names; (ptr = strchr(base, '|')) != 0; @@ -279,11 +371,28 @@ _nc_parse_entry(struct entry *entryp, int literal, bool silent) bool is_use = (strcmp(_nc_curr_token.tk_name, "use") == 0); bool is_tc = !is_use && (strcmp(_nc_curr_token.tk_name, "tc") == 0); if (is_use || is_tc) { - entryp->uses[entryp->nuses].name = _nc_save_str(_nc_curr_token.tk_valstring); - entryp->uses[entryp->nuses].line = _nc_curr_line; - entryp->nuses++; - if (entryp->nuses > 1 && is_tc) { - BAD_TC_USAGE + char *saved; + + if (!VALID_STRING(_nc_curr_token.tk_valstring) + || _nc_curr_token.tk_valstring[0] == '\0') { + _nc_warning("missing name for use-clause"); + continue; + } else if (!valid_entryname(_nc_curr_token.tk_valstring)) { + _nc_warning("invalid name for use-clause \"%s\"", + _nc_curr_token.tk_valstring); + continue; + } else if (entryp->nuses >= MAX_USES) { + _nc_warning("too many use-clauses, ignored \"%s\"", + _nc_curr_token.tk_valstring); + continue; + } + if ((saved = _nc_save_str(_nc_curr_token.tk_valstring)) != NULL) { + entryp->uses[entryp->nuses].name = saved; + entryp->uses[entryp->nuses].line = _nc_curr_line; + entryp->nuses++; + if (entryp->nuses > 1 && is_tc) { + BAD_TC_USAGE + } } } else { /* normal token lookup */ @@ -291,7 +400,7 @@ _nc_parse_entry(struct entry *entryp, int literal, bool silent) _nc_get_hash_table(_nc_syntax)); /* - * Our kluge to handle aliasing. The reason it's done + * Our kluge to handle aliasing. The reason it is done * this ugly way, with a linear search, is so the hashing * machinery doesn't have to be made really complicated * (also we get better warnings this way). No point in @@ -348,12 +457,20 @@ _nc_parse_entry(struct entry *entryp, int literal, bool silent) * define a name based on its context. */ if (entry_ptr == NOTFOUND - && _nc_user_definable - && (entry_ptr = _nc_extend_names(entryp, - _nc_curr_token.tk_name, - token_type)) != 0) { - if (_nc_tracing >= DEBUG_LEVEL(1)) - _nc_warning("extended capability '%s'", _nc_curr_token.tk_name); + && _nc_user_definable) { + if (expected_type(_nc_curr_token.tk_name, token_type, silent)) { + if ((entry_ptr = _nc_extend_names(entryp, + _nc_curr_token.tk_name, + token_type)) != 0) { + if (_nc_tracing >= DEBUG_LEVEL(1)) { + _nc_warning("extended capability '%s'", + _nc_curr_token.tk_name); + } + } + } else { + /* ignore it: we have already printed error message */ + continue; + } } #endif /* NCURSES_XNAMES */ @@ -366,7 +483,16 @@ _nc_parse_entry(struct entry *entryp, int literal, bool silent) } /* deal with bad type/value combinations. */ - if (token_type != CANCEL && entry_ptr->nte_type != token_type) { + if (token_type == CANCEL) { + /* + * Prefer terminfo in this (long-obsolete) ambiguity: + */ + if (!strcmp("ma", _nc_curr_token.tk_name)) { + entry_ptr = _nc_find_type_entry("ma", NUMBER, + _nc_syntax != 0); + assert(entry_ptr != 0); + } + } else if (entry_ptr->nte_type != token_type) { /* * Nasty special cases here handle situations in which type * information can resolve name clashes. Normal lookup @@ -381,16 +507,14 @@ _nc_parse_entry(struct entry *entryp, int literal, bool silent) && !strcmp("ma", _nc_curr_token.tk_name)) { /* tell max_attributes from arrow_key_map */ entry_ptr = _nc_find_type_entry("ma", NUMBER, - _nc_get_table(_nc_syntax - != 0)); + _nc_syntax != 0); assert(entry_ptr != 0); } else if (token_type == STRING && !strcmp("MT", _nc_curr_token.tk_name)) { /* map terminfo's string MT to MT */ entry_ptr = _nc_find_type_entry("MT", STRING, - _nc_get_table(_nc_syntax - != 0)); + _nc_syntax != 0); assert(entry_ptr != 0); } else if (token_type == BOOLEAN @@ -445,16 +569,27 @@ _nc_parse_entry(struct entry *entryp, int literal, bool silent) break; case NUMBER: - entryp->tterm.Numbers[entry_ptr->nte_index] = - _nc_curr_token.tk_valnumber; +#if !NCURSES_EXT_NUMBERS + if (_nc_curr_token.tk_valnumber > MAX_NUMBER) { + entryp->tterm.Numbers[entry_ptr->nte_index] = MAX_NUMBER; + } else +#endif + { + entryp->tterm.Numbers[entry_ptr->nte_index] = + (NCURSES_INT2) _nc_curr_token.tk_valnumber; + } break; case STRING: ptr = _nc_curr_token.tk_valstring; - if (_nc_syntax == SYN_TERMCAP) + if (_nc_syntax == SYN_TERMCAP) { + int n = entry_ptr->nte_index; ptr = _nc_captoinfo(_nc_curr_token.tk_name, ptr, - parametrized[entry_ptr->nte_index]); + (n < (int) SIZEOF(parametrized)) + ? parametrized[n] + : 0); + } entryp->tterm.Strings[entry_ptr->nte_index] = _nc_save_str(ptr); break; @@ -481,23 +616,26 @@ _nc_parse_entry(struct entry *entryp, int literal, bool silent) if (!literal) { if (_nc_syntax == SYN_TERMCAP) { bool has_base_entry = FALSE; - unsigned i; /* * Don't insert defaults if this is a `+' entry meant only * for inclusion in other entries (not sure termcap ever * had these, actually). */ - if (strchr(entryp->tterm.term_names, '+')) + if (strchr(entryp->tterm.term_names, '+')) { has_base_entry = TRUE; - else + } else { + unsigned i; /* * Otherwise, look for a base entry that will already * have picked up defaults via translation. */ - for (i = 0; i < entryp->nuses; i++) - if (!strchr((char *) entryp->uses[i].name, '+')) + for (i = 0; i < entryp->nuses; i++) { + if (entryp->uses[i].name != 0 + && !strchr(entryp->uses[i].name, '+')) has_base_entry = TRUE; + } + } postprocess_termcap(&entryp->tterm, has_base_entry); } else @@ -505,59 +643,66 @@ _nc_parse_entry(struct entry *entryp, int literal, bool silent) } _nc_wrap_entry(entryp, FALSE); - return (OK); + returnDB(OK); } NCURSES_EXPORT(int) _nc_capcmp(const char *s, const char *t) /* compare two string capabilities, stripping out padding */ { - if (!s && !t) - return (0); - else if (!s || !t) - return (1); - - for (;;) { - if (s[0] == '$' && s[1] == '<') { - for (s += 2;; s++) - if (!(isdigit(UChar(*s)) - || *s == '.' - || *s == '*' - || *s == '/' - || *s == '>')) - break; - } + bool ok_s = VALID_STRING(s); + bool ok_t = VALID_STRING(t); + + if (ok_s && ok_t) { + for (;;) { + if (s[0] == '$' && s[1] == '<') { + for (s += 2;; s++) { + if (!(isdigit(UChar(*s)) + || *s == '.' + || *s == '*' + || *s == '/' + || *s == '>')) { + break; + } + } + } - if (t[0] == '$' && t[1] == '<') { - for (t += 2;; t++) - if (!(isdigit(UChar(*t)) - || *t == '.' - || *t == '*' - || *t == '/' - || *t == '>')) - break; - } + if (t[0] == '$' && t[1] == '<') { + for (t += 2;; t++) { + if (!(isdigit(UChar(*t)) + || *t == '.' + || *t == '*' + || *t == '/' + || *t == '>')) { + break; + } + } + } - /* we've now pushed s and t past any padding they were pointing at */ + /* we've now pushed s and t past any padding they pointed at */ - if (*s == '\0' && *t == '\0') - return (0); + if (*s == '\0' && *t == '\0') + return (0); - if (*s != *t) - return (*t - *s); + if (*s != *t) + return (*t - *s); - /* else *s == *t but one is not NUL, so continue */ - s++, t++; + /* else *s == *t but one is not NUL, so continue */ + s++, t++; + } + } else if (ok_s || ok_t) { + return 1; } + return 0; } static void -append_acs0(string_desc * dst, int code, int src) +append_acs0(string_desc * dst, int code, char *src, size_t off) { - if (src != 0) { + if (src != 0 && off < strlen(src)) { char temp[3]; temp[0] = (char) code; - temp[1] = (char) src; + temp[1] = src[off]; temp[2] = 0; _nc_safe_strcat(dst, temp); } @@ -566,8 +711,8 @@ append_acs0(string_desc * dst, int code, int src) static void append_acs(string_desc * dst, int code, char *src) { - if (src != 0 && strlen(src) == 1) { - append_acs0(dst, code, *src); + if (VALID_STRING(src) && strlen(src) == 1) { + append_acs0(dst, code, src, 0); } } @@ -576,32 +721,32 @@ append_acs(string_desc * dst, int code, char *src) * list. For each capability, we may assume there is a keycap that sends the * string which is the value of that capability. */ +#define DATA(from, to) { { from }, { to } } typedef struct { - const char *from; - const char *to; + const char from[3]; + const char to[6]; } assoc; static assoc const ko_xlate[] = { - {"al", "kil1"}, /* insert line key -> KEY_IL */ - {"bt", "kcbt"}, /* back tab -> KEY_BTAB */ - {"cd", "ked"}, /* clear-to-eos key -> KEY_EOL */ - {"ce", "kel"}, /* clear-to-eol key -> KEY_EOS */ - {"cl", "kclr"}, /* clear key -> KEY_CLEAR */ - {"ct", "tbc"}, /* clear all tabs -> KEY_CATAB */ - {"dc", "kdch1"}, /* delete char -> KEY_DC */ - {"dl", "kdl1"}, /* delete line -> KEY_DL */ - {"do", "kcud1"}, /* down key -> KEY_DOWN */ - {"ei", "krmir"}, /* exit insert key -> KEY_EIC */ - {"ho", "khome"}, /* home key -> KEY_HOME */ - {"ic", "kich1"}, /* insert char key -> KEY_IC */ - {"im", "kIC"}, /* insert-mode key -> KEY_SIC */ - {"le", "kcub1"}, /* le key -> KEY_LEFT */ - {"nd", "kcuf1"}, /* nd key -> KEY_RIGHT */ - {"nl", "kent"}, /* new line key -> KEY_ENTER */ - {"st", "khts"}, /* set-tab key -> KEY_STAB */ - {"ta", CANCELLED_STRING}, - {"up", "kcuu1"}, /* up-arrow key -> KEY_UP */ - {(char *) 0, (char *) 0}, + DATA("al", "kil1"), /* insert line key -> KEY_IL */ + DATA("bt", "kcbt"), /* back tab -> KEY_BTAB */ + DATA("cd", "ked"), /* clear-to-eos key -> KEY_EOL */ + DATA("ce", "kel"), /* clear-to-eol key -> KEY_EOS */ + DATA("cl", "kclr"), /* clear key -> KEY_CLEAR */ + DATA("ct", "tbc"), /* clear all tabs -> KEY_CATAB */ + DATA("dc", "kdch1"), /* delete char -> KEY_DC */ + DATA("dl", "kdl1"), /* delete line -> KEY_DL */ + DATA("do", "kcud1"), /* down key -> KEY_DOWN */ + DATA("ei", "krmir"), /* exit insert key -> KEY_EIC */ + DATA("ho", "khome"), /* home key -> KEY_HOME */ + DATA("ic", "kich1"), /* insert char key -> KEY_IC */ + DATA("im", "kIC"), /* insert-mode key -> KEY_SIC */ + DATA("le", "kcub1"), /* le key -> KEY_LEFT */ + DATA("nd", "kcuf1"), /* nd key -> KEY_RIGHT */ + DATA("nl", "kent"), /* new line key -> KEY_ENTER */ + DATA("st", "khts"), /* set-tab key -> KEY_STAB */ + DATA("ta", ""), + DATA("up", "kcuu1"), /* up-arrow key -> KEY_UP */ }; /* @@ -615,13 +760,6 @@ static const char C_LF[] = "\n"; static const char C_BS[] = "\b"; static const char C_HT[] = "\t"; -/* - * Note that WANTED and PRESENT are not simple inverses! If a capability - * has been explicitly cancelled, it's not considered WANTED. - */ -#define WANTED(s) ((s) == ABSENT_STRING) -#define PRESENT(s) (((s) != ABSENT_STRING) && ((s) != CANCELLED_STRING)) - /* * This bit of legerdemain turns all the terminfo variable names into * references to locations in the arrays Booleans, Numbers, and Strings --- @@ -632,11 +770,15 @@ static const char C_HT[] = "\t"; #define CUR tp-> static void -postprocess_termcap(TERMTYPE *tp, bool has_base) +postprocess_termcap(TERMTYPE2 *tp, bool has_base) { char buf[MAX_LINE * 2 + 2]; string_desc result; + TR(TRACE_DATABASE, + (T_CALLED("postprocess_termcap(tp=%p, has_base=%d)"), + (void *) tp, has_base)); + /* * TERMCAP DEFAULTS AND OBSOLETE-CAPABILITY TRANSLATIONS * @@ -647,35 +789,38 @@ postprocess_termcap(TERMTYPE *tp, bool has_base) /* if there was a tc entry, assume we picked up defaults via that */ if (!has_base) { - if (WANTED(init_3string) && termcap_init2) + if (WANTED(init_3string) && PRESENT(termcap_init2)) init_3string = _nc_save_str(termcap_init2); - if (WANTED(reset_2string) && termcap_reset) + if (WANTED(reset_2string) && PRESENT(termcap_reset)) reset_2string = _nc_save_str(termcap_reset); if (WANTED(carriage_return)) { if (carriage_return_delay > 0) { - snprintf(buf, sizeof(buf), "%s$<%d>", C_CR, carriage_return_delay); + _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf)) + "%s$<%d>", C_CR, carriage_return_delay); carriage_return = _nc_save_str(buf); } else carriage_return = _nc_save_str(C_CR); } if (WANTED(cursor_left)) { if (backspace_delay > 0) { - snprintf(buf, sizeof(buf), "%s$<%d>", C_BS, backspace_delay); + _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf)) + "%s$<%d>", C_BS, backspace_delay); cursor_left = _nc_save_str(buf); } else if (backspaces_with_bs == 1) cursor_left = _nc_save_str(C_BS); else if (PRESENT(backspace_if_not_bs)) cursor_left = backspace_if_not_bs; } - /* vi doesn't use "do", but it does seems to use nl (or '\n') instead */ + /* vi doesn't use "do", but it does seem to use nl (or '\n') instead */ if (WANTED(cursor_down)) { if (PRESENT(linefeed_if_not_lf)) cursor_down = linefeed_if_not_lf; else if (linefeed_is_newline != 1) { if (new_line_delay > 0) { - snprintf(buf, sizeof(buf), "%s$<%d>", C_LF, new_line_delay); + _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf)) + "%s$<%d>", C_LF, new_line_delay); cursor_down = _nc_save_str(buf); } else cursor_down = _nc_save_str(C_LF); @@ -686,7 +831,8 @@ postprocess_termcap(TERMTYPE *tp, bool has_base) cursor_down = linefeed_if_not_lf; else if (linefeed_is_newline != 1) { if (new_line_delay > 0) { - snprintf(buf, sizeof(buf), "%s$<%d>", C_LF, new_line_delay); + _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf)) + "%s$<%d>", C_LF, new_line_delay); scroll_forward = _nc_save_str(buf); } else scroll_forward = _nc_save_str(C_LF); @@ -695,7 +841,8 @@ postprocess_termcap(TERMTYPE *tp, bool has_base) if (WANTED(newline)) { if (linefeed_is_newline == 1) { if (new_line_delay > 0) { - snprintf(buf, sizeof(buf), "%s$<%d>", C_LF, new_line_delay); + _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf)) + "%s$<%d>", C_LF, new_line_delay); newline = _nc_save_str(buf); } else newline = _nc_save_str(C_LF); @@ -737,7 +884,8 @@ postprocess_termcap(TERMTYPE *tp, bool has_base) */ if (WANTED(tab)) { if (horizontal_tab_delay > 0) { - snprintf(buf, sizeof(buf), "%s$<%d>", C_HT, horizontal_tab_delay); + _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf)) + "%s$<%d>", C_HT, horizontal_tab_delay); tab = _nc_save_str(buf); } else tab = _nc_save_str(C_HT); @@ -759,7 +907,7 @@ postprocess_termcap(TERMTYPE *tp, bool has_base) if (init_tabs != 8 && init_tabs != ABSENT_NUMERIC) _nc_warning("hardware tabs with a width other than 8: %d", init_tabs); else { - if (tab && _nc_capcmp(tab, C_HT)) + if (PRESENT(tab) && _nc_capcmp(tab, C_HT)) _nc_warning("hardware tabs with a non-^I tab string %s", _nc_visbuf(tab)); else { @@ -774,11 +922,10 @@ postprocess_termcap(TERMTYPE *tp, bool has_base) * isn't from mytinfo... */ if (PRESENT(other_non_function_keys)) { - char *base = other_non_function_keys; + char *base; char *bp, *cp, *dp; struct name_table_entry const *from_ptr; struct name_table_entry const *to_ptr; - assoc const *ap; char buf2[MAX_TERMINFO_LENGTH]; bool foundim; @@ -790,18 +937,22 @@ postprocess_termcap(TERMTYPE *tp, bool has_base) for (base = other_non_function_keys; (cp = strchr(base, ',')) != 0; base = cp + 1) { - size_t len = cp - base; - - for (ap = ko_xlate; ap->from; ap++) { - if (len == strlen(ap->from) - && strncmp(ap->from, base, len) == 0) + size_t len = (unsigned) (cp - base); + size_t n; + assoc const *ap = 0; + + for (n = 0; n < SIZEOF(ko_xlate); ++n) { + if (len == strlen(ko_xlate[n].from) + && strncmp(ko_xlate[n].from, base, len) == 0) { + ap = ko_xlate + n; break; + } } - if (!(ap->from && ap->to)) { + if (ap == 0) { _nc_warning("unknown capability `%.*s' in ko string", (int) len, base); continue; - } else if (ap->to == CANCELLED_STRING) /* ignore it */ + } else if (ap->to[0] == '\0') /* ignore it */ continue; /* now we know we found a match in ko_table, so... */ @@ -818,15 +969,14 @@ postprocess_termcap(TERMTYPE *tp, bool has_base) } if (tp->Strings[to_ptr->nte_index]) { - /* There's no point in warning about it if it's the same + const char *s = tp->Strings[from_ptr->nte_index]; + const char *t = tp->Strings[to_ptr->nte_index]; + /* There's no point in warning about it if it is the same * string; that's just an inefficiency. */ - if (strcmp( - tp->Strings[from_ptr->nte_index], - tp->Strings[to_ptr->nte_index]) != 0) + if (VALID_STRING(s) && VALID_STRING(t) && strcmp(s, t) != 0) _nc_warning("%s (%s) already has an explicit value %s, ignoring ko", - ap->to, ap->from, - _nc_visbuf(tp->Strings[to_ptr->nte_index])); + ap->to, ap->from, t); continue; } @@ -834,17 +984,22 @@ postprocess_termcap(TERMTYPE *tp, bool has_base) * The magic moment -- copy the mapped key string over, * stripping out padding. */ - for (dp = buf2, bp = tp->Strings[from_ptr->nte_index]; *bp; bp++) { - if (bp[0] == '$' && bp[1] == '<') { - while (*bp && *bp != '>') { - ++bp; - } - } else - *dp++ = *bp; - } - *dp++ = '\0'; + bp = tp->Strings[from_ptr->nte_index]; + if (VALID_STRING(bp)) { + for (dp = buf2; *bp; bp++) { + if (bp[0] == '$' && bp[1] == '<') { + while (*bp && *bp != '>') { + ++bp; + } + } else + *dp++ = *bp; + } + *dp = '\0'; - tp->Strings[to_ptr->nte_index] = _nc_save_str(buf2); + tp->Strings[to_ptr->nte_index] = _nc_save_str(buf2); + } else { + tp->Strings[to_ptr->nte_index] = bp; + } } /* @@ -853,7 +1008,7 @@ postprocess_termcap(TERMTYPE *tp, bool has_base) * got mapped to kich1 and im to kIC to avoid a collision. * If the description has im but not ic, hack kIC back to kich1. */ - if (foundim && WANTED(key_ic) && key_sic) { + if (foundim && WANTED(key_ic) && PRESENT(key_sic)) { key_ic = key_sic; key_sic = ABSENT_STRING; } @@ -905,16 +1060,21 @@ postprocess_termcap(TERMTYPE *tp, bool has_base) acs_chars = _nc_save_str(buf2); _nc_warning("acsc string synthesized from XENIX capabilities"); } - } else if (acs_chars == 0 - && enter_alt_charset_mode != 0 - && exit_alt_charset_mode != 0) { + } else if (acs_chars == ABSENT_STRING + && PRESENT(enter_alt_charset_mode) + && PRESENT(exit_alt_charset_mode)) { acs_chars = _nc_save_str(VT_ACSC); } + returnVoidDB; } static void -postprocess_terminfo(TERMTYPE *tp) +postprocess_terminfo(TERMTYPE2 *tp) { + TR(TRACE_DATABASE, + (T_CALLED("postprocess_terminfo(tp=%p)"), + (void *) tp)); + /* * TERMINFO-TO-TERMINFO MAPPINGS FOR SOURCE TRANSLATION * ---------------------------------------------------------------------- @@ -930,17 +1090,17 @@ postprocess_terminfo(TERMTYPE *tp) _nc_str_init(&result, buf2, sizeof(buf2)); _nc_safe_strcat(&result, acs_chars); - append_acs0(&result, 'l', box_chars_1[0]); /* ACS_ULCORNER */ - append_acs0(&result, 'q', box_chars_1[1]); /* ACS_HLINE */ - append_acs0(&result, 'k', box_chars_1[2]); /* ACS_URCORNER */ - append_acs0(&result, 'x', box_chars_1[3]); /* ACS_VLINE */ - append_acs0(&result, 'j', box_chars_1[4]); /* ACS_LRCORNER */ - append_acs0(&result, 'm', box_chars_1[5]); /* ACS_LLCORNER */ - append_acs0(&result, 'w', box_chars_1[6]); /* ACS_TTEE */ - append_acs0(&result, 'u', box_chars_1[7]); /* ACS_RTEE */ - append_acs0(&result, 'v', box_chars_1[8]); /* ACS_BTEE */ - append_acs0(&result, 't', box_chars_1[9]); /* ACS_LTEE */ - append_acs0(&result, 'n', box_chars_1[10]); /* ACS_PLUS */ + append_acs0(&result, 'l', box_chars_1, 0); /* ACS_ULCORNER */ + append_acs0(&result, 'q', box_chars_1, 1); /* ACS_HLINE */ + append_acs0(&result, 'k', box_chars_1, 2); /* ACS_URCORNER */ + append_acs0(&result, 'x', box_chars_1, 3); /* ACS_VLINE */ + append_acs0(&result, 'j', box_chars_1, 4); /* ACS_LRCORNER */ + append_acs0(&result, 'm', box_chars_1, 5); /* ACS_LLCORNER */ + append_acs0(&result, 'w', box_chars_1, 6); /* ACS_TTEE */ + append_acs0(&result, 'u', box_chars_1, 7); /* ACS_RTEE */ + append_acs0(&result, 'v', box_chars_1, 8); /* ACS_BTEE */ + append_acs0(&result, 't', box_chars_1, 9); /* ACS_LTEE */ + append_acs0(&result, 'n', box_chars_1, 10); /* ACS_PLUS */ if (buf2[0]) { acs_chars = _nc_save_str(buf2); @@ -951,6 +1111,7 @@ postprocess_terminfo(TERMTYPE *tp) /* * ---------------------------------------------------------------------- */ + returnVoidDB; } /* diff --git a/lib/libcurses/tinfo/read_entry.c b/lib/libcurses/tinfo/read_entry.c index 4e208e2e92f..641b8df956b 100644 --- a/lib/libcurses/tinfo/read_entry.c +++ b/lib/libcurses/tinfo/read_entry.c @@ -1,7 +1,8 @@ -/* $OpenBSD: read_entry.c,v 1.17 2015/12/03 11:29:55 nicm Exp $ */ +/* $OpenBSD: read_entry.c,v 1.18 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -42,15 +43,88 @@ #include #include -#include -MODULE_ID("$Id: read_entry.c,v 1.17 2015/12/03 11:29:55 nicm Exp $") +MODULE_ID("$Id: read_entry.c,v 1.18 2023/10/17 09:52:09 nicm Exp $") -#define TYPE_CALLOC(type,elts) typeCalloc(type, (unsigned)(elts)) +#define MyNumber(n) (short) LOW_MSB(n) -#if USE_DATABASE -static void -convert_shorts(char *buf, short *Numbers, int count) +#define SIZEOF_32BITS 4 + +#if NCURSES_USE_DATABASE +#if NCURSES_EXT_NUMBERS +static size_t +convert_16bits(char *buf, NCURSES_INT2 *Numbers, int count) +{ + int i; + size_t j; + size_t size = SIZEOF_SHORT; + for (i = 0; i < count; i++) { + unsigned mask = 0xff; + unsigned char ch = 0; + Numbers[i] = 0; + for (j = 0; j < size; ++j) { + ch = UChar(*buf++); + Numbers[i] |= (ch << (8 * j)); + mask <<= 8; + } + if (ch & 0x80) { + while (mask != 0) { + Numbers[i] |= (int) mask; + mask <<= 8; + } + } + TR(TRACE_DATABASE, ("get Numbers[%d]=%d", i, Numbers[i])); + } + return size; +} + +static size_t +convert_32bits(char *buf, NCURSES_INT2 *Numbers, int count) +{ + int i; + size_t j; + size_t size = SIZEOF_INT2; + unsigned char ch; + + assert(sizeof(NCURSES_INT2) == size); + for (i = 0; i < count; i++) { + Numbers[i] = 0; + for (j = 0; j < size; ++j) { + ch = UChar(*buf++); + Numbers[i] |= (ch << (8 * j)); + } + /* "unsigned" and NCURSES_INT2 are the same size - no sign-extension */ + TR(TRACE_DATABASE, ("get Numbers[%d]=%d", i, Numbers[i])); + } + return size; +} +#else +static size_t +convert_32bits(char *buf, NCURSES_INT2 *Numbers, int count) +{ + int i, j; + unsigned char ch; + for (i = 0; i < count; i++) { + int value = 0; + for (j = 0; j < SIZEOF_32BITS; ++j) { + ch = UChar(*buf++); + value |= (ch << (8 * j)); + } + if (value == -1) + Numbers[i] = ABSENT_NUMERIC; + else if (value == -2) + Numbers[i] = CANCELLED_NUMERIC; + else if (value > MAX_OF_TYPE(NCURSES_INT2)) + Numbers[i] = MAX_OF_TYPE(NCURSES_INT2); + else + Numbers[i] = (short) value; + TR(TRACE_DATABASE, ("get Numbers[%d]=%d", i, Numbers[i])); + } + return SIZEOF_SHORT; +} + +static size_t +convert_16bits(char *buf, NCURSES_INT2 *Numbers, int count) { int i; for (i = 0; i < count; i++) { @@ -59,39 +133,67 @@ convert_shorts(char *buf, short *Numbers, int count) else if (IS_NEG2(buf + 2 * i)) Numbers[i] = CANCELLED_NUMERIC; else - Numbers[i] = LOW_MSB(buf + 2 * i); + Numbers[i] = MyNumber(buf + 2 * i); TR(TRACE_DATABASE, ("get Numbers[%d]=%d", i, Numbers[i])); } + return SIZEOF_SHORT; } +#endif -static void -convert_strings(char *buf, char **Strings, int count, int size, char *table) +static bool +convert_strings(char *buf, char **Strings, int count, int size, + char *table, bool always) { int i; char *p; + bool success = TRUE; for (i = 0; i < count; i++) { if (IS_NEG1(buf + 2 * i)) { Strings[i] = ABSENT_STRING; } else if (IS_NEG2(buf + 2 * i)) { Strings[i] = CANCELLED_STRING; - } else if ((int) LOW_MSB(buf + 2 * i) > size) { + } else if (MyNumber(buf + 2 * i) > size) { Strings[i] = ABSENT_STRING; } else { - Strings[i] = (LOW_MSB(buf + 2 * i) + table); - TR(TRACE_DATABASE, ("Strings[%d] = %s", i, _nc_visbuf(Strings[i]))); + int nn = MyNumber(buf + 2 * i); + if (nn >= 0 && nn < size) { + Strings[i] = (nn + table); + TR(TRACE_DATABASE, ("Strings[%d] = %s", i, + _nc_visbuf(Strings[i]))); + } else { + TR(TRACE_DATABASE, + ("found out-of-range index %d to Strings[%d]", nn, i)); + success = FALSE; + break; + } } /* make sure all strings are NUL terminated */ if (VALID_STRING(Strings[i])) { - for (p = Strings[i]; p <= table + size; p++) + for (p = Strings[i]; p < table + size; p++) if (*p == '\0') break; /* if there is no NUL, ignore the string */ - if (p > table + size) + if (p >= table + size) { Strings[i] = ABSENT_STRING; + } else if (p == Strings[i] && always) { + TR(TRACE_DATABASE, + ("found empty but required Strings[%d]", i)); + success = FALSE; + break; + } + } else if (always) { /* names are always needed */ + TR(TRACE_DATABASE, + ("found invalid but required Strings[%d]", i)); + success = FALSE; + break; } } + if (!success) { + _nc_warning("corrupt data found in convert_strings"); + } + return success; } static int @@ -101,33 +203,97 @@ fake_read(char *src, int *offset, int limit, char *dst, unsigned want) if (have > 0) { if ((int) want > have) - want = have; - memcpy(dst, src + *offset, want); - *offset += want; + want = (unsigned) have; + memcpy(dst, src + *offset, (size_t) want); + *offset += (int) want; } else { want = 0; } return (int) want; } -#define Read(buf, count) fake_read(buffer, &offset, limit, buf, count) +#define Read(buf, count) fake_read(buffer, &offset, limit, (char *) buf, (unsigned) count) #define read_shorts(buf, count) \ - (Read(buf, (unsigned) (count)*2) == (int) (count)*2) + (Read(buf, (count)*SIZEOF_SHORT) == (int) (count)*SIZEOF_SHORT) + +#define read_numbers(buf, count) \ + (Read(buf, (count)*(unsigned)size_of_numbers) == (int) (count)*size_of_numbers) #define even_boundary(value) \ if ((value) % 2 != 0) Read(buf, 1) +#endif + +NCURSES_EXPORT(void) +_nc_init_termtype(TERMTYPE2 *const tp) +{ + unsigned i; + + DEBUG(2, (T_CALLED("_nc_init_termtype(tp=%p)"), (void *) tp)); + +#if NCURSES_XNAMES + tp->num_Booleans = BOOLCOUNT; + tp->num_Numbers = NUMCOUNT; + tp->num_Strings = STRCOUNT; + tp->ext_Booleans = 0; + tp->ext_Numbers = 0; + tp->ext_Strings = 0; +#endif + if (tp->Booleans == 0) + TYPE_MALLOC(NCURSES_SBOOL, BOOLCOUNT, tp->Booleans); + if (tp->Numbers == 0) + TYPE_MALLOC(NCURSES_INT2, NUMCOUNT, tp->Numbers); + if (tp->Strings == 0) + TYPE_MALLOC(char *, STRCOUNT, tp->Strings); + + for_each_boolean(i, tp) + tp->Booleans[i] = FALSE; + + for_each_number(i, tp) + tp->Numbers[i] = ABSENT_NUMERIC; + + for_each_string(i, tp) + tp->Strings[i] = ABSENT_STRING; + DEBUG(2, (T_RETURN(""))); +} + +#if NCURSES_USE_DATABASE +#if NCURSES_XNAMES +static bool +valid_shorts(char *buffer, int limit) +{ + bool result = FALSE; + int n; + for (n = 0; n < limit; ++n) { + if (MyNumber(buffer + (n * 2)) > 0) { + result = TRUE; + break; + } + } + return result; +} +#endif + +/* + * Return TGETENT_YES if read, TGETENT_NO if not found or garbled. + */ NCURSES_EXPORT(int) -_nc_read_termtype(TERMTYPE *ptr, char *buffer, int limit) -/* return 1 if read, 0 if not found or garbled */ +_nc_read_termtype(TERMTYPE2 *ptr, char *buffer, int limit) { int offset = 0; int name_size, bool_count, num_count, str_count, str_size; int i; - char buf[MAX_ENTRY_SIZE + 1]; + char buf[MAX_ENTRY_SIZE + 2]; char *string_table; unsigned want, have; + size_t (*convert_numbers) (char *, NCURSES_INT2 *, int); + int size_of_numbers; + int max_entry_size = MAX_ENTRY_SIZE; + + TR(TRACE_DATABASE, + (T_CALLED("_nc_read_termtype(ptr=%p, buffer=%p, limit=%d)"), + (void *) ptr, buffer, limit)); TR(TRACE_DATABASE, ("READ termtype header @%d", offset)); @@ -136,14 +302,33 @@ _nc_read_termtype(TERMTYPE *ptr, char *buffer, int limit) /* grab the header */ if (!read_shorts(buf, 6) || !IS_TIC_MAGIC(buf)) { - return (TGETENT_NO); + returnDB(TGETENT_NO); } +#if NCURSES_EXT_NUMBERS + if (LOW_MSB(buf) == MAGIC2) { + convert_numbers = convert_32bits; + size_of_numbers = SIZEOF_INT2; + } else { + max_entry_size = MAX_ENTRY_SIZE1; + convert_numbers = convert_16bits; + size_of_numbers = SIZEOF_SHORT; + } +#else + if (LOW_MSB(buf) == MAGIC2) { + convert_numbers = convert_32bits; + size_of_numbers = SIZEOF_32BITS; + } else { + convert_numbers = convert_16bits; + size_of_numbers = SIZEOF_INT2; + } +#endif - name_size = LOW_MSB(buf + 2); - bool_count = LOW_MSB(buf + 4); - num_count = LOW_MSB(buf + 6); - str_count = LOW_MSB(buf + 8); - str_size = LOW_MSB(buf + 10); + /* *INDENT-EQLS* */ + name_size = MyNumber(buf + 2); + bool_count = MyNumber(buf + 4); + num_count = MyNumber(buf + 6); + str_count = MyNumber(buf + 8); + str_size = MyNumber(buf + 10); TR(TRACE_DATABASE, ("TERMTYPE name_size=%d, bool=%d/%d, num=%d/%d str=%d/%d(%d)", @@ -153,42 +338,37 @@ _nc_read_termtype(TERMTYPE *ptr, char *buffer, int limit) || bool_count < 0 || num_count < 0 || str_count < 0 + || bool_count > BOOLCOUNT + || num_count > NUMCOUNT + || str_count > STRCOUNT || str_size < 0) { - return (TGETENT_NO); + returnDB(TGETENT_NO); } - want = str_size + name_size + 1; - if (str_size) { - /* try to allocate space for the string table */ - if (str_count * 2 >= (int) sizeof(buf) - || (string_table = typeMalloc(char, want)) == 0) { - return (TGETENT_NO); - } - } else { - str_count = 0; - if ((string_table = typeMalloc(char, want)) == 0) { - return (TGETENT_NO); - } + want = (unsigned) (str_size + name_size + 1); + /* try to allocate space for the string table */ + if (str_count * SIZEOF_SHORT >= max_entry_size + || (string_table = typeMalloc(char, want)) == 0) { + returnDB(TGETENT_NO); } /* grab the name (a null-terminated string) */ want = min(MAX_NAME_SIZE, (unsigned) name_size); ptr->str_table = string_table; ptr->term_names = string_table; - if ((have = Read(ptr->term_names, want)) != want) { - memset(ptr->term_names + have, 0, want - have); + if ((have = (unsigned) Read(ptr->term_names, want)) != want) { + memset(ptr->term_names + have, 0, (size_t) (want - have)); } ptr->term_names[want] = '\0'; string_table += (want + 1); if (have > MAX_NAME_SIZE) - offset = (have - MAX_NAME_SIZE); + offset = (int) (have - MAX_NAME_SIZE); /* grab the booleans */ - if ((ptr->Booleans = TYPE_CALLOC(NCURSES_SBOOL, - max(BOOLCOUNT, bool_count))) == 0 - || Read(ptr->Booleans, (unsigned) bool_count) < bool_count) { - return (TGETENT_NO); + TYPE_CALLOC(NCURSES_SBOOL, max(BOOLCOUNT, bool_count), ptr->Booleans); + if (Read(ptr->Booleans, (unsigned) bool_count) < bool_count) { + returnDB(TGETENT_NO); } /* @@ -200,24 +380,27 @@ _nc_read_termtype(TERMTYPE *ptr, char *buffer, int limit) even_boundary(name_size + bool_count); /* grab the numbers */ - if ((ptr->Numbers = TYPE_CALLOC(short, max(NUMCOUNT, num_count))) == 0 - || !read_shorts(buf, num_count)) { - return (TGETENT_NO); + TYPE_CALLOC(NCURSES_INT2, max(NUMCOUNT, num_count), ptr->Numbers); + if (!read_numbers(buf, num_count)) { + returnDB(TGETENT_NO); } - convert_shorts(buf, ptr->Numbers, num_count); + convert_numbers(buf, ptr->Numbers, num_count); - if ((ptr->Strings = TYPE_CALLOC(char *, max(STRCOUNT, str_count))) == 0) - return (TGETENT_NO); + TYPE_CALLOC(char *, max(STRCOUNT, str_count), ptr->Strings); if (str_count) { /* grab the string offsets */ if (!read_shorts(buf, str_count)) { - return (TGETENT_NO); + returnDB(TGETENT_NO); } /* finally, grab the string table itself */ - if (Read(string_table, (unsigned) str_size) != str_size) - return (TGETENT_NO); - convert_strings(buf, ptr->Strings, str_count, str_size, string_table); + if (Read(string_table, (unsigned) str_size) != str_size) { + returnDB(TGETENT_NO); + } + if (!convert_strings(buf, ptr->Strings, str_count, str_size, + string_table, FALSE)) { + returnDB(TGETENT_NO); + } } #if NCURSES_XNAMES @@ -230,115 +413,150 @@ _nc_read_termtype(TERMTYPE *ptr, char *buffer, int limit) */ even_boundary(str_size); TR(TRACE_DATABASE, ("READ extended_header @%d", offset)); - if (_nc_user_definable && read_shorts(buf, 5)) { - int ext_bool_count = LOW_MSB(buf + 0); - int ext_num_count = LOW_MSB(buf + 2); - int ext_str_count = LOW_MSB(buf + 4); - int ext_str_size = LOW_MSB(buf + 6); - int ext_str_limit = LOW_MSB(buf + 8); - unsigned need = (ext_bool_count + ext_num_count + ext_str_count); + if (_nc_user_definable && read_shorts(buf, 5) && valid_shorts(buf, 5)) { + int ext_bool_count = MyNumber(buf + 0); + int ext_num_count = MyNumber(buf + 2); + int ext_str_count = MyNumber(buf + 4); + int ext_str_usage = MyNumber(buf + 6); + int ext_str_limit = MyNumber(buf + 8); + unsigned need = (unsigned) (ext_bool_count + ext_num_count + ext_str_count); int base = 0; - if (need >= sizeof(buf) - || ext_str_size >= (int) sizeof(buf) - || ext_str_limit >= (int) sizeof(buf) + if ((int) need >= (max_entry_size / 2) + || ext_str_usage >= max_entry_size + || ext_str_limit >= max_entry_size || ext_bool_count < 0 || ext_num_count < 0 || ext_str_count < 0 - || ext_str_size < 0 - || ext_str_limit < 0) - return (TGETENT_NO); + || ext_str_usage < 0 + || ext_str_limit < 0) { + returnDB(TGETENT_NO); + } - ptr->num_Booleans = BOOLCOUNT + ext_bool_count; - ptr->num_Numbers = NUMCOUNT + ext_num_count; - ptr->num_Strings = STRCOUNT + ext_str_count; + ptr->num_Booleans = UShort(BOOLCOUNT + ext_bool_count); + ptr->num_Numbers = UShort(NUMCOUNT + ext_num_count); + ptr->num_Strings = UShort(STRCOUNT + ext_str_count); - ptr->Booleans = typeRealloc(NCURSES_SBOOL, ptr->num_Booleans, ptr->Booleans); - ptr->Numbers = typeRealloc(short, ptr->num_Numbers, ptr->Numbers); - ptr->Strings = typeRealloc(char *, ptr->num_Strings, ptr->Strings); + TYPE_REALLOC(NCURSES_SBOOL, ptr->num_Booleans, ptr->Booleans); + TYPE_REALLOC(NCURSES_INT2, ptr->num_Numbers, ptr->Numbers); + TYPE_REALLOC(char *, ptr->num_Strings, ptr->Strings); - TR(TRACE_DATABASE, ("extended header is %d/%d/%d(%d:%d)", - ext_bool_count, ext_num_count, ext_str_count, - ext_str_size, ext_str_limit)); + TR(TRACE_DATABASE, ("extended header: " + "bool %d, " + "number %d, " + "string %d(%d:%d)", + ext_bool_count, + ext_num_count, + ext_str_count, + ext_str_usage, + ext_str_limit)); TR(TRACE_DATABASE, ("READ %d extended-booleans @%d", ext_bool_count, offset)); - if ((ptr->ext_Booleans = ext_bool_count) != 0) { + if ((ptr->ext_Booleans = UShort(ext_bool_count)) != 0) { if (Read(ptr->Booleans + BOOLCOUNT, (unsigned) - ext_bool_count) != ext_bool_count) - return (TGETENT_NO); + ext_bool_count) != ext_bool_count) { + returnDB(TGETENT_NO); + } } even_boundary(ext_bool_count); TR(TRACE_DATABASE, ("READ %d extended-numbers @%d", ext_num_count, offset)); - if ((ptr->ext_Numbers = ext_num_count) != 0) { - if (!read_shorts(buf, ext_num_count)) - return (TGETENT_NO); + if ((ptr->ext_Numbers = UShort(ext_num_count)) != 0) { + if (!read_numbers(buf, ext_num_count)) { + returnDB(TGETENT_NO); + } TR(TRACE_DATABASE, ("Before converting extended-numbers")); - convert_shorts(buf, ptr->Numbers + NUMCOUNT, ext_num_count); + convert_numbers(buf, ptr->Numbers + NUMCOUNT, ext_num_count); } TR(TRACE_DATABASE, ("READ extended-offsets @%d", offset)); + if ((ext_str_count + (int) need) >= (max_entry_size / 2)) { + returnDB(TGETENT_NO); + } if ((ext_str_count || need) - && !read_shorts(buf, ext_str_count + need)) - return (TGETENT_NO); + && !read_shorts(buf, ext_str_count + (int) need)) { + returnDB(TGETENT_NO); + } TR(TRACE_DATABASE, ("READ %d bytes of extended-strings @%d", ext_str_limit, offset)); if (ext_str_limit) { - if ((ptr->ext_str_table = typeMalloc(char, ext_str_limit)) == 0) - return (TGETENT_NO); - if (Read(ptr->ext_str_table, (unsigned) ext_str_limit) != ext_str_limit) - return (TGETENT_NO); + ptr->ext_str_table = typeMalloc(char, (size_t) ext_str_limit); + if (ptr->ext_str_table == 0) { + returnDB(TGETENT_NO); + } + if (Read(ptr->ext_str_table, (unsigned) ext_str_limit) != ext_str_limit) { + returnDB(TGETENT_NO); + } TR(TRACE_DATABASE, ("first extended-string is %s", _nc_visbuf(ptr->ext_str_table))); } - if ((ptr->ext_Strings = ext_str_count) != 0) { + if ((ptr->ext_Strings = UShort(ext_str_count)) != 0) { + int check = (ext_bool_count + ext_num_count + ext_str_count); + TR(TRACE_DATABASE, - ("Before computing extended-string capabilities str_count=%d, ext_str_count=%d", + ("Before computing extended-string capabilities " + "str_count=%d, ext_str_count=%d", str_count, ext_str_count)); - convert_strings(buf, ptr->Strings + str_count, ext_str_count, - ext_str_limit, ptr->ext_str_table); + if (!convert_strings(buf, ptr->Strings + str_count, ext_str_count, + ext_str_limit, ptr->ext_str_table, FALSE)) { + returnDB(TGETENT_NO); + } for (i = ext_str_count - 1; i >= 0; i--) { TR(TRACE_DATABASE, ("MOVE from [%d:%d] %s", i, i + str_count, _nc_visbuf(ptr->Strings[i + str_count]))); ptr->Strings[i + STRCOUNT] = ptr->Strings[i + str_count]; - if (VALID_STRING(ptr->Strings[i + STRCOUNT])) - base += (strlen(ptr->Strings[i + STRCOUNT]) + 1); + if (VALID_STRING(ptr->Strings[i + STRCOUNT])) { + base += (int) (strlen(ptr->Strings[i + STRCOUNT]) + 1); + ++check; + } TR(TRACE_DATABASE, ("... to [%d] %s", i + STRCOUNT, _nc_visbuf(ptr->Strings[i + STRCOUNT]))); } + TR(TRACE_DATABASE, ("Check table-size: %d/%d", check, ext_str_usage)); +#if 0 + /* + * Phasing in a proper check will be done "later". + */ + if (check != ext_str_usage) + returnDB(TGETENT_NO); +#endif } if (need) { - if (ext_str_count >= (MAX_ENTRY_SIZE * 2)) - return (TGETENT_NO); - if ((ptr->ext_Names = TYPE_CALLOC(char *, need)) == 0) - return (TGETENT_NO); + if (ext_str_count >= (max_entry_size / 2)) { + returnDB(TGETENT_NO); + } + TYPE_CALLOC(char *, need, ptr->ext_Names); TR(TRACE_DATABASE, ("ext_NAMES starting @%d in extended_strings, first = %s", base, _nc_visbuf(ptr->ext_str_table + base))); - convert_strings(buf + (2 * ext_str_count), - ptr->ext_Names, - (int) need, - ext_str_limit, ptr->ext_str_table + base); + if (!convert_strings(buf + (2 * ext_str_count), + ptr->ext_Names, + (int) need, + ext_str_limit, ptr->ext_str_table + base, + TRUE)) { + returnDB(TGETENT_NO); + } } - T(("...done reading terminfo bool %d(%d) num %d(%d) str %d(%d)", - ptr->num_Booleans, ptr->ext_Booleans, - ptr->num_Numbers, ptr->ext_Numbers, - ptr->num_Strings, ptr->ext_Strings)); + TR(TRACE_DATABASE, + ("...done reading terminfo bool %d(%d) num %d(%d) str %d(%d)", + ptr->num_Booleans, ptr->ext_Booleans, + ptr->num_Numbers, ptr->ext_Numbers, + ptr->num_Strings, ptr->ext_Strings)); TR(TRACE_DATABASE, ("extend: num_Booleans:%d", ptr->num_Booleans)); } else #endif /* NCURSES_XNAMES */ { - T(("...done reading terminfo bool %d num %d str %d", - bool_count, num_count, str_count)); + TR(TRACE_DATABASE, ("...done reading terminfo bool %d num %d str %d", + bool_count, num_count, str_count)); #if NCURSES_XNAMES TR(TRACE_DATABASE, ("normal: num_Booleans:%d", ptr->num_Booleans)); #endif @@ -351,7 +569,7 @@ _nc_read_termtype(TERMTYPE *ptr, char *buffer, int limit) for (i = str_count; i < STRCOUNT; i++) ptr->Strings[i] = ABSENT_STRING; - return (TGETENT_YES); + returnDB(TGETENT_YES); } /* @@ -363,33 +581,191 @@ _nc_read_termtype(TERMTYPE *ptr, char *buffer, int limit) * table. */ NCURSES_EXPORT(int) -_nc_read_file_entry(const char *const filename, TERMTYPE *ptr) +_nc_read_file_entry(const char *const filename, TERMTYPE2 *ptr) /* return 1 if read, 0 if not found or garbled */ { - int code, fd = -1; - int limit; - char buffer[MAX_ENTRY_SIZE + 1]; + FILE *fp = 0; + int code; if (_nc_access(filename, R_OK) < 0 - || (fd = open(filename, O_RDONLY | O_BINARY)) < 0) { - T(("cannot open terminfo %s (errno=%d)", filename, errno)); + || (fp = safe_fopen(filename, BIN_R)) == 0) { + TR(TRACE_DATABASE, ("cannot open terminfo %s (errno=%d)", filename, errno)); code = TGETENT_NO; } else { - if ((limit = read(fd, buffer, sizeof(buffer))) > 0) { + int limit; + char buffer[MAX_ENTRY_SIZE + 1]; - T(("read terminfo %s", filename)); + limit = (int) fread(buffer, sizeof(char), sizeof(buffer), fp); + if (limit > 0) { + const char *old_source = _nc_get_source(); + + TR(TRACE_DATABASE, ("read terminfo %s", filename)); + if (old_source == NULL) + _nc_set_source(filename); if ((code = _nc_read_termtype(ptr, buffer, limit)) == TGETENT_NO) { - _nc_free_termtype(ptr); + _nc_free_termtype2(ptr); } + _nc_set_source(old_source); } else { code = TGETENT_NO; } - close(fd); + fclose(fp); } return (code); } +#if USE_HASHED_DB +/* + * Return if if we can build the filename of a ".db" file. + */ +static bool +make_db_filename(char *filename, unsigned limit, const char *const path) +{ + static const char suffix[] = DBM_SUFFIX; + + size_t lens = sizeof(suffix) - 1; + size_t size = strlen(path); + size_t test = lens + size; + bool result = FALSE; + + if (test < limit) { + if (size >= lens + && !strcmp(path + size - lens, suffix)) + _nc_STRCPY(filename, path, limit); + else + _nc_SPRINTF(filename, _nc_SLIMIT(limit) "%s%s", path, suffix); + result = TRUE; + } + return result; +} +#endif + +/* + * Return true if we can build the name of a filesystem entry. + */ +static bool +make_dir_filename(char *filename, + unsigned limit, + const char *const path, + const char *name) +{ + bool result = FALSE; + +#if NCURSES_USE_TERMCAP + if (_nc_is_dir_path(path)) +#endif + { + unsigned need = (unsigned) (LEAF_LEN + 3 + strlen(path) + strlen(name)); + + if (need <= limit) { + _nc_SPRINTF(filename, _nc_SLIMIT(limit) + "%s/" LEAF_FMT "/%s", path, *name, name); + result = TRUE; + } + } + return result; +} + +static int +lookup_b64(int *target, const char **source) +{ + int result = 3; + int j; + /* + * ncurses' quickdump writes only RFC 4648 "url/filename-safe" encoding, + * but accepts RFC-3548 + */ + for (j = 0; j < 4; ++j) { + int ch = UChar(**source); + *source += 1; + if (ch >= 'A' && ch <= 'Z') { + target[j] = (ch - 'A'); + } else if (ch >= 'a' && ch <= 'z') { + target[j] = 26 + (ch - 'a'); + } else if (ch >= '0' && ch <= '9') { + target[j] = 52 + (ch - '0'); + } else if (ch == '-' || ch == '+') { + target[j] = 62; + } else if (ch == '_' || ch == '/') { + target[j] = 63; + } else if (ch == '=') { + target[j] = 64; + result--; + } else { + result = -1; + break; + } + } + return result; +} + +static int +decode_hex(const char **source) +{ + int result = 0; + int nibble; + + for (nibble = 0; nibble < 2; ++nibble) { + int ch = UChar(**source); + result <<= 4; + *source += 1; + if (ch >= '0' && ch <= '9') { + ch -= '0'; + } else if (ch >= 'A' && ch <= 'F') { + ch -= 'A'; + ch += 10; + } else if (ch >= 'a' && ch <= 'f') { + ch -= 'a'; + ch += 10; + } else { + result = -1; + break; + } + result |= ch; + } + return result; +} + +static int +decode_quickdump(char *target, const char *source) +{ + char *base = target; + int result = 0; + + if (!strncmp(source, "b64:", (size_t) 4)) { + source += 4; + while (*source != '\0') { + int bits[4]; + int ch = lookup_b64(bits, &source); + if (ch < 0 || (ch + target - base) >= MAX_ENTRY_SIZE) { + result = 0; + break; + } + result += ch; + *target++ = (char) ((bits[0] << 2) | (bits[1] >> 4)); + if (bits[2] < 64) { + *target++ = (char) ((bits[1] << 4) | (bits[2] >> 2)); + if (bits[3] < 64) { + *target++ = (char) ((bits[2] << 6) | bits[3]); + } + } + } + } else if (!strncmp(source, "hex:", (size_t) 4)) { + source += 4; + while (*source != '\0') { + int ch = decode_hex(&source); + if (ch < 0 || (target - base) >= MAX_ENTRY_SIZE) { + result = 0; + break; + } + *target++ = (char) ch; + ++result; + } + } + return result; +} + /* * Build a terminfo pathname and try to read the data. Returns TGETENT_YES on * success, TGETENT_NO on failure. @@ -399,136 +775,134 @@ _nc_read_tic_entry(char *filename, unsigned limit, const char *const path, const char *name, - TERMTYPE *const tp) + TERMTYPE2 *const tp) { - int result = TGETENT_NO; + int code = TGETENT_NO; +#if USE_HASHED_DB + DB *capdbp; +#endif + char buffer[MAX_ENTRY_SIZE + 1]; + int used; - /* - * If we are looking in a directory, assume the entry is a file under that, - * according to the normal rules. - * - * FIXME - add caseless-filename fixup. - */ - unsigned need = 4 + strlen(path) + strlen(name); - if (need <= limit) { - (void) snprintf(filename, limit, "%s/" LEAF_FMT "/%s", path, *name, name); - if (_nc_is_dir_path(path)) - result = _nc_read_file_entry(filename, tp); - } + TR(TRACE_DATABASE, + (T_CALLED("_nc_read_tic_entry(file=%p, path=%s, name=%s)"), + filename, path, name)); -#if USE_HASHED_DB - else { - static const char suffix[] = DBM_SUFFIX; - DB *capdbp; - unsigned lens = sizeof(suffix) - 1; - unsigned size = strlen(path); - unsigned need = lens + size; + assert(TGETENT_YES == TRUE); /* simplify call for _nc_name_match */ - if (need <= limit) { - if (size >= lens - && !strcmp(path + size - lens, suffix)) - (void) strlcpy(filename, path, limit); - else - (void) snprintf(filename, limit, "%s%s", path, suffix); + if ((used = decode_quickdump(buffer, path)) != 0 + && (code = _nc_read_termtype(tp, buffer, used)) == TGETENT_YES + && (code = _nc_name_match(tp->term_names, name, "|")) == TGETENT_YES) { + TR(TRACE_DATABASE, ("loaded quick-dump for %s", name)); + /* shorten name shown by infocmp */ + _nc_STRCPY(filename, "$TERMINFO", limit); + } else +#if USE_HASHED_DB + if (make_db_filename(filename, limit, path) + && (capdbp = _nc_db_open(filename, FALSE)) != 0) { + + DBT key, data; + int reccnt = 0; + char *save = strdup(name); + + if (save == 0) + returnDB(code); + + memset(&key, 0, sizeof(key)); + key.data = save; + key.size = strlen(save); + + /* + * This lookup could return termcap data, which we do not want. We are + * looking for compiled (binary) terminfo data. + * + * cgetent uses a two-level lookup. On the first it uses the given + * name to return a record containing only the aliases for an entry. + * On the second (using that list of aliases as a key), it returns the + * content of the terminal description. We expect second lookup to + * return data beginning with the same set of aliases. + * + * For compiled terminfo, the list of aliases in the second case will + * be null-terminated. A termcap entry will not be, and will run on + * into the description. So we can easily distinguish between the two + * (source/binary) by checking the lengths. + */ + while (_nc_db_get(capdbp, &key, &data) == 0) { + char *have = (char *) data.data; + used = (int) data.size - 1; + + if (*have++ == 0) { + if (data.size > key.size + && IS_TIC_MAGIC(have)) { + code = _nc_read_termtype(tp, have, used); + if (code == TGETENT_NO) { + _nc_free_termtype2(tp); + } + } + break; + } /* - * It would be nice to optimize the dbopen/close activity, as - * done in the cgetent implementation for tc= clauses. However, - * since we support multiple database locations, we cannot do - * that. + * Just in case we have a corrupt database, do not waste time with + * it. */ - if ((capdbp = _nc_db_open(filename, FALSE)) != 0) { - DBT key, data; - int reccnt = 0; - char *save = strdup(name); - - memset(&key, 0, sizeof(key)); - key.data = save; - key.size = strlen(save); - - /* - * This lookup could return termcap data, which we do not want. - * We are looking for compiled (binary) terminfo data. - * - * cgetent uses a two-level lookup. On the first it uses the - * given name to return a record containing only the aliases - * for an entry. On the second (using that list of aliases as - * a key), it returns the content of the terminal description. - * We expect second lookup to return data beginning with the - * same set of aliases. - * - * For compiled terminfo, the list of aliases in the second - * case will be null-terminated. A termcap entry will not be, - * and will run on into the description. So we can easily - * distinguish between the two (source/binary) by checking the - * lengths. - */ - while (_nc_db_get(capdbp, &key, &data) == 0) { - int used = data.size - 1; - char *have = (char *) data.data; - - if (*have++ == 0) { - if (data.size > key.size - && IS_TIC_MAGIC(have)) { - result = _nc_read_termtype(tp, have, used); - if (result == TGETENT_NO) { - _nc_free_termtype(tp); - } - } - break; - } - - /* - * Just in case we have a corrupt database, do not waste - * time with it. - */ - if (++reccnt >= 3) - break; - - /* - * Prepare for the second level. - */ - key.data = have; - key.size = used; - } + if (++reccnt >= 3) + break; - _nc_db_close(capdbp); - free(save); - } + /* + * Prepare for the second level. + */ + key.data = have; + key.size = used; } + + free(save); + } else /* may be either filesystem or flat file */ +#endif + if (make_dir_filename(filename, limit, path, name)) { + code = _nc_read_file_entry(filename, tp); + } +#if NCURSES_USE_TERMCAP + if (code != TGETENT_YES) { + code = _nc_read_termcap_entry(name, tp); + _nc_SPRINTF(filename, _nc_SLIMIT(PATH_MAX) + "%.*s", PATH_MAX - 1, _nc_get_source()); } #endif - return result; + returnDB(code); } -#endif /* USE_DATABASE */ +#endif /* NCURSES_USE_DATABASE */ /* - * _nc_read_entry(char *name, char *filename, TERMTYPE *tp) - * - * Find and read the compiled entry for a given terminal type, - * if it exists. We take pains here to make sure no combination - * of environment variables and terminal type name can be used to - * overrun the file buffer. + * Find and read the compiled entry for a given terminal type, if it exists. + * We take pains here to make sure no combination of environment variables and + * terminal type name can be used to overrun the file buffer. */ - NCURSES_EXPORT(int) -_nc_read_entry(const char *const name, char *const filename, TERMTYPE *const tp) +_nc_read_entry2(const char *const name, char *const filename, TERMTYPE2 *const tp) { int code = TGETENT_NO; - snprintf(filename, PATH_MAX, "%s", name); + if (name == 0) + return _nc_read_entry2("", filename, tp); + + _nc_SPRINTF(filename, _nc_SLIMIT(PATH_MAX) + "%.*s", PATH_MAX - 1, name); + if (strlen(name) == 0 || strcmp(name, ".") == 0 || strcmp(name, "..") == 0 || _nc_pathlast(name) != 0 || strchr(name, NCURSES_PATHSEP) != 0) { - T(("illegal or missing entry name '%s'", name)); + TR(TRACE_DATABASE, ("illegal or missing entry name '%s'", name)); } else { -#if USE_DATABASE - DBDIRS state = dbdTIC; - int offset = 0; +#if NCURSES_USE_DATABASE + DBDIRS state; + int offset; const char *path; + _nc_first_db(&state, &offset); + code = TGETENT_ERR; while ((path = _nc_next_db(&state, &offset)) != 0) { code = _nc_read_tic_entry(filename, PATH_MAX, path, name, tp); if (code == TGETENT_YES) { @@ -536,13 +910,26 @@ _nc_read_entry(const char *const name, char *const filename, TERMTYPE *const tp) break; } } -#endif -#if USE_TERMCAP +#elif NCURSES_USE_TERMCAP if (code != TGETENT_YES) { code = _nc_read_termcap_entry(name, tp); - snprintf(filename, PATH_MAX, "%s", _nc_get_source()); + _nc_SPRINTF(filename, _nc_SLIMIT(PATH_MAX) + "%.*s", PATH_MAX - 1, _nc_get_source()); } #endif } return code; } + +#if NCURSES_EXT_NUMBERS +NCURSES_EXPORT(int) +_nc_read_entry(const char *const name, char *const filename, TERMTYPE *const tp) +{ + TERMTYPE2 dummy; + int rc; + rc = _nc_read_entry2(name, filename, &dummy); + if (rc == TGETENT_YES) + _nc_export_termtype2(tp, &dummy); + return rc; +} +#endif diff --git a/lib/libcurses/tinfo/read_termcap.c b/lib/libcurses/tinfo/read_termcap.c index e3ae954f8a6..3f69f7d3bdd 100644 --- a/lib/libcurses/tinfo/read_termcap.c +++ b/lib/libcurses/tinfo/read_termcap.c @@ -1,7 +1,8 @@ -/* $OpenBSD: read_termcap.c,v 1.23 2021/10/24 21:24:20 deraadt Exp $ */ +/* $OpenBSD: read_termcap.c,v 1.24 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * + * Copyright 2018-2021,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -56,11 +57,9 @@ #include #include -#include #include -#include -MODULE_ID("$Id: read_termcap.c,v 1.23 2021/10/24 21:24:20 deraadt Exp $") +MODULE_ID("$Id: read_termcap.c,v 1.24 2023/10/17 09:52:09 nicm Exp $") #if !PURE_TERMINFO @@ -70,17 +69,26 @@ MODULE_ID("$Id: read_termcap.c,v 1.23 2021/10/24 21:24:20 deraadt Exp $") #define TC_REF_LOOP -3 #define TC_UNRESOLVED -4 /* this is not returned by BSD cgetent */ -static NCURSES_CONST char * +static const char * get_termpath(void) { - NCURSES_CONST char *result; + const char *result; if (!use_terminfo_vars() || (result = getenv("TERMPATH")) == 0) result = TERMPATH; - T(("TERMPATH is %s", result)); + TR(TRACE_DATABASE, ("TERMPATH is %s", result)); return result; } +/* + * Note: + * getcap(), cgetent(), etc., are BSD functions. A copy of those was added to + * this file in November 1995, derived from the BSD4.4 Lite sources. + * + * The initial adaptation uses 518 lines from that source. + * The current source (in 2009) uses 183 lines of BSD4.4 Lite (441 ignoring + * whitespace). + */ #if USE_GETCAP #if HAVE_BSD_CGETENT @@ -126,6 +134,8 @@ static int _nc_nfcmp(const char *, char *); * SUCH DAMAGE. */ +/* static char sccsid[] = "@(#)getcap.c 8.3 (Berkeley) 3/25/94"; */ + #define BFRAG 1024 #define BSIZE 1024 #define MAX_RECURSION 32 /* maximum getent recursion */ @@ -154,7 +164,7 @@ _nc_cgetset(const char *ent) return (-1); } gottoprec = 0; - (void) strlcpy(toprec, ent, topreclen + 1); + _nc_STRCPY(toprec, ent, topreclen); return (0); } @@ -179,7 +189,7 @@ _nc_cgetcap(char *buf, const char *cap, int type) bp = buf; for (;;) { /* - * Skip past the current capability field - it's either the + * Skip past the current capability field - it is either the * name field if this is the first time through the loop, or * the remainder of a field whose name failed to match cap. */ @@ -287,7 +297,7 @@ _nc_getent( errno = ENOMEM; return (TC_SYS_ERR); } - (void) strlcpy(record, toprec, topreclen + BFRAG); + _nc_STRCPY(record, toprec, topreclen + BFRAG); rp = record + topreclen + 1; r_end = rp + BFRAG; current = in_array; @@ -316,7 +326,7 @@ _nc_getent( if (fd >= 0) { (void) lseek(fd, (off_t) 0, SEEK_SET); } else if ((_nc_access(db_array[current], R_OK) < 0) - || (fd = open(db_array[current], O_RDONLY)) < 0) { + || (fd = safe_open2(db_array[current], O_RDONLY)) < 0) { /* No error on unfound file. */ if (errno == ENOENT) continue; @@ -357,7 +367,7 @@ _nc_getent( if (bp >= b_end) { int n; - n = read(fd, buf, sizeof(buf)); + n = (int) read(fd, buf, sizeof(buf)); if (n <= 0) { if (myfd) (void) close(fd); @@ -376,10 +386,17 @@ _nc_getent( c = *bp++; if (c == '\n') { lineno++; - if (rp == record || *(rp - 1) != '\\') + /* + * Unlike BSD 4.3, this ignores a backslash at the + * end of a comment-line. That makes it consistent + * with the rest of ncurses -TD + */ + if (rp == record + || *record == '#' + || *(rp - 1) != '\\') break; } - *rp++ = c; + *rp++ = (char) c; /* * Enforce loop invariant: if no room @@ -390,8 +407,8 @@ _nc_getent( unsigned pos; size_t newsize; - pos = rp - record; - newsize = r_end - record + BFRAG; + pos = (unsigned) (rp - record); + newsize = (size_t) (r_end - record + BFRAG); record = DOALLOC(newsize); if (record == 0) { if (myfd) @@ -434,8 +451,10 @@ _nc_getent( break; } - if (!foundit) + if (!foundit) { + free(record); return (TC_NOT_FOUND); + } } /* @@ -447,7 +466,7 @@ _nc_getent( register int newilen; unsigned ilen; int diff, iret, tclen, oline; - char *icap, *scan, *tc, *tcstart, *tcend; + char *icap = 0, *scan, *tc, *tcstart, *tcend; /* * Loop invariants: @@ -460,8 +479,9 @@ _nc_getent( scan = record; tc_not_resolved = FALSE; for (;;) { - if ((tc = _nc_cgetcap(scan, "tc", '=')) == 0) + if ((tc = _nc_cgetcap(scan, "tc", '=')) == 0) { break; + } /* * Find end of tc=name and stomp on the trailing `:' @@ -475,25 +495,27 @@ _nc_getent( } } tcstart = tc - 3; - tclen = s - tcstart; + tclen = (int) (s - tcstart); tcend = s; + icap = 0; iret = _nc_getent(&icap, &ilen, &oline, current, db_array, fd, tc, depth + 1, 0); newicap = icap; /* Put into a register. */ - newilen = ilen; + newilen = (int) ilen; if (iret != TC_SUCCESS) { /* an error */ if (iret < TC_NOT_FOUND) { if (myfd) (void) close(fd); free(record); + FreeIfNeeded(icap); return (iret); } - if (iret == TC_UNRESOLVED) + if (iret == TC_UNRESOLVED) { tc_not_resolved = TRUE; - /* couldn't resolve tc */ - if (iret == TC_NOT_FOUND) { + /* couldn't resolve tc */ + } else if (iret == TC_NOT_FOUND) { *(s - 1) = ':'; scan = s - 1; tc_not_resolved = TRUE; @@ -504,7 +526,7 @@ _nc_getent( /* not interested in name field of tc'ed record */ s = newicap; while (*s != '\0' && *s++ != ':') ; - newilen -= s - newicap; + newilen -= (int) (s - newicap); newicap = s; /* make sure interpolated record is `:'-terminated */ @@ -523,10 +545,10 @@ _nc_getent( unsigned pos, tcpos, tcposend; size_t newsize; - pos = rp - record; - newsize = r_end - record + diff + BFRAG; - tcpos = tcstart - record; - tcposend = tcend - record; + pos = (unsigned) (rp - record); + newsize = (size_t) (r_end - record + diff + BFRAG); + tcpos = (unsigned) (tcstart - record); + tcposend = (unsigned) (tcend - record); record = DOALLOC(newsize); if (record == 0) { if (myfd) @@ -564,7 +586,7 @@ _nc_getent( */ if (myfd) (void) close(fd); - *len = rp - record - 1; /* don't count NUL */ + *len = (unsigned) (rp - record - 1); /* don't count NUL */ if (r_end > rp) { if ((record = DOALLOC((size_t) (rp - record))) == 0) { errno = ENOMEM; @@ -573,8 +595,9 @@ _nc_getent( } *cap = record; - if (tc_not_resolved) + if (tc_not_resolved) { return (TC_UNRESOLVED); + } return (current); } @@ -683,12 +706,12 @@ _nc_nfcmp(const char *nf, char *rec) * SUCH DAMAGE. */ +/* static char sccsid[] = "@(#)termcap.c 8.1 (Berkeley) 6/4/93" */ + #define PBUFSIZ 512 /* max length of filename path */ #define PVECSIZ 32 /* max number of names in path */ #define TBUFSIZ (2048*2) -static char *tbuf; - /* * On entry, srcp points to a non ':' character which is the beginning of the * token, if any. We'll try to return a string that doesn't end with a ':'. @@ -750,7 +773,7 @@ copy_tc_token(char *dst, const char *src, size_t len) dst = 0; break; } - *dst++ = ch; + *dst++ = (char) ch; } return dst; } @@ -762,28 +785,27 @@ static int _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) { static char *the_source; + register char *p; register char *cp; char *dummy = NULL; - char **fname; + CGETENT_CONST char **fname; char *home; int i; char pathbuf[PBUFSIZ]; /* holds raw path of filenames */ - char *pathvec[PVECSIZ]; /* to point to names in pathbuf */ - char **pvec; /* holds usable tail of path vector */ - NCURSES_CONST char *termpath; + CGETENT_CONST char *pathvec[PVECSIZ]; /* point to names in pathbuf */ + const char *termpath; string_desc desc; + *lineno = 1; fname = pathvec; - pvec = pathvec; - tbuf = bp; p = pathbuf; cp = use_terminfo_vars()? getenv("TERMCAP") : NULL; /* * TERMCAP can have one of two things in it. It can be the name of a file * to use instead of /etc/termcap. In this case it better start with a - * "/". Or it can be an entry to use so we don't have to read the file. + * "/". Or it can be an entry to use so we don't have to read the file. * In this case it has to already have the newlines crunched out. If * TERMCAP does not hold a file name then a path of names is searched * instead. The path is found in the TERMPATH variable, or becomes @@ -801,10 +823,11 @@ _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) if ((home = getenv("HOME")) != 0 && *home != '\0' && strchr(home, ' ') == 0 && strlen(home) < sizeof(temp) - 10) { /* setup path */ - snprintf(temp, sizeof(temp), "%s/", home); /* $HOME first */ + _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) + "%s/", home); /* $HOME first */ } /* if no $HOME look in current directory */ - strlcat(temp, ".termcap", sizeof temp); + _nc_STRCAT(temp, ".termcap", sizeof(temp)); _nc_safe_strcat(&desc, temp); _nc_safe_strcat(&desc, " "); _nc_safe_strcat(&desc, get_termpath()); @@ -830,6 +853,9 @@ _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) } } *fname = 0; /* mark end of vector */ +#if !HAVE_BSD_CGETENT + (void) _nc_cgetset(0); +#endif if (_nc_is_abs_path(cp)) { if (_nc_cgetset(cp) < 0) { return (TC_SYS_ERR); @@ -842,6 +868,7 @@ _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) * empty fields, and mistakenly use the last valid cap entry instead of * the first (breaks tc= includes) */ + *bp = '\0'; if (i >= 0) { char *pd, *ps, *tok; int endflag = FALSE; @@ -863,7 +890,7 @@ _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) } if (ignore != TRUE) { list[count++] = tok; - pd = copy_tc_token(pd, tok, TBUFSIZ - (2 + pd - bp)); + pd = copy_tc_token(pd, tok, (size_t) (TBUFSIZ - (2 + pd - bp))); if (pd == 0) { i = -1; break; @@ -921,7 +948,7 @@ add_tc(char *termpaths[], char *path, int count) if (count < MAXPATHS && _nc_access(path, R_OK) == 0) { termpaths[count++] = path; - T(("Adding termpath %s", path)); + TR(TRACE_DATABASE, ("Adding termpath %s", path)); } termpaths[count] = 0; if (save != 0) @@ -932,7 +959,7 @@ add_tc(char *termpaths[], char *path, int count) #endif /* !USE_GETCAP */ NCURSES_EXPORT(int) -_nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) +_nc_read_termcap_entry(const char *const tn, TERMTYPE2 *const tp) { int found = TGETENT_NO; ENTRY *ep; @@ -941,25 +968,26 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) #endif #if USE_GETCAP char *p, tc[TBUFSIZ]; + char *tc_buf = 0; +#define MY_SIZE sizeof(tc) - 1 int status; static char *source; static int lineno; - T(("read termcap entry for %s", tn)); + TR(TRACE_DATABASE, ("read termcap entry for %s", tn)); if (strlen(tn) == 0 || strcmp(tn, ".") == 0 || strcmp(tn, "..") == 0 || _nc_pathlast(tn) != 0) { - T(("illegal or missing entry name '%s'", tn)); + TR(TRACE_DATABASE, ("illegal or missing entry name '%s'", tn)); return TGETENT_NO; } if (use_terminfo_vars() && (p = getenv("TERMCAP")) != 0 && !_nc_is_abs_path(p) && _nc_name_match(p, tn, "|:")) { /* TERMCAP holds a termcap entry */ - strncpy(tc, p, sizeof(tc) - 1); - tc[sizeof(tc) - 1] = '\0'; + tc_buf = strdup(p); _nc_set_source("TERMCAP"); } else { /* we're using getcap(3) */ @@ -968,8 +996,13 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) _nc_curr_line = lineno; _nc_set_source(source); + tc_buf = tc; } - _nc_read_entry_source((FILE *) 0, tc, FALSE, FALSE, NULLHOOK); + if (tc_buf == 0) + return (TGETENT_ERR); + _nc_read_entry_source((FILE *) 0, tc_buf, FALSE, TRUE, NULLHOOK); + if (tc_buf != tc) + free(tc_buf); #else /* * Here is what the 4.4BSD termcap(3) page prescribes: @@ -1003,7 +1036,7 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) int j, k; bool use_buffer = FALSE; bool normal = TRUE; - char tc_buf[1024]; + char *tc_buf = 0; char pathbuf[PATH_MAX]; char *copied = 0; char *cp; @@ -1015,8 +1048,8 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) ADD_TC(tc, 0); normal = FALSE; } else if (_nc_name_match(tc, tn, "|:")) { /* treat as a capability file */ - use_buffer = TRUE; - (void) snprintf(tc_buf, sizeof(tc_buf), "%.*s\n", (int) sizeof(tc_buf) - 2, tc); + tc_buf = strdup(tc); + use_buffer = (tc_buf != 0); normal = FALSE; } } @@ -1024,22 +1057,25 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) if (normal) { /* normal case */ char envhome[PATH_MAX], *h; - copied = strdup(get_termpath()); - for (cp = copied; *cp; cp++) { - if (*cp == NCURSES_PATHSEP) - *cp = '\0'; - else if (cp == copied || cp[-1] == '\0') { - ADD_TC(cp, filecount); + if ((copied = strdup(get_termpath())) != 0) { + for (cp = copied; *cp; cp++) { + if (*cp == NCURSES_PATHSEP) + *cp = '\0'; + else if (cp == copied || cp[-1] == '\0') { + ADD_TC(cp, filecount); + } } } - -#define PRIVATE_CAP "%s/.termcap" +#define PRIVATE_CAP "%.*s/.termcap" if (use_terminfo_vars() && (h = getenv("HOME")) != NULL && *h != '\0' && (strlen(h) + sizeof(PRIVATE_CAP)) < PATH_MAX) { /* user's .termcap, if any, should override it */ - (void) strlcpy(envhome, h, sizeof(envhome); - (void) snprintf(pathbuf, sizeof(pathbuf), PRIVATE_CAP, envhome); + _nc_STRCPY(envhome, h, sizeof(envhome)); + _nc_SPRINTF(pathbuf, _nc_SLIMIT(sizeof(pathbuf)) + PRIVATE_CAP, + (int) (sizeof(pathbuf) - sizeof(PRIVATE_CAP)), + envhome); ADD_TC(pathbuf, filecount); } } @@ -1052,7 +1088,7 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) for (j = 0; j < filecount; j++) { bool omit = FALSE; if (stat(termpaths[j], &test_stat[j]) != 0 - || (test_stat[j].st_mode & S_IFMT) != S_IFREG) { + || !S_ISREG(test_stat[j].st_mode)) { omit = TRUE; } else { for (k = 0; k < j; k++) { @@ -1064,7 +1100,7 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) } } if (omit) { - T(("Path %s is a duplicate", termpaths[j])); + TR(TRACE_DATABASE, ("Path %s is a duplicate", termpaths[j])); for (k = j + 1; k < filecount; k++) { termpaths[k - 1] = termpaths[k]; test_stat[k - 1] = test_stat[k]; @@ -1081,17 +1117,18 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) /* * We don't suppress warning messages here. The presumption is - * that since it's just a single entry, they won't be a pain. + * that since it is just a single entry, they won't be a pain. */ _nc_read_entry_source((FILE *) 0, tc_buf, FALSE, FALSE, NULLHOOK); + free(tc_buf); } else { int i; for (i = 0; i < filecount; i++) { - T(("Looking for %s in %s", tn, termpaths[i])); + TR(TRACE_DATABASE, ("Looking for %s in %s", tn, termpaths[i])); if (_nc_access(termpaths[i], R_OK) == 0 - && (fp = fopen(termpaths[i], "r")) != (FILE *) 0) { + && (fp = safe_fopen(termpaths[i], "r")) != (FILE *) 0) { _nc_set_source(termpaths[i]); /* @@ -1113,7 +1150,8 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) return (TGETENT_ERR); /* resolve all use references */ - _nc_resolve_uses2(TRUE, FALSE); + if (_nc_resolve_uses2(TRUE, FALSE) != TRUE) + return (TGETENT_ERR); /* find a terminal matching tn, if we can */ #if USE_GETCAP_CACHE @@ -1127,11 +1165,10 @@ _nc_read_termcap_entry(const char *const tn, TERMTYPE *const tp) * from the list. */ *tp = ep->tterm; - _nc_delink_entry(_nc_head, &(ep->tterm)); - free(ep); + _nc_free_entry(_nc_head, &(ep->tterm)); /* - * OK, now try to write the type to user's terminfo directory. + * OK, now try to write the type to user's terminfo directory. * Next time he loads this, it will come through terminfo. * * Advantage: Second and subsequent fetches of this entry will diff --git a/lib/libcurses/tinfo/strings.c b/lib/libcurses/tinfo/strings.c index b0f06598466..a8bb21c758a 100644 --- a/lib/libcurses/tinfo/strings.c +++ b/lib/libcurses/tinfo/strings.c @@ -1,7 +1,8 @@ -/* $OpenBSD: strings.c,v 1.4 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: strings.c,v 1.5 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2000-2003,2007 Free Software Foundation, Inc. * + * Copyright 2020,2023 Thomas E. Dickey * + * Copyright 2000-2012,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -37,8 +38,9 @@ **/ #include +#include -MODULE_ID("$Id: strings.c,v 1.4 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: strings.c,v 1.5 2023/10/17 09:52:09 nicm Exp $") /**************************************************************************** * Useful string functions (especially for mvcur) @@ -95,7 +97,7 @@ _nc_str_null(string_desc * dst, size_t len) * Copy a descriptor */ NCURSES_EXPORT(string_desc *) -_nc_str_copy(string_desc * dst, string_desc * src) +_nc_str_copy(string_desc * dst, const string_desc * const src) { *dst = *src; return dst; @@ -107,12 +109,12 @@ _nc_str_copy(string_desc * dst, string_desc * src) NCURSES_EXPORT(bool) _nc_safe_strcat(string_desc * dst, const char *src) { - if (src != 0) { + if (PRESENT(src)) { size_t len = strlen(src); if (len < dst->s_size) { if (dst->s_tail != 0) { - strlcpy(dst->s_tail, src, dst->s_size); + _nc_STRCPY(dst->s_tail, src, dst->s_size); dst->s_tail += len; } dst->s_size -= len; @@ -128,12 +130,12 @@ _nc_safe_strcat(string_desc * dst, const char *src) NCURSES_EXPORT(bool) _nc_safe_strcpy(string_desc * dst, const char *src) { - if (src != 0) { + if (PRESENT(src)) { size_t len = strlen(src); if (len < dst->s_size) { if (dst->s_head != 0) { - strlcpy(dst->s_head, src, dst->s_size); + _nc_STRCPY(dst->s_head, src, dst->s_size); dst->s_tail = dst->s_head + len; } dst->s_size = dst->s_init - len; diff --git a/lib/libcurses/tinfo/tinfo_driver.c b/lib/libcurses/tinfo/tinfo_driver.c new file mode 100644 index 00000000000..1a0800f2b06 --- /dev/null +++ b/lib/libcurses/tinfo/tinfo_driver.c @@ -0,0 +1,1554 @@ +/**************************************************************************** + * Copyright 2018-2021,2022 Thomas E. Dickey * + * Copyright 2008-2016,2017 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Juergen Pfeifer * + * and: Thomas E. Dickey * + ****************************************************************************/ + +#include +#define CUR TerminalType((TERMINAL*)TCB). +#include +#include /* ospeed */ + +#if HAVE_NANOSLEEP +#include +#if HAVE_SYS_TIME_H +#include /* needed for MacOS X DP3 */ +#endif +#endif + +#if HAVE_SIZECHANGE +# if !defined(sun) || !TERMIOS +# if HAVE_SYS_IOCTL_H +# include +# endif +# endif +#endif + +MODULE_ID("$Id: tinfo_driver.c,v 1.1 2023/10/17 09:52:09 nicm Exp $") + +/* + * SCO defines TIOCGSIZE and the corresponding struct. Other systems (SunOS, + * Solaris, IRIX) define TIOCGWINSZ and struct winsize. + */ +#ifdef TIOCGSIZE +# define IOCTL_WINSIZE TIOCGSIZE +# define STRUCT_WINSIZE struct ttysize +# define WINSIZE_ROWS(n) (int)n.ts_lines +# define WINSIZE_COLS(n) (int)n.ts_cols +#else +# ifdef TIOCGWINSZ +# define IOCTL_WINSIZE TIOCGWINSZ +# define STRUCT_WINSIZE struct winsize +# define WINSIZE_ROWS(n) (int)n.ws_row +# define WINSIZE_COLS(n) (int)n.ws_col +# endif +#endif + +/* + * These should be screen structure members. They need to be globals for + * historical reasons. So we assign them in start_color() and also in + * set_term()'s screen-switching logic. + */ +#if USE_REENTRANT +NCURSES_EXPORT(int) +NCURSES_PUBLIC_VAR(COLOR_PAIRS) (void) +{ + return CURRENT_SCREEN ? CURRENT_SCREEN->_pair_count : -1; +} +NCURSES_EXPORT(int) +NCURSES_PUBLIC_VAR(COLORS) (void) +{ + return CURRENT_SCREEN ? CURRENT_SCREEN->_color_count : -1; +} +#else +NCURSES_EXPORT_VAR(int) COLOR_PAIRS = 0; +NCURSES_EXPORT_VAR(int) COLORS = 0; +#endif + +#define TCBMAGIC NCDRV_MAGIC(NCDRV_TINFO) +#define AssertTCB() assert(TCB!=0 && TCB->magic==TCBMAGIC) +#define SetSP() assert(TCB->csp!=0); sp = TCB->csp; (void) sp + +/* + * This routine needs to do all the work to make curscr look + * like newscr. + */ +static int +drv_doupdate(TERMINAL_CONTROL_BLOCK * TCB) +{ + AssertTCB(); + return TINFO_DOUPDATE(TCB->csp); +} + +static const char * +drv_Name(TERMINAL_CONTROL_BLOCK * TCB) +{ + (void) TCB; + return "tinfo"; +} + +static void +get_baudrate(TERMINAL *termp) +{ + int my_ospeed; + int result; + if (GET_TTY(termp->Filedes, &termp->Nttyb) == OK) { +#ifdef TERMIOS + termp->Nttyb.c_oflag &= (unsigned) (~OFLAGS_TABS); +#elif defined(EXP_WIN32_DRIVER) + /* noop */ +#else + termp->Nttyb.sg_flags &= (unsigned) (~XTABS); +#endif + } +#ifdef USE_OLD_TTY + result = (int) cfgetospeed(&(termp->Nttyb)); + my_ospeed = (NCURSES_OSPEED) _nc_ospeed(result); +#else /* !USE_OLD_TTY */ +#ifdef TERMIOS + my_ospeed = (NCURSES_OSPEED) cfgetospeed(&(termp->Nttyb)); +#elif defined(EXP_WIN32_DRIVER) + /* noop */ + my_ospeed = 0; +#else + my_ospeed = (NCURSES_OSPEED) termp->Nttyb.sg_ospeed; +#endif + result = _nc_baudrate(my_ospeed); +#endif + termp->_baudrate = result; + ospeed = (NCURSES_OSPEED) my_ospeed; +} + +#undef SETUP_FAIL +#define SETUP_FAIL FALSE + +#define NO_COPY {} + +static bool +drv_CanHandle(TERMINAL_CONTROL_BLOCK * TCB, const char *tname, int *errret) +{ + bool result = FALSE; + int status; + TERMINAL *termp; + SCREEN *sp; + + START_TRACE(); + T((T_CALLED("tinfo::drv_CanHandle(%p)"), (void *) TCB)); + + assert(TCB != 0 && tname != 0); + termp = (TERMINAL *) TCB; + sp = TCB->csp; + TCB->magic = TCBMAGIC; + +#if (NCURSES_USE_DATABASE || NCURSES_USE_TERMCAP) + status = _nc_setup_tinfo(tname, &TerminalType(termp)); + T(("_nc_setup_tinfo returns %d", status)); +#else + T(("no database available")); + status = TGETENT_NO; +#endif + + /* try fallback list if entry on disk */ + if (status != TGETENT_YES) { + const TERMTYPE2 *fallback = _nc_fallback2(tname); + + if (fallback) { + T(("found fallback entry")); + TerminalType(termp) = *fallback; + status = TGETENT_YES; + } + } + + if (status != TGETENT_YES) { + NCURSES_SP_NAME(del_curterm) (NCURSES_SP_ARGx termp); + if (status == TGETENT_ERR) { + ret_error0(status, "terminals database is inaccessible\n"); + } else if (status == TGETENT_NO) { + ret_error1(status, "unknown terminal type.\n", + tname, NO_COPY); + } else { + ret_error0(status, "unexpected return-code\n"); + } + } + result = TRUE; +#if NCURSES_EXT_NUMBERS + _nc_export_termtype2(&termp->type, &TerminalType(termp)); +#endif +#if !USE_REENTRANT + save_ttytype(termp); +#endif + + if (command_character) + _nc_tinfo_cmdch(termp, *command_character); + + /* + * If an application calls setupterm() rather than initscr() or + * newterm(), we will not have the def_prog_mode() call in + * _nc_setupscreen(). Do it now anyway, so we can initialize the + * baudrate. + */ + if (sp == 0 && NC_ISATTY(termp->Filedes)) { + get_baudrate(termp); + } +#if NCURSES_EXT_NUMBERS +#define cleanup_termtype() \ + _nc_free_termtype2(&TerminalType(termp)); \ + _nc_free_termtype(&termp->type) +#else +#define cleanup_termtype() \ + _nc_free_termtype2(&TerminalType(termp)) +#endif + + if (generic_type) { + /* + * BSD 4.3's termcap contains mis-typed "gn" for wy99. Do a sanity + * check before giving up. + */ + if ((VALID_STRING(cursor_address) + || (VALID_STRING(cursor_down) && VALID_STRING(cursor_home))) + && VALID_STRING(clear_screen)) { + cleanup_termtype(); + ret_error1(TGETENT_YES, "terminal is not really generic.\n", + tname, NO_COPY); + } else { + cleanup_termtype(); + ret_error1(TGETENT_NO, "I need something more specific.\n", + tname, NO_COPY); + } + } + if (hard_copy) { + cleanup_termtype(); + ret_error1(TGETENT_YES, "I can't handle hardcopy terminals.\n", + tname, NO_COPY); + } + + returnBool(result); +} + +static int +drv_dobeepflash(TERMINAL_CONTROL_BLOCK * TCB, int beepFlag) +{ + SCREEN *sp; + int res = ERR; + + AssertTCB(); + SetSP(); + + /* FIXME: should make sure that we are not in altchar mode */ + if (beepFlag) { + if (bell) { + res = NCURSES_PUTP2("bell", bell); + NCURSES_SP_NAME(_nc_flush) (sp); + } else if (flash_screen) { + res = NCURSES_PUTP2("flash_screen", flash_screen); + NCURSES_SP_NAME(_nc_flush) (sp); + } + } else { + if (flash_screen) { + res = NCURSES_PUTP2("flash_screen", flash_screen); + NCURSES_SP_NAME(_nc_flush) (sp); + } else if (bell) { + res = NCURSES_PUTP2("bell", bell); + NCURSES_SP_NAME(_nc_flush) (sp); + } + } + return res; +} + +/* + * SVr4 curses is known to interchange color codes (1,4) and (3,6), possibly + * to maintain compatibility with a pre-ANSI scheme. The same scheme is + * also used in the FreeBSD syscons. + */ +static int +toggled_colors(int c) +{ + if (c < 16) { + static const int table[] = + {0, 4, 2, 6, 1, 5, 3, 7, + 8, 12, 10, 14, 9, 13, 11, 15}; + c = table[c]; + } + return c; +} + +static int +drv_print(TERMINAL_CONTROL_BLOCK * TCB, char *data, int len) +{ + SCREEN *sp; + + AssertTCB(); + SetSP(); +#if NCURSES_EXT_FUNCS + return NCURSES_SP_NAME(mcprint) (TCB->csp, data, len); +#else + return ERR; +#endif +} + +static int +drv_defaultcolors(TERMINAL_CONTROL_BLOCK * TCB, int fg, int bg) +{ + SCREEN *sp; + int code = ERR; + + AssertTCB(); + SetSP(); + + if (sp != 0 && orig_pair && orig_colors && (initialize_pair != 0)) { +#if NCURSES_EXT_FUNCS + sp->_default_color = isDefaultColor(fg) || isDefaultColor(bg); + sp->_has_sgr_39_49 = (NCURSES_SP_NAME(tigetflag) (NCURSES_SP_ARGx + "AX") + == TRUE); + sp->_default_fg = isDefaultColor(fg) ? COLOR_DEFAULT : fg; + sp->_default_bg = isDefaultColor(bg) ? COLOR_DEFAULT : bg; + if (sp->_color_pairs != 0) { + bool save = sp->_default_color; + sp->_default_color = TRUE; + NCURSES_SP_NAME(init_pair) (NCURSES_SP_ARGx + 0, + (short)fg, + (short)bg); + sp->_default_color = save; + } +#endif + code = OK; + } + return (code); +} + +static void +drv_setcolor(TERMINAL_CONTROL_BLOCK * TCB, + int fore, + int color, + NCURSES_SP_OUTC outc) +{ + SCREEN *sp; + + AssertTCB(); + SetSP(); + + if (fore) { + if (set_a_foreground) { + TPUTS_TRACE("set_a_foreground"); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_1(set_a_foreground, color), 1, outc); + } else { + TPUTS_TRACE("set_foreground"); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_1(set_foreground, + toggled_colors(color)), 1, outc); + } + } else { + if (set_a_background) { + TPUTS_TRACE("set_a_background"); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_1(set_a_background, color), 1, outc); + } else { + TPUTS_TRACE("set_background"); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_1(set_background, + toggled_colors(color)), 1, outc); + } + } +} + +static bool +drv_rescol(TERMINAL_CONTROL_BLOCK * TCB) +{ + bool result = FALSE; + SCREEN *sp; + + AssertTCB(); + SetSP(); + + if (orig_pair != 0) { + NCURSES_PUTP2("orig_pair", orig_pair); + result = TRUE; + } + return result; +} + +static bool +drv_rescolors(TERMINAL_CONTROL_BLOCK * TCB) +{ + int result = FALSE; + SCREEN *sp; + + AssertTCB(); + SetSP(); + + if (orig_colors != 0) { + NCURSES_PUTP2("orig_colors", orig_colors); + result = TRUE; + } + return result; +} + +static int +drv_size(TERMINAL_CONTROL_BLOCK * TCB, int *linep, int *colp) +{ + SCREEN *sp; + bool useEnv = TRUE; + bool useTioctl = TRUE; + + AssertTCB(); + sp = TCB->csp; /* can be null here */ + + if (sp) { + useEnv = sp->_use_env; + useTioctl = sp->use_tioctl; + } else { + useEnv = _nc_prescreen.use_env; + useTioctl = _nc_prescreen.use_tioctl; + } + +#ifdef EXP_WIN32_DRIVER + /* If we are here, then Windows console is used in terminfo mode. + We need to figure out the size using the console API + */ + _nc_console_size(linep, colp); + T(("screen size: winconsole lines = %d columns = %d", *linep, *colp)); +#else + /* figure out the size of the screen */ + T(("screen size: terminfo lines = %d columns = %d", lines, columns)); + + *linep = (int) lines; + *colp = (int) columns; +#endif + if (useEnv || useTioctl) { + int value; + +#ifdef __EMX__ + { + int screendata[2]; + _scrsize(screendata); + *colp = screendata[0]; + *linep = ((sp != 0 && sp->_filtered) + ? 1 + : screendata[1]); + T(("EMX screen size: environment LINES = %d COLUMNS = %d", + *linep, *colp)); + } +#endif +#if HAVE_SIZECHANGE + /* try asking the OS */ + { + TERMINAL *termp = (TERMINAL *) TCB; + if (NC_ISATTY(termp->Filedes)) { + STRUCT_WINSIZE size; + + errno = 0; + do { + if (ioctl(termp->Filedes, IOCTL_WINSIZE, &size) >= 0) { + *linep = ((sp != 0 && sp->_filtered) + ? 1 + : WINSIZE_ROWS(size)); + *colp = WINSIZE_COLS(size); + T(("SYS screen size: environment LINES = %d COLUMNS = %d", + *linep, *colp)); + break; + } + } while + (errno == EINTR); + } + } +#endif /* HAVE_SIZECHANGE */ + + if (useEnv) { + if (useTioctl) { + /* + * If environment variables are used, update them. + */ + if ((sp == 0 || !sp->_filtered) && _nc_getenv_num("LINES") > 0) { + _nc_setenv_num("LINES", *linep); + } + if (_nc_getenv_num("COLUMNS") > 0) { + _nc_setenv_num("COLUMNS", *colp); + } + } + + /* + * Finally, look for environment variables. + * + * Solaris lets users override either dimension with an environment + * variable. + */ + if ((value = _nc_getenv_num("LINES")) > 0) { + *linep = value; + T(("screen size: environment LINES = %d", *linep)); + } + if ((value = _nc_getenv_num("COLUMNS")) > 0) { + *colp = value; + T(("screen size: environment COLUMNS = %d", *colp)); + } + } + + /* if we can't get dynamic info about the size, use static */ + if (*linep <= 0) { + *linep = (int) lines; + } + if (*colp <= 0) { + *colp = (int) columns; + } + + /* the ultimate fallback, assume fixed 24x80 size */ + if (*linep <= 0) { + *linep = 24; + } + if (*colp <= 0) { + *colp = 80; + } + + /* + * Put the derived values back in the screen-size caps, so + * tigetnum() and tgetnum() will do the right thing. + */ + lines = (short) (*linep); + columns = (short) (*colp); + } + + T(("screen size is %dx%d", *linep, *colp)); + return OK; +} + +static int +drv_getsize(TERMINAL_CONTROL_BLOCK * TCB, int *l, int *c) +{ + AssertTCB(); + assert(l != 0 && c != 0); + *l = lines; + *c = columns; + return OK; +} + +static int +drv_setsize(TERMINAL_CONTROL_BLOCK * TCB, int l, int c) +{ + AssertTCB(); + lines = (short) l; + columns = (short) c; + return OK; +} + +static int +drv_sgmode(TERMINAL_CONTROL_BLOCK * TCB, int setFlag, TTY * buf) +{ + SCREEN *sp = TCB->csp; + TERMINAL *_term = (TERMINAL *) TCB; + int result = OK; + + AssertTCB(); + if (setFlag) { + for (;;) { + if (SET_TTY(_term->Filedes, buf) != 0) { + if (errno == EINTR) + continue; + if (errno == ENOTTY) { + if (sp) + sp->_notty = TRUE; + } + result = ERR; + } + break; + } + } else { + for (;;) { + if (GET_TTY(_term->Filedes, buf) != 0) { + if (errno == EINTR) + continue; + result = ERR; + } + break; + } + } + return result; +} + +static int +drv_mode(TERMINAL_CONTROL_BLOCK * TCB, int progFlag, int defFlag) +{ + SCREEN *sp; + TERMINAL *_term = (TERMINAL *) TCB; + int code = ERR; + + AssertTCB(); + sp = TCB->csp; + + if (progFlag) /* prog mode */ + { + if (defFlag) { + /* def_prog_mode */ + /* + * Turn off the XTABS bit in the tty structure if it was on. + */ + if ((drv_sgmode(TCB, FALSE, &(_term->Nttyb)) == OK)) { +#ifdef TERMIOS + _term->Nttyb.c_oflag &= (unsigned) ~OFLAGS_TABS; +#elif defined(EXP_WIN32_DRIVER) + /* noop */ +#else + _term->Nttyb.sg_flags &= (unsigned) ~XTABS; +#endif + code = OK; + } + } else { + /* reset_prog_mode */ + if (drv_sgmode(TCB, TRUE, &(_term->Nttyb)) == OK) { + if (sp) { + if (sp->_keypad_on) + _nc_keypad(sp, TRUE); + } + code = OK; + } + } + } else { /* shell mode */ + if (defFlag) { + /* def_shell_mode */ + /* + * If XTABS was on, remove the tab and backtab capabilities. + */ + if (drv_sgmode(TCB, FALSE, &(_term->Ottyb)) == OK) { +#ifdef TERMIOS + if (_term->Ottyb.c_oflag & OFLAGS_TABS) + tab = back_tab = NULL; +#elif defined(EXP_WIN32_DRIVER) + /* noop */ +#else + if (_term->Ottyb.sg_flags & XTABS) + tab = back_tab = NULL; +#endif + code = OK; + } + } else { + /* reset_shell_mode */ + if (sp) { + _nc_keypad(sp, FALSE); + NCURSES_SP_NAME(_nc_flush) (sp); + } + code = drv_sgmode(TCB, TRUE, &(_term->Ottyb)); + } + } + return (code); +} + +static void +drv_wrap(SCREEN *sp) +{ + if (sp) { + sp->_mouse_wrap(sp); + NCURSES_SP_NAME(_nc_screen_wrap) (sp); + NCURSES_SP_NAME(_nc_mvcur_wrap) (sp); /* wrap up cursor addressing */ + } +} + +static void +drv_release(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED) +{ +} + +# define SGR0_TEST(mode) (mode != 0) && (exit_attribute_mode == 0 || strcmp(mode, exit_attribute_mode)) + +static void +drv_screen_init(SCREEN *sp) +{ + TERMINAL_CONTROL_BLOCK *TCB = TCBOf(sp); + + AssertTCB(); + + /* + * Check for mismatched graphic-rendition capabilities. Most SVr4 + * terminfo trees contain entries that have rmul or rmso equated to + * sgr0 (Solaris curses copes with those entries). We do this only + * for curses, since many termcap applications assume that + * smso/rmso and smul/rmul are paired, and will not function + * properly if we remove rmso or rmul. Curses applications + * shouldn't be looking at this detail. + */ + sp->_use_rmso = SGR0_TEST(exit_standout_mode); + sp->_use_rmul = SGR0_TEST(exit_underline_mode); + + /* + * Check whether we can optimize scrolling under dumb terminals in + * case we do not have any of these capabilities, scrolling + * optimization will be useless. + */ + sp->_scrolling = ((scroll_forward && scroll_reverse) || + ((parm_rindex || + parm_insert_line || + insert_line) && + (parm_index || + parm_delete_line || + delete_line))); + + NCURSES_SP_NAME(baudrate) (sp); + + NCURSES_SP_NAME(_nc_mvcur_init) (sp); + /* initialize terminal to a sane state */ + NCURSES_SP_NAME(_nc_screen_init) (sp); +} + +static void +drv_init(TERMINAL_CONTROL_BLOCK * TCB) +{ + TERMINAL *trm; + + AssertTCB(); + + trm = (TERMINAL *) TCB; + + TCB->info.initcolor = VALID_STRING(initialize_color); + TCB->info.canchange = can_change; + TCB->info.hascolor = ((VALID_NUMERIC(max_colors) && VALID_NUMERIC(max_pairs) + && (((set_foreground != NULL) + && (set_background != NULL)) + || ((set_a_foreground != NULL) + && (set_a_background != NULL)) + || set_color_pair)) ? TRUE : FALSE); + + TCB->info.caninit = !(exit_ca_mode && non_rev_rmcup); + + TCB->info.maxpairs = VALID_NUMERIC(max_pairs) ? max_pairs : 0; + TCB->info.maxcolors = VALID_NUMERIC(max_colors) ? max_colors : 0; + TCB->info.numlabels = VALID_NUMERIC(num_labels) ? num_labels : 0; + TCB->info.labelwidth = VALID_NUMERIC(label_width) ? label_width : 0; + TCB->info.labelheight = VALID_NUMERIC(label_height) ? label_height : 0; + TCB->info.nocolorvideo = VALID_NUMERIC(no_color_video) ? no_color_video + : 0; + TCB->info.tabsize = VALID_NUMERIC(init_tabs) ? (int) init_tabs : 8; + + TCB->info.defaultPalette = hue_lightness_saturation ? _nc_hls_palette : _nc_cga_palette; + + /* + * If an application calls setupterm() rather than initscr() or + * newterm(), we will not have the def_prog_mode() call in + * _nc_setupscreen(). Do it now anyway, so we can initialize the + * baudrate. + */ + if (NC_ISATTY(trm->Filedes)) { + TCB->drv->td_mode(TCB, TRUE, TRUE); + } +} + +#define MAX_PALETTE 8 +#define InPalette(n) ((n) >= 0 && (n) < MAX_PALETTE) + +static void +drv_initpair(TERMINAL_CONTROL_BLOCK * TCB, int pair, int f, int b) +{ + SCREEN *sp; + + AssertTCB(); + SetSP(); + + if ((initialize_pair != NULL) && InPalette(f) && InPalette(b)) { + const color_t *tp = InfoOf(sp).defaultPalette; + + TR(TRACE_ATTRS, + ("initializing pair: pair = %d, fg=(%d,%d,%d), bg=(%d,%d,%d)", + pair, + tp[f].red, tp[f].green, tp[f].blue, + tp[b].red, tp[b].green, tp[b].blue)); + + NCURSES_PUTP2("initialize_pair", + TIPARM_7(initialize_pair, + pair, + tp[f].red, tp[f].green, tp[f].blue, + tp[b].red, tp[b].green, tp[b].blue)); + } +} + +static int +default_fg(SCREEN *sp) +{ +#if NCURSES_EXT_FUNCS + return (sp != 0) ? sp->_default_fg : COLOR_WHITE; +#else + return COLOR_WHITE; +#endif +} + +static int +default_bg(SCREEN *sp) +{ +#if NCURSES_EXT_FUNCS + return sp != 0 ? sp->_default_bg : COLOR_BLACK; +#else + return COLOR_BLACK; +#endif +} + +static void +drv_initcolor(TERMINAL_CONTROL_BLOCK * TCB, + int color, int r, int g, int b) +{ + SCREEN *sp = TCB->csp; + + AssertTCB(); + if (initialize_color != NULL) { + NCURSES_PUTP2("initialize_color", + TIPARM_4(initialize_color, color, r, g, b)); + } +} + +static void +drv_do_color(TERMINAL_CONTROL_BLOCK * TCB, + int old_pair, + int pair, + int reverse, + NCURSES_SP_OUTC outc) +{ + SCREEN *sp = TCB->csp; + int fg = COLOR_DEFAULT; + int bg = COLOR_DEFAULT; + int old_fg, old_bg; + + AssertTCB(); + if (sp == 0) + return; + + if (pair < 0 || pair >= COLOR_PAIRS) { + return; + } else if (pair != 0) { + if (set_color_pair) { + TPUTS_TRACE("set_color_pair"); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_1(set_color_pair, pair), 1, outc); + return; + } else if (sp != 0) { + _nc_pair_content(SP_PARM, pair, &fg, &bg); + } + } + + if (old_pair >= 0 + && sp != 0 + && _nc_pair_content(SP_PARM, old_pair, &old_fg, &old_bg) != ERR) { + if ((isDefaultColor(fg) && !isDefaultColor(old_fg)) + || (isDefaultColor(bg) && !isDefaultColor(old_bg))) { +#if NCURSES_EXT_FUNCS + /* + * A minor optimization - but extension. If "AX" is specified in + * the terminal description, treat it as screen's indicator of ECMA + * SGR 39 and SGR 49, and assume the two sequences are independent. + */ + if (sp->_has_sgr_39_49 + && isDefaultColor(old_bg) + && !isDefaultColor(old_fg)) { + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx "\033[39m", 1, outc); + } else if (sp->_has_sgr_39_49 + && isDefaultColor(old_fg) + && !isDefaultColor(old_bg)) { + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx "\033[49m", 1, outc); + } else +#endif + drv_rescol(TCB); + } + } else { + drv_rescol(TCB); + if (old_pair < 0) + return; + } + +#if NCURSES_EXT_FUNCS + if (isDefaultColor(fg)) + fg = default_fg(sp); + if (isDefaultColor(bg)) + bg = default_bg(sp); +#endif + + if (reverse) { + int xx = fg; + fg = bg; + bg = xx; + } + + TR(TRACE_ATTRS, ("setting colors: pair = %d, fg = %d, bg = %d", pair, + fg, bg)); + + if (!isDefaultColor(fg)) { + drv_setcolor(TCB, TRUE, fg, outc); + } + if (!isDefaultColor(bg)) { + drv_setcolor(TCB, FALSE, bg, outc); + } +} + +#define xterm_kmous "\033[M" +static void +init_xterm_mouse(SCREEN *sp) +{ + sp->_mouse_type = M_XTERM; + sp->_mouse_xtermcap = NCURSES_SP_NAME(tigetstr) (NCURSES_SP_ARGx "XM"); + if (!VALID_STRING(sp->_mouse_xtermcap)) + sp->_mouse_xtermcap = "\033[?1000%?%p1%{1}%=%th%el%;"; +} + +static void +drv_initmouse(TERMINAL_CONTROL_BLOCK * TCB) +{ + SCREEN *sp; + + AssertTCB(); + SetSP(); + + /* we know how to recognize mouse events under "xterm" */ + if (sp != 0) { + if (NonEmpty(key_mouse)) { + init_xterm_mouse(sp); + } else if (strstr(SP_TERMTYPE term_names, "xterm") != 0) { + if (_nc_add_to_try(&(sp->_keytry), xterm_kmous, KEY_MOUSE) == OK) + init_xterm_mouse(sp); + } + } +} + +static int +drv_testmouse(TERMINAL_CONTROL_BLOCK * TCB, + int delay + EVENTLIST_2nd(_nc_eventlist * evl)) +{ + int rc = 0; + SCREEN *sp; + + AssertTCB(); + SetSP(); + +#if USE_SYSMOUSE + if ((sp->_mouse_type == M_SYSMOUSE) + && (sp->_sysmouse_head < sp->_sysmouse_tail)) { + rc = TW_MOUSE; + } else +#endif + { +#ifdef EXP_WIN32_DRIVER + rc = _nc_console_testmouse(sp, + _nc_console_handle(sp->_ifd), + delay + EVENTLIST_2nd(evl)); +#else + rc = TCBOf(sp)->drv->td_twait(TCBOf(sp), + TWAIT_MASK, + delay, + (int *) 0 + EVENTLIST_2nd(evl)); +#endif +#if USE_SYSMOUSE + if ((sp->_mouse_type == M_SYSMOUSE) + && (sp->_sysmouse_head < sp->_sysmouse_tail) + && (rc == 0) + && (errno == EINTR)) { + rc |= TW_MOUSE; + } +#endif + } + return rc; +} + +static int +drv_mvcur(TERMINAL_CONTROL_BLOCK * TCB, int yold, int xold, int ynew, int xnew) +{ + SCREEN *sp = TCB->csp; + AssertTCB(); + return NCURSES_SP_NAME(_nc_mvcur) (sp, yold, xold, ynew, xnew); +} + +static void +drv_hwlabel(TERMINAL_CONTROL_BLOCK * TCB, int labnum, char *text) +{ + SCREEN *sp = TCB->csp; + + AssertTCB(); + if (labnum > 0 && labnum <= num_labels) { + NCURSES_PUTP2("plab_norm", + TPARM_2(plab_norm, labnum, text)); + } +} + +static void +drv_hwlabelOnOff(TERMINAL_CONTROL_BLOCK * TCB, int OnFlag) +{ + SCREEN *sp = TCB->csp; + + AssertTCB(); + if (OnFlag) { + NCURSES_PUTP2("label_on", label_on); + } else { + NCURSES_PUTP2("label_off", label_off); + } +} + +static chtype +drv_conattr(TERMINAL_CONTROL_BLOCK * TCB) +{ + SCREEN *sp = TCB->csp; + chtype attrs = A_NORMAL; + + AssertTCB(); + if (enter_alt_charset_mode) + attrs |= A_ALTCHARSET; + + if (enter_blink_mode) + attrs |= A_BLINK; + + if (enter_bold_mode) + attrs |= A_BOLD; + + if (enter_dim_mode) + attrs |= A_DIM; + + if (enter_reverse_mode) + attrs |= A_REVERSE; + + if (enter_standout_mode) + attrs |= A_STANDOUT; + + if (enter_protected_mode) + attrs |= A_PROTECT; + + if (enter_secure_mode) + attrs |= A_INVIS; + + if (enter_underline_mode) + attrs |= A_UNDERLINE; + + if (sp && sp->_coloron) + attrs |= A_COLOR; + +#if USE_ITALIC + if (enter_italics_mode) + attrs |= A_ITALIC; +#endif + + return (attrs); +} + +static void +drv_setfilter(TERMINAL_CONTROL_BLOCK * TCB) +{ + AssertTCB(); + + /* *INDENT-EQLS* */ + clear_screen = ABSENT_STRING; + cursor_address = ABSENT_STRING; + cursor_down = ABSENT_STRING; + cursor_up = ABSENT_STRING; + parm_down_cursor = ABSENT_STRING; + parm_up_cursor = ABSENT_STRING; + row_address = ABSENT_STRING; + cursor_home = carriage_return; + + if (back_color_erase) + clr_eos = ABSENT_STRING; +} + +static void +drv_initacs(TERMINAL_CONTROL_BLOCK * TCB, chtype *real_map, chtype *fake_map) +{ + SCREEN *sp = TCB->csp; + + AssertTCB(); + assert(sp != 0); + if (ena_acs != NULL) { + NCURSES_PUTP2("ena_acs", ena_acs); + } +#if NCURSES_EXT_FUNCS + /* + * Linux console "supports" the "PC ROM" character set by the coincidence + * that smpch/rmpch and smacs/rmacs have the same values. ncurses has + * no codepage support (see SCO Merge for an example). Outside of the + * values defined in acsc, there are no definitions for the "PC ROM" + * character set (assumed by some applications to be codepage 437), but we + * allow those applications to use those codepoints. + * + * test/blue.c uses this feature. + */ +#define PCH_KLUDGE(a,b) (a != 0 && b != 0 && !strcmp(a,b)) + if (PCH_KLUDGE(enter_pc_charset_mode, enter_alt_charset_mode) && + PCH_KLUDGE(exit_pc_charset_mode, exit_alt_charset_mode)) { + size_t i; + for (i = 1; i < ACS_LEN; ++i) { + if (real_map[i] == 0) { + real_map[i] = (chtype) i; + if (real_map != fake_map) { + if (sp != 0) + sp->_screen_acs_map[i] = TRUE; + } + } + } + } +#endif + + if (acs_chars != NULL) { + size_t i = 0; + size_t length = strlen(acs_chars); + + while (i + 1 < length) { + if (acs_chars[i] != 0 && UChar(acs_chars[i]) < ACS_LEN) { + real_map[UChar(acs_chars[i])] = UChar(acs_chars[i + 1]) | A_ALTCHARSET; + T(("#%d real_map[%s] = %s", + (int) i, + _tracechar(UChar(acs_chars[i])), + _tracechtype(real_map[UChar(acs_chars[i])]))); + if (sp != 0) { + sp->_screen_acs_map[UChar(acs_chars[i])] = TRUE; + } + } + i += 2; + } + } +#ifdef TRACE + /* Show the equivalent mapping, noting if it does not match the + * given attribute, whether by re-ordering or duplication. + */ + if (USE_TRACEF(TRACE_CALLS)) { + size_t n, m; + char show[ACS_LEN * 2 + 1]; + for (n = 1, m = 0; n < ACS_LEN; n++) { + if (real_map[n] != 0) { + show[m++] = (char) n; + show[m++] = (char) ChCharOf(real_map[n]); + } + } + show[m] = 0; + if (acs_chars == NULL || strcmp(acs_chars, show)) + _tracef("%s acs_chars %s", + (acs_chars == NULL) ? "NULL" : "READ", + _nc_visbuf(acs_chars)); + _tracef("%s acs_chars %s", + (acs_chars == NULL) + ? "NULL" + : (strcmp(acs_chars, show) + ? "DIFF" + : "SAME"), + _nc_visbuf(show)); + _nc_unlock_global(tracef); + } +#endif /* TRACE */ +} + +#define ENSURE_TINFO(sp) (TCBOf(sp)->drv->isTerminfo) + +NCURSES_EXPORT(void) +_nc_cookie_init(SCREEN *sp) +{ + bool support_cookies = USE_XMC_SUPPORT; + TERMINAL_CONTROL_BLOCK *TCB = (TERMINAL_CONTROL_BLOCK *) (sp->_term); + + if (sp == 0 || !ENSURE_TINFO(sp)) + return; + +#if USE_XMC_SUPPORT + /* + * If we have no magic-cookie support compiled-in, or if it is suppressed + * in the environment, reset the support-flag. + */ + if (magic_cookie_glitch >= 0) { + if (getenv("NCURSES_NO_MAGIC_COOKIE") != 0) { + support_cookies = FALSE; + } + } +#endif + + if (!support_cookies && magic_cookie_glitch >= 0) { + T(("will disable attributes to work w/o magic cookies")); + } + + if (magic_cookie_glitch > 0) { /* tvi, wyse */ + + sp->_xmc_triggers = sp->_ok_attributes & XMC_CONFLICT; +#if 0 + /* + * We "should" treat colors as an attribute. The wyse350 (and its + * clones) appear to be the only ones that have both colors and magic + * cookies. + */ + if (has_colors()) { + sp->_xmc_triggers |= A_COLOR; + } +#endif + sp->_xmc_suppress = sp->_xmc_triggers & (chtype) ~(A_BOLD); + + T(("magic cookie attributes %s", _traceattr(sp->_xmc_suppress))); + /* + * Supporting line-drawing may be possible. But make the regular + * video attributes work first. + */ + acs_chars = ABSENT_STRING; + ena_acs = ABSENT_STRING; + enter_alt_charset_mode = ABSENT_STRING; + exit_alt_charset_mode = ABSENT_STRING; +#if USE_XMC_SUPPORT + /* + * To keep the cookie support simple, suppress all of the optimization + * hooks except for clear_screen and the cursor addressing. + */ + if (support_cookies) { + clr_eol = ABSENT_STRING; + clr_eos = ABSENT_STRING; + set_attributes = ABSENT_STRING; + } +#endif + } else if (magic_cookie_glitch == 0) { /* hpterm */ + } + + /* + * If magic cookies are not supported, cancel the strings that set + * video attributes. + */ + if (!support_cookies && magic_cookie_glitch >= 0) { + magic_cookie_glitch = ABSENT_NUMERIC; + set_attributes = ABSENT_STRING; + enter_blink_mode = ABSENT_STRING; + enter_bold_mode = ABSENT_STRING; + enter_dim_mode = ABSENT_STRING; + enter_reverse_mode = ABSENT_STRING; + enter_standout_mode = ABSENT_STRING; + enter_underline_mode = ABSENT_STRING; + } + + /* initialize normal acs before wide, since we use mapping in the latter */ +#if !USE_WIDEC_SUPPORT + if (_nc_unicode_locale() && _nc_locale_breaks_acs(sp->_term)) { + acs_chars = NULL; + ena_acs = NULL; + enter_alt_charset_mode = NULL; + exit_alt_charset_mode = NULL; + set_attributes = NULL; + } +#endif +} + +static int +drv_twait(TERMINAL_CONTROL_BLOCK * TCB, + int mode, + int milliseconds, + int *timeleft + EVENTLIST_2nd(_nc_eventlist * evl)) +{ + SCREEN *sp; + + AssertTCB(); + SetSP(); +#ifdef EXP_WIN32_DRIVER + return _nc_console_twait(sp, + _nc_console_handle(sp->_ifd), + mode, + milliseconds, + timeleft EVENTLIST_2nd(evl)); +#else + return _nc_timed_wait(sp, mode, milliseconds, timeleft EVENTLIST_2nd(evl)); +#endif +} + +static int +drv_read(TERMINAL_CONTROL_BLOCK * TCB, int *buf) +{ + SCREEN *sp; + int n; +#ifndef EXP_WIN32_DRIVER + unsigned char c2 = 0; +#endif + + AssertTCB(); + assert(buf); + SetSP(); + + _nc_set_read_thread(TRUE); +#ifdef EXP_WIN32_DRIVER + n = _nc_console_read(sp, + _nc_console_handle(sp->_ifd), + buf); +#else + n = (int) read(sp->_ifd, &c2, (size_t) 1); +#endif + _nc_set_read_thread(FALSE); +#ifndef EXP_WIN32_DRIVER + *buf = (int) c2; +#endif + return n; +} + +static int +drv_nap(TERMINAL_CONTROL_BLOCK * TCB GCC_UNUSED, int ms) +{ +#if HAVE_NANOSLEEP + { + struct timespec request, remaining; + request.tv_sec = ms / 1000; + request.tv_nsec = (ms % 1000) * 1000000; + while (nanosleep(&request, &remaining) == -1 + && errno == EINTR) { + request = remaining; + } + } +#elif defined(EXP_WIN32_DRIVER) + Sleep((DWORD) ms); +#else + _nc_timed_wait(0, 0, ms, (int *) 0 EVENTLIST_2nd(0)); +#endif + return OK; +} + +static int +__nc_putp(SCREEN *sp, const char *name GCC_UNUSED, const char *value) +{ + int rc = ERR; + + if (value) { + rc = NCURSES_PUTP2(name, value); + } + return rc; +} + +static int +__nc_putp_flush(SCREEN *sp, const char *name, const char *value) +{ + int rc = __nc_putp(sp, name, value); + if (rc != ERR) { + NCURSES_SP_NAME(_nc_flush) (sp); + } + return rc; +} + +static int +drv_kpad(TERMINAL_CONTROL_BLOCK * TCB, int flag) +{ + int ret = ERR; + SCREEN *sp; + + AssertTCB(); + + sp = TCB->csp; + + if (sp) { + if (flag) { + (void) __nc_putp_flush(sp, "keypad_xmit", keypad_xmit); + } else if (!flag && keypad_local) { + (void) __nc_putp_flush(sp, "keypad_local", keypad_local); + } + if (flag && !sp->_tried) { + _nc_init_keytry(sp); + sp->_tried = TRUE; + } + ret = OK; + } + + return ret; +} + +static int +drv_keyok(TERMINAL_CONTROL_BLOCK * TCB, int c, int flag) +{ + SCREEN *sp; + int code = ERR; + int count = 0; + char *s; + + AssertTCB(); + SetSP(); + + if (c >= 0) { + unsigned ch = (unsigned) c; + if (flag) { + while ((s = _nc_expand_try(sp->_key_ok, + ch, &count, (size_t) 0)) != 0) { + if (_nc_remove_key(&(sp->_key_ok), ch)) { + code = _nc_add_to_try(&(sp->_keytry), s, ch); + free(s); + count = 0; + if (code != OK) + break; + } else { + free(s); + } + } + } else { + while ((s = _nc_expand_try(sp->_keytry, + ch, &count, (size_t) 0)) != 0) { + if (_nc_remove_key(&(sp->_keytry), ch)) { + code = _nc_add_to_try(&(sp->_key_ok), s, ch); + free(s); + count = 0; + if (code != OK) + break; + } else { + free(s); + } + } + } + } + return (code); +} + +static int +drv_cursorSet(TERMINAL_CONTROL_BLOCK * TCB, int vis) +{ + SCREEN *sp; + int code = ERR; + + AssertTCB(); + SetSP(); + + T((T_CALLED("tinfo:drv_cursorSet(%p,%d)"), (void *) SP_PARM, vis)); + + if (SP_PARM != 0 && IsTermInfo(SP_PARM)) { + switch (vis) { + case 2: + code = NCURSES_PUTP2_FLUSH("cursor_visible", cursor_visible); + break; + case 1: + code = NCURSES_PUTP2_FLUSH("cursor_normal", cursor_normal); + break; + case 0: + code = NCURSES_PUTP2_FLUSH("cursor_invisible", cursor_invisible); + break; + } + } else { + code = ERR; + } + returnCode(code); +} + +static bool +drv_kyExist(TERMINAL_CONTROL_BLOCK * TCB, int key) +{ + bool res = FALSE; + + AssertTCB(); + if (TCB->csp) + res = TINFO_HAS_KEY(TCB->csp, key) == 0 ? FALSE : TRUE; + + return res; +} + +NCURSES_EXPORT_VAR (TERM_DRIVER) _nc_TINFO_DRIVER = { + TRUE, + drv_Name, /* Name */ + drv_CanHandle, /* CanHandle */ + drv_init, /* init */ + drv_release, /* release */ + drv_size, /* size */ + drv_sgmode, /* sgmode */ + drv_conattr, /* conattr */ + drv_mvcur, /* hwcur */ + drv_mode, /* mode */ + drv_rescol, /* rescol */ + drv_rescolors, /* rescolors */ + drv_setcolor, /* color */ + drv_dobeepflash, /* doBeepOrFlash */ + drv_initpair, /* initpair */ + drv_initcolor, /* initcolor */ + drv_do_color, /* docolor */ + drv_initmouse, /* initmouse */ + drv_testmouse, /* testmouse */ + drv_setfilter, /* setfilter */ + drv_hwlabel, /* hwlabel */ + drv_hwlabelOnOff, /* hwlabelOnOff */ + drv_doupdate, /* update */ + drv_defaultcolors, /* defaultcolors */ + drv_print, /* print */ + drv_getsize, /* getsize */ + drv_setsize, /* setsize */ + drv_initacs, /* initacs */ + drv_screen_init, /* scinit */ + drv_wrap, /* scexit */ + drv_twait, /* twait */ + drv_read, /* read */ + drv_nap, /* nap */ + drv_kpad, /* kpad */ + drv_keyok, /* kyOk */ + drv_kyExist, /* kyExist */ + drv_cursorSet /* cursorSet */ +}; + +#ifdef EXP_WIN32_DRIVER +/* + * The terminfo driver is mandatory and must always be present. + * So this is the natural place for the driver initialisation + * logic. + */ + +typedef struct DriverEntry { + const char *name; + TERM_DRIVER *driver; +} DRIVER_ENTRY; + +static DRIVER_ENTRY DriverTable[] = +{ +#ifdef _NC_WINDOWS + {"win32console", &_nc_WIN_DRIVER}, +#endif + {"tinfo", &_nc_TINFO_DRIVER} /* must be last */ +}; + +NCURSES_EXPORT(int) +_nc_get_driver(TERMINAL_CONTROL_BLOCK * TCB, const char *name, int *errret) +{ + int code = ERR; + size_t i; + TERM_DRIVER *res = (TERM_DRIVER *) 0; + TERM_DRIVER *use = 0; + + T((T_CALLED("_nc_get_driver(%p, %s, %p)"), + (void *) TCB, NonNull(name), (void *) errret)); + + assert(TCB != 0); + + for (i = 0; i < SIZEOF(DriverTable); i++) { + res = DriverTable[i].driver; +#ifdef _NC_WINDOWS + if ((i + 1) == SIZEOF(DriverTable)) { + /* For Windows >= 10.0.17763 Windows Console interface implements + virtual Terminal functionality. + If on Windows td_CanHandle returned FALSE although the terminal + name is empty, we default to ms-terminal as tinfo TERM type. + */ + if (name == 0 || *name == 0 || (strcmp(name, "unknown") == 0)) { + name = MS_TERMINAL; + T(("Set TERM=%s", name)); + } + } +#endif + if (strcmp(DriverTable[i].name, res->td_name(TCB)) == 0) { + if (res->td_CanHandle(TCB, name, errret)) { + use = res; + break; + } + } + } + if (use != 0) { + TCB->drv = use; + code = OK; + } + returnCode(code); +} +#endif /* EXP_WIN32_DRIVER */ diff --git a/lib/libcurses/tinfo/trim_sgr0.c b/lib/libcurses/tinfo/trim_sgr0.c index 017d715bd01..e6b05e764f7 100644 --- a/lib/libcurses/tinfo/trim_sgr0.c +++ b/lib/libcurses/tinfo/trim_sgr0.c @@ -1,7 +1,8 @@ -/* $OpenBSD: trim_sgr0.c,v 1.1 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: trim_sgr0.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2005-2006,2007 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 2005-2012,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -37,9 +38,8 @@ #include #include -#include -MODULE_ID("$Id: trim_sgr0.c,v 1.1 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: trim_sgr0.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") #undef CUR #define CUR tp-> @@ -49,23 +49,30 @@ MODULE_ID("$Id: trim_sgr0.c,v 1.1 2010/01/12 23:22:06 nicm Exp $") #define L_BRACK '[' static char * -set_attribute_9(TERMTYPE *tp, int flag) +set_attribute_9(TERMTYPE2 *tp, int flag) { - const char *result; + const char *value; + char *result; - if ((result = tparm(set_attributes, 0, 0, 0, 0, 0, 0, 0, 0, flag)) == 0) - result = ""; - return strdup(result); + value = TIPARM_9(set_attributes, 0, 0, 0, 0, 0, 0, 0, 0, flag); + if (PRESENT(value)) + result = strdup(value); + else + result = 0; + return result; } static int is_csi(const char *s) { - if (UChar(s[0]) == CSI) - return 1; - else if (s[0] == ESC && s[1] == L_BRACK) - return 2; - return 0; + int result = 0; + if (s != 0) { + if (UChar(s[0]) == CSI) + result = 1; + else if (s[0] == ESC && s[1] == L_BRACK) + result = 2; + } + return result; } static char * @@ -100,10 +107,10 @@ skip_delay(const char *s) static bool rewrite_sgr(char *s, char *attr) { - if (PRESENT(s)) { + if (s != 0) { if (PRESENT(attr)) { - unsigned len_s = strlen(s); - unsigned len_a = strlen(attr); + size_t len_s = strlen(s); + size_t len_a = strlen(attr); if (len_s > len_a && !strncmp(attr, s, len_a)) { unsigned n; @@ -111,7 +118,7 @@ rewrite_sgr(char *s, char *attr) for (n = 0; n < len_s - len_a; ++n) { s[n] = s[n + len_a]; } - strlcpy(s + n, attr, len_s - n); + _nc_STRCPY(s + n, attr, strlen(s) + 1); TR(TRACE_DATABASE, ("to:\n\t%s", s)); } } @@ -124,33 +131,35 @@ static bool similar_sgr(char *a, char *b) { bool result = FALSE; - int csi_a = is_csi(a); - int csi_b = is_csi(b); - unsigned len_a; - unsigned len_b; + if (a != 0 && b != 0) { + int csi_a = is_csi(a); + int csi_b = is_csi(b); + size_t len_a; + size_t len_b; - TR(TRACE_DATABASE, ("similar_sgr:\n\t%s\n\t%s", - _nc_visbuf2(1, a), - _nc_visbuf2(2, b))); - if (csi_a != 0 && csi_b != 0 && csi_a == csi_b) { - a += csi_a; - b += csi_b; - if (*a != *b) { - a = skip_zero(a); - b = skip_zero(b); + TR(TRACE_DATABASE, ("similar_sgr:\n\t%s\n\t%s", + _nc_visbuf2(1, a), + _nc_visbuf2(2, b))); + if (csi_a != 0 && csi_b != 0 && csi_a == csi_b) { + a += csi_a; + b += csi_b; + if (*a != *b) { + a = skip_zero(a); + b = skip_zero(b); + } } + len_a = strlen(a); + len_b = strlen(b); + if (len_a && len_b) { + if (len_a > len_b) + result = (strncmp(a, b, len_b) == 0); + else + result = (strncmp(a, b, len_a) == 0); + } + TR(TRACE_DATABASE, ("...similar_sgr: %d\n\t%s\n\t%s", result, + _nc_visbuf2(1, a), + _nc_visbuf2(2, b))); } - len_a = strlen(a); - len_b = strlen(b); - if (len_a && len_b) { - if (len_a > len_b) - result = (strncmp(a, b, len_b) == 0); - else - result = (strncmp(a, b, len_a) == 0); - } - TR(TRACE_DATABASE, ("...similar_sgr: %d\n\t%s\n\t%s", result, - _nc_visbuf2(1, a), - _nc_visbuf2(2, b))); return result; } @@ -172,13 +181,13 @@ chop_out(char *string, unsigned i, unsigned j) * Returns the number of chars from 'full' that we matched. If any mismatch * occurs, return zero. */ -static int +static unsigned compare_part(const char *part, const char *full) { const char *next_part; const char *next_full; - int used_full = 0; - int used_delay = 0; + unsigned used_full = 0; + unsigned used_delay = 0; while (*part != 0) { if (*part != *full) { @@ -201,7 +210,7 @@ compare_part(const char *part, const char *full) next_part = skip_delay(part); next_full = skip_delay(full); if (next_part != part && next_full != full) { - used_delay += (next_full - full); + used_delay += (unsigned) (next_full - full); full = next_full; part = next_part; continue; @@ -215,7 +224,7 @@ compare_part(const char *part, const char *full) } /* - * While 'sgr0' is the "same" as termcap 'me', there is a compatibility issue. + * While 'sgr0' is the "same" as termcap 'me', there is a compatibility issue. * The sgr/sgr0 capabilities include setting/clearing alternate character set * mode. A termcap application cannot use sgr, so sgr0 strings that reset * alternate character set mode will be misinterpreted. Here, we remove those @@ -226,7 +235,7 @@ compare_part(const char *part, const char *full) * an error occurs, or the original sgr0 if no change is needed. */ NCURSES_EXPORT(char *) -_nc_trim_sgr0(TERMTYPE *tp) +_nc_trim_sgr0(TERMTYPE2 *tp) { char *result = exit_attribute_mode; @@ -257,16 +266,17 @@ _nc_trim_sgr0(TERMTYPE *tp) /* * If rmacs is a substring of sgr(0), remove that chunk. */ - if (exit_alt_charset_mode != 0) { + if (PRESENT(exit_alt_charset_mode)) { TR(TRACE_DATABASE, ("scan for rmacs %s", _nc_visbuf(exit_alt_charset_mode))); j = strlen(off); k = strlen(exit_alt_charset_mode); if (j > k) { for (i = 0; i <= (j - k); ++i) { - int k2 = compare_part(exit_alt_charset_mode, off + i); + unsigned k2 = compare_part(exit_alt_charset_mode, + off + i); if (k2 != 0) { found = TRUE; - chop_out(off, i, i + k2); + chop_out(off, (unsigned) i, (unsigned) (i + k2)); break; } } @@ -276,18 +286,18 @@ _nc_trim_sgr0(TERMTYPE *tp) * SGR 10 would reset to normal font. */ if (!found) { - if ((i = is_csi(off)) != 0 + if ((i = (size_t) is_csi(off)) != 0 && off[strlen(off) - 1] == 'm') { TR(TRACE_DATABASE, ("looking for SGR 10 in %s", _nc_visbuf(off))); tmp = skip_zero(off + i); if (tmp[0] == '1' && skip_zero(tmp + 1) != tmp + 1) { - i = tmp - off; + i = (size_t) (tmp - off); if (off[i - 1] == ';') i--; - j = skip_zero(tmp + 1) - off; - i = chop_out(off, i, j); + j = (size_t) (skip_zero(tmp + 1) - off); + (void) chop_out(off, (unsigned) i, (unsigned) j); found = TRUE; } } @@ -295,10 +305,10 @@ _nc_trim_sgr0(TERMTYPE *tp) if (!found && (tmp = strstr(end, off)) != 0 && strcmp(end, off) != 0) { - i = tmp - end; + i = (size_t) (tmp - end); j = strlen(off); tmp = strdup(end); - chop_out(tmp, i, j); + chop_out(tmp, (unsigned) i, (unsigned) j); free(off); result = tmp; } diff --git a/lib/libcurses/tinfo/use_screen.c b/lib/libcurses/tinfo/use_screen.c index 2d79e734601..f3720cede93 100644 --- a/lib/libcurses/tinfo/use_screen.c +++ b/lib/libcurses/tinfo/use_screen.c @@ -1,7 +1,8 @@ -/* $OpenBSD: use_screen.c,v 1.1 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: use_screen.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2007,2008 Free Software Foundation, Inc. * + * Copyright 2018,2020 Thomas E. Dickey * + * Copyright 2007-2009,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -34,22 +35,26 @@ #include -MODULE_ID("$Id: use_screen.c,v 1.1 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: use_screen.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) use_screen(SCREEN *screen, NCURSES_SCREEN_CB func, void *data) { SCREEN *save_SP; int code = OK; + TR_FUNC_BFR(1); - T((T_CALLED("use_screen(%p,%p,%p)"), screen, func, data)); + T((T_CALLED("use_screen(%p,%s,%p)"), + (void *) screen, + TR_FUNC_ARG(0, func), + (void *) data)); /* * FIXME - add a flag so a given thread can check if _it_ has already * recurred through this point, return an error if so. */ _nc_lock_global(curses); - save_SP = SP; + save_SP = CURRENT_SCREEN; set_term(screen); code = func(screen, data); diff --git a/lib/libcurses/tinfo/write_entry.c b/lib/libcurses/tinfo/write_entry.c index 4f28313b905..2d92e8b1af1 100644 --- a/lib/libcurses/tinfo/write_entry.c +++ b/lib/libcurses/tinfo/write_entry.c @@ -1,7 +1,8 @@ -/* $OpenBSD: write_entry.c,v 1.13 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: write_entry.c,v 1.14 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -41,49 +42,76 @@ #include #include -#include - #include -#include -#ifndef S_ISDIR -#define S_ISDIR(mode) ((mode & S_IFMT) == S_IFDIR) -#endif +MODULE_ID("$Id: write_entry.c,v 1.14 2023/10/17 09:52:09 nicm Exp $") #if 1 #define TRACE_OUT(p) DEBUG(2, p) +#define TRACE_NUM(n) if (VALID_NUMERIC(Numbers[n])) { \ + TRACE_OUT(("put Numbers[%u]=%d", (unsigned) (n), Numbers[n])); } #else #define TRACE_OUT(p) /*nothing */ +#define TRACE_NUM(n) /* nothing */ #endif -MODULE_ID("$Id: write_entry.c,v 1.13 2010/01/12 23:22:06 nicm Exp $") +/* + * FIXME: special case to work around Cygwin bug in link(), which updates + * the target file's timestamp. + */ +#if HAVE_LINK && !USE_SYMLINKS && !MIXEDCASE_FILENAMES && defined(__CYGWIN__) +#define LINK_TOUCHES 1 +#else +#define LINK_TOUCHES 0 +#endif static int total_written; +static int total_parts; +static int total_size; static int make_db_root(const char *); -static int write_object(TERMTYPE *, char *, unsigned *, unsigned); #if !USE_HASHED_DB static void -write_file(char *filename, TERMTYPE *tp) +write_file(char *filename, TERMTYPE2 *tp) { char buffer[MAX_ENTRY_SIZE]; unsigned limit = sizeof(buffer); unsigned offset = 0; - FILE *fp = (_nc_access(filename, W_OK) == 0) ? fopen(filename, "wb") : 0; - if (fp == 0) { - perror(filename); - _nc_syserr_abort("can't open %s/%s", _nc_tic_dir(0), filename); - } - DEBUG(1, ("Created %s", filename)); + if (_nc_write_object(tp, buffer, &offset, limit) == ERR) { + _nc_warning("entry is larger than %u bytes", limit); + } else { + FILE *fp = ((_nc_access(filename, W_OK) == 0) + ? safe_fopen(filename, BIN_W) + : 0); + size_t actual; + + if (fp == 0) { + perror(filename); + _nc_syserr_abort("cannot open %s/%s", _nc_tic_dir(0), filename); + } - if (write_object(tp, buffer, &offset, limit) == ERR - || fwrite(buffer, sizeof(char), offset, fp) != offset) { - _nc_syserr_abort("error writing %s/%s", _nc_tic_dir(0), filename); + actual = fwrite(buffer, sizeof(char), (size_t) offset, fp); + if (actual != offset) { + int myerr = ferror(fp) ? errno : 0; + if (myerr) { + _nc_syserr_abort("error writing %s/%s: %s", + _nc_tic_dir(NULL), + filename, + strerror(myerr)); + } else { + _nc_syserr_abort("error writing %s/%s: %u bytes vs actual %lu", + _nc_tic_dir(NULL), + filename, + offset, + (unsigned long) actual); + } + } else { + fclose(fp); + DEBUG(1, ("Created %s", filename)); + } } - - fclose(fp); } /* @@ -102,50 +130,49 @@ check_writeable(int code) char dir[sizeof(LEAF_FMT)]; char *s = 0; - if (code == 0 || (s = strchr(dirnames, code)) == 0) + if (code == 0 || (s = (strchr) (dirnames, code)) == 0) { _nc_err_abort("Illegal terminfo subdirectory \"" LEAF_FMT "\"", code); - - if (verified[s - dirnames]) - return; - - snprintf(dir, sizeof(dir), LEAF_FMT, code); - if (make_db_root(dir) < 0) { - _nc_err_abort("%s/%s: permission denied", _nc_tic_dir(0), dir); + } else if (!verified[s - dirnames]) { + _nc_SPRINTF(dir, _nc_SLIMIT(sizeof(dir)) LEAF_FMT, code); + if (make_db_root(dir) < 0) { + _nc_err_abort("%s/%s: permission denied", _nc_tic_dir(NULL), dir); + } else { + verified[s - dirnames] = TRUE; + } } - - verified[s - dirnames] = TRUE; } #endif /* !USE_HASHED_DB */ static int -make_db_path(char *dst, const char *src, unsigned limit) +make_db_path(char *dst, const char *src, size_t limit) { int rc = -1; - const char *top = _nc_tic_dir(0); + const char *top = _nc_tic_dir(NULL); if (src == top || _nc_is_abs_path(src)) { if (strlen(src) + 1 <= limit) { - (void) strlcpy(dst, src, limit); + _nc_STRCPY(dst, src, limit); rc = 0; } } else { - if (strlen(top) + strlen(src) + 2 <= limit) { - (void) snprintf(dst, limit, "%s/%s", top, src); + if ((strlen(top) + strlen(src) + 6) <= limit) { + _nc_SPRINTF(dst, _nc_SLIMIT(limit) "%s/%s", top, src); rc = 0; } } #if USE_HASHED_DB if (rc == 0) { - if (_nc_is_dir_path(dst)) { - rc = -1; - } else { - unsigned have = strlen(dst); - if (have > 3 && strcmp(dst + have - 3, DBM_SUFFIX)) { - if (have + 3 <= limit) - strlcat(dst, DBM_SUFFIX, limit); - else - rc = -1; + static const char suffix[] = DBM_SUFFIX; + size_t have = strlen(dst); + size_t need = strlen(suffix); + if (have > need && strcmp(dst + (int) (have - need), suffix)) { + if (have + need <= limit) { + _nc_STRCAT(dst, suffix, limit); + } else { + rc = -1; } + } else if (_nc_is_dir_path(dst)) { + rc = -1; } } #endif @@ -165,15 +192,20 @@ make_db_root(const char *path) #if USE_HASHED_DB DB *capdbp; - if ((capdbp = _nc_db_open(fullpath, TRUE)) == NULL) + if ((capdbp = _nc_db_open(fullpath, TRUE)) == NULL) { rc = -1; - else if (_nc_db_close(capdbp) < 0) + } else if (_nc_db_close(capdbp) < 0) { rc = -1; + } #else struct stat statbuf; - if ((rc = stat(path, &statbuf)) < 0) { - rc = mkdir(path, 0777); + if ((rc = stat(path, &statbuf)) == -1) { + rc = mkdir(path +#ifndef _NC_WINDOWS + ,0777 +#endif + ); } else if (_nc_access(path, R_OK | W_OK | X_OK) < 0) { rc = -1; /* permission denied */ } else if (!(S_ISDIR(statbuf.st_mode))) { @@ -188,27 +220,34 @@ make_db_root(const char *path) * Set the write directory for compiled entries. */ NCURSES_EXPORT(void) -_nc_set_writedir(char *dir) +_nc_set_writedir(const char *dir) { const char *destination; char actual[PATH_MAX]; + bool specific = (dir != NULL); - if (dir == 0 - && use_terminfo_vars()) + if (!specific && use_terminfo_vars()) dir = getenv("TERMINFO"); - if (dir != 0) + if (dir != NULL) (void) _nc_tic_dir(dir); - destination = _nc_tic_dir(0); + destination = _nc_tic_dir(NULL); if (make_db_root(destination) < 0) { - char *home = _nc_home_terminfo(); + bool success = FALSE; - if (home != 0) { - destination = home; - if (make_db_root(destination) < 0) - _nc_err_abort("%s: permission denied (errno %d)", - destination, errno); + if (!specific) { + char *home = _nc_home_terminfo(); + + if (home != NULL) { + destination = home; + if (make_db_root(destination) == 0) + success = TRUE; + } + } + if (!success) { + _nc_err_abort("%s: permission denied (errno %d)", + destination, errno); } } @@ -220,10 +259,10 @@ _nc_set_writedir(char *dir) make_db_path(actual, destination, sizeof(actual)); #else if (chdir(_nc_tic_dir(destination)) < 0 - || getcwd(actual, sizeof(actual)) == 0) + || getcwd(actual, sizeof(actual)) == NULL) _nc_err_abort("%s: not a directory", destination); #endif - _nc_keep_tic_dir(strdup(actual)); + _nc_keep_tic_dir(actual); } /* @@ -247,7 +286,7 @@ _nc_set_writedir(char *dir) */ NCURSES_EXPORT(void) -_nc_write_entry(TERMTYPE *const tp) +_nc_write_entry(TERMTYPE2 *const tp) { #if USE_HASHED_DB @@ -268,6 +307,9 @@ _nc_write_entry(TERMTYPE *const tp) #endif #endif /* USE_SYMLINKS */ + unsigned limit2 = sizeof(filename) - (2 + LEAF_LEN); + char saved = '\0'; + static int call_count; static time_t start_time; /* time at start of writes */ @@ -276,16 +318,21 @@ _nc_write_entry(TERMTYPE *const tp) char name_list[MAX_TERMINFO_LENGTH]; char *first_name, *other_names; char *ptr; + char *term_names = tp->term_names; + size_t name_size = strlen(term_names); - assert(strlen(tp->term_names) != 0); - assert(strlen(tp->term_names) < sizeof(name_list)); + if (name_size == 0) { + _nc_syserr_abort("no terminal name found."); + } else if (name_size >= sizeof(name_list) - 1) { + _nc_syserr_abort("terminal name too long: %s", term_names); + } - (void) strlcpy(name_list, tp->term_names, sizeof(name_list)); + _nc_STRCPY(name_list, term_names, sizeof(name_list)); DEBUG(7, ("Name list = '%s'", name_list)); first_name = name_list; - ptr = &name_list[strlen(name_list) - 1]; + ptr = &name_list[name_size - 1]; other_names = ptr + 1; while (ptr > name_list && *ptr != '|') @@ -294,8 +341,9 @@ _nc_write_entry(TERMTYPE *const tp) if (ptr != name_list) { *ptr = '\0'; - for (ptr = name_list; *ptr != '\0' && *ptr != '|'; ptr++) - continue; + for (ptr = name_list; *ptr != '\0' && *ptr != '|'; ptr++) { + /* EMPTY */ ; + } if (*ptr == '\0') other_names = ptr; @@ -311,16 +359,16 @@ _nc_write_entry(TERMTYPE *const tp) _nc_set_type(first_name); #if USE_HASHED_DB - if (write_object(tp, buffer + 1, &offset, limit - 1) != ERR) { - DB *capdb = _nc_db_open(_nc_tic_dir(0), TRUE); + if (_nc_write_object(tp, buffer + 1, &offset, limit - 1) != ERR) { + DB *capdb = _nc_db_open(_nc_tic_dir(NULL), TRUE); DBT key, data; - if (capdb != 0) { + if (capdb != NULL) { buffer[0] = 0; memset(&key, 0, sizeof(key)); - key.data = tp->term_names; - key.size = strlen(tp->term_names); + key.data = term_names; + key.size = name_size; memset(&data, 0, sizeof(data)); data.data = buffer; @@ -333,13 +381,18 @@ _nc_write_entry(TERMTYPE *const tp) key.data = name_list; key.size = strlen(name_list); - strlcpy(buffer + 1, tp->term_names, sizeof(buffer) - 1); - data.size = strlen(tp->term_names) + 1; + _nc_STRCPY(buffer + 1, + term_names, + sizeof(buffer) - 1); + data.size = name_size + 1; + total_size += data.size; + total_parts++; _nc_db_put(capdb, &key, &data); while (*other_names != '\0') { ptr = other_names++; + assert(ptr < buffer + sizeof(buffer) - 1); while (*other_names != '|' && *other_names != '\0') other_names++; @@ -349,9 +402,10 @@ _nc_write_entry(TERMTYPE *const tp) key.data = ptr; key.size = strlen(ptr); + total_size += data.size; + total_parts++; _nc_db_put(capdb, &key, &data); } - _nc_db_close(capdb); } } #else /* !USE_HASHED_DB */ @@ -359,10 +413,19 @@ _nc_write_entry(TERMTYPE *const tp) start_time = 0; } - if (strlen(first_name) >= sizeof(filename) - 3) + if (strlen(first_name) >= limit2) { _nc_warning("terminal name too long."); + saved = first_name[limit2]; + first_name[limit2] = '\0'; + } + + _nc_SPRINTF(filename, _nc_SLIMIT(sizeof(filename)) + LEAF_FMT "/%.*s", UChar(first_name[0]), + (int) (sizeof(filename) - (LEAF_LEN + 2)), + first_name); - snprintf(filename, sizeof(filename), LEAF_FMT "/%s", first_name[0], first_name); + if (saved) + first_name[limit2] = saved; /* * Has this primary name been written since the first call to @@ -372,52 +435,78 @@ _nc_write_entry(TERMTYPE *const tp) if (start_time > 0 && stat(filename, &statbuf) >= 0 && statbuf.st_mtime >= start_time) { +#if HAVE_LINK && !USE_SYMLINKS + /* + * If the file has more than one link, the reason for the previous + * write could be that the current primary name used to be an alias for + * the previous entry. In that case, unlink the file so that we will + * not modify the previous entry as we write this one. + */ + if (statbuf.st_nlink > 1) { + _nc_warning("name redefined."); + unlink(filename); + } else { + _nc_warning("name multiply defined."); + } +#else _nc_warning("name multiply defined."); +#endif } check_writeable(first_name[0]); write_file(filename, tp); if (start_time == 0) { - if (stat(filename, &statbuf) < 0 + if (stat(filename, &statbuf) == -1 || (start_time = statbuf.st_mtime) == 0) { _nc_syserr_abort("error obtaining time from %s/%s", - _nc_tic_dir(0), filename); + _nc_tic_dir(NULL), filename); } } while (*other_names != '\0') { ptr = other_names++; - assert(ptr < buffer + sizeof(buffer) - 1); while (*other_names != '|' && *other_names != '\0') other_names++; if (*other_names != '\0') *(other_names++) = '\0'; - if (strlen(ptr) > sizeof(linkname) - 3) { + if (strlen(ptr) > sizeof(linkname) - (2 + LEAF_LEN)) { _nc_warning("terminal alias %s too long.", ptr); continue; } - if (strchr(ptr, '/') != 0) { + if (strchr(ptr, '/') != NULL) { _nc_warning("cannot link alias %s.", ptr); continue; } check_writeable(ptr[0]); - snprintf(linkname, sizeof(linkname), LEAF_FMT "/%s", ptr[0], ptr); + _nc_SPRINTF(linkname, _nc_SLIMIT(sizeof(linkname)) + LEAF_FMT "/%.*s", ptr[0], + (int) sizeof(linkname) - (2 + LEAF_LEN), ptr); if (strcmp(filename, linkname) == 0) { _nc_warning("self-synonym ignored"); - } else if (stat(linkname, &statbuf) >= 0 && - statbuf.st_mtime < start_time) { + } +#if !LINK_TOUCHES + else if (stat(linkname, &statbuf) >= 0 && + statbuf.st_mtime < start_time) { _nc_warning("alias %s multiply defined.", ptr); - } else if (_nc_access(linkname, W_OK) == 0) + } +#endif + else if (_nc_access(linkname, W_OK) == 0) #if HAVE_LINK { int code; #if USE_SYMLINKS - strlcpy(symlinkname, "../", sizeof(symlinkname)); - strlcat(symlinkname, filename, sizeof(symlinkname)); +#define MY_SIZE sizeof(symlinkname) - 1 + if (first_name[0] == linkname[0]) { + _nc_STRNCPY(symlinkname, first_name, MY_SIZE); + } else { + _nc_STRCPY(symlinkname, "../", sizeof(symlinkname)); + _nc_STRNCPY(symlinkname + 3, filename, MY_SIZE - 3); + } + symlinkname[MY_SIZE] = '\0'; #endif /* USE_SYMLINKS */ #if HAVE_REMOVE code = remove(linkname); @@ -444,9 +533,9 @@ _nc_write_entry(TERMTYPE *const tp) write_file(linkname, tp); else { #if MIXEDCASE_FILENAMES - _nc_syserr_abort("can't link %s to %s", filename, linkname); + _nc_syserr_abort("cannot link %s to %s", filename, linkname); #else - _nc_warning("can't link %s to %s (errno=%d)", filename, + _nc_warning("cannot link %s to %s (errno=%d)", filename, linkname, errno); #endif } @@ -461,42 +550,43 @@ _nc_write_entry(TERMTYPE *const tp) #endif /* USE_HASHED_DB */ } -static unsigned +static size_t fake_write(char *dst, unsigned *offset, - unsigned limit, + size_t limit, char *src, - unsigned want, - unsigned size) + size_t want, + size_t size) { - int have = (limit - *offset); + size_t have = (limit - *offset); want *= size; if (have > 0) { - if ((int) want > have) + if (want > have) want = have; memcpy(dst + *offset, src, want); - *offset += want; + *offset += (unsigned) want; } else { want = 0; } - return (int) (want / size); + return (want / size); } -#define Write(buf, size, count) fake_write(buffer, offset, limit, (char *) buf, count, size) +#define Write(buf, size, count) fake_write(buffer, offset, (size_t) limit, (char *) buf, (size_t) count, (size_t) size) #undef LITTLE_ENDIAN /* BSD/OS defines this as a feature macro */ #define HI(x) ((x) / 256) #define LO(x) ((x) % 256) -#define LITTLE_ENDIAN(p, x) (p)[0] = LO(x), (p)[1] = HI(x) +#define LITTLE_ENDIAN(p, x) (p)[0] = (unsigned char)LO(x), \ + (p)[1] = (unsigned char)HI(x) #define WRITE_STRING(str) (Write(str, sizeof(char), strlen(str) + 1) == strlen(str) + 1) static int -compute_offsets(char **Strings, unsigned strmax, short *offsets) +compute_offsets(char **Strings, size_t strmax, short *offsets) { - size_t nextfree = 0; - unsigned i; + int nextfree = 0; + size_t i; for (i = 0; i < strmax; i++) { if (Strings[i] == ABSENT_STRING) { @@ -504,8 +594,8 @@ compute_offsets(char **Strings, unsigned strmax, short *offsets) } else if (Strings[i] == CANCELLED_STRING) { offsets[i] = -2; } else { - offsets[i] = nextfree; - nextfree += strlen(Strings[i]) + 1; + offsets[i] = (short) nextfree; + nextfree += (int) strlen(Strings[i]) + 1; TRACE_OUT(("put Strings[%d]=%s(%d)", (int) i, _nc_visbuf(Strings[i]), (int) nextfree)); } @@ -513,10 +603,10 @@ compute_offsets(char **Strings, unsigned strmax, short *offsets) return nextfree; } -static void -convert_shorts(unsigned char *buf, short *Numbers, unsigned count) +static size_t +convert_shorts(unsigned char *buf, short *Numbers, size_t count) { - unsigned i; + size_t i; for (i = 0; i < count; i++) { if (Numbers[i] == ABSENT_NUMERIC) { /* HI/LO won't work */ buf[2 * i] = buf[2 * i + 1] = 0377; @@ -525,20 +615,55 @@ convert_shorts(unsigned char *buf, short *Numbers, unsigned count) buf[2 * i + 1] = 0377; } else { LITTLE_ENDIAN(buf + 2 * i, Numbers[i]); - TRACE_OUT(("put Numbers[%d]=%d", i, Numbers[i])); + TRACE_OUT(("put Numbers[%u]=%d", (unsigned) i, Numbers[i])); + } + } + return SIZEOF_SHORT; +} + +#if NCURSES_EXT_NUMBERS +static size_t +convert_16bit(unsigned char *buf, NCURSES_INT2 *Numbers, size_t count) +{ + size_t i, j; + size_t size = SIZEOF_SHORT; + for (i = 0; i < count; i++) { + unsigned value = (unsigned) Numbers[i]; + TRACE_NUM(i); + for (j = 0; j < size; ++j) { + *buf++ = value & 0xff; + value >>= 8; + } + } + return size; +} + +static size_t +convert_32bit(unsigned char *buf, NCURSES_INT2 *Numbers, size_t count) +{ + size_t i, j; + size_t size = SIZEOF_INT2; + for (i = 0; i < count; i++) { + unsigned value = (unsigned) Numbers[i]; + TRACE_NUM(i); + for (j = 0; j < size; ++j) { + *buf++ = value & 0xff; + value >>= 8; } } + return size; } +#endif #define even_boundary(value) \ ((value) % 2 != 0 && Write(&zero, sizeof(char), 1) != 1) #if NCURSES_XNAMES static unsigned -extended_Booleans(TERMTYPE *tp) +extended_Booleans(TERMTYPE2 *tp) { - unsigned short result = 0; - unsigned short i; + unsigned result = 0; + unsigned i; for (i = 0; i < tp->ext_Booleans; ++i) { if (tp->Booleans[BOOLCOUNT + i] == TRUE) @@ -548,10 +673,10 @@ extended_Booleans(TERMTYPE *tp) } static unsigned -extended_Numbers(TERMTYPE *tp) +extended_Numbers(TERMTYPE2 *tp) { - unsigned short result = 0; - unsigned short i; + unsigned result = 0; + unsigned i; for (i = 0; i < tp->ext_Numbers; ++i) { if (tp->Numbers[NUMCOUNT + i] != ABSENT_NUMERIC) @@ -561,14 +686,14 @@ extended_Numbers(TERMTYPE *tp) } static unsigned -extended_Strings(TERMTYPE *tp) +extended_Strings(TERMTYPE2 *tp) { unsigned short result = 0; unsigned short i; for (i = 0; i < tp->ext_Strings; ++i) { if (tp->Strings[STRCOUNT + i] != ABSENT_STRING) - result = (i + 1); + result = (unsigned short) (i + 1); } return result; } @@ -578,7 +703,7 @@ extended_Strings(TERMTYPE *tp) * clause - discard the unneeded data. */ static bool -extended_object(TERMTYPE *tp) +extended_object(TERMTYPE2 *tp) { bool result = FALSE; @@ -591,19 +716,25 @@ extended_object(TERMTYPE *tp) } #endif -static int -write_object(TERMTYPE *tp, char *buffer, unsigned *offset, unsigned limit) +NCURSES_EXPORT(int) +_nc_write_object(TERMTYPE2 *tp, char *buffer, unsigned *offset, unsigned limit) { char *namelist; - size_t namelen, boolmax, nummax, strmax; + size_t namelen, boolmax, nummax, strmax, numlen; char zero = '\0'; size_t i; - short nextfree; + int nextfree; short offsets[MAX_ENTRY_SIZE / 2]; unsigned char buf[MAX_ENTRY_SIZE]; unsigned last_bool = BOOLWRITE; unsigned last_num = NUMWRITE; unsigned last_str = STRWRITE; +#if NCURSES_EXT_NUMBERS + bool need_ints = FALSE; + size_t (*convert_numbers) (unsigned char *, NCURSES_INT2 *, size_t); +#else +#define convert_numbers convert_shorts +#endif #if NCURSES_XNAMES /* @@ -624,14 +755,21 @@ write_object(TERMTYPE *tp, char *buffer, unsigned *offset, unsigned limit) boolmax = 0; for (i = 0; i < last_bool; i++) { - if (tp->Booleans[i] == TRUE) + if (tp->Booleans[i] == TRUE) { boolmax = i + 1; + } } nummax = 0; for (i = 0; i < last_num; i++) { - if (tp->Numbers[i] != ABSENT_NUMERIC) + if (tp->Numbers[i] != ABSENT_NUMERIC) { nummax = i + 1; +#if NCURSES_EXT_NUMBERS + if (tp->Numbers[i] > MAX_OF_TYPE(NCURSES_COLOR_T)) { + need_ints = TRUE; + } +#endif + } } strmax = 0; @@ -643,7 +781,17 @@ write_object(TERMTYPE *tp, char *buffer, unsigned *offset, unsigned limit) nextfree = compute_offsets(tp->Strings, strmax, offsets); /* fill in the header */ +#if NCURSES_EXT_NUMBERS + if (need_ints) { + convert_numbers = convert_32bit; + LITTLE_ENDIAN(buf, MAGIC2); + } else { + convert_numbers = convert_16bit; + LITTLE_ENDIAN(buf, MAGIC); + } +#else LITTLE_ENDIAN(buf, MAGIC); +#endif LITTLE_ENDIAN(buf + 2, min(namelen, MAX_NAME_SIZE + 1)); LITTLE_ENDIAN(buf + 4, boolmax); LITTLE_ENDIAN(buf + 6, nummax); @@ -653,62 +801,81 @@ write_object(TERMTYPE *tp, char *buffer, unsigned *offset, unsigned limit) /* write out the header */ TRACE_OUT(("Header of %s @%d", namelist, *offset)); if (Write(buf, 12, 1) != 1 - || Write(namelist, sizeof(char), namelen) != namelen) - return (ERR); + || Write(namelist, sizeof(char), namelen) != namelen) { + return (ERR); + } - for (i = 0; i < boolmax; i++) - if (tp->Booleans[i] == TRUE) + for (i = 0; i < boolmax; i++) { + if (tp->Booleans[i] == TRUE) { buf[i] = TRUE; - else + } else { buf[i] = FALSE; - if (Write(buf, sizeof(char), boolmax) != boolmax) - return (ERR); + } + } + if (Write(buf, sizeof(char), boolmax) != boolmax) { + return (ERR); + } - if (even_boundary(namelen + boolmax)) + if (even_boundary(namelen + boolmax)) { return (ERR); + } TRACE_OUT(("Numerics begin at %04x", *offset)); /* the numerics */ - convert_shorts(buf, tp->Numbers, nummax); - if (Write(buf, 2, nummax) != nummax) + numlen = convert_numbers(buf, tp->Numbers, nummax); + if (Write(buf, numlen, nummax) != nummax) { return (ERR); + } TRACE_OUT(("String offsets begin at %04x", *offset)); /* the string offsets */ convert_shorts(buf, offsets, strmax); - if (Write(buf, 2, strmax) != strmax) + if (Write(buf, SIZEOF_SHORT, strmax) != strmax) { return (ERR); + } TRACE_OUT(("String table begins at %04x", *offset)); /* the strings */ - for (i = 0; i < strmax; i++) - if (VALID_STRING(tp->Strings[i])) - if (!WRITE_STRING(tp->Strings[i])) + for (i = 0; i < strmax; i++) { + if (VALID_STRING(tp->Strings[i])) { + if (!WRITE_STRING(tp->Strings[i])) { return (ERR); + } + } + } #if NCURSES_XNAMES if (extended_object(tp)) { - unsigned extcnt = NUM_EXT_NAMES(tp); + unsigned ext_total = (unsigned) NUM_EXT_NAMES(tp); + unsigned ext_usage = ext_total; - if (even_boundary(nextfree)) + if (even_boundary(nextfree)) { return (ERR); + } nextfree = compute_offsets(tp->Strings + STRCOUNT, - tp->ext_Strings, + (size_t) tp->ext_Strings, offsets); TRACE_OUT(("after extended string capabilities, nextfree=%d", nextfree)); - if (tp->ext_Strings >= SIZEOF(offsets)) + if (tp->ext_Strings >= SIZEOF(offsets)) { return (ERR); + } nextfree += compute_offsets(tp->ext_Names, - extcnt, + (size_t) ext_total, offsets + tp->ext_Strings); TRACE_OUT(("after extended capnames, nextfree=%d", nextfree)); - strmax = tp->ext_Strings + extcnt; + strmax = tp->ext_Strings + ext_total; + for (i = 0; i < tp->ext_Strings; ++i) { + if (VALID_STRING(tp->Strings[i + STRCOUNT])) { + ext_usage++; + } + } + TRACE_OUT(("will write %u/%lu strings", ext_usage, (unsigned long) strmax)); /* * Write the extended header @@ -716,26 +883,30 @@ write_object(TERMTYPE *tp, char *buffer, unsigned *offset, unsigned limit) LITTLE_ENDIAN(buf + 0, tp->ext_Booleans); LITTLE_ENDIAN(buf + 2, tp->ext_Numbers); LITTLE_ENDIAN(buf + 4, tp->ext_Strings); - LITTLE_ENDIAN(buf + 6, strmax); + LITTLE_ENDIAN(buf + 6, ext_usage); LITTLE_ENDIAN(buf + 8, nextfree); TRACE_OUT(("WRITE extended-header @%d", *offset)); - if (Write(buf, 10, 1) != 1) + if (Write(buf, 10, 1) != 1) { return (ERR); + } TRACE_OUT(("WRITE %d booleans @%d", tp->ext_Booleans, *offset)); if (tp->ext_Booleans && Write(tp->Booleans + BOOLCOUNT, sizeof(char), - tp->ext_Booleans) != tp->ext_Booleans) - return (ERR); + tp->ext_Booleans) != tp->ext_Booleans) { + return (ERR); + } - if (even_boundary(tp->ext_Booleans)) + if (even_boundary(tp->ext_Booleans)) { return (ERR); + } TRACE_OUT(("WRITE %d numbers @%d", tp->ext_Numbers, *offset)); if (tp->ext_Numbers) { - convert_shorts(buf, tp->Numbers + NUMCOUNT, tp->ext_Numbers); - if (Write(buf, 2, tp->ext_Numbers) != tp->ext_Numbers) + numlen = convert_numbers(buf, tp->Numbers + NUMCOUNT, (size_t) tp->ext_Numbers); + if (Write(buf, numlen, tp->ext_Numbers) != tp->ext_Numbers) { return (ERR); + } } /* @@ -744,8 +915,9 @@ write_object(TERMTYPE *tp, char *buffer, unsigned *offset, unsigned limit) */ convert_shorts(buf, offsets, strmax); TRACE_OUT(("WRITE offsets @%d", *offset)); - if (Write(buf, 2, strmax) != strmax) + if (Write(buf, SIZEOF_SHORT, strmax) != strmax) { return (ERR); + } /* * Write the string table after the offset tables so we do not @@ -755,24 +927,28 @@ write_object(TERMTYPE *tp, char *buffer, unsigned *offset, unsigned limit) if (VALID_STRING(tp->Strings[i + STRCOUNT])) { TRACE_OUT(("WRITE ext_Strings[%d]=%s", (int) i, _nc_visbuf(tp->Strings[i + STRCOUNT]))); - if (!WRITE_STRING(tp->Strings[i + STRCOUNT])) + if (!WRITE_STRING(tp->Strings[i + STRCOUNT])) { return (ERR); + } } } /* * Write the extended names */ - for (i = 0; i < extcnt; i++) { + for (i = 0; i < ext_total; i++) { TRACE_OUT(("WRITE ext_Names[%d]=%s", (int) i, tp->ext_Names[i])); - if (!WRITE_STRING(tp->ext_Names[i])) + if (!WRITE_STRING(tp->ext_Names[i])) { return (ERR); + } } } #endif /* NCURSES_XNAMES */ total_written++; + total_parts++; + total_size = total_size + (int) (*offset + 1); return (OK); } @@ -782,5 +958,7 @@ write_object(TERMTYPE *tp, char *buffer, unsigned *offset, unsigned limit) NCURSES_EXPORT(int) _nc_tic_written(void) { + TR(TRACE_DATABASE, ("_nc_tic_written %d entries, %d parts, %d size", + total_written, total_parts, total_size)); return total_written; } diff --git a/lib/libcurses/trace/lib_trace.c b/lib/libcurses/trace/lib_trace.c index ed8d45dd9e7..363b04c733e 100644 --- a/lib/libcurses/trace/lib_trace.c +++ b/lib/libcurses/trace/lib_trace.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_trace.c,v 1.8 2010/01/12 23:22:06 nicm Exp $ */ +/* $OpenBSD: lib_trace.c,v 1.9 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,12 +33,13 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer * ****************************************************************************/ /* * lib_trace.c - Tracing/Debugging routines * - * The _tracef() function is originally from pcurses (by Pavel Curtis) in 1982. + * The _tracef() function is originally from pcurses (by Pavel Curtis) in 1982. * pcurses allowed one to enable/disable tracing using traceon() and traceoff() * functions. ncurses provides a trace() function which allows one to * selectively enable or disable several tracing features. @@ -48,7 +50,7 @@ #include -MODULE_ID("$Id: lib_trace.c,v 1.8 2010/01/12 23:22:06 nicm Exp $") +MODULE_ID("$Id: lib_trace.c,v 1.9 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT_VAR(unsigned) _nc_tracing = 0; /* always define this */ @@ -58,26 +60,26 @@ NCURSES_EXPORT_VAR(unsigned) _nc_tracing = 0; /* always define this */ NCURSES_EXPORT(const char *) NCURSES_PUBLIC_VAR(_nc_tputs_trace) (void) { - return SP ? SP->_tputs_trace : _nc_prescreen._tputs_trace; + return CURRENT_SCREEN ? CURRENT_SCREEN->_tputs_trace : _nc_prescreen._tputs_trace; } NCURSES_EXPORT(long) NCURSES_PUBLIC_VAR(_nc_outchars) (void) { - return SP ? SP->_outchars : _nc_prescreen._outchars; + return CURRENT_SCREEN ? CURRENT_SCREEN->_outchars : _nc_prescreen._outchars; } NCURSES_EXPORT(void) _nc_set_tputs_trace(const char *s) { - if (SP) - SP->_tputs_trace = s; + if (CURRENT_SCREEN) + CURRENT_SCREEN->_tputs_trace = s; else _nc_prescreen._tputs_trace = s; } NCURSES_EXPORT(void) _nc_count_outchars(long increment) { - if (SP) - SP->_outchars += increment; + if (CURRENT_SCREEN) + CURRENT_SCREEN->_outchars += increment; else _nc_prescreen._outchars += increment; } @@ -86,60 +88,138 @@ NCURSES_EXPORT_VAR(const char *) _nc_tputs_trace = ""; NCURSES_EXPORT_VAR(long) _nc_outchars = 0; #endif -#define TraceFP _nc_globals.trace_fp -#define TracePath _nc_globals.trace_fname -#define TraceLevel _nc_globals.trace_level +#define MyFP _nc_globals.trace_fp +#define MyFD _nc_globals.trace_fd +#define MyInit _nc_globals.trace_opened +#define MyPath _nc_globals.trace_fname +#define MyLevel _nc_globals.trace_level +#define MyNested _nc_globals.nested_tracef +#endif /* TRACE */ -NCURSES_EXPORT(void) -trace(const unsigned int tracelevel) +#if USE_REENTRANT +#define Locked(statement) \ + do { \ + _nc_lock_global(tst_tracef); \ + statement; \ + _nc_unlock_global(tst_tracef); \ + } while (0) +#else +#define Locked(statement) statement +#endif + +NCURSES_EXPORT(unsigned) +curses_trace(unsigned tracelevel) { - if ((TraceFP == 0) && tracelevel) { - const char *mode = _nc_globals.init_trace ? "ab" : "wb"; - - if (TracePath[0] == '\0') { - int size = sizeof(TracePath) - 12; - if (getcwd(TracePath, size) == 0) { - perror("curses: Can't get working directory"); - exit(EXIT_FAILURE); + unsigned result; + +#if defined(TRACE) + int bit; + +#define DATA(name) { name, #name } + static struct { + unsigned mask; + const char *name; + } trace_names[] = { + DATA(TRACE_TIMES), + DATA(TRACE_TPUTS), + DATA(TRACE_UPDATE), + DATA(TRACE_MOVE), + DATA(TRACE_CHARPUT), + DATA(TRACE_CALLS), + DATA(TRACE_VIRTPUT), + DATA(TRACE_IEVENT), + DATA(TRACE_BITS), + DATA(TRACE_ICALLS), + DATA(TRACE_CCALLS), + DATA(TRACE_DATABASE), + DATA(TRACE_ATTRS) + }; +#undef DATA + + Locked(result = _nc_tracing); + + if ((MyFP == 0) && tracelevel) { + MyInit = TRUE; + if (MyFD >= 0) { + MyFP = fdopen(MyFD, BIN_W); + } else { + if (MyPath[0] == '\0') { + size_t size = sizeof(MyPath) - 12; + if (getcwd(MyPath, size) == 0) { + perror("curses: Can't get working directory"); + exit(EXIT_FAILURE); + } + MyPath[size] = '\0'; + assert(strlen(MyPath) <= size); + _nc_STRCAT(MyPath, "/trace", sizeof(MyPath)); + if (_nc_is_dir_path(MyPath)) { + _nc_STRCAT(MyPath, ".log", sizeof(MyPath)); + } } - TracePath[size] = '\0'; - assert(strlen(TracePath) <= size); - strlcat(TracePath, "/trace", sizeof(TracePath)); - if (_nc_is_dir_path(TracePath)) { - strlcat(TracePath, ".log", sizeof(TracePath)); +#define SAFE_MODE (O_CREAT | O_EXCL | O_RDWR) + if (_nc_access(MyPath, W_OK) < 0 + || (MyFD = safe_open3(MyPath, SAFE_MODE, 0600)) < 0 + || (MyFP = fdopen(MyFD, BIN_W)) == 0) { + ; /* EMPTY */ } } - - _nc_globals.init_trace = TRUE; - _nc_tracing = tracelevel; - if (_nc_access(TracePath, W_OK) < 0 - || (TraceFP = fopen(TracePath, mode)) == 0) { - perror("curses: Can't open 'trace' file"); - exit(EXIT_FAILURE); - } + Locked(_nc_tracing = tracelevel); /* Try to set line-buffered mode, or (failing that) unbuffered, * so that the trace-output gets flushed automatically at the - * end of each line. This is useful in case the program dies. + * end of each line. This is useful in case the program dies. */ + if (MyFP != 0) { #if HAVE_SETVBUF /* ANSI */ - (void) setvbuf(TraceFP, (char *) 0, _IOLBF, 0); -#elif HAVE_SETBUF /* POSIX */ - (void) setbuffer(TraceFP, (char *) 0); + (void) setvbuf(MyFP, (char *) 0, _IOLBF, (size_t) 0); +#elif HAVE_SETBUF /* POSIX */ + (void) setbuffer(MyFP, (char *) 0); #endif + } _tracef("TRACING NCURSES version %s.%d (tracelevel=%#x)", NCURSES_VERSION, NCURSES_VERSION_PATCH, tracelevel); + +#define SPECIAL_MASK(mask) \ + if ((tracelevel & mask) == mask) \ + _tracef("- %s (%u)", #mask, mask) + + for (bit = 0; bit < TRACE_SHIFT; ++bit) { + unsigned mask = (1U << bit) & tracelevel; + if ((mask & trace_names[bit].mask) != 0) { + _tracef("- %s (%u)", trace_names[bit].name, mask); + } + } + SPECIAL_MASK(TRACE_MAXIMUM); + else + SPECIAL_MASK(TRACE_ORDINARY); + + if (tracelevel > TRACE_MAXIMUM) { + _tracef("- DEBUG_LEVEL(%u)", tracelevel >> TRACE_SHIFT); + } } else if (tracelevel == 0) { - if (TraceFP != 0) { - fclose(TraceFP); - TraceFP = 0; + if (MyFP != 0) { + MyFD = dup(MyFD); /* allow reopen of same file */ + fclose(MyFP); + MyFP = 0; } - _nc_tracing = tracelevel; + Locked(_nc_tracing = tracelevel); } else if (_nc_tracing != tracelevel) { - _nc_tracing = tracelevel; + Locked(_nc_tracing = tracelevel); _tracef("tracelevel=%#x", tracelevel); } +#else + (void) tracelevel; + result = 0; +#endif + return result; +} + +#if defined(TRACE) +NCURSES_EXPORT(void) +trace(const unsigned int tracelevel) +{ + curses_trace(tracelevel); } static void @@ -152,16 +232,23 @@ _nc_va_tracef(const char *fmt, va_list ap) bool after = FALSE; unsigned doit = _nc_tracing; int save_err = errno; + FILE *fp = MyFP; + +#ifdef TRACE + /* verbose-trace in the command-line utilities relies on this */ + if (fp == 0 && !MyInit && _nc_tracing >= DEBUG_LEVEL(1)) + fp = stderr; +#endif if (strlen(fmt) >= sizeof(Called) - 1) { if (!strncmp(fmt, Called, sizeof(Called) - 1)) { before = TRUE; - TraceLevel++; + MyLevel++; } else if (!strncmp(fmt, Return, sizeof(Return) - 1)) { after = TRUE; } if (before || after) { - if ((TraceLevel <= 1) + if ((MyLevel <= 1) || (doit & TRACE_ICALLS) != 0) doit &= (TRACE_CALLS | TRACE_CCALLS); else @@ -169,9 +256,7 @@ _nc_va_tracef(const char *fmt, va_list ap) } } - if (doit != 0) { - if (TraceFP == 0) - TraceFP = stderr; + if (doit != 0 && fp != 0) { #ifdef USE_PTHREADS /* * TRACE_ICALLS is "really" needed to show normal use with threaded @@ -185,26 +270,32 @@ _nc_va_tracef(const char *fmt, va_list ap) # if USE_WEAK_SYMBOLS if ((pthread_self)) # endif - fprintf(TraceFP, "%#lx:", (long) (void *) pthread_self()); + fprintf(fp, "%#" PRIxPTR ":", +#ifdef _NC_WINDOWS + CASTxPTR(pthread_self().p) +#else + CASTxPTR(pthread_self()) +#endif + ); #endif if (before || after) { int n; - for (n = 1; n < TraceLevel; n++) - fputs("+ ", TraceFP); + for (n = 1; n < MyLevel; n++) + fputs("+ ", fp); } - vfprintf(TraceFP, fmt, ap); - fputc('\n', TraceFP); - fflush(TraceFP); + vfprintf(fp, fmt, ap); + fputc('\n', fp); + fflush(fp); } - if (after && TraceLevel) - TraceLevel--; + if (after && MyLevel) + MyLevel--; errno = save_err; } NCURSES_EXPORT(void) -_tracef(const char *fmt,...) +_tracef(const char *fmt, ...) { va_list ap; @@ -215,12 +306,20 @@ _tracef(const char *fmt,...) /* Trace 'bool' return-values */ NCURSES_EXPORT(NCURSES_BOOL) -_nc_retrace_bool(NCURSES_BOOL code) +_nc_retrace_bool(int code) { T((T_RETURN("%s"), code ? "TRUE" : "FALSE")); return code; } +/* Trace 'char' return-values */ +NCURSES_EXPORT(char) +_nc_retrace_char(int code) +{ + T((T_RETURN("%c"), code)); + return (char) code; +} + /* Trace 'int' return-values */ NCURSES_EXPORT(int) _nc_retrace_int(int code) @@ -273,7 +372,7 @@ _nc_retrace_void_ptr(void *code) NCURSES_EXPORT(SCREEN *) _nc_retrace_sp(SCREEN *code) { - T((T_RETURN("%p"), code)); + T((T_RETURN("%p"), (void *) code)); return code; } @@ -281,10 +380,43 @@ _nc_retrace_sp(SCREEN *code) NCURSES_EXPORT(WINDOW *) _nc_retrace_win(WINDOW *code) { - T((T_RETURN("%p"), code)); + T((T_RETURN("%p"), (void *) code)); return code; } +NCURSES_EXPORT(char *) +_nc_fmt_funcptr(char *target, const char *source, size_t size) +{ + size_t n; + char *dst = target; + bool leading = TRUE; + + union { + int value; + char bytes[sizeof(int)]; + } byteorder; + + byteorder.value = 0x1234; + + *dst++ = '0'; + *dst++ = 'x'; + + for (n = 0; n < size; ++n) { + unsigned ch = ((byteorder.bytes[0] == 0x34) + ? UChar(source[size - n - 1]) + : UChar(source[n])); + if (ch != 0 || (n + 1) >= size) + leading = FALSE; + if (!leading) { + _nc_SPRINTF(dst, _nc_SLIMIT(TR_FUNC_LEN - (size_t) (dst - target)) + "%02x", ch & 0xff); + dst += 2; + } + } + *dst = '\0'; + return target; +} + #if USE_REENTRANT /* * Check if the given trace-mask is enabled. @@ -299,13 +431,13 @@ _nc_use_tracef(unsigned mask) bool result = FALSE; _nc_lock_global(tst_tracef); - if (!_nc_globals.nested_tracef++) { + if (!MyNested++) { if ((result = (_nc_tracing & (mask))) != 0 && _nc_try_global(tracef) == 0) { /* we will call _nc_locked_tracef(), no nesting so far */ } else { /* we will not call _nc_locked_tracef() */ - _nc_globals.nested_tracef = 0; + MyNested = 0; } } else { /* we may call _nc_locked_tracef(), but with nested_tracef > 0 */ @@ -320,7 +452,7 @@ _nc_use_tracef(unsigned mask) * the tracef mutex. */ NCURSES_EXPORT(void) -_nc_locked_tracef(const char *fmt,...) +_nc_locked_tracef(const char *fmt, ...) { va_list ap; @@ -328,8 +460,9 @@ _nc_locked_tracef(const char *fmt,...) _nc_va_tracef(fmt, ap); va_end(ap); - if (--(_nc_globals.nested_tracef) == 0) + if (--(MyNested) == 0) { _nc_unlock_global(tracef); + } } #endif /* USE_REENTRANT */ diff --git a/lib/libcurses/trace/lib_traceatr.c b/lib/libcurses/trace/lib_traceatr.c deleted file mode 100644 index 34b65f3d7eb..00000000000 --- a/lib/libcurses/trace/lib_traceatr.c +++ /dev/null @@ -1,360 +0,0 @@ -/* $OpenBSD: lib_traceatr.c,v 1.6 2010/01/12 23:22:07 nicm Exp $ */ - -/**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Thomas Dickey 1996-on * - * and: Zeyd M. Ben-Halim 1992,1995 * - * and: Eric S. Raymond * - ****************************************************************************/ - -/* - * lib_traceatr.c - Tracing/Debugging routines (attributes) - */ - -#include -#include /* acs_chars */ - -MODULE_ID("$Id: lib_traceatr.c,v 1.6 2010/01/12 23:22:07 nicm Exp $") - -#define COLOR_OF(c) ((c < 0) ? "default" : (c > 7 ? color_of(c) : colors[c].name)) - -#ifdef TRACE - -static const char l_brace[] = StringOf(L_BRACE); -static const char r_brace[] = StringOf(R_BRACE); - -#ifndef USE_TERMLIB - -#define my_buffer _nc_globals.traceatr_color_buf -#define my_select _nc_globals.traceatr_color_sel -#define my_cached _nc_globals.traceatr_color_last - -static char * -color_of(int c) -{ - if (c != my_cached) { - my_cached = c; - my_select = !my_select; - if (c == COLOR_DEFAULT) - strlcpy(my_buffer[my_select], "default", _nc_globals_traceatr_color_buf_size); - else - snprintf(my_buffer[my_select], _nc_globals_traceatr_color_buf_size, "color%d", c); - } - return my_buffer[my_select]; -} - -#undef my_buffer -#undef my_select -#endif /* !USE_TERMLIB */ - -NCURSES_EXPORT(char *) -_traceattr2(int bufnum, chtype newmode) -{ - static const struct { - unsigned int val; - const char *name; - } names[] = - { - /* *INDENT-OFF* */ - { A_STANDOUT, "A_STANDOUT" }, - { A_UNDERLINE, "A_UNDERLINE" }, - { A_REVERSE, "A_REVERSE" }, - { A_BLINK, "A_BLINK" }, - { A_DIM, "A_DIM" }, - { A_BOLD, "A_BOLD" }, - { A_ALTCHARSET, "A_ALTCHARSET" }, - { A_INVIS, "A_INVIS" }, - { A_PROTECT, "A_PROTECT" }, - { A_CHARTEXT, "A_CHARTEXT" }, - { A_NORMAL, "A_NORMAL" }, - { A_COLOR, "A_COLOR" }, - /* *INDENT-ON* */ - - } -#ifndef USE_TERMLIB - , - colors[] = - { - /* *INDENT-OFF* */ - { COLOR_BLACK, "COLOR_BLACK" }, - { COLOR_RED, "COLOR_RED" }, - { COLOR_GREEN, "COLOR_GREEN" }, - { COLOR_YELLOW, "COLOR_YELLOW" }, - { COLOR_BLUE, "COLOR_BLUE" }, - { COLOR_MAGENTA, "COLOR_MAGENTA" }, - { COLOR_CYAN, "COLOR_CYAN" }, - { COLOR_WHITE, "COLOR_WHITE" }, - /* *INDENT-ON* */ - - } -#endif /* !USE_TERMLIB */ - ; - size_t n; - char temp[80]; - char *result = _nc_trace_buf(bufnum, BUFSIZ); - - if (result != 0) { - unsigned save_nc_tracing = _nc_tracing; - - _nc_tracing = 0; - - strlcpy(result, l_brace, BUFSIZ); - - for (n = 0; n < SIZEOF(names); n++) { - if ((newmode & names[n].val) != 0) { - if (result[1] != '\0') - result = _nc_trace_bufcat(bufnum, "|"); - result = _nc_trace_bufcat(bufnum, names[n].name); - - if (names[n].val == A_COLOR) { - short pairnum = PAIR_NUMBER(newmode); -#ifdef USE_TERMLIB - /* pair_content lives in libncurses */ - (void) snprintf(temp, sizeof(temp), "{%d}", pairnum); -#else - short fg, bg; - - if (pair_content(pairnum, &fg, &bg) == OK) { - (void) snprintf(temp, sizeof(temp), - "{%d = {%s, %s}}", - pairnum, - COLOR_OF(fg), - COLOR_OF(bg)); - } else { - (void) snprintf(temp, sizeof(temp), "{%d}", pairnum); - } -#endif - result = _nc_trace_bufcat(bufnum, temp); - } - } - } - if (ChAttrOf(newmode) == A_NORMAL) { - if (result != 0 && result[1] != '\0') - (void) _nc_trace_bufcat(bufnum, "|"); - (void) _nc_trace_bufcat(bufnum, "A_NORMAL"); - } - - _nc_tracing = save_nc_tracing; - result = _nc_trace_bufcat(bufnum, r_brace); - } - return result; -} - -NCURSES_EXPORT(char *) -_traceattr(attr_t newmode) -{ - return _traceattr2(0, newmode); -} - -/* Trace 'int' return-values */ -NCURSES_EXPORT(attr_t) -_nc_retrace_attr_t(attr_t code) -{ - T((T_RETURN("%s"), _traceattr(code))); - return code; -} - -const char * -_nc_altcharset_name(attr_t attr, chtype ch) -{ - typedef struct { - unsigned int val; - const char *name; - } ALT_NAMES; - static const ALT_NAMES names[] = - { - {'l', "ACS_ULCORNER"}, /* upper left corner */ - {'m', "ACS_LLCORNER"}, /* lower left corner */ - {'k', "ACS_URCORNER"}, /* upper right corner */ - {'j', "ACS_LRCORNER"}, /* lower right corner */ - {'t', "ACS_LTEE"}, /* tee pointing right */ - {'u', "ACS_RTEE"}, /* tee pointing left */ - {'v', "ACS_BTEE"}, /* tee pointing up */ - {'w', "ACS_TTEE"}, /* tee pointing down */ - {'q', "ACS_HLINE"}, /* horizontal line */ - {'x', "ACS_VLINE"}, /* vertical line */ - {'n', "ACS_PLUS"}, /* large plus or crossover */ - {'o', "ACS_S1"}, /* scan line 1 */ - {'s', "ACS_S9"}, /* scan line 9 */ - {'`', "ACS_DIAMOND"}, /* diamond */ - {'a', "ACS_CKBOARD"}, /* checker board (stipple) */ - {'f', "ACS_DEGREE"}, /* degree symbol */ - {'g', "ACS_PLMINUS"}, /* plus/minus */ - {'~', "ACS_BULLET"}, /* bullet */ - {',', "ACS_LARROW"}, /* arrow pointing left */ - {'+', "ACS_RARROW"}, /* arrow pointing right */ - {'.', "ACS_DARROW"}, /* arrow pointing down */ - {'-', "ACS_UARROW"}, /* arrow pointing up */ - {'h', "ACS_BOARD"}, /* board of squares */ - {'i', "ACS_LANTERN"}, /* lantern symbol */ - {'0', "ACS_BLOCK"}, /* solid square block */ - {'p', "ACS_S3"}, /* scan line 3 */ - {'r', "ACS_S7"}, /* scan line 7 */ - {'y', "ACS_LEQUAL"}, /* less/equal */ - {'z', "ACS_GEQUAL"}, /* greater/equal */ - {'{', "ACS_PI"}, /* Pi */ - {'|', "ACS_NEQUAL"}, /* not equal */ - {'}', "ACS_STERLING"}, /* UK pound sign */ - {'\0', (char *) 0} - }; - - const char *result = 0; - - if ((attr & A_ALTCHARSET) && (acs_chars != 0)) { - char *cp; - char *found = 0; - const ALT_NAMES *sp; - - for (cp = acs_chars; cp[0] && cp[1]; cp += 2) { - if (ChCharOf(cp[1]) == ChCharOf(ch)) { - found = cp; - /* don't exit from loop - there may be redefinitions */ - } - } - - if (found != 0) { - ch = ChCharOf(*found); - for (sp = names; sp->val; sp++) - if (sp->val == ch) { - result = sp->name; - break; - } - } - } - return result; -} - -NCURSES_EXPORT(char *) -_tracechtype2(int bufnum, chtype ch) -{ - const char *found; - char *result = _nc_trace_buf(bufnum, BUFSIZ); - - if (result != 0) { - strlcpy(result, l_brace, BUFSIZ); - if ((found = _nc_altcharset_name(ChAttrOf(ch), ch)) != 0) { - (void) _nc_trace_bufcat(bufnum, found); - } else - (void) _nc_trace_bufcat(bufnum, _nc_tracechar(SP, (int) ChCharOf(ch))); - - if (ChAttrOf(ch) != A_NORMAL) { - (void) _nc_trace_bufcat(bufnum, " | "); - (void) _nc_trace_bufcat(bufnum, - _traceattr2(bufnum + 20, ChAttrOf(ch))); - } - - result = _nc_trace_bufcat(bufnum, r_brace); - } - return result; -} - -NCURSES_EXPORT(char *) -_tracechtype(chtype ch) -{ - return _tracechtype2(0, ch); -} - -/* Trace 'chtype' return-values */ -NCURSES_EXPORT(chtype) -_nc_retrace_chtype(chtype code) -{ - T((T_RETURN("%s"), _tracechtype(code))); - return code; -} - -#if USE_WIDEC_SUPPORT -NCURSES_EXPORT(char *) -_tracecchar_t2(int bufnum, const cchar_t *ch) -{ - char *result = _nc_trace_buf(bufnum, BUFSIZ); - attr_t attr; - const char *found; - - if (result != 0) { - strlcpy(result, l_brace, BUFSIZ); - if (ch != 0) { - attr = AttrOfD(ch); - if ((found = _nc_altcharset_name(attr, (chtype) CharOfD(ch))) != 0) { - (void) _nc_trace_bufcat(bufnum, found); - attr &= ~A_ALTCHARSET; - } else if (isWidecExt(CHDEREF(ch))) { - (void) _nc_trace_bufcat(bufnum, "{NAC}"); - attr &= ~A_CHARTEXT; - } else { - PUTC_DATA; - int n; - - PUTC_INIT; - (void) _nc_trace_bufcat(bufnum, "{ "); - for (PUTC_i = 0; PUTC_i < CCHARW_MAX; ++PUTC_i) { - PUTC_ch = ch->chars[PUTC_i]; - if (PUTC_ch == L'\0') - break; - PUTC_n = wcrtomb(PUTC_buf, ch->chars[PUTC_i], &PUT_st); - if (PUTC_n <= 0) { - if (PUTC_ch != L'\0') { - /* it could not be a multibyte sequence */ - (void) _nc_trace_bufcat(bufnum, - _nc_tracechar(SP, - UChar(ch->chars[PUTC_i]))); - } - break; - } - for (n = 0; n < PUTC_n; n++) { - if (n) - (void) _nc_trace_bufcat(bufnum, ", "); - (void) _nc_trace_bufcat(bufnum, - _nc_tracechar(SP, - UChar(PUTC_buf[n]))); - } - } - (void) _nc_trace_bufcat(bufnum, " }"); - } - if (attr != A_NORMAL) { - (void) _nc_trace_bufcat(bufnum, " | "); - (void) _nc_trace_bufcat(bufnum, _traceattr2(bufnum + 20, attr)); - } - } - - result = _nc_trace_bufcat(bufnum, r_brace); - } - return result; -} - -NCURSES_EXPORT(char *) -_tracecchar_t(const cchar_t *ch) -{ - return _tracecchar_t2(0, ch); -} -#endif - -#else -EMPTY_MODULE(_nc_lib_traceatr) -#endif /* TRACE */ diff --git a/lib/libcurses/trace/lib_tracebits.c b/lib/libcurses/trace/lib_tracebits.c deleted file mode 100644 index 4905807f11f..00000000000 --- a/lib/libcurses/trace/lib_tracebits.c +++ /dev/null @@ -1,271 +0,0 @@ -/* $OpenBSD: lib_tracebits.c,v 1.10 2010/01/12 23:22:07 nicm Exp $ */ - -/**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Zeyd M. Ben-Halim 1992,1995 * - * and: Eric S. Raymond * - * and: Thomas E. Dickey 1996-on * - ****************************************************************************/ - -#include -#include /* cur_term */ - -MODULE_ID("$Id: lib_tracebits.c,v 1.10 2010/01/12 23:22:07 nicm Exp $") - -#if SVR4_TERMIO && !defined(_POSIX_SOURCE) -#define _POSIX_SOURCE -#endif - -#if HAVE_SYS_TERMIO_H -#include /* needed for ISC */ -#endif - -#ifdef __EMX__ -#include -#endif - -/* may be undefined if we're using termio.h */ -#ifndef TOSTOP -#define TOSTOP 0 -#endif - -#ifndef IEXTEN -#define IEXTEN 0 -#endif - -#ifndef ONLCR -#define ONLCR 0 -#endif - -#ifndef OCRNL -#define OCRNL 0 -#endif - -#ifndef ONOCR -#define ONOCR 0 -#endif - -#ifndef ONLRET -#define ONLRET 0 -#endif - -#ifdef TRACE - -typedef struct { - unsigned int val; - const char *name; -} BITNAMES; - -static void -lookup_bits(char *buf, size_t bufsize, const BITNAMES * table, const char *label, unsigned int val) -{ - const BITNAMES *sp; - - (void) strlcat(buf, label, bufsize); - (void) strlcat(buf, ": {", bufsize); - for (sp = table; sp->name; sp++) - if (sp->val != 0 - && (val & sp->val) == sp->val) { - (void) strlcat(buf, sp->name, bufsize); - (void) strlcat(buf, ", ", bufsize); - } - if (buf[strlen(buf) - 2] == ',') - buf[strlen(buf) - 2] = '\0'; - (void) strlcat(buf, "} ", bufsize); -} - -NCURSES_EXPORT(char *) -_nc_trace_ttymode(TTY * tty) -/* describe the state of the terminal control bits exactly */ -{ - char *buf; - size_t bufsize; - -#ifdef TERMIOS - static const BITNAMES iflags[] = - { - {BRKINT, "BRKINT"}, - {IGNBRK, "IGNBRK"}, - {IGNPAR, "IGNPAR"}, - {PARMRK, "PARMRK"}, - {INPCK, "INPCK"}, - {ISTRIP, "ISTRIP"}, - {INLCR, "INLCR"}, - {IGNCR, "IGNC"}, - {ICRNL, "ICRNL"}, - {IXON, "IXON"}, - {IXOFF, "IXOFF"}, - {0, NULL} -#define ALLIN (BRKINT|IGNBRK|IGNPAR|PARMRK|INPCK|ISTRIP|INLCR|IGNCR|ICRNL|IXON|IXOFF) - }, oflags[] = - { - {OPOST, "OPOST"}, - {OFLAGS_TABS, "XTABS"}, - {ONLCR, "ONLCR"}, - {OCRNL, "OCRNL"}, - {ONOCR, "ONOCR"}, - {ONLRET, "ONLRET"}, - {0, NULL} -#define ALLOUT (OPOST|OFLAGS_TABS|ONLCR|OCRNL|ONOCR|ONLRET) - }, cflags[] = - { - {CLOCAL, "CLOCAL"}, - {CREAD, "CREAD"}, - {CSTOPB, "CSTOPB"}, -#if !defined(CS5) || !defined(CS8) - {CSIZE, "CSIZE"}, -#endif - {HUPCL, "HUPCL"}, - {PARENB, "PARENB"}, - {PARODD | PARENB, "PARODD"}, /* concession to readability */ - {0, NULL} -#define ALLCTRL (CLOCAL|CREAD|CSIZE|CSTOPB|HUPCL|PARENB|PARODD) - }, lflags[] = - { - {ECHO, "ECHO"}, - {ECHOE | ECHO, "ECHOE"}, /* concession to readability */ - {ECHOK | ECHO, "ECHOK"}, /* concession to readability */ - {ECHONL, "ECHONL"}, - {ICANON, "ICANON"}, - {ISIG, "ISIG"}, - {NOFLSH, "NOFLSH"}, - {TOSTOP, "TOSTOP"}, - {IEXTEN, "IEXTEN"}, - {0, NULL} -#define ALLLOCAL (ECHO|ECHONL|ICANON|ISIG|NOFLSH|TOSTOP|IEXTEN) - }; - - bufsize = 8 + sizeof(iflags) + 8 + sizeof(oflags) + 8 + sizeof(cflags) + - 8 + sizeof(lflags) + 8; - buf = _nc_trace_buf(0, bufsize); - - if (buf != 0) { - - if (tty->c_iflag & ALLIN) - lookup_bits(buf, bufsize, iflags, "iflags", tty->c_iflag); - - if (tty->c_oflag & ALLOUT) - lookup_bits(buf, bufsize, oflags, "oflags", tty->c_oflag); - - if (tty->c_cflag & ALLCTRL) - lookup_bits(buf, bufsize, cflags, "cflags", tty->c_cflag); - -#if defined(CS5) && defined(CS8) - { - static struct { - int value; - const char *name; - } csizes[] = { -#define CS_DATA(name) { name, #name " " } - CS_DATA(CS5), -#ifdef CS6 - CS_DATA(CS6), -#endif -#ifdef CS7 - CS_DATA(CS7), -#endif - CS_DATA(CS8), - }; - const char *result = "CSIZE? "; - int value = (tty->c_cflag & CSIZE); - unsigned n; - - if (value != 0) { - for (n = 0; n < SIZEOF(csizes); n++) { - if (csizes[n].value == value) { - result = csizes[n].name; - break; - } - } - } - strlcat(buf, result, bufsize); - } -#endif - - if (tty->c_lflag & ALLLOCAL) - lookup_bits(buf, bufsize, lflags, "lflags", tty->c_lflag); - } -#else - /* reference: ttcompat(4M) on SunOS 4.1 */ -#ifndef EVENP -#define EVENP 0 -#endif -#ifndef LCASE -#define LCASE 0 -#endif -#ifndef LLITOUT -#define LLITOUT 0 -#endif -#ifndef ODDP -#define ODDP 0 -#endif -#ifndef TANDEM -#define TANDEM 0 -#endif - - static const BITNAMES cflags[] = - { - {CBREAK, "CBREAK"}, - {CRMOD, "CRMOD"}, - {ECHO, "ECHO"}, - {EVENP, "EVENP"}, - {LCASE, "LCASE"}, - {LLITOUT, "LLITOUT"}, - {ODDP, "ODDP"}, - {RAW, "RAW"}, - {TANDEM, "TANDEM"}, - {XTABS, "XTABS"}, - {0, NULL} -#define ALLCTRL (CBREAK|CRMOD|ECHO|EVENP|LCASE|LLITOUT|ODDP|RAW|TANDEM|XTABS) - }; - - buf = _nc_trace_buf(0, - 8 + sizeof(cflags)); - if (buf != 0) { - if (tty->sg_flags & ALLCTRL) { - lookup_bits(buf, cflags, "cflags", tty->sg_flags); - } - } -#endif - return (buf); -} - -NCURSES_EXPORT(char *) -_nc_tracebits(void) -{ - return _nc_trace_ttymode(&(cur_term->Nttyb)); -} -#else -NCURSES_EXPORT(char *) -_nc_tracebits(void) -{ - return NULL; -} -#endif /* TRACE */ diff --git a/lib/libcurses/trace/lib_tracechr.c b/lib/libcurses/trace/lib_tracechr.c deleted file mode 100644 index e909ab79262..00000000000 --- a/lib/libcurses/trace/lib_tracechr.c +++ /dev/null @@ -1,87 +0,0 @@ -/* $OpenBSD: lib_tracechr.c,v 1.5 2010/01/12 23:22:07 nicm Exp $ */ - -/**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Zeyd M. Ben-Halim 1992,1995 * - * and: Eric S. Raymond * - * and: Thomas E. Dickey 1996-on * - ****************************************************************************/ - -/* - * lib_tracechr.c - Tracing/Debugging routines - */ -#include - -#include - -MODULE_ID("$Id: lib_tracechr.c,v 1.5 2010/01/12 23:22:07 nicm Exp $") - -#ifdef TRACE - -NCURSES_EXPORT(char *) -_nc_tracechar(SCREEN *sp, int ch) -{ - NCURSES_CONST char *name; - char *MyBuffer = ((sp != 0) - ? sp->tracechr_buf - : _nc_globals.tracechr_buf); - size_t len = ((sp != 0) - ? _nc_screen_tracechr_buf_size - : _nc_globals_traceatr_color_buf_size); - - if (ch > KEY_MIN || ch < 0) { - name = _nc_keyname(sp, ch); - if (name == 0 || *name == '\0') - name = "NULL"; - (void) snprintf(MyBuffer, len, "'%.30s' = %#03o", name, ch); - } else if (!is8bits(ch) || !isprint(UChar(ch))) { - /* - * workaround for glibc bug: - * sprintf changes the result from unctrl() to an empty string if it - * does not correspond to a valid multibyte sequence. - */ - (void) snprintf(MyBuffer, len, "%#03o", ch); - } else { - name = _nc_unctrl(sp, (chtype) ch); - if (name == 0 || *name == 0) - name = "null"; /* shouldn't happen */ - (void) snprintf(MyBuffer, len, "'%.30s' = %#03o", name, ch); - } - return (MyBuffer); -} - -NCURSES_EXPORT(char *) -_tracechar(int ch) -{ - return _nc_tracechar(SP, ch); -} -#else -EMPTY_MODULE(_nc_lib_tracechr) -#endif diff --git a/lib/libcurses/trace/lib_tracedmp.c b/lib/libcurses/trace/lib_tracedmp.c deleted file mode 100644 index 71759dc21db..00000000000 --- a/lib/libcurses/trace/lib_tracedmp.c +++ /dev/null @@ -1,186 +0,0 @@ -/* $OpenBSD: lib_tracedmp.c,v 1.4 2010/01/12 23:22:07 nicm Exp $ */ - -/**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Thomas E. Dickey 1996-on * - * and: Zeyd M. Ben-Halim 1992,1995 * - * and: Eric S. Raymond * - ****************************************************************************/ - -/* - * lib_tracedmp.c - Tracing/Debugging routines - */ - -#include -#include - -MODULE_ID("$Id: lib_tracedmp.c,v 1.4 2010/01/12 23:22:07 nicm Exp $") - -#ifdef TRACE - -#define my_buffer _nc_globals.tracedmp_buf -#define my_length _nc_globals.tracedmp_used - -NCURSES_EXPORT(void) -_tracedump(const char *name, WINDOW *win) -{ - int i, j, n, width; - - /* compute narrowest possible display width */ - for (width = i = 0; i <= win->_maxy; ++i) { - n = 0; - for (j = 0; j <= win->_maxx; ++j) { - if (CharOf(win->_line[i].text[j]) != L(' ') - || AttrOf(win->_line[i].text[j]) != A_NORMAL - || GetPair(win->_line[i].text[j]) != 0) { - n = j; - } - } - - if (n > width) - width = n; - } - if (width < win->_maxx) - ++width; - if (++width + 1 > (int) my_length) { - my_length = 2 * (width + 1); - my_buffer = typeRealloc(char, my_length, my_buffer); - } - - for (n = 0; n <= win->_maxy; ++n) { - char *ep = my_buffer; - bool haveattrs, havecolors; - - /* - * Dump A_CHARTEXT part. It is more important to make the grid line up - * in the trace file than to represent control- and wide-characters, so - * we map those to '.' and '?' respectively. - */ - for (j = 0; j < width; ++j) { - chtype test = CharOf(win->_line[n].text[j]); - ep[j] = (char) ((UChar(test) == test -#if USE_WIDEC_SUPPORT - && (win->_line[n].text[j].chars[1] == 0) -#endif - ) - ? (iscntrl(UChar(test)) - ? '.' - : UChar(test)) - : '?'); - } - ep[j] = '\0'; - _tracef("%s[%2d] %3ld%3ld ='%s'", - name, n, - (long) win->_line[n].firstchar, - (long) win->_line[n].lastchar, - ep); - - /* if there are multi-column characters on the line, print them now */ - if_WIDEC({ - bool multicolumn = FALSE; - for (j = 0; j < width; ++j) - if (WidecExt(win->_line[n].text[j]) != 0) { - multicolumn = TRUE; - break; - } - if (multicolumn) { - ep = my_buffer; - for (j = 0; j < width; ++j) { - int test = WidecExt(win->_line[n].text[j]); - if (test) { - ep[j] = (char) (test + '0'); - } else { - ep[j] = ' '; - } - } - ep[j] = '\0'; - _tracef("%*s[%2d]%*s='%s'", (int) strlen(name), - "widec", n, 8, " ", my_buffer); - } - }); - - /* dump A_COLOR part, will screw up if there are more than 96 */ - havecolors = FALSE; - for (j = 0; j < width; ++j) - if (GetPair(win->_line[n].text[j]) != 0) { - havecolors = TRUE; - break; - } - if (havecolors) { - ep = my_buffer; - for (j = 0; j < width; ++j) { - int pair = GetPair(win->_line[n].text[j]); - if (pair >= 52) - ep[j] = '?'; - else if (pair >= 36) - ep[j] = (char) (pair + 'A'); - else if (pair >= 10) - ep[j] = (char) (pair + 'a'); - else if (pair >= 1) - ep[j] = (char) (pair + '0'); - else - ep[j] = ' '; - } - ep[j] = '\0'; - _tracef("%*s[%2d]%*s='%s'", (int) strlen(name), - "colors", n, 8, " ", my_buffer); - } - - for (i = 0; i < 4; ++i) { - const char *hex = " 123456789ABCDEF"; - attr_t mask = (0xf << ((i + 4) * 4)); - - haveattrs = FALSE; - for (j = 0; j < width; ++j) - if (AttrOf(win->_line[n].text[j]) & mask) { - haveattrs = TRUE; - break; - } - if (haveattrs) { - ep = my_buffer; - for (j = 0; j < width; ++j) - ep[j] = hex[(AttrOf(win->_line[n].text[j]) & mask) >> - ((i + 4) * 4)]; - ep[j] = '\0'; - _tracef("%*s%d[%2d]%*s='%s'", (int) strlen(name) - - 1, "attrs", i, n, 8, " ", my_buffer); - } - } - } -#if NO_LEAKS - free(my_buffer); - my_buffer = 0; - my_length = 0; -#endif -} - -#else -EMPTY_MODULE(_nc_lib_tracedmp) -#endif /* TRACE */ diff --git a/lib/libcurses/trace/lib_tracemse.c b/lib/libcurses/trace/lib_tracemse.c deleted file mode 100644 index 798aae9f563..00000000000 --- a/lib/libcurses/trace/lib_tracemse.c +++ /dev/null @@ -1,131 +0,0 @@ -/* $OpenBSD: lib_tracemse.c,v 1.5 2010/01/12 23:22:07 nicm Exp $ */ - -/**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Zeyd M. Ben-Halim 1992,1995 * - * and: Eric S. Raymond * - * and: Thomas E. Dickey 1996-on * - ****************************************************************************/ - -/* - * lib_tracemse.c - Tracing/Debugging routines (mouse events) - */ - -#include - -MODULE_ID("$Id: lib_tracemse.c,v 1.5 2010/01/12 23:22:07 nicm Exp $") - -#ifdef TRACE - -#define my_buffer sp->tracemse_buf - -NCURSES_EXPORT(char *) -_nc_tracemouse(SCREEN *sp, MEVENT const *ep) -{ - (void) snprintf(my_buffer, TRACEMSE_MAX, TRACEMSE_FMT, - ep->id, - ep->x, - ep->y, - ep->z, - (unsigned long) ep->bstate); - -#define SHOW(m, s) \ - if ((ep->bstate & m) == m) { \ - strlcat(my_buffer, s, TRACEMSE_MAX); \ - strlcat(my_buffer, ", ", TRACEMSE_MAX); \ -} - - SHOW(BUTTON1_RELEASED, "release-1"); - SHOW(BUTTON1_PRESSED, "press-1"); - SHOW(BUTTON1_CLICKED, "click-1"); - SHOW(BUTTON1_DOUBLE_CLICKED, "doubleclick-1"); - SHOW(BUTTON1_TRIPLE_CLICKED, "tripleclick-1"); -#if NCURSES_MOUSE_VERSION == 1 - SHOW(BUTTON1_RESERVED_EVENT, "reserved-1"); -#endif - - SHOW(BUTTON2_RELEASED, "release-2"); - SHOW(BUTTON2_PRESSED, "press-2"); - SHOW(BUTTON2_CLICKED, "click-2"); - SHOW(BUTTON2_DOUBLE_CLICKED, "doubleclick-2"); - SHOW(BUTTON2_TRIPLE_CLICKED, "tripleclick-2"); -#if NCURSES_MOUSE_VERSION == 1 - SHOW(BUTTON2_RESERVED_EVENT, "reserved-2"); -#endif - - SHOW(BUTTON3_RELEASED, "release-3"); - SHOW(BUTTON3_PRESSED, "press-3"); - SHOW(BUTTON3_CLICKED, "click-3"); - SHOW(BUTTON3_DOUBLE_CLICKED, "doubleclick-3"); - SHOW(BUTTON3_TRIPLE_CLICKED, "tripleclick-3"); -#if NCURSES_MOUSE_VERSION == 1 - SHOW(BUTTON3_RESERVED_EVENT, "reserved-3"); -#endif - - SHOW(BUTTON4_RELEASED, "release-4"); - SHOW(BUTTON4_PRESSED, "press-4"); - SHOW(BUTTON4_CLICKED, "click-4"); - SHOW(BUTTON4_DOUBLE_CLICKED, "doubleclick-4"); - SHOW(BUTTON4_TRIPLE_CLICKED, "tripleclick-4"); -#if NCURSES_MOUSE_VERSION == 1 - SHOW(BUTTON4_RESERVED_EVENT, "reserved-4"); -#endif - -#if NCURSES_MOUSE_VERSION == 2 - SHOW(BUTTON5_RELEASED, "release-5"); - SHOW(BUTTON5_PRESSED, "press-5"); - SHOW(BUTTON5_CLICKED, "click-5"); - SHOW(BUTTON5_DOUBLE_CLICKED, "doubleclick-5"); - SHOW(BUTTON5_TRIPLE_CLICKED, "tripleclick-5"); -#endif - - SHOW(BUTTON_CTRL, "ctrl"); - SHOW(BUTTON_SHIFT, "shift"); - SHOW(BUTTON_ALT, "alt"); - SHOW(ALL_MOUSE_EVENTS, "all-events"); - SHOW(REPORT_MOUSE_POSITION, "position"); - -#undef SHOW - - if (my_buffer[strlen(my_buffer) - 1] == ' ') - my_buffer[strlen(my_buffer) - 2] = '\0'; - (void) strlcat(my_buffer, "}", TRACEMSE_MAX); - return (my_buffer); -} - -NCURSES_EXPORT(char *) -_tracemouse(MEVENT const *ep) -{ - return _nc_tracemouse(SP, ep); -} - -#else /* !TRACE */ -EMPTY_MODULE(_nc_lib_tracemouse) -#endif diff --git a/lib/libcurses/trace/trace_buf.c b/lib/libcurses/trace/trace_buf.c deleted file mode 100644 index 2b57ef77a3f..00000000000 --- a/lib/libcurses/trace/trace_buf.c +++ /dev/null @@ -1,121 +0,0 @@ -/* $OpenBSD: trace_buf.c,v 1.4 2010/01/12 23:22:07 nicm Exp $ */ - -/**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Thomas E. Dickey 1997-on * - ****************************************************************************/ -/* - * trace_buf.c - Tracing/Debugging buffers (attributes) - */ - -#include - -MODULE_ID("$Id: trace_buf.c,v 1.4 2010/01/12 23:22:07 nicm Exp $") - -#define MyList _nc_globals.tracebuf_ptr -#define MySize _nc_globals.tracebuf_used - -static char * -_nc_trace_alloc(int bufnum, size_t want) -{ -#ifdef TRACE - char *result = 0; - - if (bufnum >= 0) { - if ((size_t) (bufnum + 1) > MySize) { - size_t need = (bufnum + 1) * 2; - if ((MyList = typeRealloc(TRACEBUF, need, MyList)) != 0) { - while (need > MySize) - MyList[MySize++].text = 0; - } - } - - if (MyList != 0) { - if (MyList[bufnum].text == 0 - || want > MyList[bufnum].size) { - MyList[bufnum].text = typeRealloc(char, want, MyList[bufnum].text); - if (MyList[bufnum].text != 0) - MyList[bufnum].size = want; - } - result = MyList[bufnum].text; - } - } -#if NO_LEAKS - else { - if (MySize) { - if (MyList) { - while (MySize--) { - if (MyList[MySize].text != 0) { - free(MyList[MySize].text); - } - } - free(MyList); - MyList = 0; - } - MySize = 0; - } - } -#endif - return result; -#else - return NULL; -#endif -} - -/* - * (re)Allocate a buffer big enough for the caller's wants. - */ -NCURSES_EXPORT(char *) -_nc_trace_buf(int bufnum, size_t want) -{ - char *result = _nc_trace_alloc(bufnum, want); - if (result != 0) - *result = '\0'; - return result; -} - -/* - * Append a new string to an existing buffer. - */ -NCURSES_EXPORT(char *) -_nc_trace_bufcat(int bufnum, const char *value) -{ - char *buffer = _nc_trace_alloc(bufnum, 0); - if (buffer != 0) { - size_t have = strlen(buffer), length; - - length = 1 + have + strlen(value); - buffer = _nc_trace_alloc(bufnum, length); - if (buffer != 0) - (void) strlcpy(buffer + have, value, length); - - } - return buffer; -} diff --git a/lib/libcurses/trace/trace_tries.c b/lib/libcurses/trace/trace_tries.c deleted file mode 100644 index 0a138b48cab..00000000000 --- a/lib/libcurses/trace/trace_tries.c +++ /dev/null @@ -1,83 +0,0 @@ -/* $OpenBSD: trace_tries.c,v 1.5 2010/01/12 23:22:07 nicm Exp $ */ - -/**************************************************************************** - * Copyright (c) 1999-2007,2008 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Thomas E. Dickey 1999 * - ****************************************************************************/ -/* - * trace_tries.c - Tracing/Debugging buffers (keycode tries-trees) - */ - -#include - -MODULE_ID("$Id: trace_tries.c,v 1.5 2010/01/12 23:22:07 nicm Exp $") - -#ifdef TRACE -#define my_buffer _nc_globals.tracetry_buf -#define my_length _nc_globals.tracetry_used - -static void -recur_tries(TRIES * tree, unsigned level) -{ - if (level > my_length) { - my_length = (level + 1) * 4; - my_buffer = (unsigned char *) realloc(my_buffer, my_length); - } - - while (tree != 0) { - if ((my_buffer[level] = tree->ch) == 0) - my_buffer[level] = 128; - my_buffer[level + 1] = 0; - if (tree->value != 0) { - _tracef("%5d: %s (%s)", tree->value, - _nc_visbuf((char *) my_buffer), keyname(tree->value)); - } - if (tree->child) - recur_tries(tree->child, level + 1); - tree = tree->sibling; - } -} - -NCURSES_EXPORT(void) -_nc_trace_tries(TRIES * tree) -{ - my_buffer = typeMalloc(unsigned char, my_length = 80); - _tracef("BEGIN tries %p", tree); - recur_tries(tree, 0); - _tracef(". . . tries %p", tree); - free(my_buffer); -} - -#else -NCURSES_EXPORT(void) -_nc_trace_tries(TRIES * tree) -{ -} -#endif diff --git a/lib/libcurses/trace/trace_xnames.c b/lib/libcurses/trace/trace_xnames.c deleted file mode 100644 index 2c5b0ff74dd..00000000000 --- a/lib/libcurses/trace/trace_xnames.c +++ /dev/null @@ -1,77 +0,0 @@ -/* $OpenBSD: trace_xnames.c,v 1.4 2010/01/12 23:22:07 nicm Exp $ */ - -/**************************************************************************** - * Copyright (c) 1999,2000 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Thomas E. Dickey 1999 * - ****************************************************************************/ -/* - * trace_xnames.c - Tracing/Debugging buffers (TERMTYPE extended names) - */ - -#include -#include - -MODULE_ID("$Id: trace_xnames.c,v 1.4 2010/01/12 23:22:07 nicm Exp $") - -NCURSES_EXPORT(void) -_nc_trace_xnames(TERMTYPE * tp GCC_UNUSED) -{ -#ifdef TRACE -#if NCURSES_XNAMES - int limit = tp->ext_Booleans + tp->ext_Numbers + tp->ext_Strings; - int n, m; - if (limit) { - int begin_num = tp->ext_Booleans; - int begin_str = tp->ext_Booleans + tp->ext_Numbers; - - _tracef("extended names (%s) %d = %d+%d+%d of %d+%d+%d", - tp->term_names, - limit, - tp->ext_Booleans, tp->ext_Numbers, tp->ext_Strings, - tp->num_Booleans, tp->num_Numbers, tp->num_Strings); - for (n = 0; n < limit; n++) { - if ((m = n - begin_str) >= 0) { - _tracef("[%d] %s = %s", n, - tp->ext_Names[n], - _nc_visbuf(tp->Strings[tp->num_Strings + m - tp->ext_Strings])); - } else if ((m = n - begin_num) >= 0) { - _tracef("[%d] %s = %d (num)", n, - tp->ext_Names[n], - tp->Numbers[tp->num_Numbers + m - tp->ext_Numbers]); - } else { - _tracef("[%d] %s = %d (bool)", n, - tp->ext_Names[n], - tp->Booleans[tp->num_Booleans + n - tp->ext_Booleans]); - } - } - } -#endif -#endif -} diff --git a/lib/libcurses/trace/varargs.c b/lib/libcurses/trace/varargs.c deleted file mode 100644 index 0a1d5cfa161..00000000000 --- a/lib/libcurses/trace/varargs.c +++ /dev/null @@ -1,186 +0,0 @@ -/* $OpenBSD: varargs.c,v 1.1 2010/01/12 23:22:07 nicm Exp $ */ - -/**************************************************************************** - * Copyright (c) 2001-2007,2008 Free Software Foundation, Inc. * - * * - * Permission is hereby granted, free of charge, to any person obtaining a * - * copy of this software and associated documentation files (the * - * "Software"), to deal in the Software without restriction, including * - * without limitation the rights to use, copy, modify, merge, publish, * - * distribute, distribute with modifications, sublicense, and/or sell * - * copies of the Software, and to permit persons to whom the Software is * - * furnished to do so, subject to the following conditions: * - * * - * The above copyright notice and this permission notice shall be included * - * in all copies or substantial portions of the Software. * - * * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * - * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * - * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * * - * Except as contained in this notice, the name(s) of the above copyright * - * holders shall not be used in advertising or otherwise to promote the * - * sale, use or other dealings in this Software without prior written * - * authorization. * - ****************************************************************************/ - -/**************************************************************************** - * Author: Thomas E. Dickey 2001 * - ****************************************************************************/ - -#include - -#include - -MODULE_ID("$Id: varargs.c,v 1.1 2010/01/12 23:22:07 nicm Exp $") - -#ifdef TRACE - -#define MAX_PARMS 10 - -typedef enum { - atUnknown = 0, atInteger, atFloat, atPoint, atString -} ARGTYPE; - -#define VA_INT(type) ival = va_arg(ap, type) -#define VA_FLT(type) fval = va_arg(ap, type) -#define VA_PTR(type) pval = (char *)va_arg(ap, type) -#define VA_STR(type) sval = va_arg(ap, type) - -#define MyBuffer _nc_globals.tracearg_buf -#define MyLength _nc_globals.tracearg_used - -/* - * Returns a string that represents the parameter list of a printf-style call. - */ -NCURSES_EXPORT(char *) -_nc_varargs(const char *fmt, va_list ap) -{ - static char dummy[] = ""; - - char buffer[BUFSIZ]; - const char *param; - int n; - - if (fmt == 0 || *fmt == '\0') - return dummy; - if (MyLength == 0) - MyBuffer = typeMalloc(char, MyLength = BUFSIZ); - if (MyBuffer == 0) - return dummy; - *MyBuffer = '\0'; - - while (*fmt != '\0') { - if (*fmt == '%') { - char *pval = 0; /* avoid const-cast */ - const char *sval = ""; - double fval = 0.0; - int done = FALSE; - int ival = 0; - int type = 0; - ARGTYPE parm[MAX_PARMS]; - int parms = 0; - ARGTYPE used = atUnknown; - - while (*++fmt != '\0' && !done) { - - if (*fmt == '*') { - VA_INT(int); - if (parms < MAX_PARMS) - parm[parms++] = atInteger; - } else if (isalpha(UChar(*fmt))) { - done = TRUE; - switch (*fmt) { - case 'Z': /* FALLTHRU */ - case 'h': /* FALLTHRU */ - case 'l': /* FALLTHRU */ - done = FALSE; - type = *fmt; - break; - case 'i': /* FALLTHRU */ - case 'd': /* FALLTHRU */ - case 'u': /* FALLTHRU */ - case 'x': /* FALLTHRU */ - case 'X': /* FALLTHRU */ - if (type == 'l') - VA_INT(long); - else if (type == 'Z') - VA_INT(size_t); - else - VA_INT(int); - used = atInteger; - break; - case 'f': /* FALLTHRU */ - case 'e': /* FALLTHRU */ - case 'E': /* FALLTHRU */ - case 'g': /* FALLTHRU */ - case 'G': /* FALLTHRU */ - VA_FLT(double); - used = atFloat; - break; - case 'c': - VA_INT(int); - used = atInteger; - break; - case 's': - VA_STR(const char *); - used = atString; - break; - case 'p': - VA_PTR(void *); - used = atPoint; - break; - case 'n': - VA_PTR(int *); - used = atPoint; - break; - default: - break; - } - } else if (*fmt == '%') { - done = TRUE; - } - if (used != atUnknown && parms < MAX_PARMS) { - parm[parms++] = used; - for (n = 0; n < parms; ++n) { - used = parm[n]; - param = buffer; - switch (used) { - case atInteger: - snprintf(buffer, sizeof(buffer), "%d", ival); - break; - case atFloat: - snprintf(buffer, sizeof(buffer), "%f", fval); - break; - case atPoint: - snprintf(buffer, sizeof(buffer), "%p", pval); - break; - case atString: - param = _nc_visbuf2(1, sval); - break; - case atUnknown: - default: - strlcpy(buffer, "?", sizeof(buffer)); - break; - } - MyLength += strlen(param) + 2; - MyBuffer = typeRealloc(char, MyLength, MyBuffer); - snprintf(MyBuffer + strlen(MyBuffer), MyLength - strlen(MyBuffer), ", %s", param); - } - } - used = atUnknown; - } - } else { - fmt++; - } - } - - return (MyBuffer); -} -#else -EMPTY_MODULE(_nc_varargs) -#endif diff --git a/lib/libcurses/trace/visbuf.c b/lib/libcurses/trace/visbuf.c index 47efca5e22c..644c0127cfb 100644 --- a/lib/libcurses/trace/visbuf.c +++ b/lib/libcurses/trace/visbuf.c @@ -1,7 +1,8 @@ -/* $OpenBSD: visbuf.c,v 1.1 2010/01/12 23:22:07 nicm Exp $ */ +/* $OpenBSD: visbuf.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2001-2007,2008 Free Software Foundation, Inc. * + * Copyright 2019-2021,2023 Thomas E. Dickey * + * Copyright 2001-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -44,10 +45,12 @@ #include #include -MODULE_ID("$Id: visbuf.c,v 1.1 2010/01/12 23:22:07 nicm Exp $") +MODULE_ID("$Id: visbuf.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") + +#define NUM_VISBUFS 4 #define NormalLen(len) (size_t) (((size_t)(len) + 1) * 4) -#define WideLen(len) (size_t) (((size_t)(len) + 1) * 4 * MB_CUR_MAX) +#define WideLen(len) (size_t) (((size_t)(len) + 1) * 4 * (size_t) MB_CUR_MAX) #ifdef TRACE static const char d_quote[] = StringOf(D_QUOTE); @@ -55,13 +58,23 @@ static const char l_brace[] = StringOf(L_BRACE); static const char r_brace[] = StringOf(R_BRACE); #endif +#if USE_STRING_HACKS && HAVE_SNPRINTF +#define VisChar(tp, chr, limit) _nc_vischar(tp, chr, limit) +#define LIMIT_ARG ,size_t limit +#else +#define VisChar(tp, chr, limit) _nc_vischar(tp, chr) +#define LIMIT_ARG /* nothing */ +#endif + static char * -_nc_vischar(char *tp, size_t tl, unsigned c) +_nc_vischar(char *tp, unsigned c LIMIT_ARG) { - if (c == '"' || c == '\\') { + if (tp == NULL) { + return NULL; + } else if (c == '"' || c == '\\') { *tp++ = '\\'; *tp++ = (char) c; - } else if (is7bits(c) && (isgraph(c) || c == ' ')) { + } else if (is7bits((int) c) && (isgraph((int) c) || c == ' ')) { *tp++ = (char) c; } else if (c == '\n') { *tp++ = '\\'; @@ -72,6 +85,9 @@ _nc_vischar(char *tp, size_t tl, unsigned c) } else if (c == '\b') { *tp++ = '\\'; *tp++ = 'b'; + } else if (c == '\t') { + *tp++ = '\\'; + *tp++ = 't'; } else if (c == '\033') { *tp++ = '\\'; *tp++ = 'e'; @@ -84,7 +100,8 @@ _nc_vischar(char *tp, size_t tl, unsigned c) *tp++ = '^'; *tp++ = (char) ('@' + c); } else { - snprintf(tp, tl, "\\%03lo", (unsigned long) ChCharOf(c)); + _nc_SPRINTF(tp, _nc_SLIMIT(limit) + "\\%03lo", (unsigned long) ChCharOf(c)); tp += strlen(tp); } *tp = 0; @@ -94,9 +111,9 @@ _nc_vischar(char *tp, size_t tl, unsigned c) static const char * _nc_visbuf2n(int bufnum, const char *buf, int len) { - const char *vbuf; + const char *vbuf = 0; char *tp; - int c; + int count; if (buf == 0) return ("(null)"); @@ -106,22 +123,34 @@ _nc_visbuf2n(int bufnum, const char *buf, int len) if (len < 0) len = (int) strlen(buf); + count = len; #ifdef TRACE vbuf = tp = _nc_trace_buf(bufnum, NormalLen(len)); #else { - static char *mybuf[4]; - mybuf[bufnum] = typeRealloc(char, NormalLen(len), mybuf[bufnum]); - vbuf = tp = mybuf[bufnum]; + static char *mybuf[NUM_VISBUFS]; + int c; + + if (bufnum < 0) { + for (c = 0; c < NUM_VISBUFS; ++c) { + FreeAndNull(mybuf[c]); + } + tp = 0; + } else { + mybuf[bufnum] = typeRealloc(char, NormalLen(len), mybuf[bufnum]); + vbuf = tp = mybuf[bufnum]; + } } #endif if (tp != 0) { + int c; + *tp++ = D_QUOTE; - while ((--len >= 0) && (c = *buf++) != '\0') { - tp = _nc_vischar(tp, NormalLen(len) - (tp - vbuf), UChar(c)); + while ((--count >= 0) && (c = *buf++) != '\0') { + tp = VisChar(tp, UChar(c), NormalLen(len)); } *tp++ = D_QUOTE; - *tp++ = '\0'; + *tp = '\0'; } else { vbuf = ("(_nc_visbuf2n failed)"); } @@ -167,7 +196,7 @@ _nc_viswbuf2n(int bufnum, const wchar_t *buf, int len) { const char *vbuf; char *tp; - wchar_t c; + int count; if (buf == 0) return ("(null)"); @@ -175,30 +204,34 @@ _nc_viswbuf2n(int bufnum, const wchar_t *buf, int len) if (len < 0) len = (int) wcslen(buf); + count = len; #ifdef TRACE vbuf = tp = _nc_trace_buf(bufnum, WideLen(len)); #else { - static char *mybuf[2]; + static char *mybuf[NUM_VISBUFS]; mybuf[bufnum] = typeRealloc(char, WideLen(len), mybuf[bufnum]); vbuf = tp = mybuf[bufnum]; } #endif if (tp != 0) { + wchar_t c; + *tp++ = D_QUOTE; - while ((--len >= 0) && (c = *buf++) != '\0') { + while ((--count >= 0) && (c = *buf++) != '\0') { char temp[CCHARW_MAX + 80]; int j = wctomb(temp, c), k; if (j <= 0) { - snprintf(temp, sizeof temp, "\\u%08X", (unsigned) c); + _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) + "\\u%08X", (unsigned) c); j = (int) strlen(temp); } for (k = 0; k < j; ++k) { - tp = _nc_vischar(tp, WideLen(len) - (tp - vbuf), UChar(temp[k])); + tp = VisChar(tp, UChar(temp[k]), WideLen(len)); } } *tp++ = D_QUOTE; - *tp++ = '\0'; + *tp = '\0'; } else { vbuf = ("(_nc_viswbuf2n failed)"); } @@ -231,7 +264,9 @@ _nc_viswibuf(const wint_t *buf) static unsigned mylen; unsigned n; - for (n = 0; buf[n] != 0; ++n) ; + for (n = 0; buf[n] != 0; ++n) { + ; /* empty */ + } if (mylen < ++n) { mylen = n + 80; if (mybuf != 0) @@ -239,8 +274,12 @@ _nc_viswibuf(const wint_t *buf) else mybuf = typeMalloc(wchar_t, mylen); } - for (n = 0; buf[n] != 0; ++n) - mybuf[n] = (wchar_t) buf[n]; + if (mybuf != 0) { + for (n = 0; buf[n] != 0; ++n) { + mybuf[n] = (wchar_t) buf[n]; + } + mybuf[n] = L'\0'; + } return _nc_viswbuf2(0, mybuf); } @@ -248,13 +287,13 @@ _nc_viswibuf(const wint_t *buf) /* use these functions for displaying parts of a line within a window */ NCURSES_EXPORT(const char *) -_nc_viscbuf2(int bufnum, const NCURSES_CH_T * buf, int len) +_nc_viscbuf2(int bufnum, const NCURSES_CH_T *buf, int len) { - char *result = _nc_trace_buf(bufnum, BUFSIZ); - int first; - const char *found; + char *result = _nc_trace_buf(bufnum, (size_t) BUFSIZ); if (result != 0) { + int first = 0; + #if USE_WIDEC_SUPPORT if (len < 0) len = _nc_wchstrlen(buf); @@ -263,7 +302,6 @@ _nc_viscbuf2(int bufnum, const NCURSES_CH_T * buf, int len) /* * Display one or more strings followed by attributes. */ - first = 0; while (first < len) { attr_t attr = AttrOf(buf[first]); int last = len - 1; @@ -276,47 +314,58 @@ _nc_viscbuf2(int bufnum, const NCURSES_CH_T * buf, int len) } } - result = _nc_trace_bufcat(bufnum, l_brace); - result = _nc_trace_bufcat(bufnum, d_quote); + (void) _nc_trace_bufcat(bufnum, l_brace); + (void) _nc_trace_bufcat(bufnum, d_quote); for (j = first; j <= last; ++j) { - found = _nc_altcharset_name(attr, (chtype) CharOf(buf[j])); + const char *found = _nc_altcharset_name(attr, (chtype) + CharOf(buf[j])); if (found != 0) { - result = _nc_trace_bufcat(bufnum, found); + (void) _nc_trace_bufcat(bufnum, found); attr &= ~A_ALTCHARSET; } else #if USE_WIDEC_SUPPORT if (!isWidecExt(buf[j])) { PUTC_DATA; - PUTC_INIT; for (PUTC_i = 0; PUTC_i < CCHARW_MAX; ++PUTC_i) { int k; + char temp[80]; PUTC_ch = buf[j].chars[PUTC_i]; - if (PUTC_ch == L'\0') + if (PUTC_ch == L'\0') { + if (PUTC_i == 0) + (void) _nc_trace_bufcat(bufnum, "\\000"); break; - PUTC_n = (int) wcrtomb(PUTC_buf, buf[j].chars[PUTC_i], &PUT_st); - if (PUTC_n <= 0) + } + PUTC_INIT; + PUTC_n = (int) wcrtomb(PUTC_buf, + buf[j].chars[PUTC_i], &PUT_st); + if (PUTC_n <= 0 || buf[j].chars[PUTC_i] > 255) { + _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) + "{%d:\\u%lx}", + _nc_wacs_width(buf[j].chars[PUTC_i]), + (unsigned long) buf[j].chars[PUTC_i]); + (void) _nc_trace_bufcat(bufnum, temp); break; + } for (k = 0; k < PUTC_n; k++) { - char temp[80]; - _nc_vischar(temp, sizeof(temp), UChar(PUTC_buf[k])); - result = _nc_trace_bufcat(bufnum, temp); + VisChar(temp, UChar(PUTC_buf[k]), sizeof(temp)); + (void) _nc_trace_bufcat(bufnum, temp); } } } #else { char temp[80]; - _nc_vischar(temp, sizeof(temp), UChar(buf[j])); - result = _nc_trace_bufcat(bufnum, temp); + VisChar(temp, UChar(buf[j]), sizeof(temp)); + (void) _nc_trace_bufcat(bufnum, temp); } #endif /* USE_WIDEC_SUPPORT */ } - result = _nc_trace_bufcat(bufnum, d_quote); + (void) _nc_trace_bufcat(bufnum, d_quote); if (attr != A_NORMAL) { - result = _nc_trace_bufcat(bufnum, " | "); - result = _nc_trace_bufcat(bufnum, _traceattr2(bufnum + 20, attr)); + (void) _nc_trace_bufcat(bufnum, " | "); + (void) _nc_trace_bufcat(bufnum, _traceattr2(bufnum + 20, attr)); } result = _nc_trace_bufcat(bufnum, r_brace); first = last + 1; @@ -326,7 +375,7 @@ _nc_viscbuf2(int bufnum, const NCURSES_CH_T * buf, int len) } NCURSES_EXPORT(const char *) -_nc_viscbuf(const NCURSES_CH_T * buf, int len) +_nc_viscbuf(const NCURSES_CH_T *buf, int len) { return _nc_viscbuf2(0, buf, len); } diff --git a/lib/libcurses/tty/MKexpanded.sh b/lib/libcurses/tty/MKexpanded.sh index bc6902b5bb7..7b8ce3bad0e 100644 --- a/lib/libcurses/tty/MKexpanded.sh +++ b/lib/libcurses/tty/MKexpanded.sh @@ -1,7 +1,8 @@ +# $OpenBSD: MKexpanded.sh,v 1.5 2023/10/17 09:52:09 nicm Exp $ #! /bin/sh -# $OpenBSD: MKexpanded.sh,v 1.4 2010/01/12 23:22:07 nicm Exp $ ############################################################################## -# Copyright (c) 1998-2000,2005 Free Software Foundation, Inc. # +# Copyright 2019-2020,2021 Thomas E. Dickey # +# Copyright 1998-2015,2017 Free Software Foundation, Inc. # # # # Permission is hereby granted, free of charge, to any person obtaining a # # copy of this software and associated documentation files (the "Software"), # @@ -28,9 +29,9 @@ # authorization. # ############################################################################## # -# Author: Thomas E. Dickey 1997 +# Author: Thomas E. Dickey, 1997-on # -# $Id: MKexpanded.sh,v 1.4 2010/01/12 23:22:07 nicm Exp $ +# $Id: MKexpanded.sh,v 1.5 2023/10/17 09:52:09 nicm Exp $ # # Script to generate 'expanded.c', a dummy source that contains functions # corresponding to complex macros used in this library. By making functions, @@ -49,12 +50,18 @@ else fi TMP=gen$$.c -trap "rm -f $TMP" 0 1 2 5 15 +trap "rm -f $TMP; exit 1" 1 2 3 15 +trap "rm -f $TMP" 0 cat < -#include + +#ifndef CUR +#define CUR SP_TERMTYPE +#endif + #if NCURSES_EXPANDED EOF @@ -69,29 +76,59 @@ cat >$TMP </dev/null | sed -e '1,/^IGNORE$/d' +$preprocessor $TMP 2>/dev/null | \ + sed -e '1,/^IGNORE$/d' -e 's/^@/#/' -e 's/^#[ ]*if_/#if /' -e "s,$TMP,expanded.c," cat < -MODULE_ID("$Id: hardscroll.c,v 1.7 2010/01/12 23:22:07 nicm Exp $") +MODULE_ID("$Id: hardscroll.c,v 1.8 2023/10/17 09:52:09 nicm Exp $") #if defined(SCROLLDEBUG) || defined(HASHDEBUG) # undef screen_lines -# define screen_lines MAXLINES -NCURSES_EXPORT_VAR(int) -oldnums[MAXLINES]; -# define OLDNUM(n) oldnums[n] +# define screen_lines(sp) MAXLINES +NCURSES_EXPORT_VAR (int) + oldnums[MAXLINES]; +# define OLDNUM(sp,n) oldnums[n] # define _tracef printf # undef TR # define TR(n, a) if (_nc_tracing & (n)) { _tracef a ; putchar('\n'); } -extern NCURSES_EXPORT_VAR(unsigned) _nc_tracing; +extern NCURSES_EXPORT_VAR(unsigned) _nc_tracing; #else /* no debug */ /* OLDNUM(n) indicates which line will be shifted to the position n. if OLDNUM(n) == _NEWINDEX, then the line n in new, not shifted from somewhere. */ -NCURSES_EXPORT_VAR(int *) -_nc_oldnums = 0; /* obsolete: keep for ABI compat */ +NCURSES_EXPORT_VAR (int *) + _nc_oldnums = 0; /* obsolete: keep for ABI compat */ # if USE_HASHMAP -# define oldnums SP->_oldnum_list -# define OLDNUM(n) oldnums[n] -# else /* !USE_HASHMAP */ -# define OLDNUM(n) newscr->_line[n].oldindex -# endif /* !USE_HASHMAP */ +# define oldnums(sp) (sp)->_oldnum_list +# define OLDNUM(sp,n) oldnums(sp)[n] +# else /* !USE_HASHMAP */ +# define OLDNUM(sp,n) NewScreen(sp)->_line[n].oldindex +# endif /* !USE_HASHMAP */ -#define OLDNUM_SIZE SP->_oldnum_size +#define OLDNUM_SIZE(sp) (sp)->_oldnum_size #endif /* defined(SCROLLDEBUG) || defined(HASHDEBUG) */ NCURSES_EXPORT(void) -_nc_scroll_optimize(void) +NCURSES_SP_NAME(_nc_scroll_optimize) (NCURSES_SP_DCL0) /* scroll optimization to transform curscr to newscr */ { int i; int start, end, shift; - TR(TRACE_ICALLS, (T_CALLED("_nc_scroll_optimize"))); + TR(TRACE_ICALLS, (T_CALLED("_nc_scroll_optimize(%p)"), (void *) SP_PARM)); #if !defined(SCROLLDEBUG) && !defined(HASHDEBUG) #if USE_HASHMAP /* get enough storage */ - if (OLDNUM_SIZE < screen_lines) { - int *new_oldnums = typeRealloc(int, screen_lines, oldnums); - if (!new_oldnums) + assert(OLDNUM_SIZE(SP_PARM) >= 0); + assert(screen_lines(SP_PARM) > 0); + if ((oldnums(SP_PARM) == 0) + || (OLDNUM_SIZE(SP_PARM) < screen_lines(SP_PARM))) { + int need_lines = ((OLDNUM_SIZE(SP_PARM) < screen_lines(SP_PARM)) + ? screen_lines(SP_PARM) + : OLDNUM_SIZE(SP_PARM)); + int *new_oldnums = typeRealloc(int, + (size_t) need_lines, + oldnums(SP_PARM)); + if (!new_oldnums) { + TR(TRACE_ICALLS, (T_RETURN(""))); return; - oldnums = new_oldnums; - OLDNUM_SIZE = screen_lines; + } + oldnums(SP_PARM) = new_oldnums; + OLDNUM_SIZE(SP_PARM) = need_lines; } /* calculate the indices */ - _nc_hash_map(); + NCURSES_SP_NAME(_nc_hash_map) (NCURSES_SP_ARG); + if (SP_PARM->hashtab_len < screen_lines(SP_PARM)) { + TR(TRACE_ICALLS, (T_RETURN(""))); + return; + } #endif #endif /* !defined(SCROLLDEBUG) && !defined(HASHDEBUG) */ #ifdef TRACE if (USE_TRACEF(TRACE_UPDATE | TRACE_MOVE)) { - _nc_linedump(); + NCURSES_SP_NAME(_nc_linedump) (NCURSES_SP_ARG); _nc_unlock_global(tracef); } #endif /* TRACE */ /* pass 1 - from top to bottom scrolling up */ - for (i = 0; i < screen_lines;) { - while (i < screen_lines && (OLDNUM(i) == _NEWINDEX || OLDNUM(i) <= i)) + for (i = 0; i < screen_lines(SP_PARM);) { + while (i < screen_lines(SP_PARM) + && (OLDNUM(SP_PARM, i) == _NEWINDEX || OLDNUM(SP_PARM, i) <= i)) i++; - if (i >= screen_lines) + if (i >= screen_lines(SP_PARM)) break; - shift = OLDNUM(i) - i; /* shift > 0 */ + shift = OLDNUM(SP_PARM, i) - i; /* shift > 0 */ start = i; i++; - while (i < screen_lines && OLDNUM(i) != _NEWINDEX && OLDNUM(i) - i - == shift) + while (i < screen_lines(SP_PARM) + && OLDNUM(SP_PARM, i) != _NEWINDEX + && OLDNUM(SP_PARM, i) - i == shift) i++; end = i - 1 + shift; TR(TRACE_UPDATE | TRACE_MOVE, ("scroll [%d, %d] by %d", start, end, shift)); #if !defined(SCROLLDEBUG) && !defined(HASHDEBUG) - if (_nc_scrolln(shift, start, end, screen_lines - 1) == ERR) { + if (NCURSES_SP_NAME(_nc_scrolln) (NCURSES_SP_ARGx + shift, + start, + end, + screen_lines(SP_PARM) - 1) == ERR) { TR(TRACE_UPDATE | TRACE_MOVE, ("unable to scroll")); continue; } @@ -240,23 +261,33 @@ _nc_scroll_optimize(void) } /* pass 2 - from bottom to top scrolling down */ - for (i = screen_lines - 1; i >= 0;) { - while (i >= 0 && (OLDNUM(i) == _NEWINDEX || OLDNUM(i) >= i)) + for (i = screen_lines(SP_PARM) - 1; i >= 0;) { + while (i >= 0 + && (OLDNUM(SP_PARM, i) == _NEWINDEX + || OLDNUM(SP_PARM, i) >= i)) { i--; + } if (i < 0) break; - shift = OLDNUM(i) - i; /* shift < 0 */ + shift = OLDNUM(SP_PARM, i) - i; /* shift < 0 */ end = i; i--; - while (i >= 0 && OLDNUM(i) != _NEWINDEX && OLDNUM(i) - i == shift) + while (i >= 0 + && OLDNUM(SP_PARM, i) != _NEWINDEX + && OLDNUM(SP_PARM, i) - i == shift) { i--; + } start = i + 1 - (-shift); TR(TRACE_UPDATE | TRACE_MOVE, ("scroll [%d, %d] by %d", start, end, shift)); #if !defined(SCROLLDEBUG) && !defined(HASHDEBUG) - if (_nc_scrolln(shift, start, end, screen_lines - 1) == ERR) { + if (NCURSES_SP_NAME(_nc_scrolln) (NCURSES_SP_ARGx + shift, + start, + end, + screen_lines(SP_PARM) - 1) == ERR) { TR(TRACE_UPDATE | TRACE_MOVE, ("unable to scroll")); continue; } @@ -265,24 +296,51 @@ _nc_scroll_optimize(void) TR(TRACE_ICALLS, (T_RETURN(""))); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(void) +_nc_scroll_optimize(void) +{ + NCURSES_SP_NAME(_nc_scroll_optimize) (CURRENT_SCREEN); +} +#endif + #if defined(TRACE) || defined(SCROLLDEBUG) || defined(HASHDEBUG) NCURSES_EXPORT(void) -_nc_linedump(void) +NCURSES_SP_NAME(_nc_linedump) (NCURSES_SP_DCL0) /* dump the state of the real and virtual oldnum fields */ { - int n; - char *buf = 0; - size_t want = (screen_lines + 1) * 4; - - if ((buf = typeMalloc(char, want)) != 0) { - - (void) strlcpy(buf, "virt", want); - for (n = 0; n < screen_lines; n++) - (void) snprintf(buf + strlen(buf), want - strlen(buf), " %02d", OLDNUM(n)); - TR(TRACE_UPDATE | TRACE_MOVE, (buf)); - free(buf); + if (USE_TRACEF(TRACE_UPDATE | TRACE_MOVE)) { + char *buf = 0; + size_t want = ((size_t) screen_lines(SP_PARM) + 1) * 4; + (void) SP_PARM; + + if ((buf = typeMalloc(char, want)) != 0) { + int n; + + *buf = '\0'; + for (n = 0; n < screen_lines(SP_PARM); n++) { + int number = OLDNUM(SP_PARM, n); + if (number >= -99 && number < 999) { + _nc_SPRINTF(buf + strlen(buf), + _nc_SLIMIT(want - strlen(buf)) + " %02d", number); + } else { + _nc_STRCAT(buf, " ??", want - strlen(buf)); + } + } + free(buf); + } } } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(void) +_nc_linedump(void) +{ + NCURSES_SP_NAME(_nc_linedump) (CURRENT_SCREEN); +} +#endif + #endif /* defined(TRACE) || defined(SCROLLDEBUG) */ #ifdef SCROLLDEBUG @@ -290,7 +348,7 @@ _nc_linedump(void) int main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED) { - char line[BUFSIZ], *st, *last; + char line[BUFSIZ], *st; #ifdef TRACE _nc_tracing = TRACE_MOVE; @@ -298,7 +356,7 @@ main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED) for (;;) { int n; - for (n = 0; n < screen_lines; n++) + for (n = 0; n < screen_lines(sp); n++) oldnums[n] = _NEWINDEX; /* grab the test vector */ @@ -311,11 +369,11 @@ main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED) (void) fputs(line, stderr); continue; } - st = strtok_r(line, " ", &last); + st = strtok(line, " "); do { oldnums[n++] = atoi(st); } while - ((st = strtok_r((char *) NULL, " ", &last)) != 0); + ((st = strtok((char *) NULL, " ")) != 0); /* display it */ (void) fputs("Initial input:\n", stderr); diff --git a/lib/libcurses/tty/hashmap.c b/lib/libcurses/tty/hashmap.c index 14739fa35a3..88bbc708e93 100644 --- a/lib/libcurses/tty/hashmap.c +++ b/lib/libcurses/tty/hashmap.c @@ -1,7 +1,8 @@ -/* $OpenBSD: hashmap.c,v 1.8 2010/01/12 23:22:07 nicm Exp $ */ +/* $OpenBSD: hashmap.c,v 1.9 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * + * Copyright 2019-2020,2023 Thomas E. Dickey * + * Copyright 1998-2015,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -70,40 +71,47 @@ AUTHOR *****************************************************************************/ #include -#include /* for back_color_erase */ -MODULE_ID("$Id: hashmap.c,v 1.8 2010/01/12 23:22:07 nicm Exp $") +#ifndef CUR +#define CUR SP_TERMTYPE +#endif + +MODULE_ID("$Id: hashmap.c,v 1.9 2023/10/17 09:52:09 nicm Exp $") #ifdef HASHDEBUG # define _tracef printf # undef TR +# ifdef TRACE # define TR(n, a) if (_nc_tracing & (n)) { _tracef a ; putchar('\n'); } +# else +# define TR(n, a) { _tracef a ; putchar('\n'); } +# endif # undef screen_lines -# define screen_lines MAXLINES -# define TEXTWIDTH 1 -int oldnums[MAXLINES], reallines[MAXLINES]; -static NCURSES_CH_T oldtext[MAXLINES][TEXTWIDTH]; -static NCURSES_CH_T newtext[MAXLINES][TEXTWIDTH]; -# define OLDNUM(n) oldnums[n] -# define OLDTEXT(n) oldtext[n] -# define NEWTEXT(m) newtext[m] -# define PENDING(n) 1 +# define screen_lines(sp) MAXLINES +# define TEXTWIDTH(sp) 1 +static int oldnums[MAXLINES], reallines[MAXLINES]; +static NCURSES_CH_T oldtext[MAXLINES][TEXTWIDTH(sp)]; +static NCURSES_CH_T newtext[MAXLINES][TEXTWIDTH(sp)]; +# define OLDNUM(sp,n) oldnums[n] +# define OLDTEXT(sp,n) oldtext[n] +# define NEWTEXT(sp,m) newtext[m] +# define PENDING(sp,n) 1 #else /* !HASHDEBUG */ -# define OLDNUM(n) SP->_oldnum_list[n] -# define OLDTEXT(n) curscr->_line[n].text -# define NEWTEXT(m) newscr->_line[m].text -# define TEXTWIDTH (curscr->_maxx+1) -# define PENDING(n) (newscr->_line[n].firstchar != _NOCHANGE) +# define OLDNUM(sp,n) (sp)->_oldnum_list[n] +# define OLDTEXT(sp,n) CurScreen(sp)->_line[n].text +# define NEWTEXT(sp,m) NewScreen(sp)->_line[m].text +# define TEXTWIDTH(sp) (CurScreen(sp)->_maxx + 1) +# define PENDING(sp,n) (NewScreen(sp)->_line[n].firstchar != _NOCHANGE) #endif /* !HASHDEBUG */ -#define oldhash (SP->oldhash) -#define newhash (SP->newhash) -#define hashtab (SP->hashtab) -#define lines_alloc (SP->hashtab_len) +#define oldhash(sp) ((sp)->oldhash) +#define newhash(sp) ((sp)->newhash) +#define hashtab(sp) ((sp)->hashtab) +#define lines_alloc(sp) ((sp)->hashtab_len) #if USE_WIDEC_SUPPORT #define HASH_VAL(ch) (ch.chars[0]) @@ -114,26 +122,29 @@ static NCURSES_CH_T newtext[MAXLINES][TEXTWIDTH]; static const NCURSES_CH_T blankchar = NewChar(BLANK_TEXT); static NCURSES_INLINE unsigned long -hash(NCURSES_CH_T * text) +hash(SCREEN *sp, NCURSES_CH_T *text) { int i; NCURSES_CH_T ch; unsigned long result = 0; - for (i = TEXTWIDTH; i > 0; i--) { + (void) sp; + + for (i = TEXTWIDTH(sp); i > 0; i--) { ch = *text++; - result += (result << 5) + HASH_VAL(ch); + result += (result << 5) + (unsigned long) HASH_VAL(ch); } return result; } /* approximate update cost */ static int -update_cost(NCURSES_CH_T * from, NCURSES_CH_T * to) +update_cost(SCREEN *sp, NCURSES_CH_T *from, NCURSES_CH_T *to) { int cost = 0; int i; + (void) sp; - for (i = TEXTWIDTH; i > 0; i--, from++, to++) + for (i = TEXTWIDTH(sp); i > 0; i--, from++, to++) if (!(CharEq(*from, *to))) cost++; @@ -141,16 +152,17 @@ update_cost(NCURSES_CH_T * from, NCURSES_CH_T * to) } static int -update_cost_from_blank(NCURSES_CH_T * to) +update_cost_from_blank(SCREEN *sp, NCURSES_CH_T *to) { int cost = 0; int i; NCURSES_CH_T blank = blankchar; + (void) sp; if (back_color_erase) SetPair(blank, GetPair(stdscr->_nc_bkgd)); - for (i = TEXTWIDTH; i > 0; i--, to++) + for (i = TEXTWIDTH(sp); i > 0; i--, to++) if (!(CharEq(blank, *to))) cost++; @@ -162,14 +174,14 @@ update_cost_from_blank(NCURSES_CH_T * to) * effective. 'blank' indicates whether the line 'to' would become blank. */ static NCURSES_INLINE bool -cost_effective(const int from, const int to, const bool blank) +cost_effective(SCREEN *sp, const int from, const int to, const int blank) { int new_from; if (from == to) return FALSE; - new_from = OLDNUM(from); + new_from = OLDNUM(sp, from); if (new_from == _NEWINDEX) new_from = from; @@ -177,20 +189,20 @@ cost_effective(const int from, const int to, const bool blank) * On the left side of >= is the cost before moving; * on the right side -- cost after moving. */ - return (((blank ? update_cost_from_blank(NEWTEXT(to)) - : update_cost(OLDTEXT(to), NEWTEXT(to))) - + update_cost(OLDTEXT(new_from), NEWTEXT(from))) - >= ((new_from == from ? update_cost_from_blank(NEWTEXT(from)) - : update_cost(OLDTEXT(new_from), NEWTEXT(from))) - + update_cost(OLDTEXT(from), NEWTEXT(to)))) ? TRUE : FALSE; + return (((blank ? update_cost_from_blank(sp, NEWTEXT(sp, to)) + : update_cost(sp, OLDTEXT(sp, to), NEWTEXT(sp, to))) + + update_cost(sp, OLDTEXT(sp, new_from), NEWTEXT(sp, from))) + >= ((new_from == from ? update_cost_from_blank(sp, NEWTEXT(sp, from)) + : update_cost(sp, OLDTEXT(sp, new_from), NEWTEXT(sp, from))) + + update_cost(sp, OLDTEXT(sp, from), NEWTEXT(sp, to)))) + ? TRUE : FALSE; } static void -grow_hunks(void) +grow_hunks(SCREEN *sp) { - int start, end, shift; - int back_limit, forward_limit; /* limits for cells to fill */ - int back_ref_limit, forward_ref_limit; /* limits for refrences */ + int back_limit; /* limits for cells to fill */ + int back_ref_limit; /* limit for references */ int i; int next_hunk; @@ -202,35 +214,39 @@ grow_hunks(void) back_ref_limit = 0; i = 0; - while (i < screen_lines && OLDNUM(i) == _NEWINDEX) + while (i < screen_lines(sp) && OLDNUM(sp, i) == _NEWINDEX) i++; - for (; i < screen_lines; i = next_hunk) { - start = i; - shift = OLDNUM(i) - i; + for (; i < screen_lines(sp); i = next_hunk) { + int forward_limit; + int forward_ref_limit; + int end; + int start = i; + int shift = OLDNUM(sp, i) - i; /* get forward limit */ i = start + 1; - while (i < screen_lines && OLDNUM(i) != _NEWINDEX && OLDNUM(i) - i - == shift) + while (i < screen_lines(sp) + && OLDNUM(sp, i) != _NEWINDEX + && OLDNUM(sp, i) - i == shift) i++; end = i; - while (i < screen_lines && OLDNUM(i) == _NEWINDEX) + while (i < screen_lines(sp) && OLDNUM(sp, i) == _NEWINDEX) i++; next_hunk = i; forward_limit = i; - if (i >= screen_lines || OLDNUM(i) >= i) + if (i >= screen_lines(sp) || OLDNUM(sp, i) >= i) forward_ref_limit = i; else - forward_ref_limit = OLDNUM(i); + forward_ref_limit = OLDNUM(sp, i); i = start - 1; /* grow back */ if (shift < 0) back_limit = back_ref_limit + (-shift); while (i >= back_limit) { - if (newhash[i] == oldhash[i + shift] - || cost_effective(i + shift, i, shift < 0)) { - OLDNUM(i) = i + shift; + if (newhash(sp)[i] == oldhash(sp)[i + shift] + || cost_effective(sp, i + shift, i, shift < 0)) { + OLDNUM(sp, i) = i + shift; TR(TRACE_UPDATE | TRACE_MOVE, ("connected new line %d to old line %d (backward continuation)", i, i + shift)); @@ -248,9 +264,9 @@ grow_hunks(void) if (shift > 0) forward_limit = forward_ref_limit - shift; while (i < forward_limit) { - if (newhash[i] == oldhash[i + shift] - || cost_effective(i + shift, i, shift > 0)) { - OLDNUM(i) = i + shift; + if (newhash(sp)[i] == oldhash(sp)[i + shift] + || cost_effective(sp, i + shift, i, shift > 0)) { + OLDNUM(sp, i) = i + shift; TR(TRACE_UPDATE | TRACE_MOVE, ("connected new line %d to old line %d (forward continuation)", i, i + shift)); @@ -270,51 +286,56 @@ grow_hunks(void) } NCURSES_EXPORT(void) -_nc_hash_map(void) +NCURSES_SP_NAME(_nc_hash_map) (NCURSES_SP_DCL0) { - HASHMAP *sp; + HASHMAP *hsp; register int i; - int start, shift, size; - - if (screen_lines > lines_alloc) { - if (hashtab) - free(hashtab); - hashtab = typeMalloc(HASHMAP, (screen_lines + 1) * 2); - if (!hashtab) { - if (oldhash) { - FreeAndNull(oldhash); + + if (screen_lines(SP_PARM) > lines_alloc(SP_PARM)) { + if (hashtab(SP_PARM)) + free(hashtab(SP_PARM)); + hashtab(SP_PARM) = typeMalloc(HASHMAP, + ((size_t) screen_lines(SP_PARM) + 1) * 2); + if (!hashtab(SP_PARM)) { + if (oldhash(SP_PARM)) { + FreeAndNull(oldhash(SP_PARM)); } - lines_alloc = 0; + lines_alloc(SP_PARM) = 0; return; } - lines_alloc = screen_lines; + lines_alloc(SP_PARM) = screen_lines(SP_PARM); } - if (oldhash && newhash) { + if (oldhash(SP_PARM) && newhash(SP_PARM)) { /* re-hash only changed lines */ - for (i = 0; i < screen_lines; i++) { - if (PENDING(i)) - newhash[i] = hash(NEWTEXT(i)); + for (i = 0; i < screen_lines(SP_PARM); i++) { + if (PENDING(SP_PARM, i)) + newhash(SP_PARM)[i] = hash(SP_PARM, NEWTEXT(SP_PARM, i)); } } else { /* re-hash all */ - if (oldhash == 0) - oldhash = typeCalloc(unsigned long, (unsigned) screen_lines); - if (newhash == 0) - newhash = typeCalloc(unsigned long, (unsigned) screen_lines); - if (!oldhash || !newhash) + if (oldhash(SP_PARM) == 0) + oldhash(SP_PARM) = typeCalloc(unsigned long, + (size_t) screen_lines(SP_PARM)); + if (newhash(SP_PARM) == 0) + newhash(SP_PARM) = typeCalloc(unsigned long, + (size_t) screen_lines(SP_PARM)); + if (!oldhash(SP_PARM) || !newhash(SP_PARM)) { + FreeAndNull(oldhash(SP_PARM)); + FreeAndNull(newhash(SP_PARM)); return; /* malloc failure */ - for (i = 0; i < screen_lines; i++) { - newhash[i] = hash(NEWTEXT(i)); - oldhash[i] = hash(OLDTEXT(i)); + } + for (i = 0; i < screen_lines(SP_PARM); i++) { + newhash(SP_PARM)[i] = hash(SP_PARM, NEWTEXT(SP_PARM, i)); + oldhash(SP_PARM)[i] = hash(SP_PARM, OLDTEXT(SP_PARM, i)); } } #ifdef HASH_VERIFY - for (i = 0; i < screen_lines; i++) { - if (newhash[i] != hash(NEWTEXT(i))) + for (i = 0; i < screen_lines(SP_PARM); i++) { + if (newhash(SP_PARM)[i] != hash(SP_PARM, NEWTEXT(SP_PARM, i))) fprintf(stderr, "error in newhash[%d]\n", i); - if (oldhash[i] != hash(OLDTEXT(i))) + if (oldhash(SP_PARM)[i] != hash(SP_PARM, OLDTEXT(SP_PARM, i))) fprintf(stderr, "error in oldhash[%d]\n", i); } #endif @@ -322,28 +343,30 @@ _nc_hash_map(void) /* * Set up and count line-hash values. */ - memset(hashtab, '\0', sizeof(*hashtab) * (screen_lines + 1) * 2); - for (i = 0; i < screen_lines; i++) { - unsigned long hashval = oldhash[i]; - - for (sp = hashtab; sp->hashval; sp++) - if (sp->hashval == hashval) + memset(hashtab(SP_PARM), '\0', + sizeof(*(hashtab(SP_PARM))) + * ((size_t) screen_lines(SP_PARM) + 1) * 2); + for (i = 0; i < screen_lines(SP_PARM); i++) { + unsigned long hashval = oldhash(SP_PARM)[i]; + + for (hsp = hashtab(SP_PARM); hsp->hashval; hsp++) + if (hsp->hashval == hashval) break; - sp->hashval = hashval; /* in case this is a new entry */ - sp->oldcount++; - sp->oldindex = i; + hsp->hashval = hashval; /* in case this is a new entry */ + hsp->oldcount++; + hsp->oldindex = i; } - for (i = 0; i < screen_lines; i++) { - unsigned long hashval = newhash[i]; + for (i = 0; i < screen_lines(SP_PARM); i++) { + unsigned long hashval = newhash(SP_PARM)[i]; - for (sp = hashtab; sp->hashval; sp++) - if (sp->hashval == hashval) + for (hsp = hashtab(SP_PARM); hsp->hashval; hsp++) + if (hsp->hashval == hashval) break; - sp->hashval = hashval; /* in case this is a new entry */ - sp->newcount++; - sp->newindex = i; + hsp->hashval = hashval; /* in case this is a new entry */ + hsp->newcount++; + hsp->newindex = i; - OLDNUM(i) = _NEWINDEX; /* initialize old indices array */ + OLDNUM(SP_PARM, i) = _NEWINDEX; /* initialize old indices array */ } /* @@ -353,16 +376,16 @@ _nc_hash_map(void) * extending hunks by cost_effective. Otherwise, it does not * have any side effects. */ - for (sp = hashtab; sp->hashval; sp++) - if (sp->oldcount == 1 && sp->newcount == 1 - && sp->oldindex != sp->newindex) { + for (hsp = hashtab(SP_PARM); hsp->hashval; hsp++) + if (hsp->oldcount == 1 && hsp->newcount == 1 + && hsp->oldindex != hsp->newindex) { TR(TRACE_UPDATE | TRACE_MOVE, ("new line %d is hash-identical to old line %d (unique)", - sp->newindex, sp->oldindex)); - OLDNUM(sp->newindex) = sp->oldindex; + hsp->newindex, hsp->oldindex)); + OLDNUM(SP_PARM, hsp->newindex) = hsp->oldindex; } - grow_hunks(); + grow_hunks(SP_PARM); /* * Eliminate bad or impossible shifts -- this includes removing @@ -370,58 +393,85 @@ _nc_hash_map(void) * those which are to be moved too far, they are likely to destroy * more than carry. */ - for (i = 0; i < screen_lines;) { - while (i < screen_lines && OLDNUM(i) == _NEWINDEX) + for (i = 0; i < screen_lines(SP_PARM);) { + int start, shift, size; + + while (i < screen_lines(SP_PARM) && OLDNUM(SP_PARM, i) == _NEWINDEX) i++; - if (i >= screen_lines) + if (i >= screen_lines(SP_PARM)) break; start = i; - shift = OLDNUM(i) - i; + shift = OLDNUM(SP_PARM, i) - i; i++; - while (i < screen_lines && OLDNUM(i) != _NEWINDEX && OLDNUM(i) - i - == shift) + while (i < screen_lines(SP_PARM) + && OLDNUM(SP_PARM, i) != _NEWINDEX + && OLDNUM(SP_PARM, i) - i == shift) i++; size = i - start; if (size < 3 || size + min(size / 8, 2) < abs(shift)) { while (start < i) { - OLDNUM(start) = _NEWINDEX; + OLDNUM(SP_PARM, start) = _NEWINDEX; start++; } } } /* After clearing invalid hunks, try grow the rest. */ - grow_hunks(); + grow_hunks(SP_PARM); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(void) +_nc_hash_map(void) +{ + NCURSES_SP_NAME(_nc_hash_map) (CURRENT_SCREEN); +} +#endif + +NCURSES_EXPORT(void) +NCURSES_SP_NAME(_nc_make_oldhash) (NCURSES_SP_DCLx int i) +{ + if (oldhash(SP_PARM)) + oldhash(SP_PARM)[i] = hash(SP_PARM, OLDTEXT(SP_PARM, i)); +} + +#if NCURSES_SP_FUNCS NCURSES_EXPORT(void) _nc_make_oldhash(int i) { - if (oldhash) - oldhash[i] = hash(OLDTEXT(i)); + NCURSES_SP_NAME(_nc_make_oldhash) (CURRENT_SCREEN, i); } +#endif NCURSES_EXPORT(void) -_nc_scroll_oldhash(int n, int top, int bot) +NCURSES_SP_NAME(_nc_scroll_oldhash) (NCURSES_SP_DCLx int n, int top, int bot) { size_t size; int i; - if (!oldhash) + if (!oldhash(SP_PARM)) return; - size = sizeof(*oldhash) * (bot - top + 1 - abs(n)); + size = sizeof(*(oldhash(SP_PARM))) * (size_t) (bot - top + 1 - abs(n)); if (n > 0) { - memmove(oldhash + top, oldhash + top + n, size); + memmove(oldhash(SP_PARM) + top, oldhash(SP_PARM) + top + n, size); for (i = bot; i > bot - n; i--) - oldhash[i] = hash(OLDTEXT(i)); + oldhash(SP_PARM)[i] = hash(SP_PARM, OLDTEXT(SP_PARM, i)); } else { - memmove(oldhash + top - n, oldhash + top, size); + memmove(oldhash(SP_PARM) + top - n, oldhash(SP_PARM) + top, size); for (i = top; i < top - n; i++) - oldhash[i] = hash(OLDTEXT(i)); + oldhash(SP_PARM)[i] = hash(SP_PARM, OLDTEXT(SP_PARM, i)); } } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(void) +_nc_scroll_oldhash(int n, int top, int bot) +{ + NCURSES_SP_NAME(_nc_scroll_oldhash) (CURRENT_SCREEN, n, top, bot); +} +#endif + #ifdef HASHDEBUG static void usage(void) @@ -446,20 +496,20 @@ usage(void) int main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED) { - char line[BUFSIZ], *st, *last; + char line[BUFSIZ], *st; int n; if (setupterm(NULL, fileno(stdout), (int *) 0) == ERR) return EXIT_FAILURE; (void) _nc_alloc_screen(); - for (n = 0; n < screen_lines; n++) { + for (n = 0; n < screen_lines(sp); n++) { reallines[n] = n; oldnums[n] = _NEWINDEX; CharOf(oldtext[n][0]) = CharOf(newtext[n][0]) = '.'; } - if (isatty(fileno(stdin))) + if (NC_ISATTY(fileno(stdin))) usage(); #ifdef TRACE @@ -476,22 +526,22 @@ main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED) break; case 'l': /* get initial line number vector */ - for (n = 0; n < screen_lines; n++) { + for (n = 0; n < screen_lines(sp); n++) { reallines[n] = n; oldnums[n] = _NEWINDEX; } n = 0; - st = strtok_r(line, " ", &last); + st = strtok(line, " "); do { oldnums[n++] = atoi(st); } while - ((st = strtok_r((char *) NULL, " "), &last) != 0); + ((st = strtok((char *) NULL, " ")) != 0); break; case 'n': /* use following letters as text of new lines */ - for (n = 0; n < screen_lines; n++) + for (n = 0; n < screen_lines(sp); n++) CharOf(newtext[n][0]) = '.'; - for (n = 0; n < screen_lines; n++) + for (n = 0; n < screen_lines(sp); n++) if (line[n + 1] == '\n') break; else @@ -499,9 +549,9 @@ main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED) break; case 'o': /* use following letters as text of old lines */ - for (n = 0; n < screen_lines; n++) + for (n = 0; n < screen_lines(sp); n++) CharOf(oldtext[n][0]) = '.'; - for (n = 0; n < screen_lines; n++) + for (n = 0; n < screen_lines(sp); n++) if (line[n + 1] == '\n') break; else @@ -513,12 +563,12 @@ main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED) _nc_linedump(); #endif (void) fputs("Old lines: [", stdout); - for (n = 0; n < screen_lines; n++) + for (n = 0; n < screen_lines(sp); n++) putchar(CharOf(oldtext[n][0])); putchar(']'); putchar('\n'); (void) fputs("New lines: [", stdout); - for (n = 0; n < screen_lines; n++) + for (n = 0; n < screen_lines(sp); n++) putchar(CharOf(newtext[n][0])); putchar(']'); putchar('\n'); @@ -539,11 +589,7 @@ main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED) break; } } -#if NO_LEAKS - _nc_free_and_exit(EXIT_SUCCESS); -#else - return EXIT_SUCCESS; -#endif + exit_curses(EXIT_SUCCESS); } #endif /* HASHDEBUG */ diff --git a/lib/libcurses/tty/lib_mvcur.c b/lib/libcurses/tty/lib_mvcur.c index bd0b4334345..d2d4ac34458 100644 --- a/lib/libcurses/tty/lib_mvcur.c +++ b/lib/libcurses/tty/lib_mvcur.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_mvcur.c,v 1.13 2010/01/12 23:22:07 nicm Exp $ */ +/* $OpenBSD: lib_mvcur.c,v 1.14 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,6 +33,7 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -83,8 +85,8 @@ /* * The average overhead of a full optimization computation in character - * transmission times. If it's too high, the algorithm will be a bit - * over-biased toward using cup rather than local motions; if it's too + * transmission times. If it is too high, the algorithm will be a bit + * over-biased toward using cup rather than local motions; if it is too * low, the algorithm may spend more time than is strictly optimal * looking for non-cup motions. Profile the optimizer using the `t' * command of the exerciser (see below), and round to the nearest integer. @@ -98,7 +100,7 @@ /* * LONG_DIST is the distance we consider to be just as costly to move over as a - * cup sequence is to emit. In other words, it's the length of a cup sequence + * cup sequence is to emit. In other words, it is the length of a cup sequence * adjusted for average computation overhead. The magic number is the length * of "\033[yy;xxH", the typical cup sequence these days. */ @@ -111,8 +113,8 @@ * LONG_DIST and (b) further inward from the right or left edge than LONG_DIST, * we'll consider nonlocal. */ -#define NOT_LOCAL(fy, fx, ty, tx) ((tx > LONG_DIST) \ - && (tx < screen_columns - 1 - LONG_DIST) \ +#define NOT_LOCAL(sp, fy, fx, ty, tx) ((tx > LONG_DIST) \ + && (tx < screen_columns(sp) - 1 - LONG_DIST) \ && (abs(ty-fy) + abs(tx-fx) > LONG_DIST)) /**************************************************************************** @@ -148,19 +150,27 @@ * int _rep_cost; // cost of (repeat_char) * * The USE_HARD_TABS switch controls whether it is reliable to use tab/backtabs - * for local motions. On many systems, it's not, due to uncertainties about + * for local motions. On many systems, it is not, due to uncertainties about * tab delays and whether or not tabs will be expanded in raw mode. If you * have parm_right_cursor, tab motions don't win you a lot anyhow. */ #include -#include #include -MODULE_ID("$Id: lib_mvcur.c,v 1.13 2010/01/12 23:22:07 nicm Exp $") +#ifndef CUR +#define CUR SP_TERMTYPE +#endif + +MODULE_ID("$Id: lib_mvcur.c,v 1.14 2023/10/17 09:52:09 nicm Exp $") + +#define WANT_CHAR(sp, y, x) NewScreen(sp)->_line[y].text[x] /* desired state */ -#define WANT_CHAR(y, x) SP->_newscr->_line[y].text[x] /* desired state */ -#define BAUDRATE cur_term->_baudrate /* bits per second */ +#if NCURSES_SP_FUNCS +#define BAUDRATE(sp) sp->_term->_baudrate /* bits per second */ +#else +#define BAUDRATE(sp) cur_term->_baudrate /* bits per second */ +#endif #if defined(MAIN) || defined(NCURSES_TEST) #include @@ -169,9 +179,12 @@ static bool profiling = FALSE; static float diff; #endif /* MAIN */ +#undef NCURSES_OUTC_FUNC +#define NCURSES_OUTC_FUNC myOutCh + #define OPT_SIZE 512 -static int normalized_cost(const char *const cap, int affcnt); +static int normalized_cost(NCURSES_SP_DCLx const char *const cap, int affcnt); /**************************************************************************** * @@ -181,34 +194,34 @@ static int normalized_cost(const char *const cap, int affcnt); #ifdef TRACE static int -trace_cost_of(const char *capname, const char *cap, int affcnt) +trace_cost_of(NCURSES_SP_DCLx const char *capname, const char *cap, int affcnt) { - int result = _nc_msec_cost(cap, affcnt); + int result = NCURSES_SP_NAME(_nc_msec_cost) (NCURSES_SP_ARGx cap, affcnt); TR(TRACE_CHARPUT | TRACE_MOVE, ("CostOf %s %d %s", capname, result, _nc_visbuf(cap))); return result; } -#define CostOf(cap,affcnt) trace_cost_of(#cap,cap,affcnt); +#define CostOf(cap,affcnt) trace_cost_of(NCURSES_SP_ARGx #cap, cap, affcnt) static int -trace_normalized_cost(const char *capname, const char *cap, int affcnt) +trace_normalized_cost(NCURSES_SP_DCLx const char *capname, const char *cap, int affcnt) { - int result = normalized_cost(cap, affcnt); + int result = normalized_cost(NCURSES_SP_ARGx cap, affcnt); TR(TRACE_CHARPUT | TRACE_MOVE, ("NormalizedCost %s %d %s", capname, result, _nc_visbuf(cap))); return result; } -#define NormalizedCost(cap,affcnt) trace_normalized_cost(#cap,cap,affcnt); +#define NormalizedCost(cap,affcnt) trace_normalized_cost(NCURSES_SP_ARGx #cap, cap, affcnt) #else -#define CostOf(cap,affcnt) _nc_msec_cost(cap,affcnt); -#define NormalizedCost(cap,affcnt) normalized_cost(cap,affcnt); +#define CostOf(cap,affcnt) NCURSES_SP_NAME(_nc_msec_cost)(NCURSES_SP_ARGx cap, affcnt) +#define NormalizedCost(cap,affcnt) normalized_cost(NCURSES_SP_ARGx cap, affcnt) #endif NCURSES_EXPORT(int) -_nc_msec_cost(const char *const cap, int affcnt) +NCURSES_SP_NAME(_nc_msec_cost) (NCURSES_SP_DCLx const char *const cap, int affcnt) /* compute the cost of a given operation */ { if (cap == 0) @@ -224,53 +237,65 @@ _nc_msec_cost(const char *const cap, int affcnt) for (cp += 2; *cp != '>'; cp++) { if (isdigit(UChar(*cp))) - number = number * 10 + (*cp - '0'); + number = number * 10 + (float) (*cp - '0'); else if (*cp == '*') - number *= affcnt; + number *= (float) affcnt; else if (*cp == '.' && (*++cp != '>') && isdigit(UChar(*cp))) - number += (*cp - '0') / 10.0; + number += (float) ((*cp - '0') / 10.0); } #if NCURSES_NO_PADDING - if (!GetNoPadding(SP)) + if (!GetNoPadding(SP_PARM)) #endif cum_cost += number * 10; - } else - cum_cost += SP->_char_padding; + } else if (SP_PARM) { + cum_cost += (float) SP_PARM->_char_padding; + } } return ((int) cum_cost); } } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +_nc_msec_cost(const char *const cap, int affcnt) +{ + return NCURSES_SP_NAME(_nc_msec_cost) (CURRENT_SCREEN, cap, affcnt); +} +#endif + static int -normalized_cost(const char *const cap, int affcnt) +normalized_cost(NCURSES_SP_DCLx const char *const cap, int affcnt) /* compute the effective character-count for an operation (round up) */ { - int cost = _nc_msec_cost(cap, affcnt); + int cost = NCURSES_SP_NAME(_nc_msec_cost) (NCURSES_SP_ARGx cap, affcnt); if (cost != INFINITY) - cost = (cost + SP->_char_padding - 1) / SP->_char_padding; + cost = (cost + SP_PARM->_char_padding - 1) / SP_PARM->_char_padding; return cost; } static void -reset_scroll_region(void) +reset_scroll_region(NCURSES_SP_DCL0) /* Set the scroll-region to a known state (the default) */ { if (change_scroll_region) { - TPUTS_TRACE("change_scroll_region"); - putp(TPARM_2(change_scroll_region, 0, screen_lines - 1)); + NCURSES_PUTP2("change_scroll_region", + TIPARM_2(change_scroll_region, + 0, screen_lines(SP_PARM) - 1)); } } NCURSES_EXPORT(void) -_nc_mvcur_resume(void) +NCURSES_SP_NAME(_nc_mvcur_resume) (NCURSES_SP_DCL0) /* what to do at initialization time and after each shellout */ { + if (!SP_PARM || !IsTermInfo(SP_PARM)) + return; + /* initialize screen for cursor access */ if (enter_ca_mode) { - TPUTS_TRACE("enter_ca_mode"); - putp(enter_ca_mode); + NCURSES_PUTP2("enter_ca_mode", enter_ca_mode); } /* @@ -282,53 +307,66 @@ _nc_mvcur_resume(void) * they know the screen size. This is useful when you're running * a vt100 emulation through xterm. */ - reset_scroll_region(); - SP->_cursrow = SP->_curscol = -1; + reset_scroll_region(NCURSES_SP_ARG); + SP_PARM->_cursrow = SP_PARM->_curscol = -1; /* restore cursor shape */ - if (SP->_cursor != -1) { - int cursor = SP->_cursor; - SP->_cursor = -1; - curs_set(cursor); + if (SP_PARM->_cursor != -1) { + int cursor = SP_PARM->_cursor; + SP_PARM->_cursor = -1; + NCURSES_SP_NAME(curs_set) (NCURSES_SP_ARGx cursor); } } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(void) -_nc_mvcur_init(void) +_nc_mvcur_resume(void) +{ + NCURSES_SP_NAME(_nc_mvcur_resume) (CURRENT_SCREEN); +} +#endif + +NCURSES_EXPORT(void) +NCURSES_SP_NAME(_nc_mvcur_init) (NCURSES_SP_DCL0) /* initialize the cost structure */ { - if (isatty(fileno(SP->_ofp))) - SP->_char_padding = ((BAUDBYTE * 1000 * 10) - / (BAUDRATE > 0 ? BAUDRATE : 9600)); - else - SP->_char_padding = 1; /* must be nonzero */ - if (SP->_char_padding <= 0) - SP->_char_padding = 1; /* must be nonzero */ - TR(TRACE_CHARPUT | TRACE_MOVE, ("char_padding %d msecs", SP->_char_padding)); + if (SP_PARM->_ofp && NC_ISATTY(fileno(SP_PARM->_ofp))) { + SP_PARM->_char_padding = ((BAUDBYTE * 1000 * 10) + / (BAUDRATE(SP_PARM) > 0 + ? BAUDRATE(SP_PARM) + : 9600)); + } else { + SP_PARM->_char_padding = 1; /* must be nonzero */ + } + if (SP_PARM->_char_padding <= 0) + SP_PARM->_char_padding = 1; /* must be nonzero */ + TR(TRACE_CHARPUT | TRACE_MOVE, ("char_padding %d msecs", SP_PARM->_char_padding)); /* non-parameterized local-motion strings */ - SP->_cr_cost = CostOf(carriage_return, 0); - SP->_home_cost = CostOf(cursor_home, 0); - SP->_ll_cost = CostOf(cursor_to_ll, 0); + SP_PARM->_cr_cost = CostOf(carriage_return, 0); + SP_PARM->_home_cost = CostOf(cursor_home, 0); + SP_PARM->_ll_cost = CostOf(cursor_to_ll, 0); #if USE_HARD_TABS - if (getenv("NCURSES_NO_HARD_TABS") == 0) { - SP->_ht_cost = CostOf(tab, 0); - SP->_cbt_cost = CostOf(back_tab, 0); + if (getenv("NCURSES_NO_HARD_TABS") == 0 + && dest_tabs_magic_smso == 0 + && HasHardTabs()) { + SP_PARM->_ht_cost = CostOf(tab, 0); + SP_PARM->_cbt_cost = CostOf(back_tab, 0); } else { - SP->_ht_cost = INFINITY; - SP->_cbt_cost = INFINITY; + SP_PARM->_ht_cost = INFINITY; + SP_PARM->_cbt_cost = INFINITY; } #endif /* USE_HARD_TABS */ - SP->_cub1_cost = CostOf(cursor_left, 0); - SP->_cuf1_cost = CostOf(cursor_right, 0); - SP->_cud1_cost = CostOf(cursor_down, 0); - SP->_cuu1_cost = CostOf(cursor_up, 0); - - SP->_smir_cost = CostOf(enter_insert_mode, 0); - SP->_rmir_cost = CostOf(exit_insert_mode, 0); - SP->_ip_cost = 0; + SP_PARM->_cub1_cost = CostOf(cursor_left, 0); + SP_PARM->_cuf1_cost = CostOf(cursor_right, 0); + SP_PARM->_cud1_cost = CostOf(cursor_down, 0); + SP_PARM->_cuu1_cost = CostOf(cursor_up, 0); + + SP_PARM->_smir_cost = CostOf(enter_insert_mode, 0); + SP_PARM->_rmir_cost = CostOf(exit_insert_mode, 0); + SP_PARM->_ip_cost = 0; if (insert_padding) { - SP->_ip_cost = CostOf(insert_padding, 0); + SP_PARM->_ip_cost = CostOf(insert_padding, 0); } /* @@ -337,7 +375,7 @@ _nc_mvcur_init(void) * can treat it like absolute screen addressing. This seems to be true * for all cursor_mem_address terminal types in the terminfo database. */ - SP->_address_cursor = cursor_address ? cursor_address : cursor_mem_address; + SP_PARM->_address_cursor = cursor_address ? cursor_address : cursor_mem_address; /* * Parametrized local-motion strings. This static cost computation @@ -363,40 +401,42 @@ _nc_mvcur_init(void) * All these averages depend on the assumption that all parameter values * are equally probable. */ - SP->_cup_cost = CostOf(TPARM_2(SP->_address_cursor, 23, 23), 1); - SP->_cub_cost = CostOf(TPARM_1(parm_left_cursor, 23), 1); - SP->_cuf_cost = CostOf(TPARM_1(parm_right_cursor, 23), 1); - SP->_cud_cost = CostOf(TPARM_1(parm_down_cursor, 23), 1); - SP->_cuu_cost = CostOf(TPARM_1(parm_up_cursor, 23), 1); - SP->_hpa_cost = CostOf(TPARM_1(column_address, 23), 1); - SP->_vpa_cost = CostOf(TPARM_1(row_address, 23), 1); + SP_PARM->_cup_cost = CostOf(TIPARM_2(SP_PARM->_address_cursor, 23, 23), 1); + SP_PARM->_cub_cost = CostOf(TIPARM_1(parm_left_cursor, 23), 1); + SP_PARM->_cuf_cost = CostOf(TIPARM_1(parm_right_cursor, 23), 1); + SP_PARM->_cud_cost = CostOf(TIPARM_1(parm_down_cursor, 23), 1); + SP_PARM->_cuu_cost = CostOf(TIPARM_1(parm_up_cursor, 23), 1); + SP_PARM->_hpa_cost = CostOf(TIPARM_1(column_address, 23), 1); + SP_PARM->_vpa_cost = CostOf(TIPARM_1(row_address, 23), 1); /* non-parameterized screen-update strings */ - SP->_ed_cost = NormalizedCost(clr_eos, 1); - SP->_el_cost = NormalizedCost(clr_eol, 1); - SP->_el1_cost = NormalizedCost(clr_bol, 1); - SP->_dch1_cost = NormalizedCost(delete_character, 1); - SP->_ich1_cost = NormalizedCost(insert_character, 1); + SP_PARM->_ed_cost = NormalizedCost(clr_eos, 1); + SP_PARM->_el_cost = NormalizedCost(clr_eol, 1); + SP_PARM->_el1_cost = NormalizedCost(clr_bol, 1); + SP_PARM->_dch1_cost = NormalizedCost(delete_character, 1); + SP_PARM->_ich1_cost = NormalizedCost(insert_character, 1); /* * If this is a bce-terminal, we want to bias the choice so we use clr_eol * rather than spaces at the end of a line. */ if (back_color_erase) - SP->_el_cost = 0; + SP_PARM->_el_cost = 0; /* parameterized screen-update strings */ - SP->_dch_cost = NormalizedCost(TPARM_1(parm_dch, 23), 1); - SP->_ich_cost = NormalizedCost(TPARM_1(parm_ich, 23), 1); - SP->_ech_cost = NormalizedCost(TPARM_1(erase_chars, 23), 1); - SP->_rep_cost = NormalizedCost(TPARM_2(repeat_char, ' ', 23), 1); - - SP->_cup_ch_cost = NormalizedCost(TPARM_2(SP->_address_cursor, 23, 23), 1); - SP->_hpa_ch_cost = NormalizedCost(TPARM_1(column_address, 23), 1); - SP->_cuf_ch_cost = NormalizedCost(TPARM_1(parm_right_cursor, 23), 1); - SP->_inline_cost = min(SP->_cup_ch_cost, - min(SP->_hpa_ch_cost, - SP->_cuf_ch_cost)); + SP_PARM->_dch_cost = NormalizedCost(TIPARM_1(parm_dch, 23), 1); + SP_PARM->_ich_cost = NormalizedCost(TIPARM_1(parm_ich, 23), 1); + SP_PARM->_ech_cost = NormalizedCost(TIPARM_1(erase_chars, 23), 1); + SP_PARM->_rep_cost = NormalizedCost(TIPARM_2(repeat_char, ' ', 23), 1); + + SP_PARM->_cup_ch_cost = NormalizedCost(TIPARM_2(SP_PARM->_address_cursor, + 23, 23), + 1); + SP_PARM->_hpa_ch_cost = NormalizedCost(TIPARM_1(column_address, 23), 1); + SP_PARM->_cuf_ch_cost = NormalizedCost(TIPARM_1(parm_right_cursor, 23), 1); + SP_PARM->_inline_cost = min(SP_PARM->_cup_ch_cost, + min(SP_PARM->_hpa_ch_cost, + SP_PARM->_cuf_ch_cost)); /* * If save_cursor is used within enter_ca_mode, we should not use it for @@ -413,30 +453,40 @@ _nc_mvcur_init(void) } /* - * A different, possibly better way to arrange this would be to set - * SP->_endwin = TRUE at window initialization time and let this be - * called by doupdate's return-from-shellout code. + * A different, possibly better way to arrange this would be to set the + * SCREEN's _endwin at window initialization time and let this be called by + * doupdate's return-from-shellout code. */ - _nc_mvcur_resume(); + NCURSES_SP_NAME(_nc_mvcur_resume) (NCURSES_SP_ARG); } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(void) -_nc_mvcur_wrap(void) +_nc_mvcur_init(void) +{ + NCURSES_SP_NAME(_nc_mvcur_init) (CURRENT_SCREEN); +} +#endif + +NCURSES_EXPORT(void) +NCURSES_SP_NAME(_nc_mvcur_wrap) (NCURSES_SP_DCL0) /* wrap up cursor-addressing mode */ { + if (!SP_PARM || !IsTermInfo(SP_PARM)) + return; + /* leave cursor at screen bottom */ - mvcur(-1, -1, screen_lines - 1, 0); + TINFO_MVCUR(NCURSES_SP_ARGx -1, -1, screen_lines(SP_PARM) - 1, 0); /* set cursor to normal mode */ - if (SP->_cursor != -1) { - int cursor = SP->_cursor; - curs_set(1); - SP->_cursor = cursor; + if (SP_PARM->_cursor != -1) { + int cursor = SP_PARM->_cursor; + NCURSES_SP_NAME(curs_set) (NCURSES_SP_ARGx 1); + SP_PARM->_cursor = cursor; } if (exit_ca_mode) { - TPUTS_TRACE("exit_ca_mode"); - putp(exit_ca_mode); + NCURSES_PUTP2("exit_ca_mode", exit_ca_mode); } /* * Reset terminal's tab counter. There's a long-time bug that @@ -446,9 +496,17 @@ _nc_mvcur_wrap(void) * escape sequences that reset things as column positions. * Utter a \r to reset this invisibly. */ - _nc_outch('\r'); + NCURSES_SP_NAME(_nc_outch) (NCURSES_SP_ARGx '\r'); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(void) +_nc_mvcur_wrap(void) +{ + NCURSES_SP_NAME(_nc_mvcur_wrap) (CURRENT_SCREEN); +} +#endif + /**************************************************************************** * * Optimized cursor movement @@ -461,7 +519,7 @@ _nc_mvcur_wrap(void) static NCURSES_INLINE int repeated_append(string_desc * target, int total, int num, int repeat, const char *src) { - size_t need = repeat * strlen(src); + size_t need = (size_t) repeat * strlen(src); if (need < target->s_size) { while (repeat-- > 0) { @@ -488,8 +546,13 @@ repeated_append(string_desc * target, int total, int num, int repeat, const char #define LASTTAB(fr) ((fr > 0) ? ((fr - 1) / init_tabs) * init_tabs : -1) static int -relative_move(string_desc * target, int from_y, int from_x, int to_y, int - to_x, bool ovw) +relative_move(NCURSES_SP_DCLx + string_desc * target, + int from_y, + int from_x, + int to_y, + int to_x, + int ovw) /* move via local motions (cuu/cuu1/cud/cud1/cub1/cub/cuf1/cuf/vpa/hpa) */ { string_desc save; @@ -501,39 +564,39 @@ relative_move(string_desc * target, int from_y, int from_x, int to_y, int vcost = INFINITY; if (row_address != 0 - && _nc_safe_strcat(target, TPARM_1(row_address, to_y))) { - vcost = SP->_vpa_cost; + && _nc_safe_strcat(target, TIPARM_1(row_address, to_y))) { + vcost = SP_PARM->_vpa_cost; } if (to_y > from_y) { n = (to_y - from_y); if (parm_down_cursor - && SP->_cud_cost < vcost + && SP_PARM->_cud_cost < vcost && _nc_safe_strcat(_nc_str_copy(target, &save), - TPARM_1(parm_down_cursor, n))) { - vcost = SP->_cud_cost; + TIPARM_1(parm_down_cursor, n))) { + vcost = SP_PARM->_cud_cost; } if (cursor_down - && (*cursor_down != '\n' || SP->_nl) - && (n * SP->_cud1_cost < vcost)) { + && (*cursor_down != '\n') + && (n * SP_PARM->_cud1_cost < vcost)) { vcost = repeated_append(_nc_str_copy(target, &save), 0, - SP->_cud1_cost, n, cursor_down); + SP_PARM->_cud1_cost, n, cursor_down); } } else { /* (to_y < from_y) */ n = (from_y - to_y); if (parm_up_cursor - && SP->_cuu_cost < vcost + && SP_PARM->_cuu_cost < vcost && _nc_safe_strcat(_nc_str_copy(target, &save), - TPARM_1(parm_up_cursor, n))) { - vcost = SP->_cuu_cost; + TIPARM_1(parm_up_cursor, n))) { + vcost = SP_PARM->_cuu_cost; } - if (cursor_up && (n * SP->_cuu1_cost < vcost)) { + if (cursor_up && (n * SP_PARM->_cuu1_cost < vcost)) { vcost = repeated_append(_nc_str_copy(target, &save), 0, - SP->_cuu1_cost, n, cursor_up); + SP_PARM->_cuu1_cost, n, cursor_up); } } @@ -551,18 +614,18 @@ relative_move(string_desc * target, int from_y, int from_x, int to_y, int if (column_address && _nc_safe_strcat(_nc_str_copy(target, &save), - TPARM_1(column_address, to_x))) { - hcost = SP->_hpa_cost; + TIPARM_1(column_address, to_x))) { + hcost = SP_PARM->_hpa_cost; } if (to_x > from_x) { n = to_x - from_x; if (parm_right_cursor - && SP->_cuf_cost < hcost + && SP_PARM->_cuf_cost < hcost && _nc_safe_strcat(_nc_str_copy(target, &save), - TPARM_1(parm_right_cursor, n))) { - hcost = SP->_cuf_cost; + TIPARM_1(parm_right_cursor, n))) { + hcost = SP_PARM->_cuf_cost; } if (cursor_right) { @@ -577,7 +640,7 @@ relative_move(string_desc * target, int from_y, int from_x, int to_y, int for (fr = from_x; (nxt = NEXTTAB(fr)) <= to_x; fr = nxt) { lhcost = repeated_append(&check, lhcost, - SP->_ht_cost, 1, tab); + SP_PARM->_ht_cost, 1, tab); if (lhcost == INFINITY) break; } @@ -601,7 +664,7 @@ relative_move(string_desc * target, int from_y, int from_x, int to_y, int && n < (int) check.s_size && vcost == 0 && str[0] == '\0') { - int wanted = CharOf(WANT_CHAR(to_y, from_x)); + int wanted = CharOf(WANT_CHAR(SP_PARM, to_y, from_x)); if (is8bits(wanted) && isdigit(wanted)) ovw = FALSE; } @@ -614,12 +677,12 @@ relative_move(string_desc * target, int from_y, int from_x, int to_y, int * and the time the structure WANT_CHAR would access has been * updated. */ - if (ovw) { + if (ovw && to_y >= 0) { int i; for (i = 0; i < n; i++) { - NCURSES_CH_T ch = WANT_CHAR(to_y, from_x + i); - if (!SameAttrOf(ch, SCREEN_ATTRS(SP)) + NCURSES_CH_T ch = WANT_CHAR(SP_PARM, to_y, from_x + i); + if (!SameAttrOf(ch, SCREEN_ATTRS(SP_PARM)) #if USE_WIDEC_SUPPORT || !Charable(ch) #endif @@ -629,17 +692,17 @@ relative_move(string_desc * target, int from_y, int from_x, int to_y, int } } } - if (ovw) { + if (ovw && to_y >= 0) { int i; for (i = 0; i < n; i++) - *check.s_tail++ = (char) CharOf(WANT_CHAR(to_y, + *check.s_tail++ = (char) CharOf(WANT_CHAR(SP_PARM, to_y, from_x + i)); *check.s_tail = '\0'; - check.s_size -= n; - lhcost += n * SP->_char_padding; + check.s_size -= (size_t) n; + lhcost += n * SP_PARM->_char_padding; } else { - lhcost = repeated_append(&check, lhcost, SP->_cuf1_cost, + lhcost = repeated_append(&check, lhcost, SP_PARM->_cuf1_cost, n, cursor_right); } @@ -652,10 +715,10 @@ relative_move(string_desc * target, int from_y, int from_x, int to_y, int n = from_x - to_x; if (parm_left_cursor - && SP->_cub_cost < hcost + && SP_PARM->_cub_cost < hcost && _nc_safe_strcat(_nc_str_copy(target, &save), - TPARM_1(parm_left_cursor, n))) { - hcost = SP->_cub_cost; + TIPARM_1(parm_left_cursor, n))) { + hcost = SP_PARM->_cub_cost; } if (cursor_left) { @@ -669,7 +732,8 @@ relative_move(string_desc * target, int from_y, int from_x, int to_y, int for (fr = from_x; (nxt = LASTTAB(fr)) >= to_x; fr = nxt) { lhcost = repeated_append(&check, lhcost, - SP->_cbt_cost, 1, back_tab); + SP_PARM->_cbt_cost, + 1, back_tab); if (lhcost == INFINITY) break; } @@ -678,7 +742,9 @@ relative_move(string_desc * target, int from_y, int from_x, int to_y, int } #endif /* USE_HARD_TABS */ - lhcost = repeated_append(&check, lhcost, SP->_cub1_cost, n, cursor_left); + lhcost = repeated_append(&check, lhcost, + SP_PARM->_cub1_cost, + n, cursor_left); if (lhcost < hcost && _nc_safe_strcat(_nc_str_copy(target, &save), str)) { @@ -696,7 +762,7 @@ relative_move(string_desc * target, int from_y, int from_x, int to_y, int #endif /* !NO_OPTIMIZE */ /* - * With the machinery set up above, it's conceivable that + * With the machinery set up above, it is conceivable that * onscreen_mvcur could be modified into a recursive function that does * an alpha-beta search of motion space, as though it were a chess * move tree, with the weight function being boolean and the search @@ -707,7 +773,10 @@ relative_move(string_desc * target, int from_y, int from_x, int to_y, int */ static NCURSES_INLINE int -onscreen_mvcur(int yold, int xold, int ynew, int xnew, bool ovw) +onscreen_mvcur(NCURSES_SP_DCLx + int yold, int xold, + int ynew, int xnew, int ovw, + NCURSES_SP_OUTC myOutCh) /* onscreen move from (yold, xold) to (ynew, xnew) */ { string_desc result; @@ -725,9 +794,10 @@ onscreen_mvcur(int yold, int xold, int ynew, int xnew, bool ovw) #define InitResult _nc_str_init(&result, buffer, sizeof(buffer)) /* tactic #0: use direct cursor addressing */ - if (_nc_safe_strcpy(InitResult, TPARM_2(SP->_address_cursor, ynew, xnew))) { + if (_nc_safe_strcpy(InitResult, TIPARM_2(SP_PARM->_address_cursor, + ynew, xnew))) { tactic = 0; - usecost = SP->_cup_cost; + usecost = SP_PARM->_cup_cost; #if defined(TRACE) || defined(NCURSES_TEST) if (!(_nc_optimize_enable & OPTIMIZE_MVCUR)) @@ -742,7 +812,7 @@ onscreen_mvcur(int yold, int xold, int ynew, int xnew, bool ovw) * (like, say, local-movement \n getting mapped to some obscure * character because A_ALTCHARSET is on). */ - if (yold == -1 || xold == -1 || NOT_LOCAL(yold, xold, ynew, xnew)) { + if (yold == -1 || xold == -1 || NOT_LOCAL(SP_PARM, yold, xold, ynew, xnew)) { #if defined(MAIN) || defined(NCURSES_TEST) if (!profiling) { (void) fputs("nonlocal\n", stderr); @@ -756,8 +826,10 @@ onscreen_mvcur(int yold, int xold, int ynew, int xnew, bool ovw) #ifndef NO_OPTIMIZE /* tactic #1: use local movement */ if (yold != -1 && xold != -1 - && ((newcost = relative_move(NullResult, yold, xold, ynew, xnew, - ovw)) != INFINITY) + && ((newcost = relative_move(NCURSES_SP_ARGx + NullResult, + yold, xold, + ynew, xnew, ovw)) != INFINITY) && newcost < usecost) { tactic = 1; usecost = newcost; @@ -765,42 +837,51 @@ onscreen_mvcur(int yold, int xold, int ynew, int xnew, bool ovw) /* tactic #2: use carriage-return + local movement */ if (yold != -1 && carriage_return - && ((newcost = relative_move(NullResult, yold, 0, ynew, xnew, ovw)) - != INFINITY) - && SP->_cr_cost + newcost < usecost) { + && ((newcost = relative_move(NCURSES_SP_ARGx + NullResult, + yold, 0, + ynew, xnew, ovw)) != INFINITY) + && SP_PARM->_cr_cost + newcost < usecost) { tactic = 2; - usecost = SP->_cr_cost + newcost; + usecost = SP_PARM->_cr_cost + newcost; } /* tactic #3: use home-cursor + local movement */ if (cursor_home - && ((newcost = relative_move(NullResult, 0, 0, ynew, xnew, ovw)) != INFINITY) - && SP->_home_cost + newcost < usecost) { + && ((newcost = relative_move(NCURSES_SP_ARGx + NullResult, + 0, 0, + ynew, xnew, ovw)) != INFINITY) + && SP_PARM->_home_cost + newcost < usecost) { tactic = 3; - usecost = SP->_home_cost + newcost; + usecost = SP_PARM->_home_cost + newcost; } /* tactic #4: use home-down + local movement */ if (cursor_to_ll - && ((newcost = relative_move(NullResult, screen_lines - 1, 0, ynew, - xnew, ovw)) != INFINITY) - && SP->_ll_cost + newcost < usecost) { + && ((newcost = relative_move(NCURSES_SP_ARGx + NullResult, + screen_lines(SP_PARM) - 1, 0, + ynew, xnew, ovw)) != INFINITY) + && SP_PARM->_ll_cost + newcost < usecost) { tactic = 4; - usecost = SP->_ll_cost + newcost; + usecost = SP_PARM->_ll_cost + newcost; } /* * tactic #5: use left margin for wrap to right-hand side, * unless strange wrap behavior indicated by xenl might hose us. */ - t5_cr_cost = (xold > 0 ? SP->_cr_cost : 0); + t5_cr_cost = (xold > 0 ? SP_PARM->_cr_cost : 0); if (auto_left_margin && !eat_newline_glitch && yold > 0 && cursor_left - && ((newcost = relative_move(NullResult, yold - 1, screen_columns - - 1, ynew, xnew, ovw)) != INFINITY) - && t5_cr_cost + SP->_cub1_cost + newcost < usecost) { + && ((newcost = relative_move(NCURSES_SP_ARGx + NullResult, + yold - 1, screen_columns(SP_PARM) - 1, + ynew, xnew, ovw)) != INFINITY) + && t5_cr_cost + SP_PARM->_cub1_cost + newcost < usecost) { tactic = 5; - usecost = t5_cr_cost + SP->_cub1_cost + newcost; + usecost = t5_cr_cost + SP_PARM->_cub1_cost + newcost; } /* @@ -810,26 +891,39 @@ onscreen_mvcur(int yold, int xold, int ynew, int xnew, bool ovw) InitResult; switch (tactic) { case 1: - (void) relative_move(&result, yold, xold, ynew, xnew, ovw); + (void) relative_move(NCURSES_SP_ARGx + &result, + yold, xold, + ynew, xnew, ovw); break; case 2: (void) _nc_safe_strcpy(&result, carriage_return); - (void) relative_move(&result, yold, 0, ynew, xnew, ovw); + (void) relative_move(NCURSES_SP_ARGx + &result, + yold, 0, + ynew, xnew, ovw); break; case 3: (void) _nc_safe_strcpy(&result, cursor_home); - (void) relative_move(&result, 0, 0, ynew, xnew, ovw); + (void) relative_move(NCURSES_SP_ARGx + &result, 0, 0, + ynew, xnew, ovw); break; case 4: (void) _nc_safe_strcpy(&result, cursor_to_ll); - (void) relative_move(&result, screen_lines - 1, 0, ynew, xnew, ovw); + (void) relative_move(NCURSES_SP_ARGx + &result, + screen_lines(SP_PARM) - 1, 0, + ynew, xnew, ovw); break; case 5: if (xold > 0) (void) _nc_safe_strcat(&result, carriage_return); (void) _nc_safe_strcat(&result, cursor_left); - (void) relative_move(&result, yold - 1, screen_columns - 1, ynew, - xnew, ovw); + (void) relative_move(NCURSES_SP_ARGx + &result, + yold - 1, screen_columns(SP_PARM) - 1, + ynew, xnew, ovw); break; } #endif /* !NO_OPTIMIZE */ @@ -846,26 +940,34 @@ onscreen_mvcur(int yold, int xold, int ynew, int xnew, bool ovw) #endif /* MAIN */ if (usecost != INFINITY) { + TR(TRACE_MOVE, ("mvcur tactic %d", tactic)); TPUTS_TRACE("mvcur"); - tputs(buffer, 1, _nc_outch); - SP->_cursrow = ynew; - SP->_curscol = xnew; + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + buffer, 1, myOutCh); + SP_PARM->_cursrow = ynew; + SP_PARM->_curscol = xnew; return (OK); } else return (ERR); } -NCURSES_EXPORT(int) -mvcur(int yold, int xold, int ynew, int xnew) -/* optimized cursor move from (yold, xold) to (ynew, xnew) */ +/* + * optimized cursor move from (yold, xold) to (ynew, xnew) + */ +static int +_nc_real_mvcur(NCURSES_SP_DCLx + int yold, int xold, + int ynew, int xnew, + NCURSES_SP_OUTC myOutCh, + int ovw) { NCURSES_CH_T oldattr; int code; - TR(TRACE_CALLS | TRACE_MOVE, (T_CALLED("mvcur(%d,%d,%d,%d)"), - yold, xold, ynew, xnew)); + TR(TRACE_CALLS | TRACE_MOVE, (T_CALLED("_nc_real_mvcur(%p,%d,%d,%d,%d)"), + (void *) SP_PARM, yold, xold, ynew, xnew)); - if (SP == 0) { + if (SP_PARM == 0) { code = ERR; } else if (yold == ynew && xold == xnew) { code = OK; @@ -876,9 +978,9 @@ mvcur(int yold, int xold, int ynew, int xnew) * column position implied by wraparound or the lack thereof and * rolling up the screen to get ynew on the screen. */ - if (xnew >= screen_columns) { - ynew += xnew / screen_columns; - xnew %= screen_columns; + if (xnew >= screen_columns(SP_PARM)) { + ynew += xnew / screen_columns(SP_PARM); + xnew %= screen_columns(SP_PARM); } /* @@ -886,72 +988,138 @@ mvcur(int yold, int xold, int ynew, int xnew) * character set -- these have a strong tendency to screw up the CR & * LF used for local character motions! */ - oldattr = SCREEN_ATTRS(SP); + oldattr = SCREEN_ATTRS(SP_PARM); if ((AttrOf(oldattr) & A_ALTCHARSET) || (AttrOf(oldattr) && !move_standout_mode)) { TR(TRACE_CHARPUT, ("turning off (%#lx) %s before move", (unsigned long) AttrOf(oldattr), _traceattr(AttrOf(oldattr)))); - (void) VIDATTR(A_NORMAL, 0); + VIDPUTS(SP_PARM, A_NORMAL, 0); } - if (xold >= screen_columns) { - int l; - - if (SP->_nl) { - l = (xold + 1) / screen_columns; - yold += l; - if (yold >= screen_lines) - l -= (yold - screen_lines - 1); - - if (l > 0) { - if (carriage_return) { - TPUTS_TRACE("carriage_return"); - putp(carriage_return); - } else - _nc_outch('\r'); - xold = 0; - - while (l > 0) { - if (newline) { - TPUTS_TRACE("newline"); - putp(newline); - } else - _nc_outch('\n'); - l--; + if (xold >= screen_columns(SP_PARM)) { + + int l = (xold + 1) / screen_columns(SP_PARM); + + yold += l; + if (yold >= screen_lines(SP_PARM)) + l -= (yold - screen_lines(SP_PARM) - 1); + + if (l > 0) { + if (carriage_return) { + NCURSES_PUTP2("carriage_return", carriage_return); + } else { + myOutCh(NCURSES_SP_ARGx '\r'); + } + xold = 0; + + while (l > 0) { + if (newline) { + NCURSES_PUTP2("newline", newline); + } else { + myOutCh(NCURSES_SP_ARGx '\n'); } + l--; } - } else { - /* - * If caller set nonl(), we cannot really use newlines to - * position to the next row. - */ - xold = -1; - yold = -1; } } - if (yold > screen_lines - 1) - yold = screen_lines - 1; - if (ynew > screen_lines - 1) - ynew = screen_lines - 1; + if (yold > screen_lines(SP_PARM) - 1) + yold = screen_lines(SP_PARM) - 1; + if (ynew > screen_lines(SP_PARM) - 1) + ynew = screen_lines(SP_PARM) - 1; /* destination location is on screen now */ - code = onscreen_mvcur(yold, xold, ynew, xnew, TRUE); + code = onscreen_mvcur(NCURSES_SP_ARGx yold, xold, ynew, xnew, ovw, myOutCh); /* * Restore attributes if we disabled them before moving. */ - if (!SameAttrOf(oldattr, SCREEN_ATTRS(SP))) { + if (!SameAttrOf(oldattr, SCREEN_ATTRS(SP_PARM))) { TR(TRACE_CHARPUT, ("turning on (%#lx) %s after move", (unsigned long) AttrOf(oldattr), _traceattr(AttrOf(oldattr)))); - (void) VIDATTR(AttrOf(oldattr), GetPair(oldattr)); + VIDPUTS(SP_PARM, AttrOf(oldattr), GetPair(oldattr)); } } returnCode(code); } +/* + * These entrypoints are used within the library. + */ +NCURSES_EXPORT(int) +NCURSES_SP_NAME(_nc_mvcur) (NCURSES_SP_DCLx + int yold, int xold, + int ynew, int xnew) +{ + int rc; + rc = _nc_real_mvcur(NCURSES_SP_ARGx yold, xold, ynew, xnew, + NCURSES_SP_NAME(_nc_outch), + TRUE); + /* + * With the terminal-driver, we cannot distinguish between internal and + * external calls. Flush the output if the screen has not been + * initialized, e.g., when used from low-level terminfo programs. + */ + if ((SP_PARM != 0) && (SP_PARM->_endwin == ewInitial)) + NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG); + return rc; +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +_nc_mvcur(int yold, int xold, + int ynew, int xnew) +{ + return NCURSES_SP_NAME(_nc_mvcur) (CURRENT_SCREEN, yold, xold, ynew, xnew); +} +#endif + +#if defined(USE_TERM_DRIVER) +/* + * The terminal driver does not support the external "mvcur()". + */ +NCURSES_EXPORT(int) +TINFO_MVCUR(NCURSES_SP_DCLx int yold, int xold, int ynew, int xnew) +{ + int rc; + rc = _nc_real_mvcur(NCURSES_SP_ARGx + yold, xold, + ynew, xnew, + NCURSES_SP_NAME(_nc_outch), + TRUE); + if ((SP_PARM != 0) && (SP_PARM->_endwin == ewInitial)) + NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG); + NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG); + return rc; +} + +#else /* !USE_TERM_DRIVER */ + +/* + * These entrypoints support users of the library. + */ +NCURSES_EXPORT(int) +NCURSES_SP_NAME(mvcur) (NCURSES_SP_DCLx int yold, int xold, int ynew, + int xnew) +{ + return _nc_real_mvcur(NCURSES_SP_ARGx + yold, xold, + ynew, xnew, + NCURSES_SP_NAME(_nc_putchar), + FALSE); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +mvcur(int yold, int xold, int ynew, int xnew) +{ + return NCURSES_SP_NAME(mvcur) (CURRENT_SCREEN, yold, xold, ynew, xnew); +} +#endif +#endif /* USE_TERM_DRIVER */ + #if defined(TRACE) || defined(NCURSES_TEST) NCURSES_EXPORT_VAR(int) _nc_optimize_enable = OPTIMIZE_ALL; #endif @@ -1024,13 +1192,12 @@ roll(int n) int main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED) { - strlcpy(tname, sizeof(tname), getenv("TERM")); + _nc_STRCPY(tname, getenv("TERM"), sizeof(tname)); load_term(); _nc_setupscreen(lines, columns, stdout, FALSE, 0); baudrate(); _nc_mvcur_init(); - NC_BUFFERED(FALSE); (void) puts("The mvcur tester. Type ? for help"); @@ -1041,31 +1208,26 @@ main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED) int fy, fx, ty, tx, n, i; char buf[BUFSIZ], capname[BUFSIZ]; - (void) fputs("> ", stdout); - if (fgets(buf, sizeof(buf), stdin) == NULL) { - if (ferror(stdin)) - fputs("ferror on stdin", stderr); - break; - } + if (fputs("> ", stdout) == EOF) + break; + if (fgets(buf, sizeof(buf), stdin) == 0) + break; +#define PUTS(s) (void) puts(s) +#define PUTF(s,t) (void) printf(s,t) if (buf[0] == '?') { - (void) puts("? -- display this help message"); - (void) - puts("fy fx ty tx -- (4 numbers) display (fy,fx)->(ty,tx) move"); - (void) puts("s[croll] n t b m -- display scrolling sequence"); - (void) - printf("r[eload] -- reload terminal info for %s\n", - termname()); - (void) - puts("l[oad] -- load terminal info for type "); - (void) puts("d[elete] -- delete named capability"); - (void) puts("i[nspect] -- display terminal capabilities"); - (void) - puts("c[ost] -- dump cursor-optimization cost table"); - (void) puts("o[optimize] -- toggle movement optimization"); - (void) - puts("t[orture] -- torture-test with random moves"); - (void) puts("q[uit] -- quit the program"); + PUTS("? -- display this help message"); + PUTS("fy fx ty tx -- (4 numbers) display (fy,fx)->(ty,tx) move"); + PUTS("s[croll] n t b m -- display scrolling sequence"); + PUTF("r[eload] -- reload terminal info for %s\n", + termname()); + PUTS("l[oad] -- load terminal info for type "); + PUTS("d[elete] -- delete named capability"); + PUTS("i[nspect] -- display terminal capabilities"); + PUTS("c[ost] -- dump cursor-optimization cost table"); + PUTS("o[optimize] -- toggle movement optimization"); + PUTS("t[orture] -- torture-test with random moves"); + PUTS("q[uit] -- quit the program"); } else if (sscanf(buf, "%d %d %d %d", &fy, &fx, &ty, &tx) == 4) { struct timeval before, after; @@ -1093,7 +1255,7 @@ main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED) before.tv_sec) * 1000000)); } else if (buf[0] == 'r') { - (void) strlcpy(tname, sizeof(tname), termname()); + _nc_STRCPY(tname, termname(), sizeof(tname)); load_term(); } else if (sscanf(buf, "l %s", tname) == 1) { load_term(); @@ -1126,8 +1288,9 @@ main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED) } } } else if (buf[0] == 'i') { - dump_init((char *) NULL, F_TERMINFO, S_TERMINFO, 70, 0, FALSE); - dump_entry(&cur_term->type, FALSE, TRUE, 0, 0); + dump_init(NULL, F_TERMINFO, S_TERMINFO, + FALSE, 70, 0, 0, FALSE, FALSE, 0); + dump_entry(&TerminalType(cur_term), FALSE, TRUE, 0, 0); putchar('\n'); } else if (buf[0] == 'o') { if (_nc_optimize_enable & OPTIMIZE_MVCUR) { @@ -1218,25 +1381,25 @@ main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED) speeds[i], overhead, totalest); } } else if (buf[0] == 'c') { - (void) printf("char padding: %d\n", SP->_char_padding); - (void) printf("cr cost: %d\n", SP->_cr_cost); - (void) printf("cup cost: %d\n", SP->_cup_cost); - (void) printf("home cost: %d\n", SP->_home_cost); - (void) printf("ll cost: %d\n", SP->_ll_cost); + (void) printf("char padding: %d\n", CURRENT_SCREEN->_char_padding); + (void) printf("cr cost: %d\n", CURRENT_SCREEN->_cr_cost); + (void) printf("cup cost: %d\n", CURRENT_SCREEN->_cup_cost); + (void) printf("home cost: %d\n", CURRENT_SCREEN->_home_cost); + (void) printf("ll cost: %d\n", CURRENT_SCREEN->_ll_cost); #if USE_HARD_TABS - (void) printf("ht cost: %d\n", SP->_ht_cost); - (void) printf("cbt cost: %d\n", SP->_cbt_cost); + (void) printf("ht cost: %d\n", CURRENT_SCREEN->_ht_cost); + (void) printf("cbt cost: %d\n", CURRENT_SCREEN->_cbt_cost); #endif /* USE_HARD_TABS */ - (void) printf("cub1 cost: %d\n", SP->_cub1_cost); - (void) printf("cuf1 cost: %d\n", SP->_cuf1_cost); - (void) printf("cud1 cost: %d\n", SP->_cud1_cost); - (void) printf("cuu1 cost: %d\n", SP->_cuu1_cost); - (void) printf("cub cost: %d\n", SP->_cub_cost); - (void) printf("cuf cost: %d\n", SP->_cuf_cost); - (void) printf("cud cost: %d\n", SP->_cud_cost); - (void) printf("cuu cost: %d\n", SP->_cuu_cost); - (void) printf("hpa cost: %d\n", SP->_hpa_cost); - (void) printf("vpa cost: %d\n", SP->_vpa_cost); + (void) printf("cub1 cost: %d\n", CURRENT_SCREEN->_cub1_cost); + (void) printf("cuf1 cost: %d\n", CURRENT_SCREEN->_cuf1_cost); + (void) printf("cud1 cost: %d\n", CURRENT_SCREEN->_cud1_cost); + (void) printf("cuu1 cost: %d\n", CURRENT_SCREEN->_cuu1_cost); + (void) printf("cub cost: %d\n", CURRENT_SCREEN->_cub_cost); + (void) printf("cuf cost: %d\n", CURRENT_SCREEN->_cuf_cost); + (void) printf("cud cost: %d\n", CURRENT_SCREEN->_cud_cost); + (void) printf("cuu cost: %d\n", CURRENT_SCREEN->_cuu_cost); + (void) printf("hpa cost: %d\n", CURRENT_SCREEN->_hpa_cost); + (void) printf("vpa cost: %d\n", CURRENT_SCREEN->_vpa_cost); } else if (buf[0] == 'x' || buf[0] == 'q') break; else diff --git a/lib/libcurses/tty/lib_tstp.c b/lib/libcurses/tty/lib_tstp.c index a1917182e11..d8a274f3952 100644 --- a/lib/libcurses/tty/lib_tstp.c +++ b/lib/libcurses/tty/lib_tstp.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_tstp.c,v 1.11 2011/05/30 21:59:35 deraadt Exp $ */ +/* $OpenBSD: lib_tstp.c,v 1.12 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020-2021,2022 Thomas E. Dickey * + * Copyright 1998-2014,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -44,11 +45,7 @@ #include -#if SVR4_ACTION && !defined(_POSIX_SOURCE) -#define _POSIX_SOURCE -#endif - -MODULE_ID("$Id: lib_tstp.c,v 1.11 2011/05/30 21:59:35 deraadt Exp $") +MODULE_ID("$Id: lib_tstp.c,v 1.12 2023/10/17 09:52:09 nicm Exp $") #if defined(SIGTSTP) && (HAVE_SIGACTION || HAVE_SIGVEC) #define USE_SIGTSTP 1 @@ -61,16 +58,20 @@ static const char * signal_name(int sig) { switch (sig) { +#ifdef SIGALRM case SIGALRM: return "SIGALRM"; +#endif #ifdef SIGCONT case SIGCONT: return "SIGCONT"; #endif case SIGINT: return "SIGINT"; +#ifdef SIGQUIT case SIGQUIT: return "SIGQUIT"; +#endif case SIGTERM: return "SIGTERM"; #ifdef SIGTSTP @@ -131,13 +132,14 @@ signal_name(int sig) * (this may include XENIX). * * This implementation will probably be changed to use signal(3) in - * the future. If nothing else, it's simpler... + * the future. If nothing else, it is simpler... */ #if USE_SIGTSTP static void -tstp(int dummy GCC_UNUSED) +handle_SIGTSTP(int dummy GCC_UNUSED) { + SCREEN *sp = CURRENT_SCREEN; sigset_t mask, omask; sigaction_t act, oact; @@ -145,7 +147,8 @@ tstp(int dummy GCC_UNUSED) int sigttou_blocked; #endif - T(("tstp() called")); + _nc_globals.have_sigtstp = 1; + T(("handle_SIGTSTP() called")); /* * The user may have changed the prog_mode tty bits, so save them. @@ -155,12 +158,14 @@ tstp(int dummy GCC_UNUSED) * taken ownership of the tty and modified the settings when our * parent was stopped before us, and we would likely pick up the * settings already modified by the shell. + * + * Don't do this if we're not in curses - */ - if (SP != 0 && !SP->_endwin) /* don't do this if we're not in curses */ + if (sp != 0 && (sp->_endwin == ewRunning)) #if HAVE_TCGETPGRP if (tcgetpgrp(STDIN_FILENO) == getpgrp()) #endif - def_prog_mode(); + NCURSES_SP_NAME(def_prog_mode) (NCURSES_SP_ARG); /* * Block window change and timer signals. The latter @@ -168,7 +173,9 @@ tstp(int dummy GCC_UNUSED) * to repaint the screen. */ (void) sigemptyset(&mask); +#ifdef SIGALRM (void) sigaddset(&mask, SIGALRM); +#endif #if USE_SIGWINCH (void) sigaddset(&mask, SIGWINCH); #endif @@ -187,7 +194,7 @@ tstp(int dummy GCC_UNUSED) * End window mode, which also resets the terminal state to the * original (pre-curses) modes. */ - endwin(); + NCURSES_SP_NAME(endwin) (NCURSES_SP_ARG); /* Unblock SIGTSTP. */ (void) sigemptyset(&mask); @@ -214,19 +221,19 @@ tstp(int dummy GCC_UNUSED) T(("SIGCONT received")); sigaction(SIGTSTP, &oact, NULL); - flushinp(); + NCURSES_SP_NAME(flushinp) (NCURSES_SP_ARG); /* * If the user modified the tty state while suspended, he wants * those changes to stick. So save the new "default" terminal state. */ - def_shell_mode(); + NCURSES_SP_NAME(def_shell_mode) (NCURSES_SP_ARG); /* * This relies on the fact that doupdate() will restore the * program-mode tty state, and issue enter_ca_mode if need be. */ - doupdate(); + NCURSES_SP_NAME(doupdate) (NCURSES_SP_ARG); /* Reset the signals. */ (void) sigprocmask(SIG_SETMASK, &omask, NULL); @@ -234,28 +241,24 @@ tstp(int dummy GCC_UNUSED) #endif /* USE_SIGTSTP */ static void -cleanup(int sig) +handle_SIGINT(int sig) { + SCREEN *sp = CURRENT_SCREEN; + /* - * XXX signal race. + * Much of this is unsafe from a signal handler. But we'll _try_ to clean + * up the screen and terminal settings on the way out. * + * There are at least the following problems: * 1) Walking the SCREEN list is unsafe, since all list management * is done without any signal blocking. * 2) On systems which have REENTRANT turned on, set_term() uses * _nc_lock_global() which could deadlock or misbehave in other ways. * 3) endwin() calls all sorts of stuff, many of which use stdio or * other library functions which are clearly unsafe. - * 4) The comment about atexit() is wrong. atexit() should never be - * called, because ... - * 5) The call to exit() at the bottom is unsafe: exit() depends - * depends on stdio being coherent (obviously it is not). stdio - * could call free(), and also calls atexit() and dtor handlers, - * which are probably not written to be safe. The signal handler - * should be calling _exit(). */ if (!_nc_globals.cleanup_nested++ - && (sig == SIGINT - || sig == SIGQUIT)) { + && (sig == SIGINT || sig == SIGTERM)) { #if HAVE_SIGACTION || HAVE_SIGVEC sigaction_t act; sigemptyset(&act.sa_mask); @@ -269,25 +272,49 @@ cleanup(int sig) SCREEN *scan; for (each_screen(scan)) { if (scan->_ofp != 0 - && isatty(fileno(scan->_ofp))) { - scan->_cleanup = TRUE; - scan->_outch = _nc_outch; + && NC_ISATTY(fileno(scan->_ofp))) { + scan->_outch = NCURSES_SP_NAME(_nc_outch); } set_term(scan); - endwin(); - if (SP) - SP->_endwin = FALSE; /* in case we have an atexit! */ + NCURSES_SP_NAME(endwin) (NCURSES_SP_ARG); + if (sp) + sp->_endwin = ewInitial; /* in case of reuse */ } } } - exit(EXIT_FAILURE); + _exit(EXIT_FAILURE); } +# ifndef _nc_set_read_thread +NCURSES_EXPORT(void) +_nc_set_read_thread(bool enable) +{ + _nc_lock_global(curses); + if (enable) { +# if USE_WEAK_SYMBOLS + if ((pthread_self) && (pthread_kill) && (pthread_equal)) +# endif + _nc_globals.read_thread = pthread_self(); + } else { + _nc_globals.read_thread = 0; + } + _nc_unlock_global(curses); +} +# endif + #if USE_SIGWINCH + static void -sigwinch(int sig GCC_UNUSED) +handle_SIGWINCH(int sig GCC_UNUSED) { _nc_globals.have_sigwinch = 1; +# if USE_PTHREADS_EINTR + if (_nc_globals.read_thread) { + if (!pthread_equal(pthread_self(), _nc_globals.read_thread)) + pthread_kill(_nc_globals.read_thread, SIGWINCH); + _nc_globals.read_thread = 0; + } +# endif } #endif /* USE_SIGWINCH */ @@ -296,7 +323,7 @@ sigwinch(int sig GCC_UNUSED) * handler. */ static int -CatchIfDefault(int sig, RETSIGTYPE (*handler) (int)) +CatchIfDefault(int sig, void (*handler) (int)) { int result; #if HAVE_SIGACTION || HAVE_SIGVEC @@ -326,7 +353,7 @@ CatchIfDefault(int sig, RETSIGTYPE (*handler) (int)) result = FALSE; } #else /* !HAVE_SIGACTION */ - RETSIGTYPE (*ohandler) (int); + void (*ohandler) (int); ohandler = signal(sig, SIG_IGN); if (ohandler == SIG_DFL @@ -359,7 +386,7 @@ CatchIfDefault(int sig, RETSIGTYPE (*handler) (int)) * the caller later changes its mind, but that doesn't seem correct. */ NCURSES_EXPORT(void) -_nc_signal_handler(bool enable) +_nc_signal_handler(int enable) { T((T_CALLED("_nc_signal_handler(%d)"), enable)); #if USE_SIGTSTP /* Xenix 2.x doesn't have SIGTSTP, for example */ @@ -380,7 +407,7 @@ _nc_signal_handler(bool enable) #ifdef SA_RESTART new_sigaction.sa_flags |= SA_RESTART; #endif /* SA_RESTART */ - new_sigaction.sa_handler = tstp; + new_sigaction.sa_handler = handle_SIGTSTP; (void) sigaction(SIGTSTP, &new_sigaction, NULL); } else { ignore_tstp = TRUE; @@ -391,10 +418,10 @@ _nc_signal_handler(bool enable) if (!_nc_globals.init_signals) { if (enable) { - CatchIfDefault(SIGINT, cleanup); - CatchIfDefault(SIGTERM, cleanup); + CatchIfDefault(SIGINT, handle_SIGINT); + CatchIfDefault(SIGTERM, handle_SIGINT); #if USE_SIGWINCH - CatchIfDefault(SIGWINCH, sigwinch); + CatchIfDefault(SIGWINCH, handle_SIGWINCH); #endif _nc_globals.init_signals = TRUE; } diff --git a/lib/libcurses/tty/lib_twait.c b/lib/libcurses/tty/lib_twait.c index fcbc3cfdf47..1e7f21a6bb6 100644 --- a/lib/libcurses/tty/lib_twait.c +++ b/lib/libcurses/tty/lib_twait.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_twait.c,v 1.9 2010/01/12 23:22:07 nicm Exp $ */ +/* $OpenBSD: lib_twait.c,v 1.10 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2020,2023 Thomas E. Dickey * + * Copyright 1998-2015,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -55,6 +56,11 @@ #include #endif +#if USE_KLIBC_KBD +#define INCL_KBD +#include +#endif + #if USE_FUNC_POLL # if HAVE_SYS_TIME_H # include @@ -67,37 +73,44 @@ # include # endif #endif - +#if HAVE_SYS_TIME_H +# include +#endif #undef CUR -MODULE_ID("$Id: lib_twait.c,v 1.9 2010/01/12 23:22:07 nicm Exp $") +MODULE_ID("$Id: lib_twait.c,v 1.10 2023/10/17 09:52:09 nicm Exp $") +/* + * Returns an elapsed time, in milliseconds (if possible). + */ static long -_nc_gettime(TimeType * t0, bool first) +_nc_gettime(TimeType * t0, int first) { long res; #if PRECISE_GETTIME TimeType t1; - gettimeofday(&t1, (struct timezone *) 0); - if (first) { + if (GetClockTime(&t1) == -1) { + *t0 = t1; + res = first ? 0 : 1; + } else if (first) { *t0 = t1; res = 0; } else { /* .tv_sec and .tv_usec are unsigned, be careful when subtracting */ - if (t0->tv_usec > t1.tv_usec) { - t1.tv_usec += 1000000; /* Convert 1s in 1e6 microsecs */ + if (t0->sub_secs > t1.sub_secs) { + t1.sub_secs += TimeScale; t1.tv_sec--; } - res = (t1.tv_sec - t0->tv_sec) * 1000 - + (t1.tv_usec - t0->tv_usec) / 1000; + res = (long) ((t1.tv_sec - t0->tv_sec) * 1000L + + (t1.sub_secs - t0->sub_secs) / (TimeScale / 1000L)); } #else time_t t1 = time((time_t *) 0); if (first) { *t0 = t1; } - res = (t1 - *t0) * 1000; + res = (long) ((t1 - *t0) * 1000); #endif TR(TRACE_IEVENT, ("%s time: %ld msec", first ? "get" : "elapsed", res)); return res; @@ -108,15 +121,15 @@ NCURSES_EXPORT(int) _nc_eventlist_timeout(_nc_eventlist * evl) { int event_delay = -1; - int n; if (evl != 0) { + int n; for (n = 0; n < evl->count; ++n) { _nc_event *ev = evl->events[n]; if (ev->type == _NC_EVENT_TIMEOUT_MSEC) { - event_delay = ev->data.timeout_msec; + event_delay = (int) ev->data.timeout_msec; if (event_delay < 0) event_delay = INT_MAX; /* FIXME Is this defined? */ } @@ -126,15 +139,27 @@ _nc_eventlist_timeout(_nc_eventlist * evl) } #endif /* NCURSES_WGETCH_EVENTS */ +#if (USE_FUNC_POLL || HAVE_SELECT) +# define MAYBE_UNUSED +#else +# define MAYBE_UNUSED GCC_UNUSED +#endif + +#if (USE_FUNC_POLL || HAVE_SELECT) +# define MAYBE_UNUSED +#else +# define MAYBE_UNUSED GCC_UNUSED +#endif + /* * Wait a specified number of milliseconds, returning nonzero if the timer * didn't expire before there is activity on the specified file descriptors. * The file-descriptors are specified by the mode: - * 0 - none (absolute time) - * 1 - ncurses' normal input-descriptor - * 2 - mouse descriptor, if any - * 3 - either input or mouse. - * + * TW_NONE 0 - none (absolute time) + * TW_INPUT 1 - ncurses' normal input-descriptor + * TW_MOUSE 2 - mouse descriptor, if any + * TW_ANY 3 - either input or mouse. + * TW_EVENT 4 - * Experimental: if NCURSES_WGETCH_EVENTS is defined, (mode & 4) determines * whether to pay attention to evl argument. If set, the smallest of * millisecond and of timeout of evl is taken. @@ -145,16 +170,18 @@ _nc_eventlist_timeout(_nc_eventlist * evl) * descriptors. */ NCURSES_EXPORT(int) -_nc_timed_wait(SCREEN *sp, - int mode, +_nc_timed_wait(SCREEN *sp MAYBE_UNUSED, + int mode MAYBE_UNUSED, int milliseconds, int *timeleft EVENTLIST_2nd(_nc_eventlist * evl)) { - int fd; int count; - int result = 0; + int result = TW_NONE; TimeType t0; +#if (USE_FUNC_POLL || HAVE_SELECT) + int fd; +#endif #ifdef NCURSES_WGETCH_EVENTS int timeout_is_event = 0; @@ -170,13 +197,23 @@ _nc_timed_wait(SCREEN *sp, fd_set set; #endif +#if USE_KLIBC_KBD + fd_set saved_set; + KBDKEYINFO ki; + struct timeval tv; +#endif + long starttime, returntime; +#ifdef NCURSES_WGETCH_EVENTS + (void) timeout_is_event; +#endif + TR(TRACE_IEVENT, ("start twait: %d milliseconds, mode: %d", milliseconds, mode)); #ifdef NCURSES_WGETCH_EVENTS - if (mode & 4) { + if (mode & TW_EVENT) { int event_delay = _nc_eventlist_timeout(evl); if (event_delay >= 0 @@ -193,9 +230,10 @@ _nc_timed_wait(SCREEN *sp, starttime = _nc_gettime(&t0, TRUE); count = 0; + (void) count; #ifdef NCURSES_WGETCH_EVENTS - if ((mode & 4) && evl) + if ((mode & TW_EVENT) && evl) evl->result_flags = 0; #endif @@ -203,23 +241,27 @@ _nc_timed_wait(SCREEN *sp, memset(fd_list, 0, sizeof(fd_list)); #ifdef NCURSES_WGETCH_EVENTS - if ((mode & 4) && evl) - fds = typeMalloc(struct pollfd, MIN_FDS + evl->count); + if ((mode & TW_EVENT) && evl) { + if (fds == fd_list) + fds = typeMalloc(struct pollfd, MIN_FDS + evl->count); + if (fds == 0) + return TW_NONE; + } #endif - if (mode & 1) { + if (mode & TW_INPUT) { fds[count].fd = sp->_ifd; fds[count].events = POLLIN; count++; } - if ((mode & 2) + if ((mode & TW_MOUSE) && (fd = sp->_mouse_fd) >= 0) { fds[count].fd = fd; fds[count].events = POLLIN; count++; } #ifdef NCURSES_WGETCH_EVENTS - if ((mode & 4) && evl) { + if ((mode & TW_EVENT) && evl) { for (n = 0; n < evl->count; ++n) { _nc_event *ev = evl->events[n]; @@ -233,10 +275,10 @@ _nc_timed_wait(SCREEN *sp, } #endif - result = poll(fds, (unsigned) count, milliseconds); + result = poll(fds, (size_t) count, milliseconds); #ifdef NCURSES_WGETCH_EVENTS - if ((mode & 4) && evl) { + if ((mode & TW_EVENT) && evl) { int c; if (!result) @@ -260,10 +302,6 @@ _nc_timed_wait(SCREEN *sp, } } } - - if (fds != fd_list) - free((char *) fds); - #endif #elif defined(__BEOS__) @@ -278,8 +316,8 @@ _nc_timed_wait(SCREEN *sp, * * FIXME: this assumes mode&1 if milliseconds < 0 (see lib_getch.c). */ - result = 0; - if (mode & 1) { + result = TW_NONE; + if (mode & TW_INPUT) { int step = (milliseconds < 0) ? 0 : 5000; bigtime_t d; bigtime_t useconds = milliseconds * 1000; @@ -315,17 +353,19 @@ _nc_timed_wait(SCREEN *sp, */ FD_ZERO(&set); - if (mode & 1) { +#if !USE_KLIBC_KBD + if (mode & TW_INPUT) { FD_SET(sp->_ifd, &set); count = sp->_ifd + 1; } - if ((mode & 2) +#endif + if ((mode & TW_MOUSE) && (fd = sp->_mouse_fd) >= 0) { FD_SET(fd, &set); count = max(fd, count) + 1; } #ifdef NCURSES_WGETCH_EVENTS - if ((mode & 4) && evl) { + if ((mode & TW_EVENT) && evl) { for (n = 0; n < evl->count; ++n) { _nc_event *ev = evl->events[n]; @@ -338,6 +378,31 @@ _nc_timed_wait(SCREEN *sp, } #endif +#if USE_KLIBC_KBD + for (saved_set = set;; set = saved_set) { + if ((mode & TW_INPUT) + && (sp->_extended_key + || (KbdPeek(&ki, 0) == 0 + && (ki.fbStatus & KBDTRF_FINAL_CHAR_IN)))) { + FD_ZERO(&set); + FD_SET(sp->_ifd, &set); + result = 1; + break; + } + + tv.tv_sec = 0; + tv.tv_usec = (milliseconds == 0) ? 0 : (10 * 1000); + + if ((result = select(count, &set, NULL, NULL, &tv)) != 0) + break; + + /* Time out ? */ + if (milliseconds >= 0 && _nc_gettime(&t0, FALSE) >= milliseconds) { + result = 0; + break; + } + } +#else if (milliseconds >= 0) { struct timeval ntimeout; ntimeout.tv_sec = milliseconds / 1000; @@ -346,9 +411,10 @@ _nc_timed_wait(SCREEN *sp, } else { result = select(count, &set, NULL, NULL, NULL); } +#endif #ifdef NCURSES_WGETCH_EVENTS - if ((mode & 4) && evl) { + if ((mode & TW_EVENT) && evl) { evl->result_flags = 0; for (n = 0; n < evl->count; ++n) { _nc_event *ev = evl->events[n]; @@ -372,7 +438,7 @@ _nc_timed_wait(SCREEN *sp, returntime = _nc_gettime(&t0, FALSE); if (milliseconds >= 0) - milliseconds -= (returntime - starttime); + milliseconds -= (int) (returntime - starttime); #ifdef NCURSES_WGETCH_EVENTS if (evl) { @@ -430,22 +496,29 @@ _nc_timed_wait(SCREEN *sp, } } #elif defined(__BEOS__) - result = 1; /* redundant, but simple */ + result = TW_INPUT; /* redundant, but simple */ #elif HAVE_SELECT - if ((mode & 2) + if ((mode & TW_MOUSE) && (fd = sp->_mouse_fd) >= 0 && FD_ISSET(fd, &set)) - result |= 2; - if ((mode & 1) + result |= TW_MOUSE; + if ((mode & TW_INPUT) && FD_ISSET(sp->_ifd, &set)) - result |= 1; + result |= TW_INPUT; #endif } else result = 0; } #ifdef NCURSES_WGETCH_EVENTS - if ((mode & 4) && evl && evl->result_flags) - result |= 4; + if ((mode & TW_EVENT) && evl && evl->result_flags) + result |= TW_EVENT; +#endif + +#if USE_FUNC_POLL +#ifdef NCURSES_WGETCH_EVENTS + if (fds != fd_list) + free((char *) fds); +#endif #endif return (result); diff --git a/lib/libcurses/tty/lib_vidattr.c b/lib/libcurses/tty/lib_vidattr.c index 5553a348ead..928fa79e84d 100644 --- a/lib/libcurses/tty/lib_vidattr.c +++ b/lib/libcurses/tty/lib_vidattr.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_vidattr.c,v 1.9 2010/01/12 23:22:07 nicm Exp $ */ +/* $OpenBSD: lib_vidattr.c,v 1.10 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * + * Copyright 2018-2020,2023 Thomas E. Dickey * + * Copyright 1998-2014,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,7 +32,8 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * - * and: Thomas E. Dickey 1996 on * + * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /* @@ -65,55 +67,76 @@ */ #include -#include -MODULE_ID("$Id: lib_vidattr.c,v 1.9 2010/01/12 23:22:07 nicm Exp $") +#ifndef CUR +#define CUR SP_TERMTYPE +#endif + +MODULE_ID("$Id: lib_vidattr.c,v 1.10 2023/10/17 09:52:09 nicm Exp $") -#define doPut(mode) TPUTS_TRACE(#mode); tputs(mode, 1, outc) +#define doPut(mode) \ + TPUTS_TRACE(#mode); \ + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx mode, 1, outc) -#define TurnOn(mask,mode) \ - if ((turn_on & mask) && mode) { doPut(mode); } +#define TurnOn(mask, mode) \ + if ((turn_on & mask) && mode) { \ + TPUTS_TRACE(#mode); \ + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx mode, 1, outc); \ + } -#define TurnOff(mask,mode) \ - if ((turn_off & mask) && mode) { doPut(mode); turn_off &= ~mask; } +#define TurnOff(mask, mode) \ + if ((turn_off & mask) && mode) { \ + TPUTS_TRACE(#mode); \ + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx mode, 1, outc); \ + turn_off &= ~mask; \ + } /* if there is no current screen, assume we *can* do color */ -#define SetColorsIf(why,old_attr) \ +#define SetColorsIf(why, old_attr) \ if (can_color && (why)) { \ - int old_pair = PAIR_NUMBER(old_attr); \ + int old_pair = PairNumber(old_attr); \ TR(TRACE_ATTRS, ("old pair = %d -- new pair = %d", old_pair, pair)); \ if ((pair != old_pair) \ || (fix_pair0 && (pair == 0)) \ || (reverse ^ ((old_attr & A_REVERSE) != 0))) { \ - _nc_do_color(old_pair, pair, reverse, outc); \ + NCURSES_SP_NAME(_nc_do_color) (NCURSES_SP_ARGx \ + (short) old_pair, \ + (short) pair, \ + reverse, outc); \ } \ } #define PreviousAttr _nc_prescreen.previous_attr NCURSES_EXPORT(int) -vidputs(chtype newmode, int (*outc) (int)) +NCURSES_SP_NAME(vidputs) (NCURSES_SP_DCLx + chtype newmode, + NCURSES_SP_OUTC outc) { attr_t turn_on, turn_off; int pair; bool reverse = FALSE; - bool can_color = (SP == 0 || SP->_coloron); + bool can_color = (SP_PARM == 0 || SP_PARM->_coloron); #if NCURSES_EXT_FUNCS - bool fix_pair0 = (SP != 0 && SP->_coloron && !SP->_default_color); + bool fix_pair0 = (SP_PARM != 0 && SP_PARM->_coloron && !SP_PARM->_default_color); #else #define fix_pair0 FALSE #endif newmode &= A_ATTRIBUTES; - T((T_CALLED("vidputs(%s)"), _traceattr(newmode))); + + T((T_CALLED("vidputs(%p,%s)"), (void *) SP_PARM, _traceattr(newmode))); + + if (!IsValidTIScreen(SP_PARM)) + returnCode(ERR); /* this allows us to go on whether or not newterm() has been called */ - if (SP) - PreviousAttr = AttrOf(SCREEN_ATTRS(SP)); + if (SP_PARM) + PreviousAttr = AttrOf(SCREEN_ATTRS(SP_PARM)); TR(TRACE_ATTRS, ("previous attribute was %s", _traceattr(PreviousAttr))); - if ((SP != 0) + if ((SP_PARM != 0) && (magic_cookie_glitch > 0)) { #if USE_XMC_SUPPORT static const chtype table[] = @@ -126,10 +149,17 @@ vidputs(chtype newmode, int (*outc) (int)) A_BOLD, A_INVIS, A_PROTECT, +#if USE_ITALIC + A_ITALIC, +#endif }; unsigned n; int used = 0; +#ifdef max_attributes /* not in U/Win */ int limit = (max_attributes <= 0) ? 1 : max_attributes; +#else + int limit = 1; +#endif chtype retain = 0; /* @@ -137,7 +167,7 @@ vidputs(chtype newmode, int (*outc) (int)) * the terminfo max_attributes value. */ for (n = 0; n < SIZEOF(table); ++n) { - if ((table[n] & SP->_ok_attributes) == 0) { + if ((table[n] & SP_PARM->_ok_attributes) == 0) { newmode &= ~table[n]; } else if ((table[n] & newmode) != 0) { if (used++ >= limit) { @@ -150,7 +180,7 @@ vidputs(chtype newmode, int (*outc) (int)) } } #else - newmode &= ~(SP->_xmc_suppress); + newmode &= ~(SP_PARM->_xmc_suppress); #endif TR(TRACE_ATTRS, ("suppressed attribute is %s", _traceattr(newmode))); } @@ -174,7 +204,7 @@ vidputs(chtype newmode, int (*outc) (int)) * A_ALTCHARSET (256) down 2 to line up. We use the NCURSES_BITS * macro so this will work properly for the wide-character layout. */ - unsigned value = no_color_video; + unsigned value = (unsigned) no_color_video; attr_t mask = NCURSES_BITS((value & 63) | ((value & 192) << 1) | ((value & 256) >> 2), 8); @@ -190,14 +220,14 @@ vidputs(chtype newmode, int (*outc) (int)) if (newmode == PreviousAttr) returnCode(OK); - pair = PAIR_NUMBER(newmode); + pair = PairNumber(newmode); if (reverse) { newmode &= ~A_REVERSE; } turn_off = (~newmode & PreviousAttr) & ALL_BUT_COLOR; - turn_on = (newmode & ~PreviousAttr) & ALL_BUT_COLOR; + turn_on = (newmode & ~(PreviousAttr & TPARM_ATTR)) & ALL_BUT_COLOR; SetColorsIf(((pair == 0) && !fix_pair0), PreviousAttr); @@ -210,12 +240,18 @@ vidputs(chtype newmode, int (*outc) (int)) if (exit_attribute_mode) { doPut(exit_attribute_mode); } else { - if (!SP || SP->_use_rmul) { + if (!SP_PARM || SP_PARM->_use_rmul) { TurnOff(A_UNDERLINE, exit_underline_mode); } - if (!SP || SP->_use_rmso) { + if (!SP_PARM || SP_PARM->_use_rmso) { TurnOff(A_STANDOUT, exit_standout_mode); } +#if USE_ITALIC + if (!SP_PARM || SP_PARM->_use_ritm) { + TurnOff(A_ITALIC, exit_italics_mode); + } +#endif + (void) turn_off; } PreviousAttr &= ALL_BUT_COLOR; } @@ -224,18 +260,30 @@ vidputs(chtype newmode, int (*outc) (int)) } else if (set_attributes) { if (turn_on || turn_off) { TPUTS_TRACE("set_attributes"); - tputs(tparm(set_attributes, - (newmode & A_STANDOUT) != 0, - (newmode & A_UNDERLINE) != 0, - (newmode & A_REVERSE) != 0, - (newmode & A_BLINK) != 0, - (newmode & A_DIM) != 0, - (newmode & A_BOLD) != 0, - (newmode & A_INVIS) != 0, - (newmode & A_PROTECT) != 0, - (newmode & A_ALTCHARSET) != 0), 1, outc); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_9(set_attributes, + (newmode & A_STANDOUT) != 0, + (newmode & A_UNDERLINE) != 0, + (newmode & A_REVERSE) != 0, + (newmode & A_BLINK) != 0, + (newmode & A_DIM) != 0, + (newmode & A_BOLD) != 0, + (newmode & A_INVIS) != 0, + (newmode & A_PROTECT) != 0, + (newmode & A_ALTCHARSET) != 0), + 1, outc); PreviousAttr &= ALL_BUT_COLOR; } +#if USE_ITALIC + if (!SP_PARM || SP_PARM->_use_ritm) { + if (turn_on & A_ITALIC) { + TurnOn(A_ITALIC, enter_italics_mode); + } else if (turn_off & A_ITALIC) { + TurnOff(A_ITALIC, exit_italics_mode); + } + (void) turn_off; + } +#endif SetColorsIf((pair != 0) || fix_pair0, PreviousAttr); } else { @@ -243,14 +291,18 @@ vidputs(chtype newmode, int (*outc) (int)) TurnOff(A_ALTCHARSET, exit_alt_charset_mode); - if (!SP || SP->_use_rmul) { + if (!SP_PARM || SP_PARM->_use_rmul) { TurnOff(A_UNDERLINE, exit_underline_mode); } - if (!SP || SP->_use_rmso) { + if (!SP_PARM || SP_PARM->_use_rmso) { TurnOff(A_STANDOUT, exit_standout_mode); } - +#if USE_ITALIC + if (!SP_PARM || SP_PARM->_use_ritm) { + TurnOff(A_ITALIC, exit_italics_mode); + } +#endif if (turn_off && exit_attribute_mode) { doPut(exit_attribute_mode); turn_on |= (newmode & ALL_BUT_COLOR); @@ -269,7 +321,10 @@ vidputs(chtype newmode, int (*outc) (int)) TurnOn(A_PROTECT, enter_protected_mode); TurnOn(A_INVIS, enter_secure_mode); TurnOn(A_UNDERLINE, enter_underline_mode); -#if USE_WIDEC_SUPPORT +#if USE_ITALIC + TurnOn(A_ITALIC, enter_italics_mode); +#endif +#if USE_WIDEC_SUPPORT && defined(enter_horizontal_hl_mode) TurnOn(A_HORIZONTAL, enter_horizontal_hl_mode); TurnOn(A_LEFT, enter_left_hl_mode); TurnOn(A_LOW, enter_low_hl_mode); @@ -278,63 +333,103 @@ vidputs(chtype newmode, int (*outc) (int)) TurnOn(A_VERTICAL, enter_vertical_hl_mode); #endif /* *INDENT-ON* */ - } if (reverse) newmode |= A_REVERSE; - if (SP) - SetAttr(SCREEN_ATTRS(SP), newmode); + if (SP_PARM) + SetAttr(SCREEN_ATTRS(SP_PARM), newmode); else PreviousAttr = newmode; returnCode(OK); } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(int) -vidattr(chtype newmode) +vidputs(chtype newmode, NCURSES_OUTC outc) +{ + SetSafeOutcWrapper(outc); + return NCURSES_SP_NAME(vidputs) (CURRENT_SCREEN, + newmode, + _nc_outc_wrapper); +} +#endif + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(vidattr) (NCURSES_SP_DCLx chtype newmode) { - T((T_CALLED("vidattr(%s)"), _traceattr(newmode))); + T((T_CALLED("vidattr(%p,%s)"), (void *) SP_PARM, _traceattr(newmode))); + returnCode(NCURSES_SP_NAME(vidputs) (NCURSES_SP_ARGx + newmode, + NCURSES_SP_NAME(_nc_putchar))); +} - returnCode(vidputs(newmode, _nc_outch)); +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +vidattr(chtype newmode) +{ + return NCURSES_SP_NAME(vidattr) (CURRENT_SCREEN, newmode); } +#endif NCURSES_EXPORT(chtype) -termattrs(void) +NCURSES_SP_NAME(termattrs) (NCURSES_SP_DCL0) { chtype attrs = A_NORMAL; - T((T_CALLED("termattrs()"))); - if (enter_alt_charset_mode) - attrs |= A_ALTCHARSET; + T((T_CALLED("termattrs(%p)"), (void *) SP_PARM)); + + if (HasTerminal(SP_PARM)) { +#ifdef USE_TERM_DRIVER + attrs = CallDriver(SP_PARM, td_conattr); +#else /* ! USE_TERM_DRIVER */ - if (enter_blink_mode) - attrs |= A_BLINK; + if (enter_alt_charset_mode) + attrs |= A_ALTCHARSET; - if (enter_bold_mode) - attrs |= A_BOLD; + if (enter_blink_mode) + attrs |= A_BLINK; - if (enter_dim_mode) - attrs |= A_DIM; + if (enter_bold_mode) + attrs |= A_BOLD; - if (enter_reverse_mode) - attrs |= A_REVERSE; + if (enter_dim_mode) + attrs |= A_DIM; - if (enter_standout_mode) - attrs |= A_STANDOUT; + if (enter_reverse_mode) + attrs |= A_REVERSE; - if (enter_protected_mode) - attrs |= A_PROTECT; + if (enter_standout_mode) + attrs |= A_STANDOUT; - if (enter_secure_mode) - attrs |= A_INVIS; + if (enter_protected_mode) + attrs |= A_PROTECT; - if (enter_underline_mode) - attrs |= A_UNDERLINE; + if (enter_secure_mode) + attrs |= A_INVIS; - if (SP->_coloron) - attrs |= A_COLOR; + if (enter_underline_mode) + attrs |= A_UNDERLINE; - returnChar(attrs); + if (SP_PARM->_coloron) + attrs |= A_COLOR; + +#if USE_ITALIC + if (enter_italics_mode) + attrs |= A_ITALIC; +#endif + +#endif /* USE_TERM_DRIVER */ + } + returnChtype(attrs); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(chtype) +termattrs(void) +{ + return NCURSES_SP_NAME(termattrs) (CURRENT_SCREEN); } +#endif diff --git a/lib/libcurses/tty/tty_update.c b/lib/libcurses/tty/tty_update.c index cbc114e1e2f..ec36a4fd7dd 100644 --- a/lib/libcurses/tty/tty_update.c +++ b/lib/libcurses/tty/tty_update.c @@ -1,7 +1,8 @@ -/* $OpenBSD: tty_update.c,v 1.17 2020/05/29 20:46:13 nicm Exp $ */ +/* $OpenBSD: tty_update.c,v 1.18 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2021,2022 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,6 +33,7 @@ * Author: Zeyd M. Ben-Halim 1992,1995 * * and: Eric S. Raymond * * and: Thomas E. Dickey 1996-on * + * and: Juergen Pfeifer 2009 * ****************************************************************************/ /*----------------------------------------------------------------- @@ -40,12 +42,18 @@ * * The routine doupdate() and its dependents. * All physical output is concentrated here (except _nc_outch() - * in lib_tputs.c). + * in lib_tputs.c). * *-----------------------------------------------------------------*/ +#define NEW_PAIR_INTERNAL 1 + #include +#ifndef CUR +#define CUR SP_TERMTYPE +#endif + #if defined __HAIKU__ && defined __BEOS__ #undef __BEOS__ #endif @@ -78,9 +86,8 @@ #endif #include -#include -MODULE_ID("$Id: tty_update.c,v 1.17 2020/05/29 20:46:13 nicm Exp $") +MODULE_ID("$Id: tty_update.c,v 1.18 2023/10/17 09:52:09 nicm Exp $") /* * This define controls the line-breakout optimization. Every once in a @@ -93,7 +100,7 @@ MODULE_ID("$Id: tty_update.c,v 1.17 2020/05/29 20:46:13 nicm Exp $") */ #define CHECK_INTERVAL 5 -#define FILL_BCE() (SP->_coloron && !SP->_default_color && !back_color_erase) +#define FILL_BCE(sp) (sp->_coloron && !sp->_default_color && !back_color_erase) static const NCURSES_CH_T blankchar = NewChar(BLANK_TEXT); static NCURSES_CH_T normal = NewChar(BLANK_TEXT); @@ -105,13 +112,23 @@ static NCURSES_CH_T normal = NewChar(BLANK_TEXT); */ /* #define POSITION_DEBUG */ -static NCURSES_INLINE NCURSES_CH_T ClrBlank(WINDOW *win); +static NCURSES_INLINE NCURSES_CH_T ClrBlank(NCURSES_SP_DCLx WINDOW *win); + +#if NCURSES_SP_FUNCS +static int ClrBottom(SCREEN *, int total); +static void ClearScreen(SCREEN *, NCURSES_CH_T blank); +static void ClrUpdate(SCREEN *); +static void DelChar(SCREEN *, int count); +static void InsStr(SCREEN *, NCURSES_CH_T *line, int count); +static void TransformLine(SCREEN *, int const lineno); +#else static int ClrBottom(int total); static void ClearScreen(NCURSES_CH_T blank); static void ClrUpdate(void); static void DelChar(int count); -static void InsStr(NCURSES_CH_T * line, int count); +static void InsStr(NCURSES_CH_T *line, int count); static void TransformLine(int const lineno); +#endif #ifdef POSITION_DEBUG /**************************************************************************** @@ -121,7 +138,7 @@ static void TransformLine(int const lineno); ****************************************************************************/ static void -position_check(int expected_y, int expected_x, char *legend) +position_check(NCURSES_SP_DCLx int expected_y, int expected_x, const char *legend) /* check to see if the real cursor position matches the virtual */ { char buf[20]; @@ -131,10 +148,9 @@ position_check(int expected_y, int expected_x, char *legend) if (!_nc_tracing || (expected_y < 0 && expected_x < 0)) return; - _nc_flush(); + NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG); memset(buf, '\0', sizeof(buf)); - putp("\033[6n"); /* only works on ANSI-compatibles */ - _nc_flush(); + NCURSES_PUTP2_FLUSH("cpr", "\033[6n"); /* only works on ANSI-compatibles */ *(s = buf) = 0; do { int ask = sizeof(buf) - 1 - (s - buf); @@ -154,8 +170,12 @@ position_check(int expected_y, int expected_x, char *legend) if (expected_y < 0) expected_y = y - 1; if (y - 1 != expected_y || x - 1 != expected_x) { - beep(); - tputs(tparm("\033[%d;%dH", expected_y + 1, expected_x + 1), 1, _nc_outch); + NCURSES_SP_NAME(beep) (NCURSES_SP_ARG); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_2("\033[%d;%dH", + expected_y + 1, + expected_x + 1), + 1, NCURSES_SP_NAME(_nc_outch)); _tracef("position seen (%d, %d) doesn't match expected one (%d, %d) in %s", y - 1, x - 1, expected_y, expected_x, legend); } else { @@ -174,29 +194,42 @@ position_check(int expected_y, int expected_x, char *legend) ****************************************************************************/ static NCURSES_INLINE void -GoTo(int const row, int const col) +GoTo(NCURSES_SP_DCLx int const row, int const col) { - TR(TRACE_MOVE, ("GoTo(%d, %d) from (%d, %d)", - row, col, SP->_cursrow, SP->_curscol)); - - position_check(SP->_cursrow, SP->_curscol, "GoTo"); - - mvcur(SP->_cursrow, SP->_curscol, row, col); - position_check(SP->_cursrow, SP->_curscol, "GoTo2"); + TR(TRACE_MOVE, ("GoTo(%p, %d, %d) from (%d, %d)", + (void *) SP_PARM, row, col, SP_PARM->_cursrow, SP_PARM->_curscol)); + + position_check(NCURSES_SP_ARGx + SP_PARM->_cursrow, + SP_PARM->_curscol, "GoTo"); + + TINFO_MVCUR(NCURSES_SP_ARGx + SP_PARM->_cursrow, + SP_PARM->_curscol, + row, col); + position_check(NCURSES_SP_ARGx + SP_PARM->_cursrow, + SP_PARM->_curscol, "GoTo2"); } +#if !NCURSES_WCWIDTH_GRAPHICS +#define is_wacs_value(ch) (_nc_wacs_width(ch) == 1 && wcwidth(ch) > 1) +#endif /* !NCURSES_WCWIDTH_GRAPHICS */ + static NCURSES_INLINE void -PutAttrChar(CARG_CH_T ch) +PutAttrChar(NCURSES_SP_DCLx CARG_CH_T ch) { int chlen = 1; NCURSES_CH_T my_ch; +#if USE_WIDEC_SUPPORT PUTC_DATA; +#endif NCURSES_CH_T tilde; NCURSES_CH_T attr = CHDEREF(ch); TR(TRACE_CHARPUT, ("PutAttrChar(%s) at (%d, %d)", _tracech_t(ch), - SP->_cursrow, SP->_curscol)); + SP_PARM->_cursrow, SP_PARM->_curscol)); #if USE_WIDEC_SUPPORT /* * If this is not a valid character, there is nothing more to do. @@ -209,7 +242,7 @@ PutAttrChar(CARG_CH_T ch) * Determine the number of character cells which the 'ch' value will use * on the screen. It should be at least one. */ - if ((chlen = wcwidth(CharOf(CHDEREF(ch)))) <= 0) { + if ((chlen = _nc_wacs_width(CharOf(CHDEREF(ch)))) <= 0) { static const NCURSES_CH_T blank = NewChar(BLANK_TEXT); /* @@ -226,12 +259,12 @@ PutAttrChar(CARG_CH_T ch) */ if (is8bits(CharOf(CHDEREF(ch))) && (isprint(CharOf(CHDEREF(ch))) - || (SP->_legacy_coding > 0 && CharOf(CHDEREF(ch)) >= 160) - || (SP->_legacy_coding > 1 && CharOf(CHDEREF(ch)) >= 128) + || (SP_PARM->_legacy_coding > 0 && CharOf(CHDEREF(ch)) >= 160) + || (SP_PARM->_legacy_coding > 1 && CharOf(CHDEREF(ch)) >= 128) || (AttrOf(attr) & A_ALTCHARSET && ((CharOfD(ch) < ACS_LEN - && SP->_acs_map != 0 - && SP->_acs_map[CharOfD(ch)] != 0) + && SP_PARM->_acs_map != 0 + && SP_PARM->_acs_map[CharOfD(ch)] != 0) || (CharOfD(ch) >= 128))))) { ; } else { @@ -243,9 +276,15 @@ PutAttrChar(CARG_CH_T ch) #endif if ((AttrOf(attr) & A_ALTCHARSET) - && SP->_acs_map != 0 - && CharOfD(ch) < ACS_LEN) { + && SP_PARM->_acs_map != 0 + && ((CharOfD(ch) < ACS_LEN) +#if !NCURSES_WCWIDTH_GRAPHICS + || is_wacs_value(CharOfD(ch)) +#endif + )) { + int c8; my_ch = CHDEREF(ch); /* work around const param */ + c8 = CharOf(my_ch); #if USE_WIDEC_SUPPORT /* * This is crude & ugly, but works most of the time. It checks if the @@ -253,12 +292,39 @@ PutAttrChar(CARG_CH_T ch) * character, and uses the wide-character mapping when we expect the * normal one to be broken (by mis-design ;-). */ - if (SP->_screen_acs_fix - && SP->_screen_acs_map[CharOf(my_ch)]) { - RemAttr(attr, A_ALTCHARSET); - my_ch = _nc_wacs[CharOf(my_ch)]; - } + if (SP_PARM->_screen_unicode + && _nc_wacs[CharOf(my_ch)].chars[0]) { + if (SP_PARM->_screen_acs_map[CharOf(my_ch)]) { + if (SP_PARM->_screen_acs_fix) { + RemAttr(attr, A_ALTCHARSET); + my_ch = _nc_wacs[CharOf(my_ch)]; + } + } else { + RemAttr(attr, A_ALTCHARSET); + my_ch = _nc_wacs[CharOf(my_ch)]; + } +#if !NCURSES_WCWIDTH_GRAPHICS + if (!(AttrOf(attr) & A_ALTCHARSET)) { + chlen = 1; + } +#endif /* !NCURSES_WCWIDTH_GRAPHICS */ + } else #endif + if (!SP_PARM->_screen_acs_map[c8]) { + /* + * If we found no mapping for a given alternate-character set item + * in the terminal description, attempt to use the ASCII fallback + * code which is populated in the _acs_map[] array. If that did + * not correspond to a line-drawing, etc., graphics character, the + * array entry would be empty. + */ + chtype temp = UChar(SP_PARM->_acs_map[c8]); + if (temp) { + RemAttr(attr, A_ALTCHARSET); + SetChar(my_ch, temp, AttrOf(attr)); + } + } + /* * If we (still) have alternate character set, it is the normal 8bit * flavor. The _screen_acs_map[] array tells if the character was @@ -267,45 +333,40 @@ PutAttrChar(CARG_CH_T ch) */ if (AttrOf(attr) & A_ALTCHARSET) { int j = CharOfD(ch); - chtype temp = UChar(SP->_acs_map[j]); + chtype temp = UChar(SP_PARM->_acs_map[j]); - if (!(SP->_screen_acs_map[j])) { + if (temp != 0) { + SetChar(my_ch, temp, AttrOf(attr)); + } else { + my_ch = CHDEREF(ch); RemAttr(attr, A_ALTCHARSET); - if (temp == 0) - temp = ' '; } - if (temp != 0) - SetChar(my_ch, temp, AttrOf(attr)); } ch = CHREF(my_ch); } +#if USE_WIDEC_SUPPORT && !NCURSES_WCWIDTH_GRAPHICS + else if (chlen > 1 && is_wacs_value(CharOfD(ch))) { + chlen = 1; + } +#endif if (tilde_glitch && (CharOfD(ch) == L('~'))) { SetChar(tilde, L('`'), AttrOf(attr)); ch = CHREF(tilde); } - UpdateAttrs(attr); + UpdateAttrs(SP_PARM, attr); + PUTC(CHDEREF(ch)); #if !USE_WIDEC_SUPPORT - /* FIXME - we do this special case for signal handling, should see how to - * make it work for wide characters. - */ - if (SP->_outch != 0) { - SP->_outch(UChar(ch)); - } else + COUNT_OUTCHARS(1); #endif - { - PUTC(CHDEREF(ch), SP->_ofp); /* macro's fastest... */ - COUNT_OUTCHARS(1); - } - SP->_curscol += chlen; + SP_PARM->_curscol += chlen; if (char_padding) { - TPUTS_TRACE("char_padding"); - putp(char_padding); + NCURSES_PUTP2("char_padding", char_padding); } } static bool -check_pending(void) +check_pending(NCURSES_SP_DCL0) /* check for pending input */ { bool have_pending = FALSE; @@ -315,15 +376,15 @@ check_pending(void) * have the refreshing slow down drastically (or stop) if there's an * unread character available. */ - if (SP->_fifohold != 0) + if (SP_PARM->_fifohold != 0) return FALSE; - if (SP->_checkfd >= 0) { + if (SP_PARM->_checkfd >= 0) { #if USE_FUNC_POLL struct pollfd fds[1]; - fds[0].fd = SP->_checkfd; + fds[0].fd = SP_PARM->_checkfd; fds[0].events = POLLIN; - if (poll(fds, 1, 0) > 0) { + if (poll(fds, (size_t) 1, 0) > 0) { have_pending = TRUE; } #elif defined(__BEOS__) @@ -349,43 +410,51 @@ check_pending(void) ktimeout.tv_usec = 0; FD_ZERO(&fdset); - FD_SET(SP->_checkfd, &fdset); - if (select(SP->_checkfd + 1, &fdset, NULL, NULL, &ktimeout) != 0) { + FD_SET(SP_PARM->_checkfd, &fdset); + if (select(SP_PARM->_checkfd + 1, &fdset, NULL, NULL, &ktimeout) != 0) { have_pending = TRUE; } #endif } if (have_pending) { - SP->_fifohold = 5; - _nc_flush(); + SP_PARM->_fifohold = 5; + NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG); } return FALSE; } /* put char at lower right corner */ static void -PutCharLR(const ARG_CH_T ch) +PutCharLR(NCURSES_SP_DCLx const ARG_CH_T ch) { if (!auto_right_margin) { /* we can put the char directly */ - PutAttrChar(ch); + PutAttrChar(NCURSES_SP_ARGx ch); } else if (enter_am_mode && exit_am_mode) { + int oldcol = SP_PARM->_curscol; /* we can suppress automargin */ - TPUTS_TRACE("exit_am_mode"); - putp(exit_am_mode); + NCURSES_PUTP2("exit_am_mode", exit_am_mode); - PutAttrChar(ch); - SP->_curscol--; - position_check(SP->_cursrow, SP->_curscol, "exit_am_mode"); + PutAttrChar(NCURSES_SP_ARGx ch); + SP_PARM->_curscol = oldcol; + position_check(NCURSES_SP_ARGx + SP_PARM->_cursrow, + SP_PARM->_curscol, + "exit_am_mode"); - TPUTS_TRACE("enter_am_mode"); - putp(enter_am_mode); + NCURSES_PUTP2("enter_am_mode", enter_am_mode); } else if ((enter_insert_mode && exit_insert_mode) || insert_character || parm_ich) { - GoTo(screen_lines - 1, screen_columns - 2); - PutAttrChar(ch); - GoTo(screen_lines - 1, screen_columns - 2); - InsStr(newscr->_line[screen_lines - 1].text + screen_columns - 2, 1); + GoTo(NCURSES_SP_ARGx + screen_lines(SP_PARM) - 1, + screen_columns(SP_PARM) - 2); + PutAttrChar(NCURSES_SP_ARGx ch); + GoTo(NCURSES_SP_ARGx + screen_lines(SP_PARM) - 1, + screen_columns(SP_PARM) - 2); + InsStr(NCURSES_SP_ARGx + NewScreen(SP_PARM)->_line[screen_lines(SP_PARM) - 1].text + + screen_columns(SP_PARM) - 2, 1); } } @@ -393,7 +462,7 @@ PutCharLR(const ARG_CH_T ch) * Wrap the cursor position, i.e., advance to the beginning of the next line. */ static void -wrap_cursor(void) +wrap_cursor(NCURSES_SP_DCL0) { if (eat_newline_glitch) { /* @@ -406,43 +475,50 @@ wrap_cursor(void) * An aggressive way to handle this would be to emit CR/LF after the * char and then assume the wrap is done, you're on the first position * of the next line, and the terminal out of its weird state. Here - * it's safe to just tell the code that the cursor is in hyperspace and + * it is safe to just tell the code that the cursor is in hyperspace and * let the next mvcur() call straighten things out. */ - SP->_curscol = -1; - SP->_cursrow = -1; + SP_PARM->_curscol = -1; + SP_PARM->_cursrow = -1; } else if (auto_right_margin) { - SP->_curscol = 0; - SP->_cursrow++; + SP_PARM->_curscol = 0; + SP_PARM->_cursrow++; /* * We've actually moved - but may have to work around problems with * video attributes not working. */ - if (!move_standout_mode && AttrOf(SCREEN_ATTRS(SP))) { + if (!move_standout_mode && AttrOf(SCREEN_ATTRS(SP_PARM))) { TR(TRACE_CHARPUT, ("turning off (%#lx) %s before wrapping", - (unsigned long) AttrOf(SCREEN_ATTRS(SP)), - _traceattr(AttrOf(SCREEN_ATTRS(SP))))); - (void) VIDATTR(A_NORMAL, 0); + (unsigned long) AttrOf(SCREEN_ATTRS(SP_PARM)), + _traceattr(AttrOf(SCREEN_ATTRS(SP_PARM))))); + VIDPUTS(SP_PARM, A_NORMAL, 0); } } else { - SP->_curscol--; + SP_PARM->_curscol--; } - position_check(SP->_cursrow, SP->_curscol, "wrap_cursor"); + position_check(NCURSES_SP_ARGx + SP_PARM->_cursrow, + SP_PARM->_curscol, + "wrap_cursor"); } static NCURSES_INLINE void -PutChar(const ARG_CH_T ch) +PutChar(NCURSES_SP_DCLx const ARG_CH_T ch) /* insert character, handling automargin stuff */ { - if (SP->_cursrow == screen_lines - 1 && SP->_curscol == screen_columns - 1) - PutCharLR(ch); - else - PutAttrChar(ch); + if (SP_PARM->_cursrow == screen_lines(SP_PARM) - 1 && + SP_PARM->_curscol == screen_columns(SP_PARM) - 1) { + PutCharLR(NCURSES_SP_ARGx ch); + } else { + PutAttrChar(NCURSES_SP_ARGx ch); + } - if (SP->_curscol >= screen_columns) - wrap_cursor(); + if (SP_PARM->_curscol >= screen_columns(SP_PARM)) + wrap_cursor(NCURSES_SP_ARG); - position_check(SP->_cursrow, SP->_curscol, "PutChar"); + position_check(NCURSES_SP_ARGx + SP_PARM->_cursrow, + SP_PARM->_curscol, "PutChar"); } /* @@ -452,21 +528,25 @@ PutChar(const ARG_CH_T ch) * or can be output by clearing (A_COLOR in case of bce-terminal) are excluded. */ static NCURSES_INLINE bool -can_clear_with(ARG_CH_T ch) +can_clear_with(NCURSES_SP_DCLx ARG_CH_T ch) { - if (!back_color_erase && SP->_coloron) { + if (!back_color_erase && SP_PARM->_coloron) { #if NCURSES_EXT_FUNCS int pair; - if (!SP->_default_color) + if (!SP_PARM->_default_color) return FALSE; - if (SP->_default_fg != C_MASK || SP->_default_bg != C_MASK) + if (!(isDefaultColor(SP_PARM->_default_fg) && + isDefaultColor(SP_PARM->_default_bg))) return FALSE; if ((pair = GetPair(CHDEREF(ch))) != 0) { - short fg, bg; - pair_content(pair, &fg, &bg); - if (fg != C_MASK || bg != C_MASK) + NCURSES_COLOR_T fg, bg; + if (NCURSES_SP_NAME(pair_content) (NCURSES_SP_ARGx + (short) pair, + &fg, &bg) == ERR + || !(isDefaultColor(fg) && isDefaultColor(bg))) { return FALSE; + } } #else if (AttrOfD(ch) & A_COLOR) @@ -490,7 +570,7 @@ can_clear_with(ARG_CH_T ch) * This code is optimized using ech and rep. */ static int -EmitRange(const NCURSES_CH_T * ntext, int num) +EmitRange(NCURSES_SP_DCLx const NCURSES_CH_T *ntext, int num) { int i; @@ -502,13 +582,13 @@ EmitRange(const NCURSES_CH_T * ntext, int num) NCURSES_CH_T ntext0; while (num > 1 && !CharEq(ntext[0], ntext[1])) { - PutChar(CHREF(ntext[0])); + PutChar(NCURSES_SP_ARGx CHREF(ntext[0])); ntext++; num--; } ntext0 = ntext[0]; if (num == 1) { - PutChar(CHREF(ntext0)); + PutChar(NCURSES_SP_ARGx CHREF(ntext0)); return 0; } runcount = 2; @@ -525,10 +605,10 @@ EmitRange(const NCURSES_CH_T * ntext, int num) * which it would be marginally advantageous. */ if (erase_chars - && runcount > SP->_ech_cost + SP->_cup_ch_cost - && can_clear_with(CHREF(ntext0))) { - UpdateAttrs(ntext0); - putp(TPARM_1(erase_chars, runcount)); + && runcount > SP_PARM->_ech_cost + SP_PARM->_cup_ch_cost + && can_clear_with(NCURSES_SP_ARGx CHREF(ntext0))) { + UpdateAttrs(SP_PARM, ntext0); + NCURSES_PUTP2("erase_chars", TIPARM_1(erase_chars, runcount)); /* * If this is the last part of the given interval, @@ -536,31 +616,53 @@ EmitRange(const NCURSES_CH_T * ntext, int num) * last update on the line. */ if (runcount < num) { - GoTo(SP->_cursrow, SP->_curscol + runcount); + GoTo(NCURSES_SP_ARGx + SP_PARM->_cursrow, + SP_PARM->_curscol + runcount); } else { return 1; /* cursor stays in the middle */ } - } else if (repeat_char && + } else if (repeat_char != 0 && #if BSD_TPUTS - !isdigit(UChar(CharOf(ntext0))) && + !isdigit(UChar(CharOf(ntext0))) && +#endif +#if USE_WIDEC_SUPPORT + (!SP_PARM->_screen_unicode && + (CharOf(ntext0) < ((AttrOf(ntext0) & A_ALTCHARSET) + ? ACS_LEN + : 256))) && #endif - runcount > SP->_rep_cost) { - bool wrap_possible = (SP->_curscol + runcount >= screen_columns); + runcount > SP_PARM->_rep_cost) { + NCURSES_CH_T temp; + bool wrap_possible = (SP_PARM->_curscol + runcount >= + screen_columns(SP_PARM)); int rep_count = runcount; if (wrap_possible) rep_count--; - UpdateAttrs(ntext0); - tputs(TPARM_2(repeat_char, CharOf(ntext0), rep_count), - rep_count, _nc_outch); - SP->_curscol += rep_count; + UpdateAttrs(SP_PARM, ntext0); + temp = ntext0; + if ((AttrOf(temp) & A_ALTCHARSET) && + SP_PARM->_acs_map != 0 && + (SP_PARM->_acs_map[CharOf(temp)] & A_CHARTEXT) != 0) { + SetChar(temp, + (SP_PARM->_acs_map[CharOf(ntext0)] & A_CHARTEXT), + AttrOf(ntext0) | A_ALTCHARSET); + } + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_2(repeat_char, + CharOf(temp), + rep_count), + 1, + NCURSES_SP_NAME(_nc_outch)); + SP_PARM->_curscol += rep_count; if (wrap_possible) - PutChar(CHREF(ntext0)); + PutChar(NCURSES_SP_ARGx CHREF(ntext0)); } else { for (i = 0; i < runcount; i++) - PutChar(CHREF(ntext[i])); + PutChar(NCURSES_SP_ARGx CHREF(ntext[i])); } ntext += runcount; num -= runcount; @@ -569,7 +671,7 @@ EmitRange(const NCURSES_CH_T * ntext, int num) } for (i = 0; i < num; i++) - PutChar(CHREF(ntext[i])); + PutChar(NCURSES_SP_ARGx CHREF(ntext[i])); return 0; } @@ -582,39 +684,47 @@ EmitRange(const NCURSES_CH_T * ntext, int num) * Returns: same as EmitRange */ static int -PutRange(const NCURSES_CH_T * otext, - const NCURSES_CH_T * ntext, +PutRange(NCURSES_SP_DCLx + const NCURSES_CH_T *otext, + const NCURSES_CH_T *ntext, int row, int first, int last) { - int i, j, same; + int rc; - TR(TRACE_CHARPUT, ("PutRange(%p, %p, %d, %d, %d)", - otext, ntext, row, first, last)); + TR(TRACE_CHARPUT, ("PutRange(%p, %p, %p, %d, %d, %d)", + (void *) SP_PARM, + (const void *) otext, + (const void *) ntext, + row, first, last)); if (otext != ntext - && (last - first + 1) > SP->_inline_cost) { + && (last - first + 1) > SP_PARM->_inline_cost) { + int i, j, same; + for (j = first, same = 0; j <= last; j++) { if (!same && isWidecExt(otext[j])) continue; if (CharEq(otext[j], ntext[j])) { same++; } else { - if (same > SP->_inline_cost) { - EmitRange(ntext + first, j - same - first); - GoTo(row, first = j); + if (same > SP_PARM->_inline_cost) { + EmitRange(NCURSES_SP_ARGx ntext + first, j - same - first); + GoTo(NCURSES_SP_ARGx row, first = j); } same = 0; } } - i = EmitRange(ntext + first, j - same - first); + i = EmitRange(NCURSES_SP_ARGx ntext + first, j - same - first); /* * Always return 1 for the next GoTo() after a PutRange() if we found * identical characters at end of interval */ - return (same == 0 ? i : 1); + rc = (same == 0 ? i : 1); + } else { + rc = EmitRange(NCURSES_SP_ARGx ntext + first, last - first + 1); } - return EmitRange(ntext + first, last - first + 1); + return rc; } /* leave unbracketed here so 'indent' works */ @@ -624,7 +734,7 @@ PutRange(const NCURSES_CH_T * otext, if_USE_SCROLL_HINTS(win->_line[row].oldindex = row) NCURSES_EXPORT(int) -doupdate(void) +TINFO_DOUPDATE(NCURSES_SP_DCL0) { int i; int nonempty; @@ -632,30 +742,63 @@ doupdate(void) struct tms before, after; #endif /* USE_TRACE_TIMES */ - T((T_CALLED("doupdate()"))); + T((T_CALLED("_nc_tinfo:doupdate(%p)"), (void *) SP_PARM)); + + _nc_lock_global(update); - if (curscr == 0 - || newscr == 0) + if (SP_PARM == 0) { + _nc_unlock_global(update); returnCode(ERR); + } +#if !USE_REENTRANT + /* + * It is "legal" but unlikely that an application could assign a new + * value to one of the standard windows. Check for that possibility + * and try to recover. + * + * We do not allow applications to assign new values in the reentrant + * model. + */ +#if NCURSES_SP_FUNCS + if (SP_PARM == CURRENT_SCREEN) { +#endif +#define SyncScreens(internal,exported) \ + if (internal == 0) internal = exported; \ + if (internal != exported) exported = internal + + SyncScreens(CurScreen(SP_PARM), curscr); + SyncScreens(NewScreen(SP_PARM), newscr); + SyncScreens(StdScreen(SP_PARM), stdscr); +#if NCURSES_SP_FUNCS + } +#endif +#endif /* !USE_REENTRANT */ + if (CurScreen(SP_PARM) == 0 + || NewScreen(SP_PARM) == 0 + || StdScreen(SP_PARM) == 0) { + _nc_unlock_global(update); + returnCode(ERR); + } #ifdef TRACE if (USE_TRACEF(TRACE_UPDATE)) { - if (curscr->_clear) + if (CurScreen(SP_PARM)->_clear) _tracef("curscr is clear"); else - _tracedump("curscr", curscr); - _tracedump("newscr", newscr); + _tracedump("curscr", CurScreen(SP_PARM)); + _tracedump("newscr", NewScreen(SP_PARM)); _nc_unlock_global(tracef); } #endif /* TRACE */ _nc_signal_handler(FALSE); - if (SP->_fifohold) - SP->_fifohold--; + if (SP_PARM->_fifohold) + SP_PARM->_fifohold--; #if USE_SIZECHANGE - if (SP->_endwin || _nc_handle_sigwinch(SP)) { + if ((SP_PARM->_endwin == ewSuspend) + || _nc_handle_sigwinch(SP_PARM)) { /* * This is a transparent extension: XSI does not address it, * and applications need not know that ncurses can do it. @@ -664,20 +807,20 @@ doupdate(void) * (this can happen in an xterm, for example), and resize the * ncurses data structures accordingly. */ - _nc_update_screensize(SP); + _nc_update_screensize(SP_PARM); } #endif - if (SP->_endwin) { + if (SP_PARM->_endwin == ewSuspend) { T(("coming back from shell mode")); - reset_prog_mode(); + NCURSES_SP_NAME(reset_prog_mode) (NCURSES_SP_ARG); - _nc_mvcur_resume(); - _nc_screen_resume(); - SP->_mouse_resume(SP); + NCURSES_SP_NAME(_nc_mvcur_resume) (NCURSES_SP_ARG); + NCURSES_SP_NAME(_nc_screen_resume) (NCURSES_SP_ARG); + SP_PARM->_mouse_resume(SP_PARM); - SP->_endwin = FALSE; + SP_PARM->_endwin = ewRunning; } #if USE_TRACE_TIMES /* zero the metering machinery */ @@ -688,7 +831,7 @@ doupdate(void) /* * This is the support for magic-cookie terminals. The theory: we scan * the virtual screen looking for attribute turnons. Where we find one, - * check to make sure it's realizable by seeing if the required number of + * check to make sure it is realizable by seeing if the required number of * un-attributed blanks are present before and after the attributed range; * try to shift the range boundaries over blanks (not changing the screen * display) so this becomes true. If it is, shift the beginning attribute @@ -701,11 +844,11 @@ doupdate(void) int j, k; attr_t rattr = A_NORMAL; - for (i = 0; i < screen_lines; i++) { - for (j = 0; j < screen_columns; j++) { + for (i = 0; i < screen_lines(SP_PARM); i++) { + for (j = 0; j < screen_columns(SP_PARM); j++) { bool failed = FALSE; - NCURSES_CH_T *thisline = newscr->_line[i].text; - attr_t thisattr = AttrOf(thisline[j]) & SP->_xmc_triggers; + NCURSES_CH_T *thisline = NewScreen(SP_PARM)->_line[i].text; + attr_t thisattr = AttrOf(thisline[j]) & SP_PARM->_xmc_triggers; attr_t turnon = thisattr & ~rattr; /* is an attribute turned on here? */ @@ -723,8 +866,8 @@ doupdate(void) * there's enough room to set the attribute before the first * non-blank in the run. */ -#define SAFE(a) (!((a) & SP->_xmc_triggers)) - if (ISBLANK(thisline[j]) && SAFE(turnon)) { +#define SAFE(scr,a) (!((a) & (scr)->_xmc_triggers)) + if (ISBLANK(thisline[j]) && SAFE(SP_PARM, turnon)) { RemAttr(thisline[j], turnon); continue; } @@ -733,14 +876,14 @@ doupdate(void) for (k = 1; k <= magic_cookie_glitch; k++) { if (j - k < 0 || !ISBLANK(thisline[j - k]) - || !SAFE(AttrOf(thisline[j - k]))) { + || !SAFE(SP_PARM, AttrOf(thisline[j - k]))) { failed = TRUE; TR(TRACE_ATTRS, ("No room at start in %d,%d%s%s", i, j - k, (ISBLANK(thisline[j - k]) ? "" : ":nonblank"), - (SAFE(AttrOf(thisline[j - k])) + (SAFE(SP_PARM, AttrOf(thisline[j - k])) ? "" : ":unsafe"))); break; @@ -750,11 +893,12 @@ doupdate(void) bool end_onscreen = FALSE; int m, n = j; - /* find end of span, if it's onscreen */ - for (m = i; m < screen_lines; m++) { - for (; n < screen_columns; n++) { - attr_t testattr = AttrOf(newscr->_line[m].text[n]); - if ((testattr & SP->_xmc_triggers) == rattr) { + /* find end of span, if it is onscreen */ + for (m = i; m < screen_lines(SP_PARM); m++) { + for (; n < screen_columns(SP_PARM); n++) { + attr_t testattr = + AttrOf(NewScreen(SP_PARM)->_line[m].text[n]); + if ((testattr & SP_PARM->_xmc_triggers) == rattr) { end_onscreen = TRUE; TR(TRACE_ATTRS, ("Range attributed with %s ends at (%d, %d)", @@ -770,7 +914,8 @@ doupdate(void) foundit:; if (end_onscreen) { - NCURSES_CH_T *lastline = newscr->_line[m].text; + NCURSES_CH_T *lastline = + NewScreen(SP_PARM)->_line[m].text; /* * If there are safely-attributed blanks at the end of @@ -779,15 +924,15 @@ doupdate(void) */ while (n >= 0 && ISBLANK(lastline[n]) - && SAFE(AttrOf(lastline[n]))) { + && SAFE(SP_PARM, AttrOf(lastline[n]))) { RemAttr(lastline[n--], turnon); } /* check that there's enough room at end of span */ for (k = 1; k <= magic_cookie_glitch; k++) { - if (n + k >= screen_columns + if (n + k >= screen_columns(SP_PARM) || !ISBLANK(lastline[n + k]) - || !SAFE(AttrOf(lastline[n + k]))) { + || !SAFE(SP_PARM, AttrOf(lastline[n + k]))) { failed = TRUE; TR(TRACE_ATTRS, ("No room at end in %d,%d%s%s", @@ -795,7 +940,7 @@ doupdate(void) (ISBLANK(lastline[n + k]) ? "" : ":nonblank"), - (SAFE(AttrOf(lastline[n + k])) + (SAFE(SP_PARM, AttrOf(lastline[n + k])) ? "" : ":unsafe"))); break; @@ -812,12 +957,12 @@ doupdate(void) _traceattr(turnon), i, j)); /* turn off new attributes over span */ - for (p = i; p < screen_lines; p++) { - for (; q < screen_columns; q++) { + for (p = i; p < screen_lines(SP_PARM); p++) { + for (; q < screen_columns(SP_PARM); q++) { attr_t testattr = AttrOf(newscr->_line[p].text[q]); - if ((testattr & SP->_xmc_triggers) == rattr) + if ((testattr & SP_PARM->_xmc_triggers) == rattr) goto foundend; - RemAttr(newscr->_line[p].text[q], turnon); + RemAttr(NewScreen(SP_PARM)->_line[p].text[q], turnon); } q = 0; } @@ -843,7 +988,7 @@ doupdate(void) /* show altered highlights after magic-cookie check */ if (USE_TRACEF(TRACE_UPDATE)) { _tracef("After magic-cookie check..."); - _tracedump("newscr", newscr); + _tracedump("newscr", NewScreen(SP_PARM)); _nc_unlock_global(tracef); } #endif /* TRACE */ @@ -851,23 +996,23 @@ doupdate(void) #endif /* USE_XMC_SUPPORT */ nonempty = 0; - if (curscr->_clear || newscr->_clear) { /* force refresh ? */ - ClrUpdate(); - curscr->_clear = FALSE; /* reset flag */ - newscr->_clear = FALSE; /* reset flag */ + if (CurScreen(SP_PARM)->_clear || NewScreen(SP_PARM)->_clear) { /* force refresh ? */ + ClrUpdate(NCURSES_SP_ARG); + CurScreen(SP_PARM)->_clear = FALSE; /* reset flag */ + NewScreen(SP_PARM)->_clear = FALSE; /* reset flag */ } else { int changedlines = CHECK_INTERVAL; - if (check_pending()) + if (check_pending(NCURSES_SP_ARG)) goto cleanup; - nonempty = min(screen_lines, newscr->_maxy + 1); + nonempty = min(screen_lines(SP_PARM), NewScreen(SP_PARM)->_maxy + 1); - if (SP->_scrolling) { - _nc_scroll_optimize(); + if (SP_PARM->_scrolling) { + NCURSES_SP_NAME(_nc_scroll_optimize) (NCURSES_SP_ARG); } - nonempty = ClrBottom(nonempty); + nonempty = ClrBottom(NCURSES_SP_ARGx nonempty); TR(TRACE_UPDATE, ("Transforming lines, nonempty %d", nonempty)); for (i = 0; i < nonempty; i++) { @@ -875,7 +1020,7 @@ doupdate(void) * Here is our line-breakout optimization. */ if (changedlines == CHECK_INTERVAL) { - if (check_pending()) + if (check_pending(NCURSES_SP_ARG)) goto cleanup; changedlines = 0; } @@ -886,35 +1031,35 @@ doupdate(void) * is normally set by _nc_scroll_window in the * vertical-movement optimization code, */ - if (newscr->_line[i].firstchar != _NOCHANGE - || curscr->_line[i].firstchar != _NOCHANGE) { - TransformLine(i); + if (NewScreen(SP_PARM)->_line[i].firstchar != _NOCHANGE + || CurScreen(SP_PARM)->_line[i].firstchar != _NOCHANGE) { + TransformLine(NCURSES_SP_ARGx i); changedlines++; } /* mark line changed successfully */ - if (i <= newscr->_maxy) { - MARK_NOCHANGE(newscr, i); + if (i <= NewScreen(SP_PARM)->_maxy) { + MARK_NOCHANGE(NewScreen(SP_PARM), i); } - if (i <= curscr->_maxy) { - MARK_NOCHANGE(curscr, i); + if (i <= CurScreen(SP_PARM)->_maxy) { + MARK_NOCHANGE(CurScreen(SP_PARM), i); } } } /* put everything back in sync */ - for (i = nonempty; i <= newscr->_maxy; i++) { - MARK_NOCHANGE(newscr, i); + for (i = nonempty; i <= NewScreen(SP_PARM)->_maxy; i++) { + MARK_NOCHANGE(NewScreen(SP_PARM), i); } - for (i = nonempty; i <= curscr->_maxy; i++) { - MARK_NOCHANGE(curscr, i); + for (i = nonempty; i <= CurScreen(SP_PARM)->_maxy; i++) { + MARK_NOCHANGE(CurScreen(SP_PARM), i); } - if (!newscr->_leaveok) { - curscr->_curx = newscr->_curx; - curscr->_cury = newscr->_cury; + if (!NewScreen(SP_PARM)->_leaveok) { + CurScreen(SP_PARM)->_curx = NewScreen(SP_PARM)->_curx; + CurScreen(SP_PARM)->_cury = NewScreen(SP_PARM)->_cury; - GoTo(curscr->_cury, curscr->_curx); + GoTo(NCURSES_SP_ARGx CurScreen(SP_PARM)->_cury, CurScreen(SP_PARM)->_curx); } cleanup: @@ -927,10 +1072,10 @@ doupdate(void) #if USE_XMC_SUPPORT if (magic_cookie_glitch != 0) #endif - UpdateAttrs(normal); + UpdateAttrs(SP_PARM, normal); - _nc_flush(); - WINDOW_ATTRS(curscr) = WINDOW_ATTRS(newscr); + NCURSES_SP_NAME(_nc_flush) (NCURSES_SP_ARG); + WINDOW_ATTRS(CurScreen(SP_PARM)) = WINDOW_ATTRS(NewScreen(SP_PARM)); #if USE_TRACE_TIMES (void) times(&after); @@ -943,9 +1088,18 @@ doupdate(void) _nc_signal_handler(TRUE); + _nc_unlock_global(update); returnCode(OK); } +#if NCURSES_SP_FUNCS && !defined(USE_TERM_DRIVER) +NCURSES_EXPORT(int) +doupdate(void) +{ + return TINFO_DOUPDATE(CURRENT_SCREEN); +} +#endif + /* * ClrBlank(win) * @@ -957,14 +1111,14 @@ doupdate(void) * in the wbkgd() call. Assume 'stdscr' for this case. */ #define BCE_ATTRS (A_NORMAL|A_COLOR) -#define BCE_BKGD(win) (((win) == curscr ? stdscr : (win))->_nc_bkgd) +#define BCE_BKGD(sp,win) (((win) == CurScreen(sp) ? StdScreen(sp) : (win))->_nc_bkgd) static NCURSES_INLINE NCURSES_CH_T -ClrBlank(WINDOW *win) +ClrBlank(NCURSES_SP_DCLx WINDOW *win) { NCURSES_CH_T blank = blankchar; if (back_color_erase) - AddAttr(blank, (AttrOf(BCE_BKGD(win)) & BCE_ATTRS)); + AddAttr(blank, (AttrOf(BCE_BKGD(SP_PARM, win)) & BCE_ATTRS)); return blank; } @@ -976,23 +1130,24 @@ ClrBlank(WINDOW *win) */ static void -ClrUpdate(void) +ClrUpdate(NCURSES_SP_DCL0) { - int i; - NCURSES_CH_T blank = ClrBlank(stdscr); - int nonempty = min(screen_lines, newscr->_maxy + 1); - TR(TRACE_UPDATE, (T_CALLED("ClrUpdate"))); + if (0 != SP_PARM) { + int i; + NCURSES_CH_T blank = ClrBlank(NCURSES_SP_ARGx StdScreen(SP_PARM)); + int nonempty = min(screen_lines(SP_PARM), + NewScreen(SP_PARM)->_maxy + 1); - ClearScreen(blank); + ClearScreen(NCURSES_SP_ARGx blank); - TR(TRACE_UPDATE, ("updating screen from scratch")); + TR(TRACE_UPDATE, ("updating screen from scratch")); - nonempty = ClrBottom(nonempty); - - for (i = 0; i < nonempty; i++) - TransformLine(i); + nonempty = ClrBottom(NCURSES_SP_ARGx nonempty); + for (i = 0; i < nonempty; i++) + TransformLine(NCURSES_SP_ARGx i); + } TR(TRACE_UPDATE, (T_RETURN(""))); } @@ -1003,15 +1158,16 @@ ClrUpdate(void) */ static void -ClrToEOL(NCURSES_CH_T blank, bool needclear) +ClrToEOL(NCURSES_SP_DCLx NCURSES_CH_T blank, int needclear) { - int j; + if (CurScreen(SP_PARM) != 0 + && SP_PARM->_cursrow >= 0) { + int j; - if (curscr != 0 - && SP->_cursrow >= 0) { - for (j = SP->_curscol; j < screen_columns; j++) { + for (j = SP_PARM->_curscol; j < screen_columns(SP_PARM); j++) { if (j >= 0) { - NCURSES_CH_T *cp = &(curscr->_line[SP->_cursrow].text[j]); + NCURSES_CH_T *cp = + &(CurScreen(SP_PARM)->_line[SP_PARM->_cursrow].text[j]); if (!CharEq(*cp, blank)) { *cp = blank; @@ -1019,19 +1175,16 @@ ClrToEOL(NCURSES_CH_T blank, bool needclear) } } } - } else { - needclear = TRUE; } if (needclear) { - UpdateAttrs(blank); - TPUTS_TRACE("clr_eol"); - if (clr_eol && SP->_el_cost <= (screen_columns - SP->_curscol)) { - putp(clr_eol); + UpdateAttrs(SP_PARM, blank); + if (clr_eol && SP_PARM->_el_cost <= (screen_columns(SP_PARM) - SP_PARM->_curscol)) { + NCURSES_PUTP2("clr_eol", clr_eol); } else { - int count = (screen_columns - SP->_curscol); + int count = (screen_columns(SP_PARM) - SP_PARM->_curscol); while (count-- > 0) - PutChar(CHREF(blank)); + PutChar(NCURSES_SP_ARGx CHREF(blank)); } } } @@ -1043,23 +1196,31 @@ ClrToEOL(NCURSES_CH_T blank, bool needclear) */ static void -ClrToEOS(NCURSES_CH_T blank) +ClrToEOS(NCURSES_SP_DCLx NCURSES_CH_T blank) { int row, col; - row = SP->_cursrow; - col = SP->_curscol; + row = SP_PARM->_cursrow; + col = SP_PARM->_curscol; + + if (row < 0) + row = 0; + if (col < 0) + col = 0; - UpdateAttrs(blank); + UpdateAttrs(SP_PARM, blank); TPUTS_TRACE("clr_eos"); - tputs(clr_eos, screen_lines - row, _nc_outch); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + clr_eos, + screen_lines(SP_PARM) - row, + NCURSES_SP_NAME(_nc_outch)); - while (col < screen_columns) - curscr->_line[row].text[col++] = blank; + while (col < screen_columns(SP_PARM)) + CurScreen(SP_PARM)->_line[row].text[col++] = blank; - for (row++; row < screen_lines; row++) { - for (col = 0; col < screen_columns; col++) - curscr->_line[row].text[col] = blank; + for (row++; row < screen_lines(SP_PARM); row++) { + for (col = 0; col < screen_columns(SP_PARM); col++) + CurScreen(SP_PARM)->_line[row].text[col] = blank; } } @@ -1071,26 +1232,27 @@ ClrToEOS(NCURSES_CH_T blank) * screen, checking if each is blank, and one or more are changed. */ static int -ClrBottom(int total) +ClrBottom(NCURSES_SP_DCLx int total) { - int row; - int col; int top = total; - int last = min(screen_columns, newscr->_maxx + 1); - NCURSES_CH_T blank = newscr->_line[total - 1].text[last - 1]; - bool ok; + int last = min(screen_columns(SP_PARM), NewScreen(SP_PARM)->_maxx + 1); + NCURSES_CH_T blank = NewScreen(SP_PARM)->_line[total - 1].text[last - 1]; - if (clr_eos && can_clear_with(CHREF(blank))) { + if (clr_eos && can_clear_with(NCURSES_SP_ARGx CHREF(blank))) { + int row; for (row = total - 1; row >= 0; row--) { + int col; + bool ok; + for (col = 0, ok = TRUE; ok && col < last; col++) { - ok = (CharEq(newscr->_line[row].text[col], blank)); + ok = (CharEq(NewScreen(SP_PARM)->_line[row].text[col], blank)); } if (!ok) break; for (col = 0; ok && col < last; col++) { - ok = (CharEq(curscr->_line[row].text[col], blank)); + ok = (CharEq(CurScreen(SP_PARM)->_line[row].text[col], blank)); } if (!ok) top = row; @@ -1098,11 +1260,11 @@ ClrBottom(int total) /* don't use clr_eos for just one line if clr_eol available */ if (top < total) { - GoTo(top, 0); - ClrToEOS(blank); - if (SP->oldhash && SP->newhash) { - for (row = top; row < screen_lines; row++) - SP->oldhash[row] = SP->newhash[row]; + GoTo(NCURSES_SP_ARGx top, 0); + ClrToEOS(NCURSES_SP_ARGx blank); + if (SP_PARM->oldhash && SP_PARM->newhash) { + for (row = top; row < screen_lines(SP_PARM); row++) + SP_PARM->oldhash[row] = SP_PARM->newhash[row]; } } } @@ -1111,22 +1273,22 @@ ClrBottom(int total) #if USE_XMC_SUPPORT #if USE_WIDEC_SUPPORT -#define check_xmc_transition(a, b) \ - ((((a)->attr ^ (b)->attr) & ~((a)->attr) & SP->_xmc_triggers) != 0) -#define xmc_turn_on(a,b) check_xmc_transition(&(a), &(b)) +#define check_xmc_transition(sp, a, b) \ + ((((a)->attr ^ (b)->attr) & ~((a)->attr) & (sp)->_xmc_triggers) != 0) +#define xmc_turn_on(sp,a,b) check_xmc_transition(sp,&(a), &(b)) #else -#define xmc_turn_on(a,b) ((((a)^(b)) & ~(a) & SP->_xmc_triggers) != 0) +#define xmc_turn_on(sp,a,b) ((((a)^(b)) & ~(a) & (sp)->_xmc_triggers) != 0) #endif -#define xmc_new(r,c) newscr->_line[r].text[c] -#define xmc_turn_off(a,b) xmc_turn_on(b,a) +#define xmc_new(sp,r,c) NewScreen(sp)->_line[r].text[c] +#define xmc_turn_off(sp,a,b) xmc_turn_on(sp,b,a) #endif /* USE_XMC_SUPPORT */ /* ** TransformLine(lineno) ** ** Transform the given line in curscr to the one in newscr, using -** Insert/Delete Character if _nc_idcok && has_ic(). +** Insert/Delete Character if idcok && has_ic(). ** ** firstChar = position of first different character in line ** oLastChar = position of last different character in old line @@ -1141,19 +1303,19 @@ ClrBottom(int total) */ static void -TransformLine(int const lineno) +TransformLine(NCURSES_SP_DCLx int const lineno) { int firstChar, oLastChar, nLastChar; - NCURSES_CH_T *newLine = newscr->_line[lineno].text; - NCURSES_CH_T *oldLine = curscr->_line[lineno].text; + NCURSES_CH_T *newLine = NewScreen(SP_PARM)->_line[lineno].text; + NCURSES_CH_T *oldLine = CurScreen(SP_PARM)->_line[lineno].text; int n; bool attrchanged = FALSE; - TR(TRACE_UPDATE, (T_CALLED("TransformLine(%d)"), lineno)); + TR(TRACE_UPDATE, (T_CALLED("TransformLine(%p, %d)"), (void *) SP_PARM, lineno)); /* copy new hash value to old one */ - if (SP->oldhash && SP->newhash) - SP->oldhash[lineno] = SP->newhash[lineno]; + if (SP_PARM->oldhash && SP_PARM->newhash) + SP_PARM->oldhash[lineno] = SP_PARM->newhash[lineno]; /* * If we have colors, there is the possibility of having two color pairs @@ -1161,19 +1323,20 @@ TransformLine(int const lineno) * for this case, and update the old line with the new line's colors when * they are equivalent. */ - if (SP->_coloron) { + if (SP_PARM->_coloron) { int oldPair; int newPair; - for (n = 0; n < screen_columns; n++) { + for (n = 0; n < screen_columns(SP_PARM); n++) { if (!CharEq(newLine[n], oldLine[n])) { oldPair = GetPair(oldLine[n]); newPair = GetPair(newLine[n]); if (oldPair != newPair && unColor(oldLine[n]) == unColor(newLine[n])) { - if (oldPair < COLOR_PAIRS - && newPair < COLOR_PAIRS - && SP->_color_pairs[oldPair] == SP->_color_pairs[newPair]) { + if (oldPair < SP_PARM->_pair_alloc + && newPair < SP_PARM->_pair_alloc + && (isSamePair(SP_PARM->_color_pairs[oldPair], + SP_PARM->_color_pairs[newPair]))) { SetPair(oldLine[n], GetPair(newLine[n])); } } @@ -1183,7 +1346,7 @@ TransformLine(int const lineno) if (ceol_standout_glitch && clr_eol) { firstChar = 0; - while (firstChar < screen_columns) { + while (firstChar < screen_columns(SP_PARM)) { if (!SameAttrOf(newLine[firstChar], oldLine[firstChar])) { attrchanged = TRUE; break; @@ -1195,9 +1358,13 @@ TransformLine(int const lineno) firstChar = 0; if (attrchanged) { /* we may have to disregard the whole line */ - GoTo(lineno, firstChar); - ClrToEOL(ClrBlank(curscr), FALSE); - PutRange(oldLine, newLine, lineno, 0, (screen_columns - 1)); + GoTo(NCURSES_SP_ARGx lineno, firstChar); + ClrToEOL(NCURSES_SP_ARGx + ClrBlank(NCURSES_SP_ARGx + CurScreen(SP_PARM)), FALSE); + PutRange(NCURSES_SP_ARGx + oldLine, newLine, lineno, 0, + screen_columns(SP_PARM) - 1); #if USE_XMC_SUPPORT /* @@ -1212,8 +1379,8 @@ TransformLine(int const lineno) * following operation. */ } else if (magic_cookie_glitch > 0) { - GoTo(lineno, firstChar); - for (n = 0; n < screen_columns; n++) { + GoTo(NCURSES_SP_ARGx lineno, firstChar); + for (n = 0; n < screen_columns(SP_PARM); n++) { int m = n + magic_cookie_glitch; /* check for turn-on: @@ -1222,26 +1389,30 @@ TransformLine(int const lineno) */ if (ISBLANK(newLine[n]) && ((n > 0 - && xmc_turn_on(newLine[n - 1], newLine[n])) + && xmc_turn_on(SP_PARM, newLine[n - 1], newLine[n])) || (n == 0 && lineno > 0 - && xmc_turn_on(xmc_new(lineno - 1, screen_columns - 1), + && xmc_turn_on(SP_PARM, + xmc_new(SP_PARM, lineno - 1, + screen_columns(SP_PARM) - 1), newLine[n])))) { n = m; } - PutChar(CHREF(newLine[n])); + PutChar(NCURSES_SP_ARGx CHREF(newLine[n])); /* check for turn-off: * If we are writing an attributed non-blank, where the * next cell is blank, and not attributed. */ if (!ISBLANK(newLine[n]) - && ((n + 1 < screen_columns - && xmc_turn_off(newLine[n], newLine[n + 1])) - || (n + 1 >= screen_columns - && lineno + 1 < screen_lines - && xmc_turn_off(newLine[n], xmc_new(lineno + 1, 0))))) { + && ((n + 1 < screen_columns(SP_PARM) + && xmc_turn_off(SP_PARM, newLine[n], newLine[n + 1])) + || (n + 1 >= screen_columns(SP_PARM) + && lineno + 1 < screen_lines(SP_PARM) + && xmc_turn_off(SP_PARM, + newLine[n], + xmc_new(SP_PARM, lineno + 1, 0))))) { n = m; } @@ -1252,38 +1423,40 @@ TransformLine(int const lineno) /* it may be cheap to clear leading whitespace with clr_bol */ blank = newLine[0]; - if (clr_bol && can_clear_with(CHREF(blank))) { + if (clr_bol && can_clear_with(NCURSES_SP_ARGx CHREF(blank))) { int oFirstChar, nFirstChar; - for (oFirstChar = 0; oFirstChar < screen_columns; oFirstChar++) + for (oFirstChar = 0; + oFirstChar < screen_columns(SP_PARM); + oFirstChar++) if (!CharEq(oldLine[oFirstChar], blank)) break; - for (nFirstChar = 0; nFirstChar < screen_columns; nFirstChar++) + for (nFirstChar = 0; + nFirstChar < screen_columns(SP_PARM); + nFirstChar++) if (!CharEq(newLine[nFirstChar], blank)) break; if (nFirstChar == oFirstChar) { firstChar = nFirstChar; /* find the first differing character */ - while (firstChar < screen_columns + while (firstChar < screen_columns(SP_PARM) && CharEq(newLine[firstChar], oldLine[firstChar])) firstChar++; } else if (oFirstChar > nFirstChar) { firstChar = nFirstChar; } else { /* oFirstChar < nFirstChar */ firstChar = oFirstChar; - if (SP->_el1_cost < nFirstChar - oFirstChar) { - if (nFirstChar >= screen_columns - && SP->_el_cost <= SP->_el1_cost) { - GoTo(lineno, 0); - UpdateAttrs(blank); - TPUTS_TRACE("clr_eol"); - putp(clr_eol); + if (SP_PARM->_el1_cost < nFirstChar - oFirstChar) { + if (nFirstChar >= screen_columns(SP_PARM) + && SP_PARM->_el_cost <= SP_PARM->_el1_cost) { + GoTo(NCURSES_SP_ARGx lineno, 0); + UpdateAttrs(SP_PARM, blank); + NCURSES_PUTP2("clr_eol", clr_eol); } else { - GoTo(lineno, nFirstChar - 1); - UpdateAttrs(blank); - TPUTS_TRACE("clr_bol"); - putp(clr_bol); + GoTo(NCURSES_SP_ARGx lineno, nFirstChar - 1); + UpdateAttrs(SP_PARM, blank); + NCURSES_PUTP2("clr_bol", clr_bol); } while (firstChar < nFirstChar) @@ -1292,64 +1465,81 @@ TransformLine(int const lineno) } } else { /* find the first differing character */ - while (firstChar < screen_columns + while (firstChar < screen_columns(SP_PARM) && CharEq(newLine[firstChar], oldLine[firstChar])) firstChar++; } /* if there wasn't one, we're done */ - if (firstChar >= screen_columns) { + if (firstChar >= screen_columns(SP_PARM)) { TR(TRACE_UPDATE, (T_RETURN(""))); return; } - blank = newLine[screen_columns - 1]; + blank = newLine[screen_columns(SP_PARM) - 1]; - if (!can_clear_with(CHREF(blank))) { + if (!can_clear_with(NCURSES_SP_ARGx CHREF(blank))) { /* find the last differing character */ - nLastChar = screen_columns - 1; + nLastChar = screen_columns(SP_PARM) - 1; while (nLastChar > firstChar && CharEq(newLine[nLastChar], oldLine[nLastChar])) nLastChar--; if (nLastChar >= firstChar) { - GoTo(lineno, firstChar); - PutRange(oldLine, newLine, lineno, firstChar, nLastChar); + GoTo(NCURSES_SP_ARGx lineno, firstChar); + PutRange(NCURSES_SP_ARGx + oldLine, + newLine, + lineno, + firstChar, + nLastChar); memcpy(oldLine + firstChar, newLine + firstChar, - (nLastChar - firstChar + 1) * sizeof(NCURSES_CH_T)); + (unsigned) (nLastChar - firstChar + 1) * sizeof(NCURSES_CH_T)); } TR(TRACE_UPDATE, (T_RETURN(""))); return; } /* find last non-blank character on old line */ - oLastChar = screen_columns - 1; + oLastChar = screen_columns(SP_PARM) - 1; while (oLastChar > firstChar && CharEq(oldLine[oLastChar], blank)) oLastChar--; /* find last non-blank character on new line */ - nLastChar = screen_columns - 1; + nLastChar = screen_columns(SP_PARM) - 1; while (nLastChar > firstChar && CharEq(newLine[nLastChar], blank)) nLastChar--; if ((nLastChar == firstChar) - && (SP->_el_cost < (oLastChar - nLastChar))) { - GoTo(lineno, firstChar); + && (SP_PARM->_el_cost < (oLastChar - nLastChar))) { + GoTo(NCURSES_SP_ARGx lineno, firstChar); if (!CharEq(newLine[firstChar], blank)) - PutChar(CHREF(newLine[firstChar])); - ClrToEOL(blank, FALSE); + PutChar(NCURSES_SP_ARGx CHREF(newLine[firstChar])); + ClrToEOL(NCURSES_SP_ARGx blank, FALSE); } else if ((nLastChar != oLastChar) && (!CharEq(newLine[nLastChar], oldLine[oLastChar]) - || !(_nc_idcok && has_ic()))) { - GoTo(lineno, firstChar); - if ((oLastChar - nLastChar) > SP->_el_cost) { - if (PutRange(oldLine, newLine, lineno, firstChar, nLastChar)) - GoTo(lineno, nLastChar + 1); - ClrToEOL(blank, FALSE); + || !(SP_PARM->_nc_sp_idcok + && NCURSES_SP_NAME(has_ic) (NCURSES_SP_ARG)))) { + GoTo(NCURSES_SP_ARGx lineno, firstChar); + if ((oLastChar - nLastChar) > SP_PARM->_el_cost) { + if (PutRange(NCURSES_SP_ARGx + oldLine, + newLine, + lineno, + firstChar, + nLastChar)) { + GoTo(NCURSES_SP_ARGx lineno, nLastChar + 1); + } + ClrToEOL(NCURSES_SP_ARGx blank, FALSE); } else { n = max(nLastChar, oLastChar); - PutRange(oldLine, newLine, lineno, firstChar, n); + PutRange(NCURSES_SP_ARGx + oldLine, + newLine, + lineno, + firstChar, + n); } } else { int nLastNonblank = nLastChar; @@ -1370,33 +1560,52 @@ TransformLine(int const lineno) n = min(oLastChar, nLastChar); if (n >= firstChar) { - GoTo(lineno, firstChar); - PutRange(oldLine, newLine, lineno, firstChar, n); + GoTo(NCURSES_SP_ARGx lineno, firstChar); + PutRange(NCURSES_SP_ARGx + oldLine, + newLine, + lineno, + firstChar, + n); } if (oLastChar < nLastChar) { int m = max(nLastNonblank, oLastNonblank); #if USE_WIDEC_SUPPORT - while (isWidecExt(newLine[n + 1]) && n) { - --n; - --oLastChar; + if (n) { + while (isWidecExt(newLine[n + 1]) && n) { + --n; + --oLastChar; /* increase cost */ + } + } else if (n >= firstChar && + isWidecBase(newLine[n])) { + while (isWidecExt(newLine[n + 1])) { + ++n; + ++oLastChar; /* decrease cost */ + } } #endif - GoTo(lineno, n + 1); + GoTo(NCURSES_SP_ARGx lineno, n + 1); if ((nLastChar < nLastNonblank) - || InsCharCost(nLastChar - oLastChar) > (m - n)) { - PutRange(oldLine, newLine, lineno, n + 1, m); + || InsCharCost(SP_PARM, nLastChar - oLastChar) > (m - n)) { + PutRange(NCURSES_SP_ARGx + oldLine, + newLine, + lineno, + n + 1, + m); } else { - InsStr(&newLine[n + 1], nLastChar - oLastChar); + InsStr(NCURSES_SP_ARGx &newLine[n + 1], nLastChar - oLastChar); } } else if (oLastChar > nLastChar) { - GoTo(lineno, n + 1); - if (DelCharCost(oLastChar - nLastChar) - > SP->_el_cost + nLastNonblank - (n + 1)) { - if (PutRange(oldLine, newLine, lineno, - n + 1, nLastNonblank)) - GoTo(lineno, nLastNonblank + 1); - ClrToEOL(blank, FALSE); + GoTo(NCURSES_SP_ARGx lineno, n + 1); + if (DelCharCost(SP_PARM, oLastChar - nLastChar) + > SP_PARM->_el_cost + nLastNonblank - (n + 1)) { + if (PutRange(NCURSES_SP_ARGx oldLine, newLine, lineno, + n + 1, nLastNonblank)) { + GoTo(NCURSES_SP_ARGx lineno, nLastNonblank + 1); + } + ClrToEOL(NCURSES_SP_ARGx blank, FALSE); } else { /* * The delete-char sequence will @@ -1406,18 +1615,18 @@ TransformLine(int const lineno) * setting the video attributes from * the last character on the row. */ - UpdateAttrs(blank); - DelChar(oLastChar - nLastChar); + UpdateAttrs(SP_PARM, blank); + DelChar(NCURSES_SP_ARGx oLastChar - nLastChar); } } } } /* update the code's internal representation */ - if (screen_columns > firstChar) + if (screen_columns(SP_PARM) > firstChar) memcpy(oldLine + firstChar, newLine + firstChar, - (screen_columns - firstChar) * sizeof(NCURSES_CH_T)); + (unsigned) (screen_columns(SP_PARM) - firstChar) * sizeof(NCURSES_CH_T)); TR(TRACE_UPDATE, (T_RETURN(""))); return; } @@ -1430,7 +1639,7 @@ TransformLine(int const lineno) */ static void -ClearScreen(NCURSES_CH_T blank) +ClearScreen(NCURSES_SP_DCLx NCURSES_CH_T blank) { int i, j; bool fast_clear = (clear_screen || clr_eos || clr_eol); @@ -1438,9 +1647,13 @@ ClearScreen(NCURSES_CH_T blank) TR(TRACE_UPDATE, ("ClearScreen() called")); #if NCURSES_EXT_FUNCS - if (SP->_coloron - && !SP->_default_color) { - _nc_do_color(GET_SCREEN_PAIR(SP), 0, FALSE, _nc_outch); + if (SP_PARM->_coloron + && !SP_PARM->_default_color) { + NCURSES_SP_NAME(_nc_do_color) (NCURSES_SP_ARGx + (short) GET_SCREEN_PAIR(SP_PARM), + 0, + FALSE, + NCURSES_SP_NAME(_nc_outch)); if (!back_color_erase) { fast_clear = FALSE; } @@ -1449,42 +1662,44 @@ ClearScreen(NCURSES_CH_T blank) if (fast_clear) { if (clear_screen) { - UpdateAttrs(blank); - TPUTS_TRACE("clear_screen"); - putp(clear_screen); - SP->_cursrow = SP->_curscol = 0; - position_check(SP->_cursrow, SP->_curscol, "ClearScreen"); + UpdateAttrs(SP_PARM, blank); + NCURSES_PUTP2("clear_screen", clear_screen); + SP_PARM->_cursrow = SP_PARM->_curscol = 0; + position_check(NCURSES_SP_ARGx + SP_PARM->_cursrow, + SP_PARM->_curscol, + "ClearScreen"); } else if (clr_eos) { - SP->_cursrow = SP->_curscol = -1; - GoTo(0, 0); - - UpdateAttrs(blank); + SP_PARM->_cursrow = SP_PARM->_curscol = -1; + GoTo(NCURSES_SP_ARGx 0, 0); + UpdateAttrs(SP_PARM, blank); TPUTS_TRACE("clr_eos"); - tputs(clr_eos, screen_lines, _nc_outch); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + clr_eos, + screen_lines(SP_PARM), + NCURSES_SP_NAME(_nc_outch)); } else if (clr_eol) { - SP->_cursrow = SP->_curscol = -1; - - UpdateAttrs(blank); - for (i = 0; i < screen_lines; i++) { - GoTo(i, 0); - TPUTS_TRACE("clr_eol"); - putp(clr_eol); + SP_PARM->_cursrow = SP_PARM->_curscol = -1; + UpdateAttrs(SP_PARM, blank); + for (i = 0; i < screen_lines(SP_PARM); i++) { + GoTo(NCURSES_SP_ARGx i, 0); + NCURSES_PUTP2("clr_eol", clr_eol); } - GoTo(0, 0); + GoTo(NCURSES_SP_ARGx 0, 0); } } else { - UpdateAttrs(blank); - for (i = 0; i < screen_lines; i++) { - GoTo(i, 0); - for (j = 0; j < screen_columns; j++) - PutChar(CHREF(blank)); + UpdateAttrs(SP_PARM, blank); + for (i = 0; i < screen_lines(SP_PARM); i++) { + GoTo(NCURSES_SP_ARGx i, 0); + for (j = 0; j < screen_columns(SP_PARM); j++) + PutChar(NCURSES_SP_ARGx CHREF(blank)); } - GoTo(0, 0); + GoTo(NCURSES_SP_ARGx 0, 0); } - for (i = 0; i < screen_lines; i++) { - for (j = 0; j < screen_columns; j++) - curscr->_line[i].text[j] = blank; + for (i = 0; i < screen_lines(SP_PARM); i++) { + for (j = 0; j < screen_columns(SP_PARM); j++) + CurScreen(SP_PARM)->_line[i].text[j] = blank; } TR(TRACE_UPDATE, ("screen cleared")); @@ -1498,49 +1713,51 @@ ClearScreen(NCURSES_CH_T blank) */ static void -InsStr(NCURSES_CH_T * line, int count) +InsStr(NCURSES_SP_DCLx NCURSES_CH_T *line, int count) { - TR(TRACE_UPDATE, ("InsStr(%p,%d) called", line, count)); + TR(TRACE_UPDATE, ("InsStr(%p, %p,%d) called", + (void *) SP_PARM, + (void *) line, count)); /* Prefer parm_ich as it has the smallest cost - no need to shift * the whole line on each character. */ /* The order must match that of InsCharCost. */ if (parm_ich) { TPUTS_TRACE("parm_ich"); - tputs(TPARM_1(parm_ich, count), count, _nc_outch); - while (count) { - PutAttrChar(CHREF(*line)); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_1(parm_ich, count), + 1, + NCURSES_SP_NAME(_nc_outch)); + while (count > 0) { + PutAttrChar(NCURSES_SP_ARGx CHREF(*line)); line++; count--; } } else if (enter_insert_mode && exit_insert_mode) { - TPUTS_TRACE("enter_insert_mode"); - putp(enter_insert_mode); - while (count) { - PutAttrChar(CHREF(*line)); + NCURSES_PUTP2("enter_insert_mode", enter_insert_mode); + while (count > 0) { + PutAttrChar(NCURSES_SP_ARGx CHREF(*line)); if (insert_padding) { - TPUTS_TRACE("insert_padding"); - putp(insert_padding); + NCURSES_PUTP2("insert_padding", insert_padding); } line++; count--; } - TPUTS_TRACE("exit_insert_mode"); - putp(exit_insert_mode); + NCURSES_PUTP2("exit_insert_mode", exit_insert_mode); } else { - while (count) { - TPUTS_TRACE("insert_character"); - putp(insert_character); - PutAttrChar(CHREF(*line)); + while (count > 0) { + NCURSES_PUTP2("insert_character", insert_character); + PutAttrChar(NCURSES_SP_ARGx CHREF(*line)); if (insert_padding) { - TPUTS_TRACE("insert_padding"); - putp(insert_padding); + NCURSES_PUTP2("insert_padding", insert_padding); } line++; count--; } } - position_check(SP->_cursrow, SP->_curscol, "InsStr"); + position_check(NCURSES_SP_ARGx + SP_PARM->_cursrow, + SP_PARM->_curscol, "InsStr"); } /* @@ -1551,22 +1768,24 @@ InsStr(NCURSES_CH_T * line, int count) */ static void -DelChar(int count) +DelChar(NCURSES_SP_DCLx int count) { - int n; - - TR(TRACE_UPDATE, ("DelChar(%d) called, position = (%ld,%ld)", - count, - (long) newscr->_cury, - (long) newscr->_curx)); + TR(TRACE_UPDATE, ("DelChar(%p, %d) called, position = (%ld,%ld)", + (void *) SP_PARM, count, + (long) NewScreen(SP_PARM)->_cury, + (long) NewScreen(SP_PARM)->_curx)); if (parm_dch) { TPUTS_TRACE("parm_dch"); - tputs(TPARM_1(parm_dch, count), count, _nc_outch); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_1(parm_dch, count), + 1, + NCURSES_SP_NAME(_nc_outch)); } else { + int n; + for (n = 0; n < count; n++) { - TPUTS_TRACE("delete_character"); - putp(delete_character); + NCURSES_PUTP2("delete_character", delete_character); } } } @@ -1605,54 +1824,62 @@ DelChar(int count) /* Try to scroll up assuming given csr (miny, maxy). Returns ERR on failure */ static int -scroll_csr_forward(int n, int top, int bot, int miny, int maxy, NCURSES_CH_T blank) +scroll_csr_forward(NCURSES_SP_DCLx + int n, + int top, + int bot, + int miny, + int maxy, + NCURSES_CH_T blank) { int i; if (n == 1 && scroll_forward && top == miny && bot == maxy) { - GoTo(bot, 0); - UpdateAttrs(blank); - TPUTS_TRACE("scroll_forward"); - putp(scroll_forward); + GoTo(NCURSES_SP_ARGx bot, 0); + UpdateAttrs(SP_PARM, blank); + NCURSES_PUTP2("scroll_forward", scroll_forward); } else if (n == 1 && delete_line && bot == maxy) { - GoTo(top, 0); - UpdateAttrs(blank); - TPUTS_TRACE("delete_line"); - putp(delete_line); + GoTo(NCURSES_SP_ARGx top, 0); + UpdateAttrs(SP_PARM, blank); + NCURSES_PUTP2("delete_line", delete_line); } else if (parm_index && top == miny && bot == maxy) { - GoTo(bot, 0); - UpdateAttrs(blank); + GoTo(NCURSES_SP_ARGx bot, 0); + UpdateAttrs(SP_PARM, blank); TPUTS_TRACE("parm_index"); - tputs(TPARM_2(parm_index, n, 0), n, _nc_outch); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_1(parm_index, n), + n, + NCURSES_SP_NAME(_nc_outch)); } else if (parm_delete_line && bot == maxy) { - GoTo(top, 0); - UpdateAttrs(blank); + GoTo(NCURSES_SP_ARGx top, 0); + UpdateAttrs(SP_PARM, blank); TPUTS_TRACE("parm_delete_line"); - tputs(TPARM_2(parm_delete_line, n, 0), n, _nc_outch); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_1(parm_delete_line, n), + n, + NCURSES_SP_NAME(_nc_outch)); } else if (scroll_forward && top == miny && bot == maxy) { - GoTo(bot, 0); - UpdateAttrs(blank); + GoTo(NCURSES_SP_ARGx bot, 0); + UpdateAttrs(SP_PARM, blank); for (i = 0; i < n; i++) { - TPUTS_TRACE("scroll_forward"); - putp(scroll_forward); + NCURSES_PUTP2("scroll_forward", scroll_forward); } } else if (delete_line && bot == maxy) { - GoTo(top, 0); - UpdateAttrs(blank); + GoTo(NCURSES_SP_ARGx top, 0); + UpdateAttrs(SP_PARM, blank); for (i = 0; i < n; i++) { - TPUTS_TRACE("delete_line"); - putp(delete_line); + NCURSES_PUTP2("delete_line", delete_line); } } else return ERR; #if NCURSES_EXT_FUNCS - if (FILL_BCE()) { + if (FILL_BCE(SP_PARM)) { int j; for (i = 0; i < n; i++) { - GoTo(bot - i, 0); - for (j = 0; j < screen_columns; j++) - PutChar(CHREF(blank)); + GoTo(NCURSES_SP_ARGx bot - i, 0); + for (j = 0; j < screen_columns(SP_PARM); j++) + PutChar(NCURSES_SP_ARGx CHREF(blank)); } } #endif @@ -1662,55 +1889,62 @@ scroll_csr_forward(int n, int top, int bot, int miny, int maxy, NCURSES_CH_T bla /* Try to scroll down assuming given csr (miny, maxy). Returns ERR on failure */ /* n > 0 */ static int -scroll_csr_backward(int n, int top, int bot, int miny, int maxy, +scroll_csr_backward(NCURSES_SP_DCLx + int n, + int top, + int bot, + int miny, + int maxy, NCURSES_CH_T blank) { int i; if (n == 1 && scroll_reverse && top == miny && bot == maxy) { - GoTo(top, 0); - UpdateAttrs(blank); - TPUTS_TRACE("scroll_reverse"); - putp(scroll_reverse); + GoTo(NCURSES_SP_ARGx top, 0); + UpdateAttrs(SP_PARM, blank); + NCURSES_PUTP2("scroll_reverse", scroll_reverse); } else if (n == 1 && insert_line && bot == maxy) { - GoTo(top, 0); - UpdateAttrs(blank); - TPUTS_TRACE("insert_line"); - putp(insert_line); + GoTo(NCURSES_SP_ARGx top, 0); + UpdateAttrs(SP_PARM, blank); + NCURSES_PUTP2("insert_line", insert_line); } else if (parm_rindex && top == miny && bot == maxy) { - GoTo(top, 0); - UpdateAttrs(blank); + GoTo(NCURSES_SP_ARGx top, 0); + UpdateAttrs(SP_PARM, blank); TPUTS_TRACE("parm_rindex"); - tputs(TPARM_2(parm_rindex, n, 0), n, _nc_outch); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_1(parm_rindex, n), + n, + NCURSES_SP_NAME(_nc_outch)); } else if (parm_insert_line && bot == maxy) { - GoTo(top, 0); - UpdateAttrs(blank); + GoTo(NCURSES_SP_ARGx top, 0); + UpdateAttrs(SP_PARM, blank); TPUTS_TRACE("parm_insert_line"); - tputs(TPARM_2(parm_insert_line, n, 0), n, _nc_outch); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_1(parm_insert_line, n), + n, + NCURSES_SP_NAME(_nc_outch)); } else if (scroll_reverse && top == miny && bot == maxy) { - GoTo(top, 0); - UpdateAttrs(blank); + GoTo(NCURSES_SP_ARGx top, 0); + UpdateAttrs(SP_PARM, blank); for (i = 0; i < n; i++) { - TPUTS_TRACE("scroll_reverse"); - putp(scroll_reverse); + NCURSES_PUTP2("scroll_reverse", scroll_reverse); } } else if (insert_line && bot == maxy) { - GoTo(top, 0); - UpdateAttrs(blank); + GoTo(NCURSES_SP_ARGx top, 0); + UpdateAttrs(SP_PARM, blank); for (i = 0; i < n; i++) { - TPUTS_TRACE("insert_line"); - putp(insert_line); + NCURSES_PUTP2("insert_line", insert_line); } } else return ERR; #if NCURSES_EXT_FUNCS - if (FILL_BCE()) { + if (FILL_BCE(SP_PARM)) { int j; for (i = 0; i < n; i++) { - GoTo(top + i, 0); - for (j = 0; j < screen_columns; j++) - PutChar(CHREF(blank)); + GoTo(NCURSES_SP_ARGx top + i, 0); + for (j = 0; j < screen_columns(SP_PARM); j++) + PutChar(NCURSES_SP_ARGx CHREF(blank)); } } #endif @@ -1720,40 +1954,42 @@ scroll_csr_backward(int n, int top, int bot, int miny, int maxy, /* scroll by using delete_line at del and insert_line at ins */ /* n > 0 */ static int -scroll_idl(int n, int del, int ins, NCURSES_CH_T blank) +scroll_idl(NCURSES_SP_DCLx int n, int del, int ins, NCURSES_CH_T blank) { int i; if (!((parm_delete_line || delete_line) && (parm_insert_line || insert_line))) return ERR; - GoTo(del, 0); - UpdateAttrs(blank); + GoTo(NCURSES_SP_ARGx del, 0); + UpdateAttrs(SP_PARM, blank); if (n == 1 && delete_line) { - TPUTS_TRACE("delete_line"); - putp(delete_line); + NCURSES_PUTP2("delete_line", delete_line); } else if (parm_delete_line) { TPUTS_TRACE("parm_delete_line"); - tputs(TPARM_2(parm_delete_line, n, 0), n, _nc_outch); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_1(parm_delete_line, n), + n, + NCURSES_SP_NAME(_nc_outch)); } else { /* if (delete_line) */ for (i = 0; i < n; i++) { - TPUTS_TRACE("delete_line"); - putp(delete_line); + NCURSES_PUTP2("delete_line", delete_line); } } - GoTo(ins, 0); - UpdateAttrs(blank); + GoTo(NCURSES_SP_ARGx ins, 0); + UpdateAttrs(SP_PARM, blank); if (n == 1 && insert_line) { - TPUTS_TRACE("insert_line"); - putp(insert_line); + NCURSES_PUTP2("insert_line", insert_line); } else if (parm_insert_line) { TPUTS_TRACE("parm_insert_line"); - tputs(TPARM_2(parm_insert_line, n, 0), n, _nc_outch); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_1(parm_insert_line, n), + n, + NCURSES_SP_NAME(_nc_outch)); } else { /* if (insert_line) */ for (i = 0; i < n; i++) { - TPUTS_TRACE("insert_line"); - putp(insert_line); + NCURSES_PUTP2("insert_line", insert_line); } } @@ -1769,15 +2005,25 @@ scroll_idl(int n, int del, int ins, NCURSES_CH_T blank) * save/restore cursor capabilities if the terminal has them. */ NCURSES_EXPORT(int) -_nc_scrolln(int n, int top, int bot, int maxy) +NCURSES_SP_NAME(_nc_scrolln) (NCURSES_SP_DCLx + int n, + int top, + int bot, + int maxy) /* scroll region from top to bot by n lines */ { - NCURSES_CH_T blank = ClrBlank(stdscr); + NCURSES_CH_T blank; int i; bool cursor_saved = FALSE; int res; - TR(TRACE_MOVE, ("mvcur_scrolln(%d, %d, %d, %d)", n, top, bot, maxy)); + TR(TRACE_MOVE, ("_nc_scrolln(%p, %d, %d, %d, %d)", + (void *) SP_PARM, n, top, bot, maxy)); + + if (!IsValidScreen(SP_PARM)) + return (ERR); + + blank = ClrBlank(NCURSES_SP_ARGx StdScreen(SP_PARM)); #if USE_XMC_SUPPORT /* @@ -1793,34 +2039,32 @@ _nc_scrolln(int n, int top, int bot, int maxy) * Explicitly clear if stuff pushed off top of region might * be saved by the terminal. */ - res = scroll_csr_forward(n, top, bot, 0, maxy, blank); + res = scroll_csr_forward(NCURSES_SP_ARGx n, top, bot, 0, maxy, blank); if (res == ERR && change_scroll_region) { if ((((n == 1 && scroll_forward) || parm_index) - && (SP->_cursrow == bot || SP->_cursrow == bot - 1)) + && (SP_PARM->_cursrow == bot || SP_PARM->_cursrow == bot - 1)) && save_cursor && restore_cursor) { cursor_saved = TRUE; - TPUTS_TRACE("save_cursor"); - putp(save_cursor); + NCURSES_PUTP2("save_cursor", save_cursor); } - TPUTS_TRACE("change_scroll_region"); - putp(TPARM_2(change_scroll_region, top, bot)); + NCURSES_PUTP2("change_scroll_region", + TIPARM_2(change_scroll_region, top, bot)); if (cursor_saved) { - TPUTS_TRACE("restore_cursor"); - putp(restore_cursor); + NCURSES_PUTP2("restore_cursor", restore_cursor); } else { - SP->_cursrow = SP->_curscol = -1; + SP_PARM->_cursrow = SP_PARM->_curscol = -1; } - res = scroll_csr_forward(n, top, bot, top, bot, blank); + res = scroll_csr_forward(NCURSES_SP_ARGx n, top, bot, top, bot, blank); - TPUTS_TRACE("change_scroll_region"); - putp(TPARM_2(change_scroll_region, 0, maxy)); - SP->_cursrow = SP->_curscol = -1; + NCURSES_PUTP2("change_scroll_region", + TIPARM_2(change_scroll_region, 0, maxy)); + SP_PARM->_cursrow = SP_PARM->_curscol = -1; } - if (res == ERR && _nc_idlok) - res = scroll_idl(n, top, bot - n + 1, blank); + if (res == ERR && SP_PARM->_nc_sp_idlok) + res = scroll_idl(NCURSES_SP_ARGx n, top, bot - n + 1, blank); /* * Clear the newly shifted-in text. @@ -1829,44 +2073,45 @@ _nc_scrolln(int n, int top, int bot, int maxy) && (non_dest_scroll_region || (memory_below && bot == maxy))) { static const NCURSES_CH_T blank2 = NewChar(BLANK_TEXT); if (bot == maxy && clr_eos) { - GoTo(bot - n + 1, 0); - ClrToEOS(blank2); + GoTo(NCURSES_SP_ARGx bot - n + 1, 0); + ClrToEOS(NCURSES_SP_ARGx blank2); } else { for (i = 0; i < n; i++) { - GoTo(bot - i, 0); - ClrToEOL(blank2, FALSE); + GoTo(NCURSES_SP_ARGx bot - i, 0); + ClrToEOL(NCURSES_SP_ARGx blank2, FALSE); } } } } else { /* (n < 0) - scroll down (backward) */ - res = scroll_csr_backward(-n, top, bot, 0, maxy, blank); + res = scroll_csr_backward(NCURSES_SP_ARGx -n, top, bot, 0, maxy, blank); if (res == ERR && change_scroll_region) { - if (top != 0 && (SP->_cursrow == top || SP->_cursrow == top - 1) + if (top != 0 + && (SP_PARM->_cursrow == top || + SP_PARM->_cursrow == top - 1) && save_cursor && restore_cursor) { cursor_saved = TRUE; - TPUTS_TRACE("save_cursor"); - putp(save_cursor); + NCURSES_PUTP2("save_cursor", save_cursor); } - TPUTS_TRACE("change_scroll_region"); - putp(TPARM_2(change_scroll_region, top, bot)); + NCURSES_PUTP2("change_scroll_region", + TIPARM_2(change_scroll_region, top, bot)); if (cursor_saved) { - TPUTS_TRACE("restore_cursor"); - putp(restore_cursor); + NCURSES_PUTP2("restore_cursor", restore_cursor); } else { - SP->_cursrow = SP->_curscol = -1; + SP_PARM->_cursrow = SP_PARM->_curscol = -1; } - res = scroll_csr_backward(-n, top, bot, top, bot, blank); + res = scroll_csr_backward(NCURSES_SP_ARGx + -n, top, bot, top, bot, blank); - TPUTS_TRACE("change_scroll_region"); - putp(TPARM_2(change_scroll_region, 0, maxy)); - SP->_cursrow = SP->_curscol = -1; + NCURSES_PUTP2("change_scroll_region", + TIPARM_2(change_scroll_region, 0, maxy)); + SP_PARM->_cursrow = SP_PARM->_curscol = -1; } - if (res == ERR && _nc_idlok) - res = scroll_idl(-n, bot + n + 1, top, blank); + if (res == ERR && SP_PARM->_nc_sp_idlok) + res = scroll_idl(NCURSES_SP_ARGx -n, bot + n + 1, top, blank); /* * Clear the newly shifted-in text. @@ -1875,8 +2120,8 @@ _nc_scrolln(int n, int top, int bot, int maxy) && (non_dest_scroll_region || (memory_above && top == 0))) { static const NCURSES_CH_T blank2 = NewChar(BLANK_TEXT); for (i = 0; i < -n; i++) { - GoTo(i + top, 0); - ClrToEOL(blank2, FALSE); + GoTo(NCURSES_SP_ARGx i + top, 0); + ClrToEOL(NCURSES_SP_ARGx blank2, FALSE); } } } @@ -1884,99 +2129,165 @@ _nc_scrolln(int n, int top, int bot, int maxy) if (res == ERR) return (ERR); - _nc_scroll_window(curscr, n, top, bot, blank); + _nc_scroll_window(CurScreen(SP_PARM), n, + (NCURSES_SIZE_T) top, + (NCURSES_SIZE_T) bot, + blank); /* shift hash values too - they can be reused */ - _nc_scroll_oldhash(n, top, bot); + NCURSES_SP_NAME(_nc_scroll_oldhash) (NCURSES_SP_ARGx n, top, bot); return (OK); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +_nc_scrolln(int n, int top, int bot, int maxy) +{ + return NCURSES_SP_NAME(_nc_scrolln) (CURRENT_SCREEN, n, top, bot, maxy); +} +#endif + NCURSES_EXPORT(void) -_nc_screen_resume(void) +NCURSES_SP_NAME(_nc_screen_resume) (NCURSES_SP_DCL0) { + assert(SP_PARM); + /* make sure terminal is in a sane known state */ - SetAttr(SCREEN_ATTRS(SP), A_NORMAL); - newscr->_clear = TRUE; + SetAttr(SCREEN_ATTRS(SP_PARM), A_NORMAL); + NewScreen(SP_PARM)->_clear = TRUE; /* reset color pairs and definitions */ - if (SP->_coloron || SP->_color_defs) - _nc_reset_colors(); + if (SP_PARM->_coloron || SP_PARM->_color_defs) + NCURSES_SP_NAME(_nc_reset_colors) (NCURSES_SP_ARG); /* restore user-defined colors, if any */ - if (SP->_color_defs < 0) { + if (SP_PARM->_color_defs < 0 && !SP_PARM->_direct_color.value) { int n; - SP->_color_defs = -(SP->_color_defs); - for (n = 0; n < SP->_color_defs; ++n) { - if (SP->_color_table[n].init) { - init_color(n, - SP->_color_table[n].r, - SP->_color_table[n].g, - SP->_color_table[n].b); + SP_PARM->_color_defs = -(SP_PARM->_color_defs); + for (n = 0; n < SP_PARM->_color_defs; ++n) { + if (SP_PARM->_color_table[n].init) { + _nc_init_color(SP_PARM, + n, + SP_PARM->_color_table[n].r, + SP_PARM->_color_table[n].g, + SP_PARM->_color_table[n].b); } } } if (exit_attribute_mode) - putp(exit_attribute_mode); + NCURSES_PUTP2("exit_attribute_mode", exit_attribute_mode); else { /* turn off attributes */ if (exit_alt_charset_mode) - putp(exit_alt_charset_mode); + NCURSES_PUTP2("exit_alt_charset_mode", exit_alt_charset_mode); if (exit_standout_mode) - putp(exit_standout_mode); + NCURSES_PUTP2("exit_standout_mode", exit_standout_mode); if (exit_underline_mode) - putp(exit_underline_mode); + NCURSES_PUTP2("exit_underline_mode", exit_underline_mode); } if (exit_insert_mode) - putp(exit_insert_mode); - if (enter_am_mode && exit_am_mode) - putp(auto_right_margin ? enter_am_mode : exit_am_mode); + NCURSES_PUTP2("exit_insert_mode", exit_insert_mode); + if (enter_am_mode && exit_am_mode) { + if (auto_right_margin) { + NCURSES_PUTP2("enter_am_mode", enter_am_mode); + } else { + NCURSES_PUTP2("exit_am_mode", exit_am_mode); + } + } +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(void) +_nc_screen_resume(void) +{ + NCURSES_SP_NAME(_nc_screen_resume) (CURRENT_SCREEN); +} +#endif + +NCURSES_EXPORT(void) +NCURSES_SP_NAME(_nc_screen_init) (NCURSES_SP_DCL0) +{ + NCURSES_SP_NAME(_nc_screen_resume) (NCURSES_SP_ARG); } +#if NCURSES_SP_FUNCS NCURSES_EXPORT(void) _nc_screen_init(void) { - _nc_screen_resume(); + NCURSES_SP_NAME(_nc_screen_init) (CURRENT_SCREEN); } +#endif /* wrap up screen handling */ NCURSES_EXPORT(void) -_nc_screen_wrap(void) +NCURSES_SP_NAME(_nc_screen_wrap) (NCURSES_SP_DCL0) { - UpdateAttrs(normal); -#if NCURSES_EXT_FUNCS - if (SP->_coloron - && !SP->_default_color) { - static const NCURSES_CH_T blank = NewChar(BLANK_TEXT); - SP->_default_color = TRUE; - _nc_do_color(-1, 0, FALSE, _nc_outch); - SP->_default_color = FALSE; - - mvcur(SP->_cursrow, SP->_curscol, screen_lines - 1, 0); + if (SP_PARM != 0) { - ClrToEOL(blank, TRUE); - } + UpdateAttrs(SP_PARM, normal); +#if NCURSES_EXT_FUNCS + if (SP_PARM->_coloron + && !SP_PARM->_default_color) { + static const NCURSES_CH_T blank = NewChar(BLANK_TEXT); + SP_PARM->_default_color = TRUE; + NCURSES_SP_NAME(_nc_do_color) (NCURSES_SP_ARGx + -1, + 0, + FALSE, + NCURSES_SP_NAME(_nc_outch)); + SP_PARM->_default_color = FALSE; + + TINFO_MVCUR(NCURSES_SP_ARGx + SP_PARM->_cursrow, + SP_PARM->_curscol, + screen_lines(SP_PARM) - 1, + 0); + + ClrToEOL(NCURSES_SP_ARGx blank, TRUE); + } #endif - if (SP->_color_defs) { - _nc_reset_colors(); + if (SP_PARM->_color_defs) { + NCURSES_SP_NAME(_nc_reset_colors) (NCURSES_SP_ARG); + } } } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(void) +_nc_screen_wrap(void) +{ + NCURSES_SP_NAME(_nc_screen_wrap) (CURRENT_SCREEN); +} +#endif + #if USE_XMC_SUPPORT NCURSES_EXPORT(void) -_nc_do_xmc_glitch(attr_t previous) +NCURSES_SP_NAME(_nc_do_xmc_glitch) (NCURSES_SP_DCLx attr_t previous) { - attr_t chg = XMC_CHANGES(previous ^ AttrOf(SCREEN_ATTRS(SP))); - - while (chg != 0) { - if (chg & 1) { - SP->_curscol += magic_cookie_glitch; - if (SP->_curscol >= SP->_columns) - wrap_cursor(); - TR(TRACE_UPDATE, ("bumped to %d,%d after cookie", SP->_cursrow, SP->_curscol)); + if (SP_PARM != 0) { + attr_t chg = XMC_CHANGES(previous ^ AttrOf(SCREEN_ATTRS(SP_PARM))); + + while (chg != 0) { + if (chg & 1) { + SP_PARM->_curscol += magic_cookie_glitch; + if (SP_PARM->_curscol >= SP_PARM->_columns) + wrap_cursor(NCURSES_SP_ARG); + TR(TRACE_UPDATE, ("bumped to %d,%d after cookie", + SP_PARM->_cursrow, SP_PARM->_curscol)); + } + chg >>= 1; } - chg >>= 1; } } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(void) +_nc_do_xmc_glitch(attr_t previous) +{ + NCURSES_SP_NAME(_nc_do_xmc_glitch) (CURRENT_SCREEN, previous); +} +#endif + #endif /* USE_XMC_SUPPORT */ diff --git a/lib/libcurses/unctrl.h b/lib/libcurses/unctrl.h index eb9f9ce16a0..64484a48291 100644 --- a/lib/libcurses/unctrl.h +++ b/lib/libcurses/unctrl.h @@ -1,7 +1,8 @@ -/* $OpenBSD: unctrl.h,v 1.9 2010/01/12 23:21:59 nicm Exp $ */ +/* $OpenBSD: unctrl.h,v 1.10 2023/10/17 09:52:08 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998,2000 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2001,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -41,13 +42,13 @@ * as ^?. Printable characters are displayed as is. */ -/* $Id: unctrl.h,v 1.9 2010/01/12 23:21:59 nicm Exp $ */ +/* $Id: unctrl.h,v 1.10 2023/10/17 09:52:08 nicm Exp $ */ #ifndef NCURSES_UNCTRL_H_incl #define NCURSES_UNCTRL_H_incl 1 #undef NCURSES_VERSION -#define NCURSES_VERSION "5.7" +#define NCURSES_VERSION "6.4" #ifdef __cplusplus extern "C" { @@ -58,6 +59,10 @@ extern "C" { #undef unctrl NCURSES_EXPORT(NCURSES_CONST char *) unctrl (chtype); +#if 1 +NCURSES_EXPORT(NCURSES_CONST char *) NCURSES_SP_NAME(unctrl) (SCREEN*, chtype); +#endif + #ifdef __cplusplus } #endif diff --git a/lib/libcurses/user_caps.5 b/lib/libcurses/user_caps.5 new file mode 100644 index 00000000000..b3e4302b029 --- /dev/null +++ b/lib/libcurses/user_caps.5 @@ -0,0 +1,441 @@ +'\" t +.\"*************************************************************************** +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 2017 Free Software Foundation, Inc. * +.\" * +.\" Permission is hereby granted, free of charge, to any person obtaining a * +.\" copy of this software and associated documentation files (the * +.\" "Software"), to deal in the Software without restriction, including * +.\" without limitation the rights to use, copy, modify, merge, publish, * +.\" distribute, distribute with modifications, sublicense, and/or sell * +.\" copies of the Software, and to permit persons to whom the Software is * +.\" furnished to do so, subject to the following conditions: * +.\" * +.\" The above copyright notice and this permission notice shall be included * +.\" in all copies or substantial portions of the Software. * +.\" * +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * +.\" IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * +.\" DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * +.\" OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * +.\" THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +.\" * +.\" Except as contained in this notice, the name(s) of the above copyright * +.\" holders shall not be used in advertising or otherwise to promote the * +.\" sale, use or other dealings in this Software without prior written * +.\" authorization. * +.\"*************************************************************************** +.\" +.\" $Id: user_caps.5,v 1.1 2023/10/17 09:52:08 nicm Exp $ +.TH user_caps 5 2023-08-19 "ncurses 6.4" "File formats" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de NS +.ie n .sp +.el .sp .5 +.ie n .in +4 +.el .in +2 +.nf +.ft CR \" Courier +.. +.de NE +.fi +.ft R +.ie n .in -4 +.el .in -2 +.. +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.SH NAME +user_caps \- user-defined terminfo capabilities +.SH SYNOPSIS +.B tic -x, infocmp -x +.SH DESCRIPTION +.SS Background +Before ncurses 5.0, +terminfo databases used a \fIfixed repertoire\fP of terminal +capabilities designed for the SVr2 terminal database in 1984, +and extended in stages through SVr4 (1989), +and standardized in the Single Unix Specification beginning in 1995. +.PP +Most of the \fIextensions\fP in this fixed repertoire were additions +to the tables of boolean, numeric and string capabilities. +Rather than change the meaning of an existing capability, a new name was added. +The terminfo database uses a binary format; binary compatibility was +ensured by using a header which gave the number of items in the +tables for each type of capability. +The standardization was incomplete: +.bP +The \fIbinary format\fP itself is not described +in the X/Open Curses documentation. +Only the \fIsource format\fP is described. +.IP +Library developers rely upon the SVr4 documentation, +and reverse-engineering the compiled terminfo files to match the binary format. +.bP +Lacking a standard for the binary format, most implementations +copy the SVr2 binary format, which uses 16-bit signed integers, +and is limited to 4096-byte entries. +.IP +The format cannot represent very large numeric capabilities, +nor can it represent large numbers of special keyboard definitions. +.bP +The tables of capability names differ between implementations. +.IP +Although they \fImay\fP provide all of the standard capability names, +the position in the tables differs because some features were added as needed, +while others were added (out of order) to comply with X/Open Curses. +.IP +While ncurses' repertoire of predefined capabilities is closest to Solaris, +Solaris's terminfo database has a few differences from +the list published by X/Open Curses. +For example, ncurses can be configured with tables which match the +terminal databases for AIX, HP-UX or OSF/1, +rather than the default Solaris-like configuration. +.bP +In SVr4 curses and ncurses, +the terminal database is defined at compile-time using a text file +which lists the different terminal capabilities. +.IP +In principle, the text-file can be extended, +but doing this requires recompiling and reinstalling the library. +The text-file used in ncurses for terminal capabilities includes +details for various systems past the documented X/Open Curses features. +For example, ncurses supports these capabilities in each configuration: +.RS 8 +.TP 5 +memory_lock +(meml) +lock memory above cursor +.TP 5 +memory_unlock +(memu) +unlock memory +.TP 5 +box_chars_1 +(box1) +box characters primary set +.RE +.IP +The memory lock/unlock capabilities were included because they were used +in the X11R6 terminal description for \fBxterm\fP(1). +The \fIbox1\fP capability is used in tic to help with terminal descriptions +written for AIX. +.PP +During the 1990s, some users were reluctant to use terminfo +in spite of its performance advantages over termcap: +.bP +The fixed repertoire prevented users from adding features +for unanticipated terminal improvements +(or required them to reuse existing capabilities as a workaround). +.bP +The limitation to 16-bit signed integers was also mentioned. +Because termcap stores everything as a string, +it could represent larger numbers. +.PP +Although termcap's extensibility was rarely used +(it was never the \fIspeaker\fP who had actually used the feature), +the criticism had a point. +ncurses 5.0 provided a way to detect nonstandard capabilities, +determine their +type and optionally store and retrieve them in a way which did not interfere +with other applications. +These are referred to as \fIuser-defined capabilities\fP because no +modifications to the toolset's predefined capability names are needed. +.PP +The ncurses utilities \fBtic\fP and \fBinfocmp\fP have a command-line +option \*(``\-x\*('' to control whether the nonstandard capabilities +are stored or retrieved. +A library function \fBuse_extended_names\fP +is provided for the same purpose. +.PP +When compiling a terminal database, if \*(``\-x\*('' is set, +\fBtic\fP will store a user-defined capability if the capability name is not +one of the predefined names. +.PP +Because ncurses provides a termcap library interface, +these user-defined capabilities may be visible to termcap applications: +.bP +The termcap interface (like all implementations of termcap) +requires that the capability names are 2-characters. +.IP +When the capability is simple enough for use in a termcap application, +it is provided as a 2-character name. +.bP +There are other +user-defined capabilities which refer to features not usable in termcap, +e.g., parameterized strings that use more than two parameters +or use more than the trivial expression support provided by termcap. +For these, the terminfo database should have only capability names with +3 or more characters. +.bP +Some terminals can send distinct strings for special keys (cursor-, +keypad- or function-keys) depending on modifier keys (shift, control, etc.). +While terminfo and termcap have a set of 60 predefined function-key names, +to which a series of keys can be assigned, +that is insufficient for more than a dozen keys multiplied by more than +a couple of modifier combinations. +The ncurses database uses a convention based on \fBxterm\fP(1) to +provide extended special-key names. +.IP +Fitting that into termcap's limitation of 2-character names +would be pointless. +These extended keys are available only with terminfo. +.SS Recognized capabilities +The ncurses library uses the user-definable capabilities. +While the terminfo database may have other extensions, +ncurses makes explicit checks for these: +.RS 3 +.TP 3 +AX +\fIboolean\fP, asserts that the terminal interprets SGR 39 and SGR 49 +by resetting the foreground and background color, respectively, to the default. +.IP +This is a feature recognized by the \fBscreen\fP program as well. +.TP 3 +E3 +\fIstring\fP, tells how to clear the terminal's scrollback buffer. +When present, the \fBclear\fP(1) program sends this before clearing +the terminal. +.IP +The command \*(``\fBtput clear\fP\*('' does the same thing. +.TP 3 +NQ +used to suppress a consistency check in tic for the ncurses capabilities +in user6 through user9 (u6, u7, u8 and u9) +which tell how to query the terminal's cursor position +and its device attributes. +.TP 3 +RGB +\fIboolean\fP, \fInumber\fP \fBor\fP \fIstring\fP, +used to assert that the +\fBset_a_foreground\fP and +\fBset_a_background\fP capabilities correspond to \fIdirect colors\fP, +using an RGB (red/green/blue) convention. +This capability allows the \fBcolor_content\fP function to +return appropriate values without requiring the application +to initialize colors using \fBinit_color\fP. +.IP +The capability type determines the values which ncurses sees: +.RS 3 +.TP 3 +\fIboolean\fP +implies that the number of bits for red, green and blue are the same. +Using the maximum number of colors, +ncurses adds two, divides that sum by three, and assigns the result +to red, green and blue in that order. +.IP +If the number of bits needed for the number of colors is not a multiple +of three, the blue (and green) components lose in comparison to red. +.TP 3 +\fInumber\fP +tells ncurses what result to add to red, green and blue. +If ncurses runs out of bits, +blue (and green) lose just as in the \fIboolean\fP case. +.TP 3 +\fIstring\fP +explicitly list the number of bits used for red, green and blue components +as a slash-separated list of decimal integers. +.RE +.IP +Because there are several RGB encodings in use, +applications which make assumptions about the number of bits per color +are unlikely to work reliably. +As a trivial case, for example, one could define \fBRGB#1\fP +to represent the standard eight ANSI colors, i.e., one bit per color. +.TP 3 +U8 +\fInumber\fP, +asserts that ncurses must use Unicode values for line-drawing characters, +and that it should ignore the alternate character set capabilities +when the locale uses UTF-8 encoding. +For more information, see the discussion of +\fBNCURSES_NO_UTF8_ACS\fP in \fBncurses\fP(3). +.IP +Set this capability to a nonzero value to enable it. +.TP 3 +XM +\fIstring\fP, +override ncurses's built-in string which +enables/disables \fBxterm\fP(1) mouse mode. +.IP +ncurses sends a character sequence to the terminal to initialize mouse mode, +and when the user clicks the mouse buttons or (in certain modes) moves the +mouse, handles the characters sent back by the terminal to tell it what +was done with the mouse. +.IP +The mouse protocol is enabled when +the \fImask\fP passed in the \fBmousemask\fP function is nonzero. +By default, ncurses handles the responses for the X11 xterm mouse protocol. +It also knows about the \fISGR 1006\fP xterm mouse protocol, +but must to be told to look for this specifically. +It will not be able to guess which mode is used, +because the responses are enough alike that only confusion would result. +.IP +The \fBXM\fP capability has a single parameter. +If nonzero, the mouse protocol should be enabled. +If zero, the mouse protocol should be disabled. +ncurses inspects this capability if it is present, +to see whether the 1006 protocol is used. +If so, it expects the responses to use the \fISGR 1006\fP xterm mouse protocol. +.IP +The xterm mouse protocol is used by other terminal emulators. +The terminal database uses building-blocks for the various xterm mouse +protocols which can be used in customized terminal descriptions. +.IP +The terminal database building blocks for this mouse +feature also have an experimental capability \fIxm\fP. +The \*(``xm\*('' capability describes the mouse response. +Currently there is no interpreter which would use this +information to make the mouse support completely data-driven. +.IP +\fIxm\fP shows the format of the mouse responses. +In this experimental capability, the parameters are +.RS 5 +.TP 5 +.I p1 +y-ordinate +.TP 5 +.I p2 +x-ordinate +.TP 5 +.I p3 +button +.TP 5 +.I p4 +state, e.g., pressed or released +.TP 5 +.I p5 +y-ordinate starting region +.TP 5 +.I p6 +x-ordinate starting region +.TP 5 +.I p7 +y-ordinate ending region +.TP 5 +.I p8 +x-ordinate ending region +.RE +.IP +Here are examples from the terminal database for the most commonly used +xterm mouse protocols: +.IP +.nf + xterm+x11mouse|X11 xterm mouse protocol, + kmous=\\E[M, XM=\\E[?1000%?%p1%{1}%=%th%el%;, + xm=\\E[M + %?%p4%t%p3%e%{3}%;%'\ '%+%c + %p2%'!'%+%c + %p1%'!'%+%c, + + xterm+sm+1006|xterm SGR-mouse, + kmous=\\E[<, XM=\\E[?1006;1000%?%p1%{1}%=%th%el%;, + xm=\\E[<%i%p3%d; + %p1%d; + %p2%d; + %?%p4%tM%em%;, +.fi +. +.SS Extended key-definitions +Several terminals provide the ability to send distinct strings for +combinations of modified special keys. +There is no standard for what those keys can send. +.PP +Since 1999, \fBxterm\fP(1) has supported +\fIshift\fP, \fIcontrol\fP, \fIalt\fP, and \fImeta\fP modifiers which produce +distinct special-key strings. +In a terminal description, ncurses has no special knowledge of the +modifiers used. +Applications can use the \fInaming convention\fP established for \fBxterm\fP +to find these special keys in the terminal description. +.PP +Starting with the curses convention that \fIkey names\fP begin with \*(``k\*('' +and that shifted special keys are an uppercase name, +ncurses' terminal database defines these names to which a suffix is added: +.PP +.RS 5 +.TS +tab(/) ; +l l . +\fBName\fP/\fBDescription\fP +_ +kDC/special form of kdch1 (delete character) +kDN/special form of kcud1 (cursor down) +kEND/special form of kend (End) +kHOM/special form of khome (Home) +kLFT/special form of kcub1 (cursor-left or cursor-back) +kNXT/special form of knext (Next, or Page-Down) +kPRV/special form of kprev (Prev, or Page-Up) +kRIT/special form of kcuf1 (cursor-right, or cursor-forward) +kUP/special form of kcuu1 (cursor-up) +.TE +.RE +.PP +These are the suffixes used to denote the modifiers: +.PP +.RS 5 +.TS +tab(/) ; +l l . +\fBValue\fP/\fBDescription\fP +_ +2/Shift +3/Alt +4/Shift + Alt +5/Control +6/Shift + Control +7/Alt + Control +8/Shift + Alt + Control +9/Meta +10/Meta + Shift +11/Meta + Alt +12/Meta + Alt + Shift +13/Meta + Ctrl +14/Meta + Ctrl + Shift +15/Meta + Ctrl + Alt +16/Meta + Ctrl + Alt + Shift +.TE +.RE +.PP +None of these are predefined; terminal descriptions can refer to \fInames\fP +which ncurses will allocate at runtime to \fIkey-codes\fP. +To use these keys in an ncurses program, an application could do this: +.bP +using a list of extended key \fInames\fP, +ask \fBtigetstr\fP(3) for their values, and +.bP +given the list of values, +ask \fBkey_defined\fP(3) for the \fIkey-code\fP which +would be returned for those keys by \fBwgetch\fP(3). +.\" +.SH PORTABILITY +The \*(``\-x\*('' extension feature of \fBtic\fP and \fBinfocmp\fP +has been adopted in NetBSD curses. +That implementation stores user-defined capabilities, +but makes no use of these capabilities itself. +.\" +.SH SEE ALSO +\fBinfocmp\fP(1), +\fBtic\fP(1). +.PP +The terminal database section +.I "NCURSES USER-DEFINABLE CAPABILITIES" +summarizes commonly-used user-defined capabilities +which are used in the terminal descriptions. +Some of those features are mentioned in \fBscreen\fP(1) or \fBtmux\fP(1). +.PP +.I "XTerm Control Sequences" +provides further information on the \fBxterm\fP(1) features +which are used in these extended capabilities. +.\" +.SH AUTHORS +Thomas E. Dickey +.br +beginning with ncurses 5.0 (1999) diff --git a/lib/libcurses/wcwidth.h b/lib/libcurses/wcwidth.h new file mode 100644 index 00000000000..76673da6584 --- /dev/null +++ b/lib/libcurses/wcwidth.h @@ -0,0 +1,328 @@ +/* + * This is an implementation of wcwidth() and wcswidth() (defined in + * IEEE Std 1002.1-2001) for Unicode. + * + * http://www.opengroup.org/onlinepubs/007904975/functions/wcwidth.html + * http://www.opengroup.org/onlinepubs/007904975/functions/wcswidth.html + * + * In fixed-width output devices, Latin characters all occupy a single + * "cell" position of equal width, whereas ideographic CJK characters + * occupy two such cells. Interoperability between terminal-line + * applications and (teletype-style) character terminals using the + * UTF-8 encoding requires agreement on which character should advance + * the cursor by how many cell positions. No established formal + * standards exist at present on which Unicode character shall occupy + * how many cell positions on character terminals. These routines are + * a first attempt of defining such behavior based on simple rules + * applied to data provided by the Unicode Consortium. + * + * For some graphical characters, the Unicode standard explicitly + * defines a character-cell width via the definition of the East Asian + * FullWidth (F), Wide (W), Half-width (H), and Narrow (Na) classes. + * In all these cases, there is no ambiguity about which width a + * terminal shall use. For characters in the East Asian Ambiguous (A) + * class, the width choice depends purely on a preference of backward + * compatibility with either historic CJK or Western practice. + * Choosing single-width for these characters is easy to justify as + * the appropriate long-term solution, as the CJK practice of + * displaying these characters as double-width comes from historic + * implementation simplicity (8-bit encoded characters were displayed + * single-width and 16-bit ones double-width, even for Greek, + * Cyrillic, etc.) and not any typographic considerations. + * + * Much less clear is the choice of width for the Not East Asian + * (Neutral) class. Existing practice does not dictate a width for any + * of these characters. It would nevertheless make sense + * typographically to allocate two character cells to characters such + * as for instance EM SPACE or VOLUME INTEGRAL, which cannot be + * represented adequately with a single-width glyph. The following + * routines at present merely assign a single-cell width to all + * neutral characters, in the interest of simplicity. This is not + * entirely satisfactory and should be reconsidered before + * establishing a formal standard in this area. At the moment, the + * decision which Not East Asian (Neutral) characters should be + * represented by double-width glyphs cannot yet be answered by + * applying a simple rule from the Unicode database content. Setting + * up a proper standard for the behavior of UTF-8 character terminals + * will require a careful analysis not only of each Unicode character, + * but also of each presentation form, something the author of these + * routines has avoided to do so far. + * + * http://www.unicode.org/unicode/reports/tr11/ + * + * Markus Kuhn -- 2007-05-26 (Unicode 5.0) + * + * Permission to use, copy, modify, and distribute this software + * for any purpose and without fee is hereby granted. The author + * disclaims all warranties with regard to this software. + * + * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c + */ + +#ifndef _WCWIDTH_H_incl +#define _WCWIDTH_H_incl 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +#include + +struct interval { + int first; + int last; +}; + +/* auxiliary function for binary search in interval table */ +static int bisearch(wchar_t ucs, const struct interval *table, int max) { + int min = 0; + int mid; + + if (ucs < table[0].first || ucs > table[max].last) + return 0; + while (max >= min) { + mid = (min + max) / 2; + if (ucs > table[mid].last) + min = mid + 1; + else if (ucs < table[mid].first) + max = mid - 1; + else + return 1; + } + + return 0; +} + + +/* The following two functions define the column width of an ISO 10646 + * character as follows: + * + * - The null character (U+0000) has a column width of 0. + * + * - Other C0/C1 control characters and DEL will lead to a return + * value of -1. + * + * - Non-spacing and enclosing combining characters (general + * category code Mn or Me in the Unicode database) have a + * column width of 0. + * + * - SOFT HYPHEN (U+00AD) has a column width of 1. + * + * - Other format characters (general category code Cf in the Unicode + * database) and ZERO WIDTH SPACE (U+200B) have a column width of 0. + * + * - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF) + * have a column width of 0. + * + * - Spacing characters in the East Asian Wide (W) or East Asian + * Full-width (F) category as defined in Unicode Technical + * Report #11 have a column width of 2. + * + * - All remaining characters (including all printable + * ISO 8859-1 and WGL4 characters, Unicode control characters, + * etc.) have a column width of 1. + * + * This implementation assumes that wchar_t characters are encoded + * in ISO 10646. + */ + +NCURSES_EXPORT(int) mk_wcwidth(wchar_t ucs) +{ + /* sorted list of non-overlapping intervals of non-spacing characters */ + /* generated by "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c" */ + static const struct interval combining[] = { + { 0x0300, 0x036F }, { 0x0483, 0x0486 }, { 0x0488, 0x0489 }, + { 0x0591, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 }, + { 0x05C4, 0x05C5 }, { 0x05C7, 0x05C7 }, { 0x0600, 0x0603 }, + { 0x0610, 0x0615 }, { 0x064B, 0x065E }, { 0x0670, 0x0670 }, + { 0x06D6, 0x06E4 }, { 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED }, + { 0x070F, 0x070F }, { 0x0711, 0x0711 }, { 0x0730, 0x074A }, + { 0x07A6, 0x07B0 }, { 0x07EB, 0x07F3 }, { 0x0901, 0x0902 }, + { 0x093C, 0x093C }, { 0x0941, 0x0948 }, { 0x094D, 0x094D }, + { 0x0951, 0x0954 }, { 0x0962, 0x0963 }, { 0x0981, 0x0981 }, + { 0x09BC, 0x09BC }, { 0x09C1, 0x09C4 }, { 0x09CD, 0x09CD }, + { 0x09E2, 0x09E3 }, { 0x0A01, 0x0A02 }, { 0x0A3C, 0x0A3C }, + { 0x0A41, 0x0A42 }, { 0x0A47, 0x0A48 }, { 0x0A4B, 0x0A4D }, + { 0x0A70, 0x0A71 }, { 0x0A81, 0x0A82 }, { 0x0ABC, 0x0ABC }, + { 0x0AC1, 0x0AC5 }, { 0x0AC7, 0x0AC8 }, { 0x0ACD, 0x0ACD }, + { 0x0AE2, 0x0AE3 }, { 0x0B01, 0x0B01 }, { 0x0B3C, 0x0B3C }, + { 0x0B3F, 0x0B3F }, { 0x0B41, 0x0B43 }, { 0x0B4D, 0x0B4D }, + { 0x0B56, 0x0B56 }, { 0x0B82, 0x0B82 }, { 0x0BC0, 0x0BC0 }, + { 0x0BCD, 0x0BCD }, { 0x0C3E, 0x0C40 }, { 0x0C46, 0x0C48 }, + { 0x0C4A, 0x0C4D }, { 0x0C55, 0x0C56 }, { 0x0CBC, 0x0CBC }, + { 0x0CBF, 0x0CBF }, { 0x0CC6, 0x0CC6 }, { 0x0CCC, 0x0CCD }, + { 0x0CE2, 0x0CE3 }, { 0x0D41, 0x0D43 }, { 0x0D4D, 0x0D4D }, + { 0x0DCA, 0x0DCA }, { 0x0DD2, 0x0DD4 }, { 0x0DD6, 0x0DD6 }, + { 0x0E31, 0x0E31 }, { 0x0E34, 0x0E3A }, { 0x0E47, 0x0E4E }, + { 0x0EB1, 0x0EB1 }, { 0x0EB4, 0x0EB9 }, { 0x0EBB, 0x0EBC }, + { 0x0EC8, 0x0ECD }, { 0x0F18, 0x0F19 }, { 0x0F35, 0x0F35 }, + { 0x0F37, 0x0F37 }, { 0x0F39, 0x0F39 }, { 0x0F71, 0x0F7E }, + { 0x0F80, 0x0F84 }, { 0x0F86, 0x0F87 }, { 0x0F90, 0x0F97 }, + { 0x0F99, 0x0FBC }, { 0x0FC6, 0x0FC6 }, { 0x102D, 0x1030 }, + { 0x1032, 0x1032 }, { 0x1036, 0x1037 }, { 0x1039, 0x1039 }, + { 0x1058, 0x1059 }, { 0x1160, 0x11FF }, { 0x135F, 0x135F }, + { 0x1712, 0x1714 }, { 0x1732, 0x1734 }, { 0x1752, 0x1753 }, + { 0x1772, 0x1773 }, { 0x17B4, 0x17B5 }, { 0x17B7, 0x17BD }, + { 0x17C6, 0x17C6 }, { 0x17C9, 0x17D3 }, { 0x17DD, 0x17DD }, + { 0x180B, 0x180D }, { 0x18A9, 0x18A9 }, { 0x1920, 0x1922 }, + { 0x1927, 0x1928 }, { 0x1932, 0x1932 }, { 0x1939, 0x193B }, + { 0x1A17, 0x1A18 }, { 0x1B00, 0x1B03 }, { 0x1B34, 0x1B34 }, + { 0x1B36, 0x1B3A }, { 0x1B3C, 0x1B3C }, { 0x1B42, 0x1B42 }, + { 0x1B6B, 0x1B73 }, { 0x1DC0, 0x1DCA }, { 0x1DFE, 0x1DFF }, + { 0x200B, 0x200F }, { 0x202A, 0x202E }, { 0x2060, 0x2063 }, + { 0x206A, 0x206F }, { 0x20D0, 0x20EF }, { 0x302A, 0x302F }, + { 0x3099, 0x309A }, { 0xA806, 0xA806 }, { 0xA80B, 0xA80B }, + { 0xA825, 0xA826 }, { 0xFB1E, 0xFB1E }, { 0xFE00, 0xFE0F }, + { 0xFE20, 0xFE23 }, { 0xFEFF, 0xFEFF }, { 0xFFF9, 0xFFFB }, + { 0x10A01, 0x10A03 }, { 0x10A05, 0x10A06 }, { 0x10A0C, 0x10A0F }, + { 0x10A38, 0x10A3A }, { 0x10A3F, 0x10A3F }, { 0x1D167, 0x1D169 }, + { 0x1D173, 0x1D182 }, { 0x1D185, 0x1D18B }, { 0x1D1AA, 0x1D1AD }, + { 0x1D242, 0x1D244 }, { 0xE0001, 0xE0001 }, { 0xE0020, 0xE007F }, + { 0xE0100, 0xE01EF } + }; + + /* test for 8-bit control characters */ + if (ucs == 0) + return 0; + if (ucs < 32 || (ucs >= 0x7f && ucs < 0xa0)) + return -1; + + /* binary search in table of non-spacing characters */ + if (bisearch(ucs, combining, + sizeof(combining) / sizeof(struct interval) - 1)) + return 0; + + /* if we arrive here, ucs is not a combining or C0/C1 control character */ + + return 1 + + (ucs >= 0x1100 && + (ucs <= 0x115f || /* Hangul Jamo init. consonants */ + ucs == 0x2329 || ucs == 0x232a || + (ucs >= 0x2e80 && ucs <= 0xa4cf && + ucs != 0x303f) /* CJK ... Yi */ + || (ucs >= 0xac00 && ucs <= 0xd7a3) /* Hangul Syllables */ + || (ucs >= 0xf900 && ucs <= 0xfaff) /* CJK Compatibility Ideographs */ + || (ucs >= 0xfe10 && ucs <= 0xfe19) /* Vertical forms */ + || (ucs >= 0xfe30 && ucs <= 0xfe6f) /* CJK Compatibility Forms */ + || (ucs >= 0xff00 && ucs <= 0xff60) /* Fullwidth Forms */ + || (ucs >= 0xffe0 && ucs <= 0xffe6) +#if !defined(SIZEOF_WCHAR_T) || (SIZEOF_WCHAR_T >= 4) + || (ucs >= 0x20000 && ucs <= 0x2fffd) + || (ucs >= 0x30000 && ucs <= 0x3fffd) +#endif + )); +} + + +NCURSES_EXPORT(int) mk_wcswidth(const wchar_t *pwcs, size_t n) +{ + int w, width = 0; + + for (;*pwcs && n-- > 0; pwcs++) + if ((w = mk_wcwidth(*pwcs)) < 0) + return -1; + else + width += w; + + return width; +} + + +/* + * The following functions are the same as mk_wcwidth() and + * mk_wcswidth(), except that spacing characters in the East Asian + * Ambiguous (A) category as defined in Unicode Technical Report #11 + * have a column width of 2. This variant might be useful for users of + * CJK legacy encodings who want to migrate to UCS without changing + * the traditional terminal character-width behaviour. It is not + * otherwise recommended for general use. + */ +NCURSES_EXPORT(int) mk_wcwidth_cjk(wchar_t ucs) +{ + /* sorted list of non-overlapping intervals of East Asian Ambiguous + * characters, generated by "uniset +WIDTH-A -cat=Me -cat=Mn -cat=Cf c" */ + static const struct interval ambiguous[] = { + { 0x00A1, 0x00A1 }, { 0x00A4, 0x00A4 }, { 0x00A7, 0x00A8 }, + { 0x00AA, 0x00AA }, { 0x00AE, 0x00AE }, { 0x00B0, 0x00B4 }, + { 0x00B6, 0x00BA }, { 0x00BC, 0x00BF }, { 0x00C6, 0x00C6 }, + { 0x00D0, 0x00D0 }, { 0x00D7, 0x00D8 }, { 0x00DE, 0x00E1 }, + { 0x00E6, 0x00E6 }, { 0x00E8, 0x00EA }, { 0x00EC, 0x00ED }, + { 0x00F0, 0x00F0 }, { 0x00F2, 0x00F3 }, { 0x00F7, 0x00FA }, + { 0x00FC, 0x00FC }, { 0x00FE, 0x00FE }, { 0x0101, 0x0101 }, + { 0x0111, 0x0111 }, { 0x0113, 0x0113 }, { 0x011B, 0x011B }, + { 0x0126, 0x0127 }, { 0x012B, 0x012B }, { 0x0131, 0x0133 }, + { 0x0138, 0x0138 }, { 0x013F, 0x0142 }, { 0x0144, 0x0144 }, + { 0x0148, 0x014B }, { 0x014D, 0x014D }, { 0x0152, 0x0153 }, + { 0x0166, 0x0167 }, { 0x016B, 0x016B }, { 0x01CE, 0x01CE }, + { 0x01D0, 0x01D0 }, { 0x01D2, 0x01D2 }, { 0x01D4, 0x01D4 }, + { 0x01D6, 0x01D6 }, { 0x01D8, 0x01D8 }, { 0x01DA, 0x01DA }, + { 0x01DC, 0x01DC }, { 0x0251, 0x0251 }, { 0x0261, 0x0261 }, + { 0x02C4, 0x02C4 }, { 0x02C7, 0x02C7 }, { 0x02C9, 0x02CB }, + { 0x02CD, 0x02CD }, { 0x02D0, 0x02D0 }, { 0x02D8, 0x02DB }, + { 0x02DD, 0x02DD }, { 0x02DF, 0x02DF }, { 0x0391, 0x03A1 }, + { 0x03A3, 0x03A9 }, { 0x03B1, 0x03C1 }, { 0x03C3, 0x03C9 }, + { 0x0401, 0x0401 }, { 0x0410, 0x044F }, { 0x0451, 0x0451 }, + { 0x2010, 0x2010 }, { 0x2013, 0x2016 }, { 0x2018, 0x2019 }, + { 0x201C, 0x201D }, { 0x2020, 0x2022 }, { 0x2024, 0x2027 }, + { 0x2030, 0x2030 }, { 0x2032, 0x2033 }, { 0x2035, 0x2035 }, + { 0x203B, 0x203B }, { 0x203E, 0x203E }, { 0x2074, 0x2074 }, + { 0x207F, 0x207F }, { 0x2081, 0x2084 }, { 0x20AC, 0x20AC }, + { 0x2103, 0x2103 }, { 0x2105, 0x2105 }, { 0x2109, 0x2109 }, + { 0x2113, 0x2113 }, { 0x2116, 0x2116 }, { 0x2121, 0x2122 }, + { 0x2126, 0x2126 }, { 0x212B, 0x212B }, { 0x2153, 0x2154 }, + { 0x215B, 0x215E }, { 0x2160, 0x216B }, { 0x2170, 0x2179 }, + { 0x2190, 0x2199 }, { 0x21B8, 0x21B9 }, { 0x21D2, 0x21D2 }, + { 0x21D4, 0x21D4 }, { 0x21E7, 0x21E7 }, { 0x2200, 0x2200 }, + { 0x2202, 0x2203 }, { 0x2207, 0x2208 }, { 0x220B, 0x220B }, + { 0x220F, 0x220F }, { 0x2211, 0x2211 }, { 0x2215, 0x2215 }, + { 0x221A, 0x221A }, { 0x221D, 0x2220 }, { 0x2223, 0x2223 }, + { 0x2225, 0x2225 }, { 0x2227, 0x222C }, { 0x222E, 0x222E }, + { 0x2234, 0x2237 }, { 0x223C, 0x223D }, { 0x2248, 0x2248 }, + { 0x224C, 0x224C }, { 0x2252, 0x2252 }, { 0x2260, 0x2261 }, + { 0x2264, 0x2267 }, { 0x226A, 0x226B }, { 0x226E, 0x226F }, + { 0x2282, 0x2283 }, { 0x2286, 0x2287 }, { 0x2295, 0x2295 }, + { 0x2299, 0x2299 }, { 0x22A5, 0x22A5 }, { 0x22BF, 0x22BF }, + { 0x2312, 0x2312 }, { 0x2460, 0x24E9 }, { 0x24EB, 0x254B }, + { 0x2550, 0x2573 }, { 0x2580, 0x258F }, { 0x2592, 0x2595 }, + { 0x25A0, 0x25A1 }, { 0x25A3, 0x25A9 }, { 0x25B2, 0x25B3 }, + { 0x25B6, 0x25B7 }, { 0x25BC, 0x25BD }, { 0x25C0, 0x25C1 }, + { 0x25C6, 0x25C8 }, { 0x25CB, 0x25CB }, { 0x25CE, 0x25D1 }, + { 0x25E2, 0x25E5 }, { 0x25EF, 0x25EF }, { 0x2605, 0x2606 }, + { 0x2609, 0x2609 }, { 0x260E, 0x260F }, { 0x2614, 0x2615 }, + { 0x261C, 0x261C }, { 0x261E, 0x261E }, { 0x2640, 0x2640 }, + { 0x2642, 0x2642 }, { 0x2660, 0x2661 }, { 0x2663, 0x2665 }, + { 0x2667, 0x266A }, { 0x266C, 0x266D }, { 0x266F, 0x266F }, + { 0x273D, 0x273D }, { 0x2776, 0x277F }, { 0xE000, 0xF8FF }, + { 0xFFFD, 0xFFFD }, { 0xF0000, 0xFFFFD }, { 0x100000, 0x10FFFD } + }; + + /* binary search in table of non-spacing characters */ + if (bisearch(ucs, ambiguous, + sizeof(ambiguous) / sizeof(struct interval) - 1)) + return 2; + + return mk_wcwidth(ucs); +} + + +NCURSES_EXPORT(int) mk_wcswidth_cjk(const wchar_t *pwcs, size_t n) +{ + int w, width = 0; + + for (;*pwcs && n-- > 0; pwcs++) + if ((w = mk_wcwidth_cjk(*pwcs)) < 0) + return -1; + else + width += w; + + return width; +} + +#ifdef __cplusplus +} +#endif + +#endif /* _WCWIDTH_H_incl 1 */ diff --git a/lib/libcurses/widechar/charable.c b/lib/libcurses/widechar/charable.c index 1654c7ef1e4..75a55d5f503 100644 --- a/lib/libcurses/widechar/charable.c +++ b/lib/libcurses/widechar/charable.c @@ -1,7 +1,8 @@ -/* $OpenBSD: charable.c,v 1.1 2010/09/06 17:26:17 nicm Exp $ */ +/* $OpenBSD: charable.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2003-2005,2008 Free Software Foundation, Inc. * + * Copyright 2018,2020 Thomas E. Dickey * + * Copyright 2003-2005,2008 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -34,7 +35,7 @@ #include -MODULE_ID("$Id: charable.c,v 1.1 2010/09/06 17:26:17 nicm Exp $") +MODULE_ID("$Id: charable.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(bool) _nc_is_charable(wchar_t ch) { @@ -59,6 +60,8 @@ NCURSES_EXPORT(int) _nc_to_char(wint_t ch) result = UChar(temp[0]); else result = -1; +#else +#error expected either wctob/wctomb #endif return result; } @@ -77,6 +80,8 @@ NCURSES_EXPORT(wint_t) _nc_to_widechar(int ch) result = convert; else result = WEOF; +#else +#error expected either btowc/mbtowc #endif return result; } diff --git a/lib/libcurses/widechar/lib_add_wch.c b/lib/libcurses/widechar/lib_add_wch.c index 1d75bf62eb6..5c73571ea89 100644 --- a/lib/libcurses/widechar/lib_add_wch.c +++ b/lib/libcurses/widechar/lib_add_wch.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_add_wch.c,v 1.1 2010/09/06 17:26:17 nicm Exp $ */ +/* $OpenBSD: lib_add_wch.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2004,2006 Free Software Foundation, Inc. * + * Copyright 2019-2021,2023 Thomas E. Dickey * + * Copyright 2004-2011,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -37,79 +38,415 @@ #include -MODULE_ID("$Id: lib_add_wch.c,v 1.1 2010/09/06 17:26:17 nicm Exp $") +#if HAVE_WCTYPE_H +#include +#endif -NCURSES_EXPORT(int) -wadd_wch(WINDOW *win, const cchar_t *wch) +MODULE_ID("$Id: lib_add_wch.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") + +/* clone/adapt lib_addch.c */ +static const cchar_t blankchar = NewChar(BLANK_TEXT); + +/* + * Ugly microtweaking alert. Everything from here to end of module is + * likely to be speed-critical -- profiling data sure says it is! + * Most of the important screen-painting functions are shells around + * wadd_wch(). So we make every effort to reduce function-call overhead + * by inlining stuff, even at the cost of making wrapped copies for + * export. Also we supply some internal versions that don't call the + * window sync hook, for use by string-put functions. + */ + +/* Return bit mask for clearing color pair number if given ch has color */ +#define COLOR_MASK(ch) (~(attr_t)(((ch) & A_COLOR) ? A_COLOR : 0)) + +static NCURSES_INLINE cchar_t +render_char(WINDOW *win, cchar_t ch) +/* compute a rendition of the given char correct for the current context */ { - PUTC_DATA; - int n; - int code = ERR; + attr_t a = WINDOW_ATTRS(win); + int pair = GetPair(ch); + + if (ISBLANK(ch) + && AttrOf(ch) == A_NORMAL + && pair == 0) { + /* color/pair in attrs has precedence over bkgrnd */ + ch = win->_nc_bkgd; + SetAttr(ch, a | AttrOf(win->_nc_bkgd)); + if ((pair = GET_WINDOW_PAIR(win)) == 0) + pair = GetPair(win->_nc_bkgd); + SetPair(ch, pair); + } else { + /* color in attrs has precedence over bkgrnd */ + a |= AttrOf(win->_nc_bkgd) & COLOR_MASK(a); + /* color in ch has precedence */ + if (pair == 0) { + if ((pair = GET_WINDOW_PAIR(win)) == 0) + pair = GetPair(win->_nc_bkgd); + } + AddAttr(ch, (a & COLOR_MASK(AttrOf(ch)))); + SetPair(ch, pair); + } + + TR(TRACE_VIRTPUT, + ("render_char bkg %s (%d), attrs %s (%d) -> ch %s (%d)", + _tracech_t2(1, CHREF(win->_nc_bkgd)), + GetPair(win->_nc_bkgd), + _traceattr(WINDOW_ATTRS(win)), + GET_WINDOW_PAIR(win), + _tracech_t2(3, CHREF(ch)), + GetPair(ch))); + + return (ch); +} + +/* check if position is legal; if not, return error */ +#ifndef NDEBUG /* treat this like an assertion */ +#define CHECK_POSITION(win, x, y) \ + if (y > win->_maxy \ + || x > win->_maxx \ + || y < 0 \ + || x < 0) { \ + TR(TRACE_VIRTPUT, ("Alert! Win=%p _curx = %d, _cury = %d " \ + "(_maxx = %d, _maxy = %d)", win, x, y, \ + win->_maxx, win->_maxy)); \ + return(ERR); \ + } +#else +#define CHECK_POSITION(win, x, y) /* nothing */ +#endif + +static bool +newline_forces_scroll(WINDOW *win, NCURSES_SIZE_T *ypos) +{ + bool result = FALSE; + + if (*ypos >= win->_regtop && *ypos == win->_regbottom) { + *ypos = win->_regbottom; + result = TRUE; + } else { + *ypos = (NCURSES_SIZE_T) (*ypos + 1); + } + return result; +} - TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("wadd_wch(%p, %s)"), win, - _tracech_t(wch))); - - if (win != 0) { - PUTC_INIT; - for (PUTC_i = 0; PUTC_i < CCHARW_MAX; ++PUTC_i) { - attr_t attrs = (wch->attr & A_ATTRIBUTES); - - if ((PUTC_ch = wch->chars[PUTC_i]) == L'\0') - break; - if ((PUTC_n = wcrtomb(PUTC_buf, PUTC_ch, &PUT_st)) <= 0) { - code = ERR; - if (is8bits(PUTC_ch)) - code = waddch(win, UChar(PUTC_ch) | attrs); - break; +/* + * The _WRAPPED flag is useful only for telling an application that we've just + * wrapped the cursor. We don't do anything with this flag except set it when + * wrapping, and clear it whenever we move the cursor. If we try to wrap at + * the lower-right corner of a window, we cannot move the cursor (since that + * wouldn't be legal). So we return an error (which is what SVr4 does). + * Unlike SVr4, we can successfully add a character to the lower-right corner + * (Solaris 2.6 does this also, however). + */ +static int +wrap_to_next_line(WINDOW *win) +{ + win->_flags |= _WRAPPED; + if (newline_forces_scroll(win, &(win->_cury))) { + win->_curx = win->_maxx; + if (!win->_scroll) + return (ERR); + scroll(win); + } + win->_curx = 0; + return (OK); +} + +static int wadd_wch_literal(WINDOW *, cchar_t); +/* + * Fill the given number of cells with blanks using the current background + * rendition. This saves/restores the current x-position. + */ +static void +fill_cells(WINDOW *win, int count) +{ + cchar_t blank = blankchar; + int save_x = win->_curx; + int save_y = win->_cury; + + while (count-- > 0) { + if (wadd_wch_literal(win, blank) == ERR) + break; + } + win->_curx = (NCURSES_SIZE_T) save_x; + win->_cury = (NCURSES_SIZE_T) save_y; +} + +static int +wadd_wch_literal(WINDOW *win, cchar_t ch) +{ + int x; + int y; + struct ldat *line; + + x = win->_curx; + y = win->_cury; + + CHECK_POSITION(win, x, y); + + ch = render_char(win, ch); + + line = win->_line + y; + + CHANGED_CELL(line, x); + + /* + * Non-spacing characters are added to the current cell. + * + * Spacing characters that are wider than one column require some display + * adjustments. + */ + { + int len = _nc_wacs_width(CharOf(ch)); + int i; + int j; + wchar_t *chars; + + if (len == 0) { /* non-spacing */ + if ((x > 0 && y >= 0) + || (win->_maxx >= 0 && win->_cury >= 1)) { + if (x > 0 && y >= 0) { + for (j = x - 1; j > 0; --j) { + if (!isWidecExt(win->_line[y].text[j])) { + break; + } + } + chars = (win->_line[y].text[j].chars); + } else { + chars = (win->_line[y - 1].text[win->_maxx].chars); + } + for (i = 0; i < CCHARW_MAX; ++i) { + if (chars[i] == 0) { + TR(TRACE_VIRTPUT, + ("added non-spacing %d: %x", + x, (int) CharOf(ch))); + chars[i] = CharOf(ch); + break; + } + } } - for (n = 0; n < PUTC_n; n++) { - if ((code = waddch(win, UChar(PUTC_buf[n]) | attrs)) == ERR) { + goto testwrapping; + } else if (len > 1) { /* multi-column characters */ + /* + * Check if the character will fit on the current line. If it does + * not fit, fill in the remainder of the line with blanks. and + * move to the next line. + */ + if (len > win->_maxx + 1) { + TR(TRACE_VIRTPUT, ("character will not fit")); + return ERR; + } else if (x + len > win->_maxx + 1) { + int count = win->_maxx + 1 - x; + TR(TRACE_VIRTPUT, ("fill %d remaining cells", count)); + fill_cells(win, count); + if (wrap_to_next_line(win) == ERR) + return ERR; + x = win->_curx; + y = win->_cury; + line = win->_line + y; + } + /* + * Check for cells which are orphaned by adding this character, set + * those to blanks. + * + * FIXME: this actually could fill j-i cells, more complicated to + * setup though. + */ + for (i = 0; i < len; ++i) { + if (isWidecBase(win->_line[y].text[x + i])) { + break; + } else if (isWidecExt(win->_line[y].text[x + i])) { + for (j = i; x + j <= win->_maxx; ++j) { + if (!isWidecExt(win->_line[y].text[x + j])) { + TR(TRACE_VIRTPUT, ("fill %d orphan cells", j)); + fill_cells(win, j); + break; + } + } break; } } - if (code == ERR) - break; + /* + * Finally, add the cells for this character. + */ + for (i = 0; i < len; ++i) { + cchar_t value = ch; + SetWidecExt(value, i); + TR(TRACE_VIRTPUT, ("multicolumn %d:%d (%d,%d)", + i + 1, len, + win->_begy + y, win->_begx + x)); + line->text[x] = value; + CHANGED_CELL(line, x); + ++x; + } + goto testwrapping; } } - TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_RETURN("%d"), code)); - return (code); + /* + * Single-column characters. + */ + line->text[x++] = ch; + /* + * This label is used only for wide-characters. + */ + testwrapping: + + TR(TRACE_VIRTPUT, ("cell (%ld, %ld..%d) = %s", + (long) win->_cury, (long) win->_curx, x - 1, + _tracech_t(CHREF(ch)))); + + if (x > win->_maxx) { + return wrap_to_next_line(win); + } + win->_curx = (NCURSES_SIZE_T) x; + return OK; } -NCURSES_EXPORT(int) -wecho_wchar(WINDOW *win, const cchar_t *wch) +static NCURSES_INLINE int +wadd_wch_nosync(WINDOW *win, cchar_t ch) +/* the workhorse function -- add a character to the given window */ { - PUTC_DATA; - int n; - int code = ERR; + NCURSES_SIZE_T x, y; + wchar_t *s; + int tabsize = 8; +#if USE_REENTRANT + SCREEN *sp = _nc_screen_of(win); +#endif - TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("wecho_wchar(%p, %s)"), win, - _tracech_t(wch))); - - if (win != 0) { - PUTC_INIT; - for (PUTC_i = 0; PUTC_i < CCHARW_MAX; ++PUTC_i) { - attr_t attrs = (wch->attr & A_ATTRIBUTES); - - if ((PUTC_ch = wch->chars[PUTC_i]) == L'\0') - break; - if ((PUTC_n = wcrtomb(PUTC_buf, PUTC_ch, &PUT_st)) <= 0) { - code = ERR; - if (is8bits(PUTC_ch)) - code = waddch(win, UChar(PUTC_ch) | attrs); - break; + /* + * If we are using the alternate character set, forget about locale. + * Otherwise, if the locale claims the code is printable, treat it that + * way. + */ + if ((AttrOf(ch) & A_ALTCHARSET) + || iswprint((wint_t) CharOf(ch))) + return wadd_wch_literal(win, ch); + + /* + * Handle carriage control and other codes that are not printable, or are + * known to expand to more than one character according to unctrl(). + */ + x = win->_curx; + y = win->_cury; + + switch (CharOf(ch)) { + case '\t': +#if USE_REENTRANT + tabsize = *ptrTabsize(sp); +#else + tabsize = TABSIZE; +#endif + x = (NCURSES_SIZE_T) (x + (tabsize - (x % tabsize))); + /* + * Space-fill the tab on the bottom line so that we'll get the + * "correct" cursor position. + */ + if ((!win->_scroll && (y == win->_regbottom)) + || (x <= win->_maxx)) { + cchar_t blank = blankchar; + AddAttr(blank, AttrOf(ch)); + while (win->_curx < x) { + if (wadd_wch_literal(win, blank) == ERR) + return (ERR); } - for (n = 0; n < PUTC_n; n++) { - if ((code = waddch(win, UChar(PUTC_buf[n]) | attrs)) == ERR) { - break; + break; + } else { + wclrtoeol(win); + win->_flags |= _WRAPPED; + if (newline_forces_scroll(win, &y)) { + x = win->_maxx; + if (win->_scroll) { + scroll(win); + x = 0; } + } else { + x = 0; + } + } + break; + case '\n': + wclrtoeol(win); + if (newline_forces_scroll(win, &y)) { + if (win->_scroll) + scroll(win); + else + return (ERR); + } + /* FALLTHRU */ + case '\r': + x = 0; + win->_flags &= ~_WRAPPED; + break; + case '\b': + if (x == 0) + return (OK); + x--; + win->_flags &= ~_WRAPPED; + break; + default: + if ((s = wunctrl(&ch)) != 0) { + while (*s) { + cchar_t sch; + SetChar(sch, *s++, AttrOf(ch)); + if_EXT_COLORS(SetPair(sch, GetPair(ch))); + if (wadd_wch_literal(win, sch) == ERR) + return ERR; } - if (code == ERR) - break; + return OK; } - wrefresh(win); + return ERR; + } + + win->_curx = x; + win->_cury = y; + + return OK; +} + +/* + * The versions below call _nc_synchook(). We wanted to avoid this in the + * version exported for string puts; they'll call _nc_synchook once at end + * of run. + */ + +/* These are actual entry points */ + +NCURSES_EXPORT(int) +wadd_wch(WINDOW *win, const cchar_t *wch) +{ + int code = ERR; + + TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("wadd_wch(%p, %s)"), + (void *) win, + _tracecchar_t(wch))); + + if (win && (wadd_wch_nosync(win, *wch) != ERR)) { + _nc_synchook(win); + code = OK; } TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_RETURN("%d"), code)); return (code); } + +NCURSES_EXPORT(int) +wecho_wchar(WINDOW *win, const cchar_t *wch) +{ + int code = ERR; + + TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_CALLED("wechochar(%p, %s)"), + (void *) win, + _tracecchar_t(wch))); + + if (win && (wadd_wch_nosync(win, *wch) != ERR)) { + bool save_immed = win->_immed; + win->_immed = TRUE; + _nc_synchook(win); + win->_immed = save_immed; + code = OK; + } + TR(TRACE_VIRTPUT | TRACE_CCALLS, (T_RETURN("%d"), code)); + return (code); +} diff --git a/lib/libcurses/widechar/lib_box_set.c b/lib/libcurses/widechar/lib_box_set.c index 869ac22a3e3..9ab5026eebc 100644 --- a/lib/libcurses/widechar/lib_box_set.c +++ b/lib/libcurses/widechar/lib_box_set.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_box_set.c,v 1.1 2010/09/06 17:26:17 nicm Exp $ */ +/* $OpenBSD: lib_box_set.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2002 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 2002-2009,2011 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -41,7 +42,7 @@ #include -MODULE_ID("$Id: lib_box_set.c,v 1.1 2010/09/06 17:26:17 nicm Exp $") +MODULE_ID("$Id: lib_box_set.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) wborder_set(WINDOW *win, @@ -54,8 +55,8 @@ wborder_set(WINDOW *win, NCURSES_SIZE_T endx, endy; NCURSES_CH_T wls, wrs, wts, wbs, wtl, wtr, wbl, wbr; - T((T_CALLED("wborder(%p,%s,%s,%s,%s,%s,%s,%s,%s)"), - win, + T((T_CALLED("wborder_set(%p,%s,%s,%s,%s,%s,%s,%s,%s)"), + (void *) win, _tracech_t2(1, ls), _tracech_t2(2, rs), _tracech_t2(3, ts), diff --git a/lib/libcurses/widechar/lib_cchar.c b/lib/libcurses/widechar/lib_cchar.c index 778c7b53b15..8054b2364fa 100644 --- a/lib/libcurses/widechar/lib_cchar.c +++ b/lib/libcurses/widechar/lib_cchar.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_cchar.c,v 1.1 2010/09/06 17:26:17 nicm Exp $ */ +/* $OpenBSD: lib_cchar.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2001-2005,2007 Free Software Foundation, Inc. * + * Copyright 2019-2021,2022 Thomas E. Dickey * + * Copyright 2001-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -36,10 +37,11 @@ */ #include +#include -MODULE_ID("$Id: lib_cchar.c,v 1.1 2010/09/06 17:26:17 nicm Exp $") +MODULE_ID("$Id: lib_cchar.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") -/* +/* * The SuSv2 description leaves some room for interpretation. We'll assume wch * points to a string which is L'\0' terminated, contains at least one * character with strictly positive width, which must be the first, and @@ -49,22 +51,25 @@ NCURSES_EXPORT(int) setcchar(cchar_t *wcval, const wchar_t *wch, const attr_t attrs, - short color_pair, + NCURSES_PAIRS_T pair_arg, const void *opts) { - int i; - int len; int code = OK; + int color_pair = pair_arg; + unsigned len; - TR(TRACE_CCALLS, (T_CALLED("setcchar(%p,%s,%lu,%d,%p)"), - wcval, _nc_viswbuf(wch), + TR(TRACE_CCALLS, (T_CALLED("setcchar(%p,%s,attrs=%lu,pair=%d,%p)"), + (void *) wcval, _nc_viswbuf(wch), (unsigned long) attrs, color_pair, opts)); - len = wcslen(wch); - if (opts != NULL - || (len > 1 && wcwidth(wch[0]) < 0)) { + set_extended_pair(opts, color_pair); + if (wch == NULL + || ((len = (unsigned) wcslen(wch)) > 1 && _nc_wacs_width(wch[0]) < 0) + || color_pair < 0) { code = ERR; } else { + unsigned i; + if (len > CCHARW_MAX) len = CCHARW_MAX; @@ -73,7 +78,7 @@ setcchar(cchar_t *wcval, * are only interested in adding non-spacing characters. */ for (i = 1; i < len; ++i) { - if (wcwidth(wch[i]) != 0) { + if (_nc_wacs_width(wch[i]) != 0) { len = i; break; } @@ -82,7 +87,7 @@ setcchar(cchar_t *wcval, memset(wcval, 0, sizeof(*wcval)); if (len != 0) { - SetAttr(*wcval, attrs | COLOR_PAIR(color_pair)); + SetAttr(*wcval, attrs); SetPair(CHDEREF(wcval), color_pair); memcpy(&wcval->chars, wch, len * sizeof(wchar_t)); TR(TRACE_CCALLS, ("copy %d wchars, first is %s", len, @@ -98,31 +103,55 @@ NCURSES_EXPORT(int) getcchar(const cchar_t *wcval, wchar_t *wch, attr_t *attrs, - short *color_pair, + NCURSES_PAIRS_T *pair_arg, void *opts) { - wchar_t *wp; - int len; int code = ERR; TR(TRACE_CCALLS, (T_CALLED("getcchar(%p,%p,%p,%p,%p)"), - wcval, wch, attrs, color_pair, opts)); - - if (opts == NULL) { - len = (wp = wmemchr(wcval->chars, L'\0', CCHARW_MAX)) - ? wp - wcval->chars - : CCHARW_MAX; - + (const void *) wcval, + (void *) wch, + (void *) attrs, + (void *) pair_arg, + opts)); + +#if !NCURSES_EXT_COLORS + if (opts != NULL) { + ; /* empty */ + } else +#endif + if (wcval != NULL) { + wchar_t *wp; + int len; + +#if HAVE_WMEMCHR + len = ((wp = wmemchr(wcval->chars, L'\0', (size_t) CCHARW_MAX)) + ? (int) (wp - wcval->chars) + : CCHARW_MAX); +#else + len = wcsnlen(wcval->chars, CCHARW_MAX); +#endif if (wch == NULL) { - code = len; - } else if (attrs == 0 || color_pair == 0) { + /* + * If the value is a null, set the length to 1. + * If the value is not a null, return the length plus 1 for null. + */ + code = (len < CCHARW_MAX) ? (len + 1) : CCHARW_MAX; + } else if (attrs == 0 || pair_arg == 0) { code = ERR; } else if (len >= 0) { + int color_pair; + + TR(TRACE_CCALLS, ("copy %d wchars, first is %s", len, + _tracecchar_t(wcval))); *attrs = AttrOf(*wcval) & A_ATTRIBUTES; - *color_pair = GetPair(*wcval); - wmemcpy(wch, wcval->chars, (unsigned) len); + color_pair = GetPair(*wcval); + get_extended_pair(opts, color_pair); + *pair_arg = limit_PAIRS(color_pair); + wmemcpy(wch, wcval->chars, (size_t) len); wch[len] = L'\0'; - code = OK; + if (*pair_arg >= 0) + code = OK; } } diff --git a/lib/libcurses/widechar/lib_erasewchar.c b/lib/libcurses/widechar/lib_erasewchar.c index c6bcb8e16f0..fe7c9e3a1b2 100644 --- a/lib/libcurses/widechar/lib_erasewchar.c +++ b/lib/libcurses/widechar/lib_erasewchar.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_erasewchar.c,v 1.1 2010/09/06 17:26:17 nicm Exp $ */ +/* $OpenBSD: lib_erasewchar.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2002 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 2002-2010,2014 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -34,46 +35,64 @@ #include -MODULE_ID("$Id: lib_erasewchar.c,v 1.1 2010/09/06 17:26:17 nicm Exp $") +MODULE_ID("$Id: lib_erasewchar.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") /* * erasewchar() * * Return erase character as given in cur_term->Ottyb. - * */ NCURSES_EXPORT(int) -erasewchar(wchar_t * wch) +NCURSES_SP_NAME(erasewchar) (NCURSES_SP_DCLx wchar_t *wch); +NCURSES_EXPORT(int) +NCURSES_SP_NAME(erasewchar) (NCURSES_SP_DCLx wchar_t *wch) { int value; int result = ERR; T((T_CALLED("erasewchar()"))); - if ((value = erasechar()) != ERR) { - *wch = value; + if ((value = NCURSES_SP_NAME(erasechar) (NCURSES_SP_ARG)) != ERR) { + *wch = (wchar_t) value; result = OK; } returnCode(result); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +erasewchar(wchar_t *wch) +{ + return NCURSES_SP_NAME(erasewchar) (CURRENT_SCREEN, wch); +} +#endif + /* * killwchar() * * Return kill character as given in cur_term->Ottyb. - * */ NCURSES_EXPORT(int) -killwchar(wchar_t * wch) +NCURSES_SP_NAME(killwchar) (NCURSES_SP_DCLx wchar_t *wch); +NCURSES_EXPORT(int) +NCURSES_SP_NAME(killwchar) (NCURSES_SP_DCLx wchar_t *wch) { int value; int result = ERR; T((T_CALLED("killwchar()"))); - if ((value = killchar()) != ERR) { - *wch = value; + if ((value = NCURSES_SP_NAME(killchar) (NCURSES_SP_ARG)) != ERR) { + *wch = (wchar_t) value; result = OK; } returnCode(result); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +killwchar(wchar_t *wch) +{ + return NCURSES_SP_NAME(killwchar) (CURRENT_SCREEN, wch); +} +#endif diff --git a/lib/libcurses/widechar/lib_get_wch.c b/lib/libcurses/widechar/lib_get_wch.c index c9c0fb4238d..36137c5481d 100644 --- a/lib/libcurses/widechar/lib_get_wch.c +++ b/lib/libcurses/widechar/lib_get_wch.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_get_wch.c,v 1.1 2010/09/06 17:26:17 nicm Exp $ */ +/* $OpenBSD: lib_get_wch.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2002-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 2002-2011,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -42,38 +43,19 @@ #include #include -MODULE_ID("$Id: lib_get_wch.c,v 1.1 2010/09/06 17:26:17 nicm Exp $") - -#if HAVE_MBTOWC && HAVE_MBLEN -#define reset_mbytes(state) mblen(NULL, 0), mbtowc(NULL, NULL, 0) -#define count_mbytes(buffer,length,state) mblen(buffer,length) -#define check_mbytes(wch,buffer,length,state) \ - (int) mbtowc(&wch, buffer, length) -#define state_unused -#elif HAVE_MBRTOWC && HAVE_MBRLEN -#define reset_mbytes(state) init_mb(state) -#define count_mbytes(buffer,length,state) mbrlen(buffer,length,&state) -#define check_mbytes(wch,buffer,length,state) \ - (int) mbrtowc(&wch, buffer, length, &state) -#else -make an error -#endif +MODULE_ID("$Id: lib_get_wch.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) wget_wch(WINDOW *win, wint_t *result) { SCREEN *sp; int code; - char buffer[(MB_LEN_MAX * 9) + 1]; /* allow some redundant shifts */ - int status; - size_t count = 0; - unsigned long value; - wchar_t wch; + int value = 0; #ifndef state_unused mbstate_t state; #endif - T((T_CALLED("wget_wch(%p)"), win)); + T((T_CALLED("wget_wch(%p)"), (void *) win)); /* * We can get a stream of single-byte characters and KEY_xxx codes from @@ -81,8 +63,13 @@ wget_wch(WINDOW *win, wint_t *result) */ _nc_lock_global(curses); sp = _nc_screen_of(win); + if (sp != 0) { + size_t count = 0; + for (;;) { + char buffer[(MB_LEN_MAX * 9) + 1]; /* allow some redundant shifts */ + T(("reading %d of %d", (int) count + 1, (int) sizeof(buffer))); code = _nc_wgetch(win, &value, TRUE EVENTLIST_2nd((_nc_eventlist *) 0)); @@ -97,23 +84,26 @@ wget_wch(WINDOW *win, wint_t *result) * whether the improvement would be worth the effort. */ if (count != 0) { - _nc_ungetch(sp, (int) value); + safe_ungetch(SP_PARM, value); code = ERR; } break; } else if (count + 1 >= sizeof(buffer)) { - _nc_ungetch(sp, (int) value); + safe_ungetch(SP_PARM, value); code = ERR; break; } else { + int status; + buffer[count++] = (char) UChar(value); reset_mbytes(state); status = count_mbytes(buffer, count, state); if (status >= 0) { + wchar_t wch; reset_mbytes(state); if (check_mbytes(wch, buffer, count, state) != status) { code = ERR; /* the two calls should match */ - _nc_ungetch(sp, (int) value); + safe_ungetch(SP_PARM, value); } value = wch; break; @@ -123,8 +113,11 @@ wget_wch(WINDOW *win, wint_t *result) } else { code = ERR; } - *result = value; + + if (result != 0) + *result = (wint_t) value; + _nc_unlock_global(curses); - T(("result %#lo", value)); + T(("result %#o", value)); returnCode(code); } diff --git a/lib/libcurses/widechar/lib_get_wstr.c b/lib/libcurses/widechar/lib_get_wstr.c index 0ad01d318d7..06bdb7eaa98 100644 --- a/lib/libcurses/widechar/lib_get_wstr.c +++ b/lib/libcurses/widechar/lib_get_wstr.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_get_wstr.c,v 1.1 2010/09/06 17:26:17 nicm Exp $ */ +/* $OpenBSD: lib_get_wstr.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2002-2004,2008 Free Software Foundation, Inc. * + * Copyright 2018-2021,2023 Thomas E. Dickey * + * Copyright 2002-2009,2011 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -40,9 +41,8 @@ */ #include -#include -MODULE_ID("$Id: lib_get_wstr.c,v 1.1 2010/09/06 17:26:17 nicm Exp $") +MODULE_ID("$Id: lib_get_wstr.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") static int wadd_wint(WINDOW *win, wint_t *src) @@ -52,7 +52,7 @@ wadd_wint(WINDOW *win, wint_t *src) wch[0] = (wchar_t) (*src); wch[1] = 0; - setcchar(&tmp, wch, A_NORMAL, 0, NULL); + setcchar(&tmp, wch, A_NORMAL, (short) 0, NULL); return wadd_wch(win, &tmp); } @@ -61,7 +61,7 @@ wadd_wint(WINDOW *win, wint_t *src) * or other character, and handles reverse wraparound. */ static wint_t * -WipeOut(WINDOW *win, int y, int x, wint_t *first, wint_t *last, bool echoed) +WipeOut(WINDOW *win, int y, int x, wint_t *first, wint_t *last, int echoed) { if (last > first) { *--last = '\0'; @@ -90,32 +90,31 @@ wgetn_wstr(WINDOW *win, wint_t *str, int maxlen) { SCREEN *sp = _nc_screen_of(win); TTY buf; - bool oldnl, oldecho, oldraw, oldcbreak; - wint_t erasec; - wint_t killc; + TTY_FLAGS save_flags; + wchar_t erasec = 0; + wchar_t killc = 0; wint_t *oldstr = str; wint_t *tmpstr = str; wint_t ch; int y, x, code; - T((T_CALLED("wgetn_wstr(%p,%p, %d)"), win, str, maxlen)); + T((T_CALLED("wgetn_wstr(%p,%p, %d)"), (void *) win, (void *) str, maxlen)); if (!win) returnCode(ERR); + maxlen = _nc_getstr_limit(maxlen); + _nc_get_tty_mode(&buf); - oldnl = sp->_nl; - oldecho = sp->_echo; - oldraw = sp->_raw; - oldcbreak = sp->_cbreak; - nl(); - noecho(); - noraw(); - cbreak(); + save_flags = sp->_tty_flags; + NCURSES_SP_NAME(nl) (NCURSES_SP_ARG); + NCURSES_SP_NAME(noecho) (NCURSES_SP_ARG); + if (!save_flags._raw) + NCURSES_SP_NAME(cbreak) (NCURSES_SP_ARG); - erasec = (wint_t) erasechar(); - killc = (wint_t) killchar(); + NCURSES_SP_NAME(erasewchar) (NCURSES_SP_ARGx &erasec); + NCURSES_SP_NAME(killwchar) (NCURSES_SP_ARGx &killc); getyx(win, y, x); @@ -132,12 +131,12 @@ wgetn_wstr(WINDOW *win, wint_t *str, int maxlen) code = KEY_CODE_YES; ch = KEY_ENTER; } - if (ch < KEY_MIN) { - if (ch == erasec) { + if (ch != 0 && ch < KEY_MIN) { + if (ch == (wint_t) erasec) { ch = KEY_BACKSPACE; code = KEY_CODE_YES; } - if (ch == killc) { + if (ch == (wint_t) killc) { ch = KEY_EOL; code = KEY_CODE_YES; } @@ -145,12 +144,12 @@ wgetn_wstr(WINDOW *win, wint_t *str, int maxlen) if (code == KEY_CODE_YES) { /* * Some terminals (the Wyse-50 is the most common) generate a \n - * from the down-arrow key. With this logic, it's the user's + * from the down-arrow key. With this logic, it is the user's * choice whether to set kcud=\n for wget_wch(); terminating * *getn_wstr() with \n should work either way. */ if (ch == KEY_DOWN || ch == KEY_ENTER) { - if (oldecho == TRUE + if (save_flags._echo == TRUE && win->_cury == win->_maxy && win->_scroll) wechochar(win, (chtype) '\n'); @@ -158,21 +157,21 @@ wgetn_wstr(WINDOW *win, wint_t *str, int maxlen) } if (ch == KEY_LEFT || ch == KEY_BACKSPACE) { if (tmpstr > oldstr) { - tmpstr = WipeOut(win, y, x, oldstr, tmpstr, oldecho); + tmpstr = WipeOut(win, y, x, oldstr, tmpstr, save_flags._echo); } } else if (ch == KEY_EOL) { while (tmpstr > oldstr) { - tmpstr = WipeOut(win, y, x, oldstr, tmpstr, oldecho); + tmpstr = WipeOut(win, y, x, oldstr, tmpstr, save_flags._echo); } } else { beep(); } - } else if (maxlen >= 0 && tmpstr - oldstr >= maxlen) { + } else if (tmpstr - oldstr >= maxlen) { beep(); } else { *tmpstr++ = ch; *tmpstr = 0; - if (oldecho == TRUE) { + if (save_flags._echo == TRUE) { int oldy = win->_cury; if (wadd_wint(win, tmpstr - 1) == ERR) { @@ -182,9 +181,9 @@ wgetn_wstr(WINDOW *win, wint_t *str, int maxlen) */ win->_flags &= ~_WRAPPED; waddch(win, (chtype) ' '); - tmpstr = WipeOut(win, y, x, oldstr, tmpstr, oldecho); + tmpstr = WipeOut(win, y, x, oldstr, tmpstr, save_flags._echo); continue; - } else if (win->_flags & _WRAPPED) { + } else if (IS_WRAPPED(win)) { /* * If the last waddch forced a wrap & scroll, adjust our * reference point for erasures. @@ -212,11 +211,7 @@ wgetn_wstr(WINDOW *win, wint_t *str, int maxlen) /* Restore with a single I/O call, to fix minor asymmetry between * raw/noraw, etc. */ - sp->_nl = oldnl; - sp->_echo = oldecho; - sp->_raw = oldraw; - sp->_cbreak = oldcbreak; - + sp->_tty_flags = save_flags; (void) _nc_set_tty_mode(&buf); *tmpstr = 0; diff --git a/lib/libcurses/widechar/lib_hline_set.c b/lib/libcurses/widechar/lib_hline_set.c index 4f5b90fb1ca..eef3b861ee1 100644 --- a/lib/libcurses/widechar/lib_hline_set.c +++ b/lib/libcurses/widechar/lib_hline_set.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_hline_set.c,v 1.1 2010/09/06 17:26:17 nicm Exp $ */ +/* $OpenBSD: lib_hline_set.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2002 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 2002-2010,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -41,23 +42,21 @@ #include -MODULE_ID("$Id: lib_hline_set.c,v 1.1 2010/09/06 17:26:17 nicm Exp $") +MODULE_ID("$Id: lib_hline_set.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) -whline_set(WINDOW *win, const cchar_t * ch, int n) +whline_set(WINDOW *win, const cchar_t *ch, int n) { int code = ERR; - NCURSES_SIZE_T start; - NCURSES_SIZE_T end; - T((T_CALLED("whline_set(%p,%s,%d)"), win, _tracecchar_t(ch), n)); + T((T_CALLED("whline_set(%p,%s,%d)"), (void *) win, _tracecchar_t(ch), n)); if (win) { struct ldat *line = &(win->_line[win->_cury]); NCURSES_CH_T wch; + int start = win->_curx; + int end = start + n - 1; - start = win->_curx; - end = start + n - 1; if (end > win->_maxx) end = win->_maxx; diff --git a/lib/libcurses/widechar/lib_in_wch.c b/lib/libcurses/widechar/lib_in_wch.c index 811dfe4b209..d686197b031 100644 --- a/lib/libcurses/widechar/lib_in_wch.c +++ b/lib/libcurses/widechar/lib_in_wch.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_in_wch.c,v 1.1 2010/09/06 17:26:17 nicm Exp $ */ +/* $OpenBSD: lib_in_wch.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2002-2004,2006 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 2002-2009,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -41,17 +42,19 @@ #include -MODULE_ID("$Id: lib_in_wch.c,v 1.1 2010/09/06 17:26:17 nicm Exp $") +MODULE_ID("$Id: lib_in_wch.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) win_wch(WINDOW *win, cchar_t *wcval) { - int row, col; int code = OK; - TR(TRACE_CCALLS, (T_CALLED("win_wch(%p,%p)"), win, wcval)); + TR(TRACE_CCALLS, (T_CALLED("win_wch(%p,%p)"), (void *) win, (void *) wcval)); + if (win != 0 && wcval != 0) { + int row, col; + getyx(win, row, col); *wcval = win->_line[row].text[col]; diff --git a/lib/libcurses/widechar/lib_in_wchnstr.c b/lib/libcurses/widechar/lib_in_wchnstr.c index d70ea5ffe52..d96f2f9d162 100644 --- a/lib/libcurses/widechar/lib_in_wchnstr.c +++ b/lib/libcurses/widechar/lib_in_wchnstr.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_in_wchnstr.c,v 1.1 2010/09/06 17:26:17 nicm Exp $ */ +/* $OpenBSD: lib_in_wchnstr.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2002-2004-2007 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 2002-2007,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -41,14 +42,14 @@ #include -MODULE_ID("$Id: lib_in_wchnstr.c,v 1.1 2010/09/06 17:26:17 nicm Exp $") +MODULE_ID("$Id: lib_in_wchnstr.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) win_wchnstr(WINDOW *win, cchar_t *wchstr, int n) { int code = OK; - T((T_CALLED("win_wchnstr(%p,%p,%d)"), win, wchstr, n)); + T((T_CALLED("win_wchnstr(%p,%p,%d)"), (void *) win, (void *) wchstr, n)); if (win != 0 && wchstr != 0) { NCURSES_CH_T *src; diff --git a/lib/libcurses/widechar/lib_ins_wch.c b/lib/libcurses/widechar/lib_ins_wch.c index 28b39d82fcf..b063044f22c 100644 --- a/lib/libcurses/widechar/lib_ins_wch.c +++ b/lib/libcurses/widechar/lib_ins_wch.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_ins_wch.c,v 1.1 2010/09/06 17:26:17 nicm Exp $ */ +/* $OpenBSD: lib_ins_wch.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2002-2003,2005 Free Software Foundation, Inc. * + * Copyright 2019,2020 Thomas E. Dickey * + * Copyright 2002-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -41,53 +42,56 @@ #include -MODULE_ID("$Id: lib_ins_wch.c,v 1.1 2010/09/06 17:26:17 nicm Exp $") +MODULE_ID("$Id: lib_ins_wch.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") /* * Insert the given character, updating the current location to simplify * inserting a string. */ -static int +NCURSES_EXPORT(int) _nc_insert_wch(WINDOW *win, const cchar_t *wch) { - int cells = wcwidth(CharOf(CHDEREF(wch))); - int cell; - - if (cells <= 0) - cells = 1; - - if (win->_curx <= win->_maxx) { - struct ldat *line = &(win->_line[win->_cury]); - NCURSES_CH_T *end = &(line->text[win->_curx]); - NCURSES_CH_T *temp1 = &(line->text[win->_maxx]); - NCURSES_CH_T *temp2 = temp1 - cells; - - CHANGED_TO_EOL(line, win->_curx, win->_maxx); - while (temp1 > end) - *temp1-- = *temp2--; + int cells = _nc_wacs_width(CharOf(CHDEREF(wch))); + int code = OK; + + if (cells < 0) { + code = winsch(win, (chtype) CharOf(CHDEREF(wch))); + } else { + if (cells == 0) + cells = 1; + + if (win->_curx <= win->_maxx) { + int cell; + struct ldat *line = &(win->_line[win->_cury]); + NCURSES_CH_T *end = &(line->text[win->_curx]); + NCURSES_CH_T *temp1 = &(line->text[win->_maxx]); + NCURSES_CH_T *temp2 = temp1 - cells; + + CHANGED_TO_EOL(line, win->_curx, win->_maxx); + while (temp1 > end) + *temp1-- = *temp2--; + + *temp1 = _nc_render(win, *wch); + for (cell = 1; cell < cells; ++cell) { + SetWidecExt(temp1[cell], cell); + } - *temp1 = _nc_render(win, *wch); - for (cell = 1; cell < cells; ++cell) { - SetWidecExt(temp1[cell], cell); + win->_curx = (NCURSES_SIZE_T) (win->_curx + cells); } - - win->_curx++; } - return OK; + return code; } NCURSES_EXPORT(int) wins_wch(WINDOW *win, const cchar_t *wch) { - NCURSES_SIZE_T oy; - NCURSES_SIZE_T ox; int code = ERR; - T((T_CALLED("wins_wch(%p, %s)"), win, _tracecchar_t(wch))); + T((T_CALLED("wins_wch(%p, %s)"), (void *) win, _tracecchar_t(wch))); if (win != 0) { - oy = win->_cury; - ox = win->_curx; + NCURSES_SIZE_T oy = win->_cury; + NCURSES_SIZE_T ox = win->_curx; code = _nc_insert_wch(win, wch); @@ -102,36 +106,38 @@ NCURSES_EXPORT(int) wins_nwstr(WINDOW *win, const wchar_t *wstr, int n) { int code = ERR; - NCURSES_SIZE_T oy; - NCURSES_SIZE_T ox; - const wchar_t *cp; - T((T_CALLED("wins_nwstr(%p,%s,%d)"), win, _nc_viswbufn(wstr, n), n)); + T((T_CALLED("wins_nwstr(%p,%s,%d)"), + (void *) win, _nc_viswbufn(wstr, n), n)); if (win != 0 && wstr != 0) { if (n < 1) - n = wcslen(wstr); + n = INT_MAX; code = OK; + if (n > 0) { - oy = win->_cury; - ox = win->_curx; - for (cp = wstr; *cp && ((cp - wstr) < n); cp++) { - int len = wcwidth(*cp); + const wchar_t *cp; + SCREEN *sp = _nc_screen_of(win); + NCURSES_SIZE_T oy = win->_cury; + NCURSES_SIZE_T ox = win->_curx; + + for (cp = wstr; (*cp != L'\0') && ((cp - wstr) < n); cp++) { + int len = _nc_wacs_width(*cp); - if (len != 1 || !is8bits(*cp)) { + if ((len >= 0 && len != 1) || !is7bits(*cp)) { cchar_t tmp_cchar; wchar_t tmp_wchar = *cp; memset(&tmp_cchar, 0, sizeof(tmp_cchar)); (void) setcchar(&tmp_cchar, &tmp_wchar, WA_NORMAL, - 0, + (short) 0, (void *) 0); code = _nc_insert_wch(win, &tmp_cchar); } else { /* tabs, other ASCII stuff */ - code = _nc_insert_ch(win, (chtype) (*cp)); + code = _nc_insert_ch(sp, win, (chtype) (*cp)); } if (code != OK) break; diff --git a/lib/libcurses/widechar/lib_inwstr.c b/lib/libcurses/widechar/lib_inwstr.c index 0dd27d77cf8..8cb46a3c791 100644 --- a/lib/libcurses/widechar/lib_inwstr.c +++ b/lib/libcurses/widechar/lib_inwstr.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_inwstr.c,v 1.1 2010/09/06 17:26:17 nicm Exp $ */ +/* $OpenBSD: lib_inwstr.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2002,2004 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 2002-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -41,31 +42,39 @@ #include -MODULE_ID("$Id: lib_inwstr.c,v 1.1 2010/09/06 17:26:17 nicm Exp $") +MODULE_ID("$Id: lib_inwstr.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) winnwstr(WINDOW *win, wchar_t *wstr, int n) { - int row, col, inx; int count = 0; - int last = 0; cchar_t *text; - wchar_t wch; - T((T_CALLED("winnwstr(%p,%p,%d)"), win, wstr, n)); + T((T_CALLED("winnwstr(%p,%p,%d)"), (void *) win, (void *) wstr, n)); if (wstr != 0) { if (win) { + int row, col; + int last = 0; + bool done = FALSE; + getyx(win, row, col); text = win->_line[row].text; - while (count < n && count != ERR) { + while (count < n && !done && count != ERR) { + if (!isWidecExt(text[col])) { + int inx; + wchar_t wch; + for (inx = 0; (inx < CCHARW_MAX) && ((wch = text[col].chars[inx]) != 0); ++inx) { if (count + 1 > n) { - if ((count = last) == 0) { + done = TRUE; + if (last == 0) { count = ERR; /* error if we store nothing */ + } else { + count = last; /* only store complete chars */ } break; } @@ -95,8 +104,13 @@ NCURSES_EXPORT(int) winwstr(WINDOW *win, wchar_t *wstr) { int result = OK; - T((T_CALLED("winwstr(%p,%p)"), win, wstr)); - if (winnwstr(win, wstr, CCHARW_MAX * (win->_maxx - win->_curx + 1)) == ERR) + + T((T_CALLED("winwstr(%p,%p)"), (void *) win, (void *) wstr)); + if (win == 0) { + result = ERR; + } else if (winnwstr(win, wstr, + CCHARW_MAX * (win->_maxx - win->_curx + 1)) == ERR) { result = ERR; + } returnCode(result); } diff --git a/lib/libcurses/widechar/lib_key_name.c b/lib/libcurses/widechar/lib_key_name.c index 8c511f2c1d7..a58bdd61159 100644 --- a/lib/libcurses/widechar/lib_key_name.c +++ b/lib/libcurses/widechar/lib_key_name.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_key_name.c,v 1.1 2010/09/06 17:26:17 nicm Exp $ */ +/* $OpenBSD: lib_key_name.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2007 Free Software Foundation, Inc. * + * Copyright 2020,2023 Thomas E. Dickey * + * Copyright 2007-2008,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -37,7 +38,9 @@ #include -MODULE_ID("$Id: lib_key_name.c,v 1.1 2010/09/06 17:26:17 nicm Exp $") +MODULE_ID("$Id: lib_key_name.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") + +#define MyData _nc_globals.key_name NCURSES_EXPORT(NCURSES_CONST char *) key_name(wchar_t c) @@ -45,20 +48,22 @@ key_name(wchar_t c) cchar_t my_cchar; wchar_t *my_wchars; size_t len; - - /* FIXME: move to _nc_globals */ - static char result[MB_LEN_MAX + 1]; + NCURSES_CONST char *result = NULL; memset(&my_cchar, 0, sizeof(my_cchar)); my_cchar.chars[0] = c; my_cchar.chars[1] = L'\0'; my_wchars = wunctrl(&my_cchar); - len = wcstombs(result, my_wchars, sizeof(result) - 1); - if (isEILSEQ(len) || (len == 0)) { - return 0; + /* + * wunctrl() could return a wide character rather than just a "printable" + * representation. Check for that and return a corresponding multibyte + * character string. + */ + len = wcstombs(MyData, my_wchars, sizeof(MyData) - 1); + if (!isEILSEQ(len) && (len != 0) && (len <= MB_LEN_MAX)) { + MyData[len] = '\0'; + result = MyData; } - - result[len] = '\0'; return result; } diff --git a/lib/libcurses/widechar/lib_pecho_wchar.c b/lib/libcurses/widechar/lib_pecho_wchar.c index 867fd5065cc..252472375ad 100644 --- a/lib/libcurses/widechar/lib_pecho_wchar.c +++ b/lib/libcurses/widechar/lib_pecho_wchar.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_pecho_wchar.c,v 1.1 2010/09/06 17:26:17 nicm Exp $ */ +/* $OpenBSD: lib_pecho_wchar.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 2004,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -34,17 +35,17 @@ #include -MODULE_ID("$Id: lib_pecho_wchar.c,v 1.1 2010/09/06 17:26:17 nicm Exp $") +MODULE_ID("$Id: lib_pecho_wchar.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) -pecho_wchar(WINDOW *pad, const cchar_t * wch) +pecho_wchar(WINDOW *pad, const cchar_t *wch) { - T((T_CALLED("pecho_wchar(%p, %s)"), pad, _tracech_t(wch))); + T((T_CALLED("pecho_wchar(%p, %s)"), (void *) pad, _tracech_t(wch))); if (pad == 0) returnCode(ERR); - if (!(pad->_flags & _ISPAD)) + if (!IS_PAD(pad)) returnCode(wecho_wchar(pad, wch)); wadd_wch(pad, wch); diff --git a/lib/libcurses/widechar/lib_slk_wset.c b/lib/libcurses/widechar/lib_slk_wset.c index 84cb0ff4a60..00f96526a95 100644 --- a/lib/libcurses/widechar/lib_slk_wset.c +++ b/lib/libcurses/widechar/lib_slk_wset.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_slk_wset.c,v 1.1 2010/09/06 17:26:17 nicm Exp $ */ +/* $OpenBSD: lib_slk_wset.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2003-2004,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 2003-2011,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -42,32 +43,37 @@ #include #endif -MODULE_ID("$Id: lib_slk_wset.c,v 1.1 2010/09/06 17:26:17 nicm Exp $") +MODULE_ID("$Id: lib_slk_wset.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) slk_wset(int i, const wchar_t *astr, int format) { int result = ERR; - size_t arglen; const wchar_t *str; - char *mystr; mbstate_t state; T((T_CALLED("slk_wset(%d, %s, %d)"), i, _nc_viswbuf(astr), format)); - init_mb(state); - str = astr; - if ((arglen = wcsrtombs(NULL, &str, 0, &state)) != (size_t) -1) { - if ((mystr = (char *) _nc_doalloc(0, arglen + 1)) != 0) { - str = astr; - if (wcsrtombs(mystr, &str, arglen, &state) != (size_t) -1) { - /* glibc documentation claims that the terminating L'\0' - * is written, but it is not... - */ - mystr[arglen] = 0; - result = slk_set(i, mystr, format); + if (astr != 0) { + size_t arglen; + + init_mb(state); + str = astr; + + if ((arglen = wcsrtombs(NULL, &str, (size_t) 0, &state)) != (size_t) -1) { + char *mystr; + + if ((mystr = (char *) _nc_doalloc(0, arglen + 1)) != 0) { + str = astr; + if (wcsrtombs(mystr, &str, arglen, &state) != (size_t) -1) { + /* glibc documentation claims that the terminating L'\0' + * is written, but it is not... + */ + mystr[arglen] = 0; + result = slk_set(i, mystr, format); + } + free(mystr); } - free(mystr); } } returnCode(result); diff --git a/lib/libcurses/widechar/lib_unget_wch.c b/lib/libcurses/widechar/lib_unget_wch.c index c1db3e91a62..3bc4527ec16 100644 --- a/lib/libcurses/widechar/lib_unget_wch.c +++ b/lib/libcurses/widechar/lib_unget_wch.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_unget_wch.c,v 1.1 2010/09/06 17:26:17 nicm Exp $ */ +/* $OpenBSD: lib_unget_wch.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2002-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020,2023 Thomas E. Dickey * + * Copyright 2002-2011,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -41,7 +42,7 @@ #include -MODULE_ID("$Id: lib_unget_wch.c,v 1.1 2010/09/06 17:26:17 nicm Exp $") +MODULE_ID("$Id: lib_unget_wch.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") /* * Wrapper for wcrtomb() which obtains the length needed for the given @@ -57,24 +58,23 @@ _nc_wcrtomb(char *target, wchar_t source, mbstate_t * state) const wchar_t *tempp = temp; temp[0] = source; temp[1] = 0; - result = wcsrtombs(NULL, &tempp, 0, state); + result = (int) wcsrtombs(NULL, &tempp, (size_t) 0, state); } else { - result = wcrtomb(target, source, state); + result = (int) wcrtomb(target, source, state); } - if (!isEILSEQ(result) && (result == 0)) + if (!isEILSEQ(result) && ((result == 0) || (result > MB_LEN_MAX))) result = 1; - return result; + return (size_t) result; } NCURSES_EXPORT(int) -unget_wch(const wchar_t wch) +NCURSES_SP_NAME(unget_wch) (NCURSES_SP_DCLx const wchar_t wch) { int result = OK; mbstate_t state; size_t length; - int n; - T((T_CALLED("unget_wch(%#lx)"), (unsigned long) wch)); + T((T_CALLED("unget_wch(%p, %#lx)"), (void *) SP_PARM, (unsigned long) wch)); init_mb(state); length = _nc_wcrtomb(0, wch, &state); @@ -84,11 +84,15 @@ unget_wch(const wchar_t wch) char *string; if ((string = (char *) malloc(length)) != 0) { + int n; + init_mb(state); - wcrtomb(string, wch, &state); + /* ignore the result, since we already validated the character */ + IGNORE_RC((int) wcrtomb(string, wch, &state)); for (n = (int) (length - 1); n >= 0; --n) { - if (_nc_ungetch(SP, string[n]) != OK) { + if (NCURSES_SP_NAME(ungetch) (NCURSES_SP_ARGx + UChar(string[n])) !=OK) { result = ERR; break; } @@ -103,3 +107,11 @@ unget_wch(const wchar_t wch) returnCode(result); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +unget_wch(const wchar_t wch) +{ + return NCURSES_SP_NAME(unget_wch) (CURRENT_SCREEN, wch); +} +#endif diff --git a/lib/libcurses/widechar/lib_vid_attr.c b/lib/libcurses/widechar/lib_vid_attr.c index b5f3131cfad..861ab9d20a4 100644 --- a/lib/libcurses/widechar/lib_vid_attr.c +++ b/lib/libcurses/widechar/lib_vid_attr.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_vid_attr.c,v 1.1 2010/09/06 17:26:17 nicm Exp $ */ +/* $OpenBSD: lib_vid_attr.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2002-2006,2007 Free Software Foundation, Inc. * + * Copyright 2018-2020,2023 Thomas E. Dickey * + * Copyright 2002-2014,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,70 +34,95 @@ ****************************************************************************/ #include -#include -MODULE_ID("$Id: lib_vid_attr.c,v 1.1 2010/09/06 17:26:17 nicm Exp $") +#ifndef CUR +#define CUR SP_TERMTYPE +#endif -#define doPut(mode) TPUTS_TRACE(#mode); tputs(mode, 1, outc) +MODULE_ID("$Id: lib_vid_attr.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") -#define TurnOn(mask,mode) \ - if ((turn_on & mask) && mode) { doPut(mode); } +#define doPut(mode) \ + TPUTS_TRACE(#mode); \ + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx mode, 1, outc) -#define TurnOff(mask,mode) \ - if ((turn_off & mask) && mode) { doPut(mode); turn_off &= ~mask; } +#define TurnOn(mask, mode) \ + if ((turn_on & mask) && mode) { \ + TPUTS_TRACE(#mode); \ + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx mode, 1, outc); \ + } + +#define TurnOff(mask, mode) \ + if ((turn_off & mask) && mode) { \ + TPUTS_TRACE(#mode); \ + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx mode, 1, outc); \ + turn_off &= ~mask; \ + } /* if there is no current screen, assume we *can* do color */ #define SetColorsIf(why, old_attr, old_pair) \ if (can_color && (why)) { \ - TR(TRACE_ATTRS, ("old pair = %d -- new pair = %d", old_pair, pair)); \ - if ((pair != old_pair) \ - || (fix_pair0 && (pair == 0)) \ + TR(TRACE_ATTRS, ("old pair = %d -- new pair = %d", old_pair, color_pair)); \ + if ((color_pair != old_pair) \ + || (fix_pair0 && (color_pair == 0)) \ || (reverse ^ ((old_attr & A_REVERSE) != 0))) { \ - _nc_do_color(old_pair, pair, reverse, outc); \ + NCURSES_SP_NAME(_nc_do_color) (NCURSES_SP_ARGx \ + old_pair, color_pair, \ + reverse, outc); \ } \ } -#define set_color(mode, pair) mode &= ALL_BUT_COLOR; mode |= COLOR_PAIR(pair) +#define set_color(mode, pair) \ + mode &= ALL_BUT_COLOR; \ + mode |= (attr_t) ColorPair(pair) NCURSES_EXPORT(int) -vid_puts(attr_t newmode, short pair, void *opts GCC_UNUSED, int (*outc) (int)) +NCURSES_SP_NAME(vid_puts) (NCURSES_SP_DCLx + attr_t newmode, + NCURSES_PAIRS_T pair_arg, + void *opts OPTIONAL_PAIR, + NCURSES_SP_OUTC outc) { + int color_pair = pair_arg; #if NCURSES_EXT_COLORS static attr_t previous_attr = A_NORMAL; static int previous_pair = 0; attr_t turn_on, turn_off; bool reverse = FALSE; - bool can_color = (SP == 0 || SP->_coloron); + bool can_color = (SP_PARM == 0 || SP_PARM->_coloron); #if NCURSES_EXT_FUNCS - bool fix_pair0 = (SP != 0 && SP->_coloron && !SP->_default_color); + bool fix_pair0 = (SP_PARM != 0 && SP_PARM->_coloron && !SP_PARM->_default_color); #else #define fix_pair0 FALSE #endif + if (!IsValidTIScreen(SP_PARM)) + returnCode(ERR); + newmode &= A_ATTRIBUTES; - T((T_CALLED("vid_puts(%s,%d)"), _traceattr(newmode), pair)); + set_extended_pair(opts, color_pair); + T((T_CALLED("vid_puts(%s,%d)"), _traceattr(newmode), color_pair)); /* this allows us to go on whether or not newterm() has been called */ - if (SP) { - previous_attr = AttrOf(SCREEN_ATTRS(SP)); - previous_pair = GetPair(SCREEN_ATTRS(SP)); + if (SP_PARM) { + previous_attr = AttrOf(SCREEN_ATTRS(SP_PARM)); + previous_pair = GetPair(SCREEN_ATTRS(SP_PARM)); } TR(TRACE_ATTRS, ("previous attribute was %s, %d", _traceattr(previous_attr), previous_pair)); #if !USE_XMC_SUPPORT - if ((SP != 0) + if ((SP_PARM != 0) && (magic_cookie_glitch > 0)) - newmode &= ~(SP->_xmc_suppress); + newmode &= ~(SP_PARM->_xmc_suppress); #endif /* * If we have a terminal that cannot combine color with video * attributes, use the colors in preference. */ - if ((pair != 0 + if ((color_pair != 0 || fix_pair0) && (no_color_video > 0)) { /* @@ -111,7 +137,7 @@ vid_puts(attr_t newmode, short pair, void *opts GCC_UNUSED, int (*outc) (int)) * A_ALTCHARSET (256) down 2 to line up. We use the NCURSES_BITS * macro so this will work properly for the wide-character layout. */ - unsigned value = no_color_video; + unsigned value = (unsigned) no_color_video; attr_t mask = NCURSES_BITS((value & 63) | ((value & 192) << 1) | ((value & 256) >> 2), 8); @@ -125,7 +151,7 @@ vid_puts(attr_t newmode, short pair, void *opts GCC_UNUSED, int (*outc) (int)) } if (newmode == previous_attr - && pair == previous_pair) + && color_pair == previous_pair) returnCode(OK); if (reverse) { @@ -133,9 +159,9 @@ vid_puts(attr_t newmode, short pair, void *opts GCC_UNUSED, int (*outc) (int)) } turn_off = (~newmode & previous_attr) & ALL_BUT_COLOR; - turn_on = (newmode & ~previous_attr) & ALL_BUT_COLOR; + turn_on = (newmode & ~(previous_attr & TPARM_ATTR)) & ALL_BUT_COLOR; - SetColorsIf(((pair == 0) && !fix_pair0), previous_attr, previous_pair); + SetColorsIf(((color_pair == 0) && !fix_pair0), previous_attr, previous_pair); if (newmode == A_NORMAL) { if ((previous_attr & A_ALTCHARSET) && exit_alt_charset_mode) { @@ -146,56 +172,78 @@ vid_puts(attr_t newmode, short pair, void *opts GCC_UNUSED, int (*outc) (int)) if (exit_attribute_mode) { doPut(exit_attribute_mode); } else { - if (!SP || SP->_use_rmul) { + if (!SP_PARM || SP_PARM->_use_rmul) { TurnOff(A_UNDERLINE, exit_underline_mode); } - if (!SP || SP->_use_rmso) { + if (!SP_PARM || SP_PARM->_use_rmso) { TurnOff(A_STANDOUT, exit_standout_mode); } +#if USE_ITALIC + if (!SP_PARM || SP_PARM->_use_ritm) { + TurnOff(A_ITALIC, exit_italics_mode); + } +#endif + (void) turn_off; } previous_attr &= ALL_BUT_COLOR; previous_pair = 0; } - SetColorsIf((pair != 0) || fix_pair0, previous_attr, previous_pair); + SetColorsIf((color_pair != 0) || fix_pair0, previous_attr, previous_pair); } else if (set_attributes) { if (turn_on || turn_off) { TPUTS_TRACE("set_attributes"); - tputs(TPARM_9(set_attributes, - (newmode & A_STANDOUT) != 0, - (newmode & A_UNDERLINE) != 0, - (newmode & A_REVERSE) != 0, - (newmode & A_BLINK) != 0, - (newmode & A_DIM) != 0, - (newmode & A_BOLD) != 0, - (newmode & A_INVIS) != 0, - (newmode & A_PROTECT) != 0, - (newmode & A_ALTCHARSET) != 0), 1, outc); + NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx + TIPARM_9(set_attributes, + (newmode & A_STANDOUT) != 0, + (newmode & A_UNDERLINE) != 0, + (newmode & A_REVERSE) != 0, + (newmode & A_BLINK) != 0, + (newmode & A_DIM) != 0, + (newmode & A_BOLD) != 0, + (newmode & A_INVIS) != 0, + (newmode & A_PROTECT) != 0, + (newmode & A_ALTCHARSET) != 0), + 1, outc); previous_attr &= ALL_BUT_COLOR; previous_pair = 0; } - SetColorsIf((pair != 0) || fix_pair0, previous_attr, previous_pair); +#if USE_ITALIC + if (!SP_PARM || SP_PARM->_use_ritm) { + if (turn_on & A_ITALIC) { + TurnOn(A_ITALIC, enter_italics_mode); + } else if (turn_off & A_ITALIC) { + TurnOff(A_ITALIC, exit_italics_mode); + } + (void) turn_off; + } +#endif + SetColorsIf((color_pair != 0) || fix_pair0, previous_attr, previous_pair); } else { TR(TRACE_ATTRS, ("turning %s off", _traceattr(turn_off))); TurnOff(A_ALTCHARSET, exit_alt_charset_mode); - if (!SP || SP->_use_rmul) { + if (!SP_PARM || SP_PARM->_use_rmul) { TurnOff(A_UNDERLINE, exit_underline_mode); } - if (!SP || SP->_use_rmso) { + if (!SP_PARM || SP_PARM->_use_rmso) { TurnOff(A_STANDOUT, exit_standout_mode); } - +#if USE_ITALIC + if (!SP_PARM || SP_PARM->_use_ritm) { + TurnOff(A_ITALIC, exit_italics_mode); + } +#endif if (turn_off && exit_attribute_mode) { doPut(exit_attribute_mode); turn_on |= (newmode & ALL_BUT_COLOR); previous_attr &= ALL_BUT_COLOR; previous_pair = 0; } - SetColorsIf((pair != 0) || fix_pair0, previous_attr, previous_pair); + SetColorsIf((color_pair != 0) || fix_pair0, previous_attr, previous_pair); TR(TRACE_ATTRS, ("turning %s on", _traceattr(turn_on))); /* *INDENT-OFF* */ @@ -208,7 +256,10 @@ vid_puts(attr_t newmode, short pair, void *opts GCC_UNUSED, int (*outc) (int)) TurnOn(A_PROTECT, enter_protected_mode); TurnOn(A_INVIS, enter_secure_mode); TurnOn(A_UNDERLINE, enter_underline_mode); -#if USE_WIDEC_SUPPORT +#if USE_ITALIC + TurnOn(A_ITALIC, enter_italics_mode); +#endif +#if USE_WIDEC_SUPPORT && defined(enter_horizontal_hl_mode) TurnOn(A_HORIZONTAL, enter_horizontal_hl_mode); TurnOn(A_LEFT, enter_left_hl_mode); TurnOn(A_LOW, enter_low_hl_mode); @@ -217,61 +268,104 @@ vid_puts(attr_t newmode, short pair, void *opts GCC_UNUSED, int (*outc) (int)) TurnOn(A_VERTICAL, enter_vertical_hl_mode); #endif /* *INDENT-ON* */ - } if (reverse) newmode |= A_REVERSE; - if (SP) { - SetAttr(SCREEN_ATTRS(SP), newmode); - SetPair(SCREEN_ATTRS(SP), pair); + if (SP_PARM) { + SetAttr(SCREEN_ATTRS(SP_PARM), newmode); + SetPair(SCREEN_ATTRS(SP_PARM), color_pair); } else { previous_attr = newmode; - previous_pair = pair; + previous_pair = color_pair; } returnCode(OK); #else - T((T_CALLED("vid_puts(%s,%d)"), _traceattr(newmode), pair)); - set_color(newmode, pair); - returnCode(vidputs(newmode, outc)); + T((T_CALLED("vid_puts(%s,%d)"), _traceattr(newmode), color_pair)); + (void) opts; + set_color(newmode, color_pair); + returnCode(NCURSES_SP_NAME(vidputs) (NCURSES_SP_ARGx newmode, outc)); #endif } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +vid_puts(attr_t newmode, + NCURSES_PAIRS_T pair_arg, + void *opts GCC_UNUSED, + NCURSES_OUTC outc) +{ + SetSafeOutcWrapper(outc); + return NCURSES_SP_NAME(vid_puts) (CURRENT_SCREEN, + newmode, + pair_arg, + opts, + _nc_outc_wrapper); +} +#endif + #undef vid_attr NCURSES_EXPORT(int) -vid_attr(attr_t newmode, short pair, void *opts) +NCURSES_SP_NAME(vid_attr) (NCURSES_SP_DCLx + attr_t newmode, + NCURSES_PAIRS_T pair_arg, + void *opts) { - T((T_CALLED("vid_attr(%s,%d)"), _traceattr(newmode), pair)); - returnCode(vid_puts(newmode, pair, opts, _nc_outch)); + T((T_CALLED("vid_attr(%s,%d)"), _traceattr(newmode), (int) pair_arg)); + returnCode(NCURSES_SP_NAME(vid_puts) (NCURSES_SP_ARGx + newmode, + pair_arg, + opts, + NCURSES_SP_NAME(_nc_putchar))); } +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +vid_attr(attr_t newmode, NCURSES_PAIRS_T pair_arg, void *opts) +{ + return NCURSES_SP_NAME(vid_attr) (CURRENT_SCREEN, newmode, pair_arg, opts); +} +#endif + /* * This implementation uses the same mask values for A_xxx and WA_xxx, so * we can use termattrs() for part of the logic. */ NCURSES_EXPORT(attr_t) -term_attrs(void) +NCURSES_SP_NAME(term_attrs) (NCURSES_SP_DCL0) { - attr_t attrs; + attr_t attrs = 0; T((T_CALLED("term_attrs()"))); - attrs = termattrs(); - - /* these are only supported for wide-character mode */ - if (enter_horizontal_hl_mode) - attrs |= WA_HORIZONTAL; - if (enter_left_hl_mode) - attrs |= WA_LEFT; - if (enter_low_hl_mode) - attrs |= WA_LOW; - if (enter_right_hl_mode) - attrs |= WA_RIGHT; - if (enter_top_hl_mode) - attrs |= WA_TOP; - if (enter_vertical_hl_mode) - attrs |= WA_VERTICAL; + if (SP_PARM) { + attrs = NCURSES_SP_NAME(termattrs) (NCURSES_SP_ARG); + +#if USE_WIDEC_SUPPORT && defined(enter_horizontal_hl_mode) + /* these are only supported for wide-character mode */ + if (enter_horizontal_hl_mode) + attrs |= WA_HORIZONTAL; + if (enter_left_hl_mode) + attrs |= WA_LEFT; + if (enter_low_hl_mode) + attrs |= WA_LOW; + if (enter_right_hl_mode) + attrs |= WA_RIGHT; + if (enter_top_hl_mode) + attrs |= WA_TOP; + if (enter_vertical_hl_mode) + attrs |= WA_VERTICAL; +#endif + } returnAttr(attrs); } + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(attr_t) +term_attrs(void) +{ + return NCURSES_SP_NAME(term_attrs) (CURRENT_SCREEN); +} +#endif diff --git a/lib/libcurses/widechar/lib_vline_set.c b/lib/libcurses/widechar/lib_vline_set.c index 22e0974d303..55597ecc2d4 100644 --- a/lib/libcurses/widechar/lib_vline_set.c +++ b/lib/libcurses/widechar/lib_vline_set.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_vline_set.c,v 1.1 2010/09/06 17:26:17 nicm Exp $ */ +/* $OpenBSD: lib_vline_set.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2002 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 2002-2010,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -41,22 +42,21 @@ #include -MODULE_ID("$Id: lib_vline_set.c,v 1.1 2010/09/06 17:26:17 nicm Exp $") +MODULE_ID("$Id: lib_vline_set.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(int) -wvline_set(WINDOW *win, const cchar_t * ch, int n) +wvline_set(WINDOW *win, const cchar_t *ch, int n) { int code = ERR; - NCURSES_SIZE_T row, col; - NCURSES_SIZE_T end; - T((T_CALLED("wvline(%p,%s,%d)"), win, _tracecchar_t(ch), n)); + T((T_CALLED("wvline(%p,%s,%d)"), (void *) win, _tracecchar_t(ch), n)); if (win) { NCURSES_CH_T wch; - row = win->_cury; - col = win->_curx; - end = row + n - 1; + int row = win->_cury; + int col = win->_curx; + int end = row + n - 1; + if (end > win->_maxy) end = win->_maxy; diff --git a/lib/libcurses/widechar/lib_wacs.c b/lib/libcurses/widechar/lib_wacs.c index 65653dac7e7..47a7921cc0e 100644 --- a/lib/libcurses/widechar/lib_wacs.c +++ b/lib/libcurses/widechar/lib_wacs.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_wacs.c,v 1.1 2010/09/06 17:26:17 nicm Exp $ */ +/* $OpenBSD: lib_wacs.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2002,2006 Free Software Foundation, Inc. * + * Copyright 2018,2020 Thomas E. Dickey * + * Copyright 2002-2015,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,9 +34,8 @@ ****************************************************************************/ #include -#include -MODULE_ID("$Id: lib_wacs.c,v 1.1 2010/09/06 17:26:17 nicm Exp $") +MODULE_ID("$Id: lib_wacs.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT_VAR(cchar_t) * _nc_wacs = 0; @@ -44,7 +44,7 @@ _nc_init_wacs(void) { /* *INDENT-OFF* */ static const struct { - int map; + unsigned map; int value[2]; } table[] = { /* VT100 symbols */ @@ -82,10 +82,33 @@ _nc_init_wacs(void) { '{', { '*', 0x03c0 }}, /* greek pi */ { '|', { '!', 0x2260 }}, /* not-equal */ { '}', { 'f', 0x00a3 }}, /* pound-sterling symbol */ + /* thick-line-drawing */ + { 'L', { '+', 0x250f }}, /* upper left corner */ + { 'M', { '+', 0x2517 }}, /* lower left corner */ + { 'K', { '+', 0x2513 }}, /* upper right corner */ + { 'J', { '+', 0x251b }}, /* lower right corner */ + { 'T', { '+', 0x2523 }}, /* tee pointing left */ + { 'U', { '+', 0x252b }}, /* tee pointing right */ + { 'V', { '+', 0x253b }}, /* tee pointing up */ + { 'W', { '+', 0x2533 }}, /* tee pointing down */ + { 'Q', { '-', 0x2501 }}, /* horizontal line */ + { 'X', { '|', 0x2503 }}, /* vertical line */ + { 'N', { '+', 0x254b }}, /* large plus or crossover */ + /* double-line-drawing */ + { 'C', { '+', 0x2554 }}, /* upper left corner */ + { 'D', { '+', 0x255a }}, /* lower left corner */ + { 'B', { '+', 0x2557 }}, /* upper right corner */ + { 'A', { '+', 0x255d }}, /* lower right corner */ + { 'G', { '+', 0x2563 }}, /* tee pointing left */ + { 'F', { '+', 0x2560 }}, /* tee pointing right */ + { 'H', { '+', 0x2569 }}, /* tee pointing up */ + { 'I', { '+', 0x2566 }}, /* tee pointing down */ + { 'R', { '-', 0x2550 }}, /* horizontal line */ + { 'Y', { '|', 0x2551 }}, /* vertical line */ + { 'E', { '+', 0x256c }}, /* large plus or crossover */ }; /* *INDENT-ON* */ - unsigned n, m; int active = _nc_unicode_locale(); /* @@ -98,22 +121,30 @@ _nc_init_wacs(void) T(("initializing WIDE-ACS map (Unicode is%s active)", active ? "" : " not")); - _nc_wacs = typeCalloc(cchar_t, ACS_LEN); - for (n = 0; n < SIZEOF(table); ++n) { - int wide = wcwidth(table[n].value[active]); + if ((_nc_wacs = typeCalloc(cchar_t, ACS_LEN)) != 0) { + unsigned n; - m = table[n].map; - if (active && (wide == 1)) { - SetChar(_nc_wacs[m], table[n].value[active], A_NORMAL); - } else if (acs_map[m] & A_ALTCHARSET) { - SetChar(_nc_wacs[m], m, A_ALTCHARSET); - } else { - SetChar(_nc_wacs[m], table[n].value[0], A_NORMAL); - } + for (n = 0; n < SIZEOF(table); ++n) { + unsigned m; +#if NCURSES_WCWIDTH_GRAPHICS + int wide = wcwidth((wchar_t) table[n].value[active]); +#else + int wide = 1; +#endif + + m = table[n].map; + if (active && (wide == 1)) { + SetChar(_nc_wacs[m], table[n].value[1], A_NORMAL); + } else if (acs_map[m] & A_ALTCHARSET) { + SetChar(_nc_wacs[m], m, A_ALTCHARSET); + } else { + SetChar(_nc_wacs[m], table[n].value[0], A_NORMAL); + } - T(("#%d, SetChar(%c, %#04x) = %s", - n, m, - table[n].value[active], - _tracecchar_t(&_nc_wacs[m]))); + T(("#%d, width:%d SetChar(%c, %s) = %s", + n, wide, m, + _tracechar(table[n].value[active]), + _tracecchar_t(&_nc_wacs[m]))); + } } } diff --git a/lib/libcurses/widechar/lib_wunctrl.c b/lib/libcurses/widechar/lib_wunctrl.c index 0ea8dada860..37bda4c239f 100644 --- a/lib/libcurses/widechar/lib_wunctrl.c +++ b/lib/libcurses/widechar/lib_wunctrl.c @@ -1,7 +1,8 @@ -/* $OpenBSD: lib_wunctrl.c,v 1.1 2010/09/06 17:26:17 nicm Exp $ */ +/* $OpenBSD: lib_wunctrl.c,v 1.2 2023/10/17 09:52:09 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 2001-2005,2007 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 2001-2011,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -37,21 +38,36 @@ #include -MODULE_ID("$Id: lib_wunctrl.c,v 1.1 2010/09/06 17:26:17 nicm Exp $") +MODULE_ID("$Id: lib_wunctrl.c,v 1.2 2023/10/17 09:52:09 nicm Exp $") NCURSES_EXPORT(wchar_t *) -wunctrl(cchar_t *wc) +NCURSES_SP_NAME(wunctrl) (NCURSES_SP_DCLx cchar_t *wc) { - static wchar_t str[CCHARW_MAX + 1], *sp; + static wchar_t str[CCHARW_MAX + 1], *wsp; + wchar_t *result; - if (Charable(*wc)) { - const char *p = unctrl((unsigned) _nc_to_char((wint_t) CharOf(*wc))); + if (wc == 0) { + result = 0; + } else if (SP_PARM != 0 && Charable(*wc)) { + const char *p = + NCURSES_SP_NAME(unctrl) (NCURSES_SP_ARGx + (unsigned) _nc_to_char((wint_t)CharOf(*wc))); - for (sp = str; *p; ++p) { - *sp++ = _nc_to_widechar(*p); + for (wsp = str; *p; ++p) { + *wsp++ = (wchar_t) _nc_to_widechar(*p); } - *sp = 0; - return str; - } else - return wc->chars; + *wsp = 0; + result = str; + } else { + result = wc->chars; + } + return result; +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(wchar_t *) +wunctrl(cchar_t *wc) +{ + return NCURSES_SP_NAME(wunctrl) (CURRENT_SCREEN, wc); } +#endif diff --git a/lib/libcurses/widechar/widechars.c b/lib/libcurses/widechar/widechars.c new file mode 100644 index 00000000000..90748cafa8f --- /dev/null +++ b/lib/libcurses/widechar/widechars.c @@ -0,0 +1,153 @@ +/**************************************************************************** + * Copyright 2018,2020 Thomas E. Dickey * + * Copyright 2012,2013 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +#include + +#if USE_WIDEC_SUPPORT + +MODULE_ID("$Id: widechars.c,v 1.1 2023/10/17 09:52:09 nicm Exp $") + +#if (defined(_NC_WINDOWS)) && !defined(_NC_MSC) +/* + * MinGW has wide-character functions, but they do not work correctly. + */ + +int +_nc_mbtowc(wchar_t *pwc, const char *s, size_t n) +{ + int result; + int count; + int try; + + if (s != 0 && n != 0) { + /* + * MultiByteToWideChar() can decide to return more than one + * wide-character. We want only one. Ignore any trailing null, both + * in the initial count and in the conversion. + */ + count = 0; + for (try = 1; try <= (int) n; ++try) { + count = MultiByteToWideChar(CP_UTF8, + MB_ERR_INVALID_CHARS, + s, + try, + pwc, + 0); + TR(TRACE_BITS, ("...try %d:%d", try, count)); + if (count > 0) { + break; + } + } + if (count < 1 || count > 2) { + result = -1; + } else { + wchar_t actual[2]; + memset(&actual, 0, sizeof(actual)); + count = MultiByteToWideChar(CP_UTF8, + MB_ERR_INVALID_CHARS, + s, + try, + actual, + 2); + TR(TRACE_BITS, ("\twin32 ->%#x, %#x", actual[0], actual[1])); + *pwc = actual[0]; + if (actual[1] != 0) + result = -1; + else + result = try; + } + } else { + result = 0; + } + + return result; +} + +int +_nc_mblen(const char *s, size_t n) +{ + int result = -1; + int count; + wchar_t temp; + + if (s != 0 && n != 0) { + count = _nc_mbtowc(&temp, s, n); + if (count == 1) { + int check = WideCharToMultiByte(CP_UTF8, + 0, + &temp, + 1, + NULL, + 0, /* compute length only */ + NULL, + NULL); + TR(TRACE_BITS, ("\tcheck ->%d\n", check)); + if (check > 0 && (size_t) check <= n) { + result = check; + } + } + } else { + result = 0; + } + + return result; +} + +int __MINGW_NOTHROW +_nc_wctomb(char *s, wchar_t wc) +{ + int result; + int check; + + check = WideCharToMultiByte(CP_UTF8, + 0, + &wc, + 1, + NULL, + 0, /* compute length only */ + NULL, + NULL); + if (check > 0) { + result = WideCharToMultiByte(CP_UTF8, + 0, + &wc, + 1, + s, + check + 1, + NULL, + NULL); + } else { + result = -1; + } + return result; +} + +#endif /* _NC_WINDOWS */ + +#endif /* USE_WIDEC_SUPPORT */ diff --git a/lib/libcurses/wresize.3 b/lib/libcurses/wresize.3 index 8e6b09eefb9..252bc58e2aa 100644 --- a/lib/libcurses/wresize.3 +++ b/lib/libcurses/wresize.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: wresize.3,v 1.7 2010/01/12 23:21:59 nicm Exp $ +.\" $OpenBSD: wresize.3,v 1.8 2023/10/17 09:52:08 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2003,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -30,37 +31,37 @@ .\" .\" Author: Thomas E. Dickey 1996 .\" -.\" $Id: wresize.3,v 1.7 2010/01/12 23:21:59 nicm Exp $ -.TH wresize 3 "" +.\" $Id: wresize.3,v 1.8 2023/10/17 09:52:08 nicm Exp $ +.TH wresize 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBwresize\fR - resize a curses window +\fBwresize\fP \- resize a curses window .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .sp -\fBint wresize(WINDOW *win, int lines, int columns);\fR +\fBint wresize(WINDOW *\fIwin\fB, int \fIlines\fB, int \fIcolumns\fB);\fR .SH DESCRIPTION -The \fBwresize\fR function reallocates storage for an \fBncurses\fR +This is an extension to the curses library. +It reallocates storage for an \fBncurses\fP window to adjust its dimensions to the specified values. If either dimension is larger than the current values, the window's data is filled with blanks that have the current background rendition -(as set by \fBwbkgndset\fR) merged into them. +(as set by \fBwbkgdset\fP) merged into them. .SH RETURN VALUE -The function returns the integer \fBERR\fR upon failure and \fBOK\fR on success. +The function returns the integer \fBERR\fP upon failure and \fBOK\fP on success. It will fail if either of the dimensions less than or equal to zero, or if an error occurs while (re)allocating memory for the window. .SH NOTES The only restriction placed on the dimensions is that they be greater than zero. -The dimensions are not compared to \fBcurses\fR screen dimensions to -simplify the logic of \fBresizeterm\fR. +The dimensions are not compared to \fBcurses\fP screen dimensions to +simplify the logic of \fBresizeterm\fP. The caller must ensure that the window's dimensions fit within the actual screen dimensions. +.SH PORTABILITY +It is not possible to resize windows with SVr4 curses. +.PP +This extension of ncurses was introduced in mid-1995. +It was adopted in NetBSD curses (2001) and PDCurses (2003). .SH SEE ALSO -\fBresizeterm\fR(3). +\fBresizeterm\fP(3). .SH AUTHOR Thomas Dickey (from an equivalent function written in 1988 for BSD curses). -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: diff --git a/lib/libedit/shlib_version b/lib/libedit/shlib_version index 715ca914844..9c1551636c5 100644 --- a/lib/libedit/shlib_version +++ b/lib/libedit/shlib_version @@ -1,2 +1,2 @@ -major=5 -minor=2 +major=6 +minor=0 diff --git a/lib/libform/Makefile b/lib/libform/Makefile index b7d5e2146c0..c1f1821ee93 100644 --- a/lib/libform/Makefile +++ b/lib/libform/Makefile @@ -1,20 +1,23 @@ +# $OpenBSD: Makefile,v 1.17 2023/10/17 09:52:10 nicm Exp $ + LIB= form -SRCS= fld_arg.c fld_attr.c fld_current.c fld_def.c fld_dup.c fld_ftchoice.c \ - fld_ftlink.c fld_info.c fld_just.c fld_link.c fld_max.c fld_move.c \ - fld_newftyp.c fld_opts.c fld_pad.c fld_page.c fld_stat.c fld_type.c \ - fld_user.c frm_cursor.c frm_data.c frm_def.c \ +SRCS= fld_arg.c fld_attr.c fld_current.c fld_def.c fld_dup.c \ + fld_ftchoice.c fld_ftlink.c fld_info.c fld_just.c fld_link.c \ + fld_max.c fld_move.c fld_newftyp.c fld_opts.c fld_pad.c fld_page.c \ + fld_stat.c fld_type.c fld_user.c frm_cursor.c frm_data.c frm_def.c \ frm_driver.c frm_hook.c frm_opts.c frm_page.c frm_post.c \ - frm_req_name.c frm_scale.c frm_sub.c frm_user.c frm_win.c fty_alnum.c \ - fty_alpha.c fty_enum.c fty_int.c fty_ipv4.c fty_num.c fty_regex.c \ - f_trace.c + frm_req_name.c frm_scale.c frm_sub.c frm_user.c frm_win.c \ + fty_alnum.c fty_alpha.c fty_enum.c fty_generic.c fty_int.c \ + fty_ipv4.c fty_num.c fty_regex.c HDRS= form.h -CFLAGS+=-I${.CURDIR}/../libmenu -I${.CURDIR}/../libcurses +CFLAGS+=-I${.CURDIR}/../libcurses -I${.CURDIR}/../libmenu -D_XOPEN_SOURCE_EXTENDED -DNDEBUG MAN= form.3 form_cursor.3 form_data.3 form_driver.3 form_field.3 \ form_field_attributes.3 form_field_buffer.3 form_field_info.3 \ form_field_just.3 form_field_new.3 form_field_opts.3 \ form_field_userptr.3 form_field_validation.3 form_fieldtype.3 \ form_hook.3 form_new.3 form_new_page.3 form_opts.3 form_page.3 \ - form_post.3 form_requestname.3 form_userptr.3 form_win.3 + form_post.3 form_requestname.3 form_userptr.3 form_variables.3 \ + form_win.3 includes: @cd ${.CURDIR}; for i in ${HDRS}; do \ diff --git a/lib/libform/READ.ME b/lib/libform/READ.ME index a2d2bb1bb26..6d8a1dd5ff1 100644 --- a/lib/libform/READ.ME +++ b/lib/libform/READ.ME @@ -1,5 +1,6 @@ ------------------------------------------------------------------------------- --- Copyright (c) 1998-2003,2006 Free Software Foundation, Inc. -- +-- Copyright 2020,2021 Thomas E. Dickey -- +-- Copyright 1998-2003,2006 Free Software Foundation, Inc. -- -- -- -- Permission is hereby granted, free of charge, to any person obtaining a -- -- copy of this software and associated documentation files (the -- @@ -25,18 +26,18 @@ -- sale, use or other dealings in this Software without prior written -- -- authorization. -- ------------------------------------------------------------------------------- --- $Id: READ.ME,v 1.3 2010/01/12 23:22:07 nicm Exp $ +-- $Id: READ.ME,v 1.4 2023/10/17 09:52:10 nicm Exp $ ------------------------------------------------------------------------------- This is a clone of the form library that is available with typical System V curses implementations (ETI). It is modelled after the documentation that comes for this library with -a 386 based SVR4 implementation (ESIX). +a 386 based SVR4 implementation (ESIX). The development environment was and is an ELF based Linux system. -For things that still need doing, see the TO-DO file in the top-level +For things that still need doing, see the TO-DO file in the top-level directory. Juergen Pfeifer diff --git a/lib/libform/fld_arg.c b/lib/libform/fld_arg.c index 9124c88a3b8..515455f52bf 100644 --- a/lib/libform/fld_arg.c +++ b/lib/libform/fld_arg.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fld_arg.c,v 1.6 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fld_arg.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2018,2020 Thomas E. Dickey * + * Copyright 1998-2012,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,7 +34,7 @@ #include "form.priv.h" -MODULE_ID("$Id: fld_arg.c,v 1.6 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fld_arg.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- | Facility : libnform @@ -61,18 +62,23 @@ MODULE_ID("$Id: fld_arg.c,v 1.6 2015/01/23 22:48:51 krw Exp $") | Return Values : E_OK - success | E_BAD_ARGUMENT - invalid argument +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) set_fieldtype_arg(FIELDTYPE *typ, void *(*const make_arg)(va_list *), void *(*const copy_arg)(const void *), void (*const free_arg) (void *)) { - T((T_CALLED("set_fieldtype_arg(%p,%p,%p,%p)"), - typ, make_arg, copy_arg, free_arg)); + TR_FUNC_BFR(3); + + T((T_CALLED("set_fieldtype_arg(%p,%s,%s,%s)"), + (void *)typ, + TR_FUNC_ARG(0, make_arg), + TR_FUNC_ARG(1, copy_arg), + TR_FUNC_ARG(2, free_arg))); if (typ != 0 && make_arg != (void *)0) { - typ->status |= _HAS_ARGS; + SetStatus(typ, _HAS_ARGS); typ->makearg = make_arg; typ->copyarg = copy_arg; typ->freearg = free_arg; @@ -85,14 +91,14 @@ set_fieldtype_arg(FIELDTYPE *typ, | Facility : libnform | Function : void *field_arg(const FIELD *field) | -| Description : Retrieve pointer to the fields argument structure. +| Description : Retrieve pointer to the field's argument structure. | | Return Values : Pointer to structure or NULL if none is defined. +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(void *) +FORM_EXPORT(void *) field_arg(const FIELD *field) { - T((T_CALLED("field_arg(%p)"), field)); + T((T_CALLED("field_arg(%p)"), (const void *)field)); returnVoidPtr(Normalize_Field(field)->arg); } diff --git a/lib/libform/fld_attr.c b/lib/libform/fld_attr.c index e369734c6a6..8cf5575af5d 100644 --- a/lib/libform/fld_attr.c +++ b/lib/libform/fld_attr.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fld_attr.c,v 1.6 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fld_attr.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2010,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,17 +34,17 @@ #include "form.priv.h" -MODULE_ID("$Id: fld_attr.c,v 1.6 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fld_attr.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") /*---------------------------------------------------------------------------- Field-Attribute manipulation routines --------------------------------------------------------------------------*/ -/* "Template" macro to generate a function to set a fields attribute */ +/* "Template" macro to generate a function to set a field's attribute */ #define GEN_FIELD_ATTR_SET_FCT( name ) \ -NCURSES_IMPEXP int NCURSES_API set_field_ ## name (FIELD * field, chtype attr)\ +FORM_IMPEXP int NCURSES_API set_field_ ## name (FIELD * field, chtype attr)\ {\ int res = E_BAD_ARGUMENT;\ - T((T_CALLED("set_field_" #name "(%p,%s)"), field, _traceattr(attr)));\ + T((T_CALLED("set_field_" #name "(%p,%s)"), (void *)field, _traceattr(attr)));\ if ( attr==A_NORMAL || ((attr & A_ATTRIBUTES)==attr) )\ {\ Normalize_Field( field );\ @@ -63,11 +64,11 @@ NCURSES_IMPEXP int NCURSES_API set_field_ ## name (FIELD * field, chtype attr)\ RETURN(res);\ } -/* "Template" macro to generate a function to get a fields attribute */ +/* "Template" macro to generate a function to get a field's attribute */ #define GEN_FIELD_ATTR_GET_FCT( name ) \ -NCURSES_IMPEXP chtype NCURSES_API field_ ## name (const FIELD * field)\ +FORM_IMPEXP chtype NCURSES_API field_ ## name (const FIELD * field)\ {\ - T((T_CALLED("field_" #name "(%p)"), field));\ + T((T_CALLED("field_" #name "(%p)"), (const void *) field));\ returnAttr( A_ATTRIBUTES & (Normalize_Field( field ) -> name) );\ } @@ -88,7 +89,7 @@ GEN_FIELD_ATTR_SET_FCT(fore) | Facility : libnform | Function : chtype field_fore(const FIELD *) | -| Description : Retrieve fields foreground attribute +| Description : Retrieve field's foreground attribute | | Return Values : The foreground attribute +--------------------------------------------------------------------------*/ @@ -99,7 +100,7 @@ GEN_FIELD_ATTR_GET_FCT(fore) | Function : int set_field_back(FIELD *field, chtype attr) | | Description : Sets the background of the field used to display the -| fields extend. +| field's extend. | | Return Values : E_OK - success | E_BAD_ARGUMENT - invalid attributes @@ -111,7 +112,7 @@ GEN_FIELD_ATTR_SET_FCT(back) | Facility : libnform | Function : chtype field_back(const | -| Description : Retrieve fields background attribute +| Description : Retrieve field's background attribute | | Return Values : The background attribute +--------------------------------------------------------------------------*/ diff --git a/lib/libform/fld_current.c b/lib/libform/fld_current.c index 0b2e973eaa8..5c283017d4f 100644 --- a/lib/libform/fld_current.c +++ b/lib/libform/fld_current.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fld_current.c,v 1.6 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fld_current.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2010,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,7 +34,7 @@ #include "form.priv.h" -MODULE_ID("$Id: fld_current.c,v 1.6 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fld_current.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- | Facility : libnform @@ -48,12 +49,12 @@ MODULE_ID("$Id: fld_current.c,v 1.6 2015/01/23 22:48:51 krw Exp $") | E_INVALID_FIELD - current field can't be left | E_SYSTEM_ERROR - system error +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) set_current_field(FORM *form, FIELD *field) { int err = E_OK; - T((T_CALLED("set_current_field(%p,%p)"), form, field)); + T((T_CALLED("set_current_field(%p,%p)"), (void *)form, (void *)field)); if (form == 0 || field == 0) { RETURN(E_BAD_ARGUMENT); @@ -77,7 +78,7 @@ set_current_field(FORM *form, FIELD *field) { if (form->current != field) { - if (!_nc_Internal_Validation(form)) + if (form->current && !_nc_Internal_Validation(form)) { err = E_INVALID_FIELD; } @@ -103,6 +104,32 @@ set_current_field(FORM *form, FIELD *field) RETURN(err); } +/*--------------------------------------------------------------------------- +| Facility : libnform +| Function : int unfocus_current_field(FORM * form) +| +| Description : Removes focus from the current field. +| +| Return Values : E_OK - success +| E_BAD_ARGUMENT - invalid form pointer +| E_REQUEST_DENIED - there is no current field to unfocus ++--------------------------------------------------------------------------*/ +FORM_EXPORT(int) +unfocus_current_field(FORM *const form) +{ + T((T_CALLED("unfocus_current_field(%p)"), (const void *)form)); + if (form == 0) + { + RETURN(E_BAD_ARGUMENT); + } + else if (form->current == 0) + { + RETURN(E_REQUEST_DENIED); + } + _nc_Unset_Current_Field(form); + RETURN(E_OK); +} + /*--------------------------------------------------------------------------- | Facility : libnform | Function : FIELD *current_field(const FORM * form) @@ -111,10 +138,10 @@ set_current_field(FORM *form, FIELD *field) | | Return Values : Pointer to the current field. +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(FIELD *) +FORM_EXPORT(FIELD *) current_field(const FORM *form) { - T((T_CALLED("current_field(%p)"), form)); + T((T_CALLED("current_field(%p)"), (const void *)form)); returnField(Normalize_Form(form)->current); } @@ -128,10 +155,10 @@ current_field(const FORM *form) | Return Values : >= 0 : field index | -1 : fieldpointer invalid or field not connected +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) field_index(const FIELD *field) { - T((T_CALLED("field_index(%p)"), field)); + T((T_CALLED("field_index(%p)"), (const void *)field)); returnCode((field != 0 && field->form != 0) ? (int)field->index : -1); } diff --git a/lib/libform/fld_def.c b/lib/libform/fld_def.c index 54674a927be..0a5bc6d5db7 100644 --- a/lib/libform/fld_def.c +++ b/lib/libform/fld_def.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fld_def.c,v 1.9 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fld_def.c,v 1.10 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2007 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2012,2014 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,7 +34,7 @@ #include "form.priv.h" -MODULE_ID("$Id: fld_def.c,v 1.9 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fld_def.c,v 1.10 2023/10/17 09:52:10 nicm Exp $") /* this can't be readonly */ static FIELD default_field = @@ -54,7 +55,7 @@ static FIELD default_field = (int)' ', /* pad */ A_NORMAL, /* fore */ A_NORMAL, /* back */ - ALL_FIELD_OPTS, /* opts */ + STD_FIELD_OPTS, /* opts */ (FIELD *)0, /* snext */ (FIELD *)0, /* sprev */ (FIELD *)0, /* link */ @@ -66,8 +67,7 @@ static FIELD default_field = NCURSES_FIELD_EXTENSION }; -NCURSES_EXPORT_VAR(FIELD *) -_nc_Default_Field = &default_field; +FORM_EXPORT_VAR(FIELD *) _nc_Default_Field = &default_field; /*--------------------------------------------------------------------------- | Facility : libnform @@ -83,18 +83,17 @@ _nc_Default_Field = &default_field; | Return Values : Pointer to argument structure. Maybe NULL. | In case of an error in *err an error counter is increased. +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(TypeArgument *) +FORM_EXPORT(TypeArgument *) _nc_Make_Argument(const FIELDTYPE *typ, va_list *ap, int *err) { TypeArgument *res = (TypeArgument *)0; - TypeArgument *p; if (typ != 0 && (typ->status & _HAS_ARGS) != 0) { assert(err != 0 && ap != (va_list *)0); if ((typ->status & _LINKED_TYPE) != 0) { - p = typeMalloc(TypeArgument, 1); + TypeArgument *p = typeMalloc(TypeArgument, 1); if (p != 0) { @@ -131,18 +130,17 @@ _nc_Make_Argument(const FIELDTYPE *typ, va_list *ap, int *err) | Return Values : Pointer to argument structure. Maybe NULL. | In case of an error in *err an error counter is increased. +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(TypeArgument *) +FORM_EXPORT(TypeArgument *) _nc_Copy_Argument(const FIELDTYPE *typ, const TypeArgument *argp, int *err) { TypeArgument *res = (TypeArgument *)0; - TypeArgument *p; if (typ != 0 && (typ->status & _HAS_ARGS) != 0) { assert(err != 0 && argp != 0); if ((typ->status & _LINKED_TYPE) != 0) { - p = typeMalloc(TypeArgument, 1); + TypeArgument *p = typeMalloc(TypeArgument, 1); if (p != 0) { @@ -180,17 +178,19 @@ _nc_Copy_Argument(const FIELDTYPE *typ, const TypeArgument *argp, int *err) | | Return Values : - +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(void) +FORM_EXPORT(void) _nc_Free_Argument(const FIELDTYPE *typ, TypeArgument *argp) { if (typ != 0 && (typ->status & _HAS_ARGS) != 0) { if ((typ->status & _LINKED_TYPE) != 0) { - assert(argp != 0); - _nc_Free_Argument(typ->left, argp->left); - _nc_Free_Argument(typ->right, argp->right); - free(argp); + if (argp != 0) + { + _nc_Free_Argument(typ->left, argp->left); + _nc_Free_Argument(typ->right, argp->right); + free(argp); + } } else { @@ -211,7 +211,7 @@ _nc_Free_Argument(const FIELDTYPE *typ, TypeArgument *argp) | Return Values : TRUE - copy worked | FALSE - error occurred +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(bool) +FORM_EXPORT(bool) _nc_Copy_Type(FIELD *dst, FIELD const *src) { int err = 0; @@ -246,15 +246,15 @@ _nc_Copy_Type(FIELD *dst, FIELD const *src) | | Return Values : - +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(void) +FORM_EXPORT(void) _nc_Free_Type(FIELD *field) { assert(field != 0); if (field->type != 0) { field->type->ref--; + _nc_Free_Argument(field->type, (TypeArgument *)(field->arg)); } - _nc_Free_Argument(field->type, (TypeArgument *)(field->arg)); } /*--------------------------------------------------------------------------- @@ -273,7 +273,7 @@ _nc_Free_Type(FIELD *field) | | Return Values : Pointer to the new field or NULL if failure. +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(FIELD *) +FORM_EXPORT(FIELD *) new_field(int rows, int cols, int frow, int fcol, int nrow, int nbuf) { static const FIELD_CELL blank = BLANK; @@ -292,16 +292,16 @@ new_field(int rows, int cols, int frow, int fcol, int nrow, int nbuf) ((err = E_SYSTEM_ERROR) != 0) && /* trick: this resets the default error */ (New_Field = typeMalloc(FIELD, 1)) != 0) { - T((T_CREATE("field %p"), New_Field)); + T((T_CREATE("field %p"), (void *)New_Field)); *New_Field = default_field; - New_Field->rows = rows; - New_Field->cols = cols; + New_Field->rows = (short)rows; + New_Field->cols = (short)cols; New_Field->drows = rows + nrow; New_Field->dcols = cols; - New_Field->frow = frow; - New_Field->fcol = fcol; + New_Field->frow = (short)frow; + New_Field->fcol = (short)fcol; New_Field->nrow = nrow; - New_Field->nbuf = nbuf; + New_Field->nbuf = (short)nbuf; New_Field->link = New_Field; #if USE_WIDEC_SUPPORT @@ -353,10 +353,10 @@ new_field(int rows, int cols, int frow, int fcol, int nrow, int nbuf) | E_BAD_ARGUMENT - invalid field pointer | E_CONNECTED - field is connected +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) free_field(FIELD *field) { - T((T_CALLED("free_field(%p)"), field)); + T((T_CALLED("free_field(%p)"), (void *)field)); if (!field) { RETURN(E_BAD_ARGUMENT); diff --git a/lib/libform/fld_dup.c b/lib/libform/fld_dup.c index 41288344459..4295e72390e 100644 --- a/lib/libform/fld_dup.c +++ b/lib/libform/fld_dup.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fld_dup.c,v 1.6 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fld_dup.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2004,2007 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,7 +34,7 @@ #include "form.priv.h" -MODULE_ID("$Id: fld_dup.c,v 1.6 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fld_dup.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- | Facility : libnform @@ -48,21 +49,21 @@ MODULE_ID("$Id: fld_dup.c,v 1.6 2015/01/23 22:48:51 krw Exp $") | | Return Values : Pointer to the new field or NULL if failure +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(FIELD *) +FORM_EXPORT(FIELD *) dup_field(FIELD *field, int frow, int fcol) { FIELD *New_Field = (FIELD *)0; int err = E_BAD_ARGUMENT; - T((T_CALLED("dup_field(%p,%d,%d)"), field, frow, fcol)); + T((T_CALLED("dup_field(%p,%d,%d)"), (void *)field, frow, fcol)); if (field && (frow >= 0) && (fcol >= 0) && ((err = E_SYSTEM_ERROR) != 0) && /* trick : this resets the default error */ (New_Field = typeMalloc(FIELD, 1))) { - T((T_CREATE("field %p"), New_Field)); + T((T_CREATE("field %p"), (void *)New_Field)); *New_Field = *_nc_Default_Field; - New_Field->frow = frow; - New_Field->fcol = fcol; + New_Field->frow = (short)frow; + New_Field->fcol = (short)fcol; New_Field->link = New_Field; New_Field->rows = field->rows; New_Field->cols = field->cols; @@ -80,13 +81,12 @@ dup_field(FIELD *field, int frow, int fcol) if (_nc_Copy_Type(New_Field, field)) { - size_t i, len; + size_t len; len = Total_Buffer_Size(New_Field); - if ((New_Field->buf = (FIELD_CELL *)malloc(len))) + if ((New_Field->buf = (FIELD_CELL *)malloc(len * 20))) { - for (i = 0; i < len; ++i) - New_Field->buf[i] = field->buf[i]; + memcpy(New_Field->buf, field->buf, len); returnField(New_Field); } } diff --git a/lib/libform/fld_ftchoice.c b/lib/libform/fld_ftchoice.c index d67a2a036e5..db1634a3f65 100644 --- a/lib/libform/fld_ftchoice.c +++ b/lib/libform/fld_ftchoice.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fld_ftchoice.c,v 1.6 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fld_ftchoice.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2018-2020,2021 Thomas E. Dickey * + * Copyright 1998-2012,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,10 +34,10 @@ #include "form.priv.h" -MODULE_ID("$Id: fld_ftchoice.c,v 1.6 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fld_ftchoice.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int set_fieldtype_choice( | FIELDTYPE *typ, | bool (* const next_choice)(FIELD *,const void *), @@ -47,19 +48,29 @@ MODULE_ID("$Id: fld_ftchoice.c,v 1.6 2015/01/23 22:48:51 krw Exp $") | Return Values : E_OK - success | E_BAD_ARGUMENT - invalid arguments +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) set_fieldtype_choice(FIELDTYPE *typ, bool (*const next_choice) (FIELD *, const void *), bool (*const prev_choice) (FIELD *, const void *)) { - T((T_CALLED("set_fieldtype_choice(%p,%p,%p)"), typ, next_choice, prev_choice)); + TR_FUNC_BFR(2); + + T((T_CALLED("set_fieldtype_choice(%p,%s,%s)"), + (void *)typ, + TR_FUNC_ARG(0, next_choice), + TR_FUNC_ARG(1, prev_choice))); if (!typ || !next_choice || !prev_choice) RETURN(E_BAD_ARGUMENT); - typ->status |= _HAS_CHOICE; + SetStatus(typ, _HAS_CHOICE); +#if NCURSES_INTEROP_FUNCS + typ->enum_next.onext = next_choice; + typ->enum_prev.oprev = prev_choice; +#else typ->next = next_choice; typ->prev = prev_choice; +#endif RETURN(E_OK); } diff --git a/lib/libform/fld_ftlink.c b/lib/libform/fld_ftlink.c index f149c4cfa18..ca44010311e 100644 --- a/lib/libform/fld_ftlink.c +++ b/lib/libform/fld_ftlink.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fld_ftlink.c,v 1.6 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fld_ftlink.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2004,2007 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,41 +34,41 @@ #include "form.priv.h" -MODULE_ID("$Id: fld_ftlink.c,v 1.6 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fld_ftlink.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : FIELDTYPE *link_fieldtype( | FIELDTYPE *type1, | FIELDTYPE *type2) -| +| | Description : Create a new fieldtype built from the two given types. | They are connected by an logical 'OR'. -| If an error occurs, errno is set to +| If an error occurs, errno is set to | E_BAD_ARGUMENT - invalid arguments | E_SYSTEM_ERROR - system error (no memory) | | Return Values : Fieldtype pointer or NULL if error occurred. +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(FIELDTYPE *) +FORM_EXPORT(FIELDTYPE *) link_fieldtype(FIELDTYPE *type1, FIELDTYPE *type2) { FIELDTYPE *nftyp = (FIELDTYPE *)0; - T((T_CALLED("link_fieldtype(%p,%p)"), type1, type2)); + T((T_CALLED("link_fieldtype(%p,%p)"), (void *)type1, (void *)type2)); if (type1 && type2) { nftyp = typeMalloc(FIELDTYPE, 1); if (nftyp) { - T((T_CREATE("fieldtype %p"), nftyp)); + T((T_CREATE("fieldtype %p"), (void *)nftyp)); *nftyp = *_nc_Default_FieldType; - nftyp->status |= _LINKED_TYPE; + SetStatus(nftyp, _LINKED_TYPE); if ((type1->status & _HAS_ARGS) || (type2->status & _HAS_ARGS)) - nftyp->status |= _HAS_ARGS; + SetStatus(nftyp, _HAS_ARGS); if ((type1->status & _HAS_CHOICE) || (type2->status & _HAS_CHOICE)) - nftyp->status |= _HAS_CHOICE; + SetStatus(nftyp, _HAS_CHOICE); nftyp->left = type1; nftyp->right = type2; type1->ref++; diff --git a/lib/libform/fld_info.c b/lib/libform/fld_info.c index 9a732302ea1..4187b7de6fd 100644 --- a/lib/libform/fld_info.c +++ b/lib/libform/fld_info.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fld_info.c,v 1.6 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fld_info.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2004,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,31 +34,31 @@ #include "form.priv.h" -MODULE_ID("$Id: fld_info.c,v 1.6 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fld_info.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int field_info(const FIELD *field, | int *rows, int *cols, | int *frow, int *fcol, | int *nrow, int *nbuf) -| -| Description : Retrieve infos about the fields creation parameters. +| +| Description : Retrieve information about the field's creation parameters. | | Return Values : E_OK - success | E_BAD_ARGUMENT - invalid field pointer +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) field_info(const FIELD *field, int *rows, int *cols, int *frow, int *fcol, int *nrow, int *nbuf) { T((T_CALLED("field_info(%p,%p,%p,%p,%p,%p,%p)"), - field, - rows, cols, - frow, fcol, - nrow, nbuf)); + (const void *)field, + (void *)rows, (void *)cols, + (void *)frow, (void *)fcol, + (void *)nrow, (void *)nbuf)); if (!field) RETURN(E_BAD_ARGUMENT); @@ -78,21 +79,25 @@ field_info(const FIELD *field, } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int dynamic_field_info(const FIELD *field, | int *drows, int *dcols, | int *maxgrow) -| -| Description : Retrieve informations about a dynamic fields current +| +| Description : Retrieve information about a dynamic field's current | dynamic parameters. | | Return Values : E_OK - success | E_BAD_ARGUMENT - invalid argument +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) dynamic_field_info(const FIELD *field, int *drows, int *dcols, int *maxgrow) { - T((T_CALLED("dynamic_field_info(%p,%p,%p,%p)"), field, drows, dcols, maxgrow)); + T((T_CALLED("dynamic_field_info(%p,%p,%p,%p)"), + (const void *)field, + (void *)drows, + (void *)dcols, + (void *)maxgrow)); if (!field) RETURN(E_BAD_ARGUMENT); diff --git a/lib/libform/fld_just.c b/lib/libform/fld_just.c index eeb6fc6a55d..79b87ef7eb4 100644 --- a/lib/libform/fld_just.c +++ b/lib/libform/fld_just.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fld_just.c,v 1.6 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fld_just.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,24 +34,24 @@ #include "form.priv.h" -MODULE_ID("$Id: fld_just.c,v 1.6 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fld_just.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int set_field_just(FIELD *field, int just) -| -| Description : Set the fields type of justification. +| +| Description : Set the field's type of justification. | | Return Values : E_OK - success | E_BAD_ARGUMENT - one of the arguments was incorrect | E_SYSTEM_ERROR - system error +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) set_field_just(FIELD *field, int just) { int res = E_BAD_ARGUMENT; - T((T_CALLED("set_field_just(%p,%d)"), field, just)); + T((T_CALLED("set_field_just(%p,%d)"), (void *)field, just)); if ((just == NO_JUSTIFICATION) || (just == JUSTIFY_LEFT) || @@ -60,7 +61,7 @@ set_field_just(FIELD *field, int just) Normalize_Field(field); if (field->just != just) { - field->just = just; + field->just = (short)just; res = _nc_Synchronize_Attributes(field); } else @@ -70,17 +71,17 @@ set_field_just(FIELD *field, int just) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int field_just( const FIELD *field ) -| -| Description : Retrieve the fields type of justification +| +| Description : Retrieve the field's type of justification | | Return Values : The justification type. +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) field_just(const FIELD *field) { - T((T_CALLED("field_just(%p)"), field)); + T((T_CALLED("field_just(%p)"), (const void *)field)); returnCode(Normalize_Field(field)->just); } diff --git a/lib/libform/fld_link.c b/lib/libform/fld_link.c index edf34899d3d..668401c4ad3 100644 --- a/lib/libform/fld_link.c +++ b/lib/libform/fld_link.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fld_link.c,v 1.6 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fld_link.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2004,2007 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,37 +34,37 @@ #include "form.priv.h" -MODULE_ID("$Id: fld_link.c,v 1.6 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fld_link.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform -| Function : FIELD *link_field(FIELD *field, int frow, int fcol) -| +| Facility : libnform +| Function : FIELD *link_field(FIELD *field, int frow, int fcol) +| | Description : Duplicates the field at the specified position. The | new field shares its buffers with the original one, | the attributes are independent. | If an error occurs, errno is set to -| +| | E_BAD_ARGUMENT - invalid argument | E_SYSTEM_ERROR - system error | | Return Values : Pointer to the new field or NULL if failure +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(FIELD *) +FORM_EXPORT(FIELD *) link_field(FIELD *field, int frow, int fcol) { FIELD *New_Field = (FIELD *)0; int err = E_BAD_ARGUMENT; - T((T_CALLED("link_field(%p,%d,%d)"), field, frow, fcol)); + T((T_CALLED("link_field(%p,%d,%d)"), (void *)field, frow, fcol)); if (field && (frow >= 0) && (fcol >= 0) && ((err = E_SYSTEM_ERROR) != 0) && /* trick: this resets the default error */ (New_Field = typeMalloc(FIELD, 1))) { - T((T_CREATE("field %p"), New_Field)); + T((T_CREATE("field %p"), (void *)New_Field)); *New_Field = *_nc_Default_Field; - New_Field->frow = frow; - New_Field->fcol = fcol; + New_Field->frow = (short)frow; + New_Field->fcol = (short)fcol; New_Field->link = field->link; field->link = New_Field; diff --git a/lib/libform/fld_max.c b/lib/libform/fld_max.c index b40e631de73..0a71babaf78 100644 --- a/lib/libform/fld_max.c +++ b/lib/libform/fld_max.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fld_max.c,v 1.6 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fld_max.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2019-2020,2021 Thomas E. Dickey * + * Copyright 1998-2012,2013 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,22 +34,22 @@ #include "form.priv.h" -MODULE_ID("$Id: fld_max.c,v 1.6 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fld_max.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int set_max_field(FIELD *field, int maxgrow) -| +| | Description : Set the maximum growth for a dynamic field. If maxgrow=0 | the field may grow to any possible size. | | Return Values : E_OK - success | E_BAD_ARGUMENT - invalid argument +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) set_max_field(FIELD *field, int maxgrow) { - T((T_CALLED("set_max_field(%p,%d)"), field, maxgrow)); + T((T_CALLED("set_max_field(%p,%d)"), (void *)field, maxgrow)); if (!field || (maxgrow < 0)) RETURN(E_BAD_ARGUMENT); @@ -58,18 +59,23 @@ set_max_field(FIELD *field, int maxgrow) if (maxgrow > 0) { - if ((single_line_field && (maxgrow < field->dcols)) || - (!single_line_field && (maxgrow < field->drows))) + if (((single_line_field && (maxgrow < field->dcols)) || + (!single_line_field && (maxgrow < field->drows))) && + !Field_Has_Option(field, O_INPUT_LIMIT)) RETURN(E_BAD_ARGUMENT); } field->maxgrow = maxgrow; - field->status &= ~_MAY_GROW; - if (!(field->opts & O_STATIC)) + /* shrink */ + if (maxgrow > 0 && Field_Has_Option(field, O_INPUT_LIMIT) && + field->dcols > maxgrow) + field->dcols = maxgrow; + ClrStatus(field, _MAY_GROW); + if (!((unsigned)field->opts & O_STATIC)) { if ((maxgrow == 0) || (single_line_field && (field->dcols < maxgrow)) || (!single_line_field && (field->drows < maxgrow))) - field->status |= _MAY_GROW; + SetStatus(field, _MAY_GROW); } } RETURN(E_OK); diff --git a/lib/libform/fld_move.c b/lib/libform/fld_move.c index 2871bd984a6..add1d7acb37 100644 --- a/lib/libform/fld_move.c +++ b/lib/libform/fld_move.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fld_move.c,v 1.6 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fld_move.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,23 +34,23 @@ #include "form.priv.h" -MODULE_ID("$Id: fld_move.c,v 1.6 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fld_move.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int move_field(FIELD *field,int frow, int fcol) -| +| | Description : Moves the disconnected field to the new location in -| the forms subwindow. +| the form's subwindow. | | Return Values : E_OK - success | E_BAD_ARGUMENT - invalid argument passed | E_CONNECTED - field is connected +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) move_field(FIELD *field, int frow, int fcol) { - T((T_CALLED("move_field(%p,%d,%d)"), field, frow, fcol)); + T((T_CALLED("move_field(%p,%d,%d)"), (void *)field, frow, fcol)); if (!field || (frow < 0) || (fcol < 0)) RETURN(E_BAD_ARGUMENT); @@ -57,8 +58,8 @@ move_field(FIELD *field, int frow, int fcol) if (field->form) RETURN(E_CONNECTED); - field->frow = frow; - field->fcol = fcol; + field->frow = (short)frow; + field->fcol = (short)fcol; RETURN(E_OK); } diff --git a/lib/libform/fld_newftyp.c b/lib/libform/fld_newftyp.c index 748a8882203..885b2aa8805 100644 --- a/lib/libform/fld_newftyp.c +++ b/lib/libform/fld_newftyp.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fld_newftyp.c,v 1.7 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fld_newftyp.c,v 1.8 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2004,2007 Free Software Foundation, Inc. * + * Copyright 2018,2020 Thomas E. Dickey * + * Copyright 1998-2010,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,9 +34,9 @@ #include "form.priv.h" -MODULE_ID("$Id: fld_newftyp.c,v 1.7 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fld_newftyp.c,v 1.8 2023/10/17 09:52:10 nicm Exp $") -static FIELDTYPE const default_fieldtype = +static FIELDTYPE default_fieldtype = { 0, /* status */ 0L, /* reference count */ @@ -44,14 +45,17 @@ static FIELDTYPE const default_fieldtype = NULL, /* makearg function */ NULL, /* copyarg function */ NULL, /* freearg function */ - NULL, /* field validation function */ - NULL, /* Character check function */ - NULL, /* enumerate next function */ - NULL /* enumerate previous function */ + INIT_FT_FUNC(NULL), /* field validation function */ + INIT_FT_FUNC(NULL), /* Character check function */ + INIT_FT_FUNC(NULL), /* enumerate next function */ + INIT_FT_FUNC(NULL), /* enumerate previous function */ +#if NCURSES_INTEROP_FUNCS + NULL /* generic callback alternative to makearg */ +#endif }; -NCURSES_EXPORT_VAR(const FIELDTYPE *) -_nc_Default_FieldType = &default_fieldtype; +FORM_EXPORT_VAR(FIELDTYPE *) + _nc_Default_FieldType = &default_fieldtype; /*--------------------------------------------------------------------------- | Facility : libnform @@ -68,23 +72,33 @@ _nc_Default_FieldType = &default_fieldtype; | | Return Values : Fieldtype pointer or NULL if error occurred +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(FIELDTYPE *) +FORM_EXPORT(FIELDTYPE *) new_fieldtype(bool (*const field_check) (FIELD *, const void *), bool (*const char_check) (int, const void *)) { FIELDTYPE *nftyp = (FIELDTYPE *)0; - T((T_CALLED("new_fieldtype(%p,%p)"), field_check, char_check)); + TR_FUNC_BFR(2); + + T((T_CALLED("new_fieldtype(%s,%s)"), + TR_FUNC_ARG(0, field_check), + TR_FUNC_ARG(1, char_check))); + if ((field_check) || (char_check)) { nftyp = typeMalloc(FIELDTYPE, 1); if (nftyp) { - T((T_CREATE("fieldtype %p"), nftyp)); + T((T_CREATE("fieldtype %p"), (void *)nftyp)); *nftyp = default_fieldtype; +#if NCURSES_INTEROP_FUNCS + nftyp->fieldcheck.ofcheck = field_check; + nftyp->charcheck.occheck = char_check; +#else nftyp->fcheck = field_check; nftyp->ccheck = char_check; +#endif } else { @@ -108,10 +122,10 @@ new_fieldtype(bool (*const field_check) (FIELD *, const void *), | E_CONNECTED - there are fields referencing the type | E_BAD_ARGUMENT - invalid fieldtype pointer +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) free_fieldtype(FIELDTYPE *typ) { - T((T_CALLED("free_fieldtype(%p)"), typ)); + T((T_CALLED("free_fieldtype(%p)"), (void *)typ)); if (!typ) RETURN(E_BAD_ARGUMENT); diff --git a/lib/libform/fld_opts.c b/lib/libform/fld_opts.c index c6349baeaaf..d6ad0eece92 100644 --- a/lib/libform/fld_opts.c +++ b/lib/libform/fld_opts.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fld_opts.c,v 1.7 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fld_opts.c,v 1.8 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2004,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,16 +34,16 @@ #include "form.priv.h" -MODULE_ID("$Id: fld_opts.c,v 1.7 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fld_opts.c,v 1.8 2023/10/17 09:52:10 nicm Exp $") /*---------------------------------------------------------------------------- Field-Options manipulation routines --------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int set_field_opts(FIELD *field, Field_Options opts) -| +| | Description : Turns on the named options for this field and turns | off all the remaining options. | @@ -51,12 +52,12 @@ MODULE_ID("$Id: fld_opts.c,v 1.7 2015/01/23 22:48:51 krw Exp $") | E_BAD_ARGUMENT - invalid options | E_SYSTEM_ERROR - system error +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) set_field_opts(FIELD *field, Field_Options opts) { int res = E_BAD_ARGUMENT; - T((T_CALLED("set_field_opts(%p,%d)"), field, opts)); + T((T_CALLED("set_field_opts(%p,%d)"), (void *)field, opts)); opts &= ALL_FIELD_OPTS; if (!(opts & ~ALL_FIELD_OPTS)) @@ -65,26 +66,26 @@ set_field_opts(FIELD *field, Field_Options opts) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : Field_Options field_opts(const FIELD *field) -| -| Description : Retrieve the fields options. +| +| Description : Retrieve the field's options. | | Return Values : The options. +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(Field_Options) +FORM_EXPORT(Field_Options) field_opts(const FIELD *field) { - T((T_CALLED("field_opts(%p)"), field)); + T((T_CALLED("field_opts(%p)"), (const void *)field)); returnCode(ALL_FIELD_OPTS & Normalize_Field(field)->opts); } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int field_opts_on(FIELD *field, Field_Options opts) -| -| Description : Turns on the named options for this field and all the +| +| Description : Turns on the named options for this field and all the | remaining options are unchanged. | | Return Values : E_OK - success @@ -92,12 +93,12 @@ field_opts(const FIELD *field) | E_BAD_ARGUMENT - invalid options | E_SYSTEM_ERROR - system error +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) field_opts_on(FIELD *field, Field_Options opts) { int res = E_BAD_ARGUMENT; - T((T_CALLED("field_opts_on(%p,%d)"), field, opts)); + T((T_CALLED("field_opts_on(%p,%d)"), (void *)field, opts)); opts &= ALL_FIELD_OPTS; if (!(opts & ~ALL_FIELD_OPTS)) @@ -109,10 +110,10 @@ field_opts_on(FIELD *field, Field_Options opts) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int field_opts_off(FIELD *field, Field_Options opts) -| -| Description : Turns off the named options for this field and all the +| +| Description : Turns off the named options for this field and all the | remaining options are unchanged. | | Return Values : E_OK - success @@ -120,12 +121,12 @@ field_opts_on(FIELD *field, Field_Options opts) | E_BAD_ARGUMENT - invalid options | E_SYSTEM_ERROR - system error +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) field_opts_off(FIELD *field, Field_Options opts) { int res = E_BAD_ARGUMENT; - T((T_CALLED("field_opts_off(%p,%d)"), field, opts)); + T((T_CALLED("field_opts_off(%p,%d)"), (void *)field, opts)); opts &= ALL_FIELD_OPTS; if (!(opts & ~ALL_FIELD_OPTS)) diff --git a/lib/libform/fld_pad.c b/lib/libform/fld_pad.c index 5c8124597b8..130b39c902c 100644 --- a/lib/libform/fld_pad.c +++ b/lib/libform/fld_pad.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fld_pad.c,v 1.6 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fld_pad.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2004,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,12 +34,12 @@ #include "form.priv.h" -MODULE_ID("$Id: fld_pad.c,v 1.6 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fld_pad.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int set_field_pad(FIELD *field, int ch) -| +| | Description : Set the pad character used to fill the field. This must | be a printable character. | @@ -46,12 +47,12 @@ MODULE_ID("$Id: fld_pad.c,v 1.6 2015/01/23 22:48:51 krw Exp $") | E_BAD_ARGUMENT - invalid field pointer or pad character | E_SYSTEM_ERROR - system error +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) set_field_pad(FIELD *field, int ch) { int res = E_BAD_ARGUMENT; - T((T_CALLED("set_field_pad(%p,%d)"), field, ch)); + T((T_CALLED("set_field_pad(%p,%d)"), (void *)field, ch)); Normalize_Field(field); if (isprint(UChar(ch))) @@ -68,17 +69,17 @@ set_field_pad(FIELD *field, int ch) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int field_pad(const FIELD *field) -| -| Description : Retrieve the fields pad character. +| +| Description : Retrieve the field's pad character. | | Return Values : The pad character. +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) field_pad(const FIELD *field) { - T((T_CALLED("field_pad(%p)"), field)); + T((T_CALLED("field_pad(%p)"), (const void *)field)); returnCode(Normalize_Field(field)->pad); } diff --git a/lib/libform/fld_page.c b/lib/libform/fld_page.c index 7e4a668bff9..4ab4bc0a08e 100644 --- a/lib/libform/fld_page.c +++ b/lib/libform/fld_page.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fld_page.c,v 1.6 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fld_page.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,49 +34,49 @@ #include "form.priv.h" -MODULE_ID("$Id: fld_page.c,v 1.6 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fld_page.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int set_new_page(FIELD *field, bool new_page_flag) -| -| Description : Marks the field as the beginning of a new page of +| +| Description : Marks the field as the beginning of a new page of | the form. | | Return Values : E_OK - success | E_CONNECTED - field is connected +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) set_new_page(FIELD *field, bool new_page_flag) { - T((T_CALLED("set_new_page(%p,%d)"), field, new_page_flag)); + T((T_CALLED("set_new_page(%p,%d)"), (void *)field, new_page_flag)); Normalize_Field(field); if (field->form) RETURN(E_CONNECTED); if (new_page_flag) - field->status |= _NEWPAGE; + SetStatus(field, _NEWPAGE); else - field->status &= ~_NEWPAGE; + ClrStatus(field, _NEWPAGE); RETURN(E_OK); } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : bool new_page(const FIELD *field) -| -| Description : Retrieve the info whether or not the field starts a -| new page on the form. +| +| Description : Retrieve the information whether or not the field starts +| a new page on the form. | | Return Values : TRUE - field starts a new page | FALSE - field doesn't start a new page +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(bool) +FORM_EXPORT(bool) new_page(const FIELD *field) { - T((T_CALLED("new_page(%p)"), field)); + T((T_CALLED("new_page(%p)"), (const void *)field)); returnBool((Normalize_Field(field)->status & _NEWPAGE) ? TRUE : FALSE); } diff --git a/lib/libform/fld_stat.c b/lib/libform/fld_stat.c index 66717502565..3528d096fdd 100644 --- a/lib/libform/fld_stat.c +++ b/lib/libform/fld_stat.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fld_stat.c,v 1.8 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fld_stat.c,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,46 +34,46 @@ #include "form.priv.h" -MODULE_ID("$Id: fld_stat.c,v 1.8 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fld_stat.c,v 1.9 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int set_field_status(FIELD *field, bool status) -| +| | Description : Set or clear the 'changed' indication flag for that -| fields primary buffer. +| field's primary buffer. | | Return Values : E_OK - success +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) set_field_status(FIELD *field, bool status) { - T((T_CALLED("set_field_status(%p,%d)"), field, status)); + T((T_CALLED("set_field_status(%p,%d)"), (void *)field, status)); Normalize_Field(field); if (status) - field->status |= _CHANGED; + SetStatus(field, _CHANGED); else - field->status &= ~_CHANGED; + ClrStatus(field, _CHANGED); RETURN(E_OK); } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : bool field_status(const FIELD *field) -| +| | Description : Retrieve the value of the 'changed' indication flag -| for that fields primary buffer. +| for that field's primary buffer. | | Return Values : TRUE - buffer has been changed | FALSE - buffer has not been changed +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(bool) +FORM_EXPORT(bool) field_status(const FIELD *field) { - T((T_CALLED("field_status(%p)"), field)); + T((T_CALLED("field_status(%p)"), (const void *)field)); returnBool((Normalize_Field(field)->status & _CHANGED) ? TRUE : FALSE); } diff --git a/lib/libform/fld_type.c b/lib/libform/fld_type.c index 8562637190e..1a818f4d1d4 100644 --- a/lib/libform/fld_type.c +++ b/lib/libform/fld_type.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fld_type.c,v 1.8 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fld_type.c,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2004,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,12 +34,12 @@ #include "form.priv.h" -MODULE_ID("$Id: fld_type.c,v 1.8 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fld_type.c,v 1.9 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int set_field_type(FIELD *field, FIELDTYPE *type,...) -| +| | Description : Associate the specified fieldtype with the field. | Certain field types take additional arguments. Look | at the spec of the field types ! @@ -46,14 +47,14 @@ MODULE_ID("$Id: fld_type.c,v 1.8 2015/01/23 22:48:51 krw Exp $") | Return Values : E_OK - success | E_SYSTEM_ERROR - system error +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -set_field_type(FIELD *field, FIELDTYPE *type,...) +FORM_EXPORT(int) +set_field_type(FIELD *field, FIELDTYPE *type, ...) { va_list ap; int res = E_SYSTEM_ERROR; int err = 0; - T((T_CALLED("set_field_type(%p,%p)"), field, type)); + T((T_CALLED("set_field_type(%p,%p)"), (void *)field, (void *)type)); va_start(ap, type); @@ -81,17 +82,17 @@ set_field_type(FIELD *field, FIELDTYPE *type,...) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : FIELDTYPE *field_type(const FIELD *field) -| +| | Description : Retrieve the associated fieldtype for this field. | | Return Values : Pointer to fieldtype of NULL if none is defined. +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(FIELDTYPE *) +FORM_EXPORT(FIELDTYPE *) field_type(const FIELD *field) { - T((T_CALLED("field_type(%p)"), field)); + T((T_CALLED("field_type(%p)"), (const void *)field)); returnFieldType(Normalize_Field(field)->type); } diff --git a/lib/libform/fld_user.c b/lib/libform/fld_user.c index 6191fe22895..20bc443ed1f 100644 --- a/lib/libform/fld_user.c +++ b/lib/libform/fld_user.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fld_user.c,v 1.8 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fld_user.c,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2004,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,40 +34,40 @@ #include "form.priv.h" -MODULE_ID("$Id: fld_user.c,v 1.8 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fld_user.c,v 1.9 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int set_field_userptr(FIELD *field, void *usrptr) -| +| | Description : Set the pointer that is reserved in any field to store -| application relevant informations +| application relevant information. | | Return Values : E_OK - on success +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) set_field_userptr(FIELD *field, void *usrptr) { - T((T_CALLED("set_field_userptr(%p,%p)"), field, usrptr)); + T((T_CALLED("set_field_userptr(%p,%p)"), (void *)field, (void *)usrptr)); Normalize_Field(field)->usrptr = usrptr; RETURN(E_OK); } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : void *field_userptr(const FIELD *field) -| +| | Description : Return the pointer that is reserved in any field to -| store application relevant informations. +| store application relevant information. | | Return Values : Value of pointer. If no such pointer has been set, | NULL is returned +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(void *) +FORM_EXPORT(void *) field_userptr(const FIELD *field) { - T((T_CALLED("field_userptr(%p)"), field)); + T((T_CALLED("field_userptr(%p)"), (const void *)field)); returnVoidPtr(Normalize_Field(field)->usrptr); } diff --git a/lib/libform/form.3 b/lib/libform/form.3 index 3fe0fd9512a..da81ab19ab5 100644 --- a/lib/libform/form.3 +++ b/lib/libform/form.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form.3,v 1.6 2019/02/13 07:18:58 nicm Exp $ +.\" $OpenBSD: form.3,v 1.7 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. * +.\" Copyright 2018-2021,2023 Thomas E. Dickey * +.\" Copyright 1998-2016,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,23 +30,31 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form.3,v 1.6 2019/02/13 07:18:58 nicm Exp $ -.TH form 3 "" +.\" $Id: form.3,v 1.7 2023/10/17 09:52:10 nicm Exp $ +.TH form 3 2023-08-19 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .SH NAME -\fBform\fR - curses extension for programming forms +\fBform\fP \- curses extension for programming forms .SH SYNOPSIS -\fB#include \fR -.br +\fB#include \fP .SH DESCRIPTION -The \fBform\fR library provides terminal-independent facilities for composing -form screens on character-cell terminals. The library includes: field +The \fBform\fP library provides terminal-independent facilities for composing +form screens on character-cell terminals. +The library includes: field routines, which create and modify form fields; and form routines, which group fields into forms, display forms on the screen, and handle interaction with the user. .PP -The \fBform\fR library uses the \fBcurses\fR libraries. -To use the \fBform\fR library, link with the options -\fB-lform -lcurses\fR. +The \fBform\fP library uses the \fBcurses\fP libraries. +To use the \fBform\fP library, link with the options +\fB\-lform \-lcurses\fP. .PP Your program should set up the locale, e.g., .sp @@ -53,105 +62,111 @@ Your program should set up the locale, e.g., .sp so that input/output processing will work. .PP -A curses initialization routine such as \fBinitscr\fR must be called +A curses initialization routine such as \fBinitscr\fP must be called before using any of these functions. . .SS Current Default Values for Field Attributes . -The \fBform\fR library maintains a default value for field attributes. You -can get or set this default by calling the appropriate \fBset_\fR +The \fBform\fP library maintains a default value for field attributes. +You +can get or set this default by calling the appropriate \fBset_\fP or retrieval -routine with a \fBNULL\fR field pointer. Changing this default with a -\fBset_\fR function affects future field creations, but does not change the +routine with a \fBNULL\fP field pointer. +Changing this default with a +\fBset_\fP function affects future field creations, but does not change the rendering of fields already created. . .SS Routine Name Index . -The following table lists each \fBform\fR routine and the name of +The following table lists each \fBform\fP routine and the name of the manual page on which it is described. -. +Routines flagged with \*(``*\*('' +are ncurses-specific, not present in SVr4. +.PP .TS l l l l . -\fBcurses\fR Routine Name Manual Page Name +\fBcurses\fP Routine Name Manual Page Name = -current_field \fBform_page\fR(3) -data_ahead \fBform_data\fR(3) -data_behind \fBform_data\fR(3) -dup_field \fBform_field_new\fR(3) -dynamic_field_info \fBform_field_info\fR(3) -field_arg \fBform_field_validation\fR(3) -field_back \fBform_field_attributes\fR(3) -field_buffer \fBform_field_buffer\fR(3) -field_count \fBform_field\fR(3) -field_fore \fBform_field_attributes\fR(3) -field_index \fBform_page\fR(3) -field_info \fBform_field_info\fR(3) -field_init \fBform_hook\fR(3) -field_just \fBform_field_just\fR(3) -field_opts \fBform_field_opts\fR(3) -field_opts_off \fBform_field_opts\fR(3) -field_opts_on \fBform_field_opts\fR(3) -field_pad \fBform_field_attributes\fR(3) -field_status \fBform_field_buffer\fR(3) -field_term \fBform_hook\fR(3) -field_type \fBform_field_validation\fR(3) -field_userptr \fBform_field_userptr\fR(3) -form_driver \fBform_driver\fR(3) -form_fields \fBform_field\fR(3) -form_init \fBform_hook\fR(3) -form_opts \fBform_opts\fR(3) -form_opts_off \fBform_opts\fR(3) -form_opts_on \fBform_opts\fR(3) -form_page \fBform_page\fR(3) -form_request_by_name \fBform_requestname\fR(3) -form_request_name \fBform_requestname\fR(3) -form_sub \fBform_win\fR(3) -form_term \fBform_hook\fR(3) -form_userptr \fBform_userptr\fR(3) -form_win \fBform_win\fR(3) -free_field \fBform_field_new\fR(3) -free_fieldtype \fBform_fieldtype\fR(3) -free_form \fBform_new\fR(3) -link_field \fBform_field_new\fR(3) -link_fieldtype \fBform_fieldtype\fR(3) -move_field \fBform_field\fR(3) -new_field \fBform_field_new\fR(3) -new_fieldtype \fBform_fieldtype\fR(3) -new_form \fBform_new\fR(3) -new_page \fBform_new_page\fR(3) -pos_form_cursor \fBform_cursor\fR(3) -post_form \fBform_post\fR(3) -scale_form \fBform_win\fR(3) -set_current_field \fBform_page\fR(3) -set_field_back \fBform_field_attributes\fR(3) -set_field_buffer \fBform_field_buffer\fR(3) -set_field_fore \fBform_field_attributes\fR(3) -set_field_init \fBform_hook\fR(3) -set_field_just \fBform_field_just\fR(3) -set_field_opts \fBform_field_opts\fR(3) -set_field_pad \fBform_field_attributes\fR(3) -set_field_status \fBform_field_buffer\fR(3) -set_field_term \fBform_hook\fR(3) -set_field_type \fBform_field_validation\fR(3) -set_field_userptr \fBform_field_userptr\fR(3) -set_fieldtype_arg \fBform_fieldtype\fR(3) -set_fieldtype_choice \fBform_fieldtype\fR(3) -set_form_fields \fBform_field\fR(3) -set_form_init \fBform_hook\fR(3) -set_form_opts \fBform_field_opts\fR(3) -set_form_page \fBform_page\fR(3) -set_form_sub \fBform_win\fR(3) -set_form_term \fBform_hook\fR(3) -set_form_userptr \fBform_userptr\fR(3) -set_form_win \fBform_win\fR(3) -set_max_field \fBform_field_buffer\fR(3) -set_new_page \fBform_new_page\fR(3) -unpost_form \fBform_post\fR(3) +current_field \fBform_page\fP(3) +data_ahead \fBform_data\fP(3) +data_behind \fBform_data\fP(3) +dup_field \fBform_field_new\fP(3) +dynamic_field_info \fBform_field_info\fP(3) +field_arg \fBform_field_validation\fP(3) +field_back \fBform_field_attributes\fP(3) +field_buffer \fBform_field_buffer\fP(3) +field_count \fBform_field\fP(3) +field_fore \fBform_field_attributes\fP(3) +field_index \fBform_page\fP(3) +field_info \fBform_field_info\fP(3) +field_init \fBform_hook\fP(3) +field_just \fBform_field_just\fP(3) +field_opts \fBform_field_opts\fP(3) +field_opts_off \fBform_field_opts\fP(3) +field_opts_on \fBform_field_opts\fP(3) +field_pad \fBform_field_attributes\fP(3) +field_status \fBform_field_buffer\fP(3) +field_term \fBform_hook\fP(3) +field_type \fBform_field_validation\fP(3) +field_userptr \fBform_field_userptr\fP(3) +form_driver \fBform_driver\fP(3) +form_driver_w \fBform_driver\fP(3)* +form_fields \fBform_field\fP(3) +form_init \fBform_hook\fP(3) +form_opts \fBform_opts\fP(3) +form_opts_off \fBform_opts\fP(3) +form_opts_on \fBform_opts\fP(3) +form_page \fBform_page\fP(3) +form_request_by_name \fBform_requestname\fP(3)* +form_request_name \fBform_requestname\fP(3)* +form_sub \fBform_win\fP(3) +form_term \fBform_hook\fP(3) +form_userptr \fBform_userptr\fP(3) +form_win \fBform_win\fP(3) +free_field \fBform_field_new\fP(3) +free_fieldtype \fBform_fieldtype\fP(3) +free_form \fBform_new\fP(3) +link_field \fBform_field_new\fP(3) +link_fieldtype \fBform_fieldtype\fP(3) +move_field \fBform_field\fP(3) +new_field \fBform_field_new\fP(3) +new_fieldtype \fBform_fieldtype\fP(3) +new_form \fBform_new\fP(3) +new_page \fBform_new_page\fP(3) +pos_form_cursor \fBform_cursor\fP(3) +post_form \fBform_post\fP(3) +scale_form \fBform_win\fP(3) +set_current_field \fBform_page\fP(3) +set_field_back \fBform_field_attributes\fP(3) +set_field_buffer \fBform_field_buffer\fP(3) +set_field_fore \fBform_field_attributes\fP(3) +set_field_init \fBform_hook\fP(3) +set_field_just \fBform_field_just\fP(3) +set_field_opts \fBform_field_opts\fP(3) +set_field_pad \fBform_field_attributes\fP(3) +set_field_status \fBform_field_buffer\fP(3) +set_field_term \fBform_hook\fP(3) +set_field_type \fBform_field_validation\fP(3) +set_field_userptr \fBform_field_userptr\fP(3) +set_fieldtype_arg \fBform_fieldtype\fP(3) +set_fieldtype_choice \fBform_fieldtype\fP(3) +set_form_fields \fBform_field\fP(3) +set_form_init \fBform_hook\fP(3) +set_form_opts \fBform_field_opts\fP(3) +set_form_page \fBform_page\fP(3) +set_form_sub \fBform_win\fP(3) +set_form_term \fBform_hook\fP(3) +set_form_userptr \fBform_userptr\fP(3) +set_form_win \fBform_win\fP(3) +set_max_field \fBform_field_buffer\fP(3) +set_new_page \fBform_new_page\fP(3) +unfocus_current_field \fBform_page\fP(3)* +unpost_form \fBform_post\fP(3) .TE .SH RETURN VALUE -Routines that return pointers return \fBNULL\fR on error, -and set errno to the corresponding error-code returned by functions +Routines that return pointers return \fBNULL\fP on error, +and set \fBerrno\fP to the corresponding error-code returned by functions returning an integer. Routines that return an integer return one of the following error codes: @@ -187,32 +202,44 @@ The form is already posted. The form driver could not process the request. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .TP 5 .B E_UNKNOWN_COMMAND The form driver code saw an unknown request code. -.SH SEE ALSO -\fBcurses\fR(3) and related pages whose names begin "form_" for detailed -descriptions of the entry points. .SH NOTES -The header file \fB\fR automatically includes the header files -\fB\fR and \fB\fR. +The header file \fB\fP automatically includes the header files +\fB\fP and \fB\fP. .PP In your library list, libform.a should be before libncurses.a; that is, -you want to say `-lform -lncurses', not the other way around (which would -give you a link error using most linkers). +you want to say \*(``\-lform \-lncurses\*('', not the other way around +(which would give you a link error when using static libraries). .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. +.PP +The menu facility was documented in SVr4.2 in +\fICharacter User Interface Programming (UNIX SVR4.2)\fP. +.PP +It is not part of X/Open Curses. +.PP +Aside from ncurses, there are few implementations: +.bP +systems based on SVr4 source code, e.g., Solaris. +.bP +NetBSD curses. +.PP +A few functions in this implementation are extensions added for ncurses, +but not provided by other implementations, e.g., +\fBform_driver_w\fP, +\fBunfocus_current_field\fP. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for ncurses by Eric +Juergen Pfeifer. +Manual pages and adaptation for ncurses by Eric S. Raymond. .SH SEE ALSO -This describes \fBncurses\fR -version 5.7. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3) and related pages whose names begin \*(``form_\*('' for detailed +descriptions of the entry points. +.PP +This describes \fBncurses\fP +version 6.4 (patch 20230826). diff --git a/lib/libform/form.h b/lib/libform/form.h index 1302210b91a..88b58ca9e2e 100644 --- a/lib/libform/form.h +++ b/lib/libform/form.h @@ -1,6 +1,7 @@ -/* $OpenBSD: form.h,v 1.8 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: form.h,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2018-2019-2020,2021 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,10 +32,11 @@ * Author: Juergen Pfeifer, 1995,1997 * ****************************************************************************/ -/* $Id: form.h,v 1.8 2015/01/23 22:48:51 krw Exp $ */ +/* $Id: form.h,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ #ifndef FORM_H #define FORM_H +/* *INDENT-OFF*/ #include #include @@ -43,6 +45,17 @@ extern "C" { #endif +#if defined(BUILDING_FORM) +# define FORM_IMPEXP NCURSES_EXPORT_GENERAL_EXPORT +#else +# define FORM_IMPEXP NCURSES_EXPORT_GENERAL_IMPORT +#endif + +#define FORM_WRAPPED_VAR(type,name) extern FORM_IMPEXP type NCURSES_PUBLIC_VAR(name)(void) + +#define FORM_EXPORT(type) FORM_IMPEXP type NCURSES_API +#define FORM_EXPORT_VAR(type) FORM_IMPEXP type + #ifndef FORM_PRIV_H typedef void *FIELD_CELL; #endif @@ -58,18 +71,24 @@ typedef int Field_Options; * _PAGE * **********/ -typedef struct { +typedef struct pagenode +#if !NCURSES_OPAQUE_FORM +{ short pmin; /* index of first field on page */ short pmax; /* index of last field on page */ short smin; /* index of top leftmost field on page */ short smax; /* index of bottom rightmost field on page */ -} _PAGE; +} +#endif /* !NCURSES_OPAQUE_FORM */ +_PAGE; /********** * FIELD * **********/ -typedef struct fieldnode { +typedef struct fieldnode +#if 1 /* not yet: !NCURSES_OPAQUE_FORM */ +{ unsigned short status; /* flags */ short rows; /* size in rows */ short cols; /* size in cols */ @@ -98,42 +117,25 @@ typedef struct fieldnode { /* * The wide-character configuration requires extra information. Because * there are existing applications that manipulate the members of FIELD - * directly, we cannot make the struct opaque. Offsets of members up to - * this point are the same in the narrow- and wide-character configuration. - * But note that the type of buf depends on the configuration, and is made - * opaque for that reason. + * directly, we cannot make the struct opaque, except by changing the ABI. + * Offsets of members up to this point are the same in the narrow- and + * wide-character configuration. But note that the type of buf depends on + * the configuration, and is made opaque for that reason. */ NCURSES_FIELD_INTERNALS -} FIELD; - - /************** - * FIELDTYPE * - **************/ +} +#endif /* NCURSES_OPAQUE_FORM */ +FIELD; -typedef struct typenode { - unsigned short status; /* flags */ - long ref; /* reference count */ - struct typenode * left; /* ptr to operand for | */ - struct typenode * right; /* ptr to operand for | */ - - void* (*makearg)(va_list *); /* make fieldtype arg */ - void* (*copyarg)(const void *); /* copy fieldtype arg */ - void (*freearg)(void *); /* free fieldtype arg */ - - bool (*fcheck)(FIELD *,const void *); /* field validation */ - bool (*ccheck)(int,const void *); /* character validation */ - - bool (*next)(FIELD *,const void *); /* enumerate next value */ - bool (*prev)(FIELD *,const void *); /* enumerate prev value */ - -} FIELDTYPE; /********* * FORM * *********/ -typedef struct formnode { - unsigned short status; /* flags */ +typedef struct formnode +#if 1 /* not yet: !NCURSES_OPAQUE_FORM */ +{ + unsigned short status; /* flags */ short rows; /* size in rows */ short cols; /* size in cols */ int currow; /* current row in field window */ @@ -157,7 +159,56 @@ typedef struct formnode { void (*fieldinit)(struct formnode *); void (*fieldterm)(struct formnode *); -} FORM; +} +#endif /* !NCURSES_OPAQUE_FORM */ +FORM; + + + /************** + * FIELDTYPE * + **************/ + +typedef struct typenode +#if !NCURSES_OPAQUE_FORM +{ + unsigned short status; /* flags */ + long ref; /* reference count */ + struct typenode * left; /* ptr to operand for | */ + struct typenode * right; /* ptr to operand for | */ + + void* (*makearg)(va_list *); /* make fieldtype arg */ + void* (*copyarg)(const void *); /* copy fieldtype arg */ + void (*freearg)(void *); /* free fieldtype arg */ + +#if NCURSES_INTEROP_FUNCS + union { + bool (*ofcheck)(FIELD *,const void *); /* field validation */ + bool (*gfcheck)(FORM*,FIELD *,const void*); /* generic field validation */ + } fieldcheck; + union { + bool (*occheck)(int,const void *); /* character validation */ + bool (*gccheck)(int,FORM*, + FIELD*,const void*); /* generic char validation */ + } charcheck; + union { + bool (*onext)(FIELD *,const void *); /* enumerate next value */ + bool (*gnext)(FORM*,FIELD*,const void*); /* generic enumerate next */ + } enum_next; + union { + bool (*oprev)(FIELD *,const void *); /* enumerate prev value */ + bool (*gprev)(FORM*,FIELD*,const void*); /* generic enumerate prev */ + } enum_prev; + void* (*genericarg)(void*); /* Alternate Arg method */ +#else + bool (*fcheck)(FIELD *,const void *); /* field validation */ + bool (*ccheck)(int,const void *); /* character validation */ + + bool (*next)(FIELD *,const void *); /* enumerate next value */ + bool (*prev)(FIELD *,const void *); /* enumerate prev value */ +#endif +} +#endif /* !NCURSES_OPAQUE_FORM */ +FIELDTYPE; typedef void (*Form_Hook)(FORM *); @@ -182,6 +233,10 @@ typedef void (*Form_Hook)(FORM *); #define O_NULLOK (0x0080U) #define O_PASSOK (0x0100U) #define O_STATIC (0x0200U) +#define O_DYNAMIC_JUSTIFY (0x0400U) /* ncurses extension */ +#define O_NO_LEFT_STRIP (0x0800U) /* ncurses extension */ +#define O_EDGE_INSERT_STAY (0x1000U) /* ncurses extension */ +#define O_INPUT_LIMIT (0x2000U) /* ncurses extension */ /* form options */ #define O_NL_OVERLOAD (0x0001U) @@ -266,139 +321,141 @@ typedef void (*Form_Hook)(FORM *); /************************* * standard field types * *************************/ -extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_ALPHA; -extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_ALNUM; -extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_ENUM; -extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_INTEGER; -extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_NUMERIC; -extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_REGEXP; +extern FORM_EXPORT_VAR(FIELDTYPE *) TYPE_ALPHA; +extern FORM_EXPORT_VAR(FIELDTYPE *) TYPE_ALNUM; +extern FORM_EXPORT_VAR(FIELDTYPE *) TYPE_ENUM; +extern FORM_EXPORT_VAR(FIELDTYPE *) TYPE_INTEGER; +extern FORM_EXPORT_VAR(FIELDTYPE *) TYPE_NUMERIC; +extern FORM_EXPORT_VAR(FIELDTYPE *) TYPE_REGEXP; /************************************ * built-in additional field types * * They are not defined in SVr4 * ************************************/ -extern NCURSES_EXPORT_VAR(FIELDTYPE *) TYPE_IPV4; /* Internet IP Version 4 address */ - - /*********************** - * Default objects * - ***********************/ -extern NCURSES_EXPORT_VAR(FORM *) _nc_Default_Form; -extern NCURSES_EXPORT_VAR(FIELD *) _nc_Default_Field; - +extern FORM_EXPORT_VAR(FIELDTYPE *) TYPE_IPV4; /* Internet IP Version 4 address */ /*********************** * FIELDTYPE routines * ***********************/ -extern NCURSES_EXPORT(FIELDTYPE *) new_fieldtype ( +extern FORM_EXPORT(FIELDTYPE *) new_fieldtype ( bool (* const field_check)(FIELD *,const void *), bool (* const char_check)(int,const void *)); -extern NCURSES_EXPORT(FIELDTYPE *) link_fieldtype( +extern FORM_EXPORT(FIELDTYPE *) link_fieldtype( FIELDTYPE *, FIELDTYPE *); -extern NCURSES_EXPORT(int) free_fieldtype (FIELDTYPE *); -extern NCURSES_EXPORT(int) set_fieldtype_arg (FIELDTYPE *, +extern FORM_EXPORT(int) free_fieldtype (FIELDTYPE *); +extern FORM_EXPORT(int) set_fieldtype_arg (FIELDTYPE *, void * (* const make_arg)(va_list *), void * (* const copy_arg)(const void *), void (* const free_arg)(void *)); -extern NCURSES_EXPORT(int) set_fieldtype_choice (FIELDTYPE *, +extern FORM_EXPORT(int) set_fieldtype_choice (FIELDTYPE *, bool (* const next_choice)(FIELD *,const void *), bool (* const prev_choice)(FIELD *,const void *)); /******************* * FIELD routines * *******************/ -extern NCURSES_EXPORT(FIELD *) new_field (int,int,int,int,int,int); -extern NCURSES_EXPORT(FIELD *) dup_field (FIELD *,int,int); -extern NCURSES_EXPORT(FIELD *) link_field (FIELD *,int,int); - -extern NCURSES_EXPORT(int) free_field (FIELD *); -extern NCURSES_EXPORT(int) field_info (const FIELD *,int *,int *,int *,int *,int *,int *); -extern NCURSES_EXPORT(int) dynamic_field_info (const FIELD *,int *,int *,int *); -extern NCURSES_EXPORT(int) set_max_field ( FIELD *,int); -extern NCURSES_EXPORT(int) move_field (FIELD *,int,int); -extern NCURSES_EXPORT(int) set_field_type (FIELD *,FIELDTYPE *,...); -extern NCURSES_EXPORT(int) set_new_page (FIELD *,bool); -extern NCURSES_EXPORT(int) set_field_just (FIELD *,int); -extern NCURSES_EXPORT(int) field_just (const FIELD *); -extern NCURSES_EXPORT(int) set_field_fore (FIELD *,chtype); -extern NCURSES_EXPORT(int) set_field_back (FIELD *,chtype); -extern NCURSES_EXPORT(int) set_field_pad (FIELD *,int); -extern NCURSES_EXPORT(int) field_pad (const FIELD *); -extern NCURSES_EXPORT(int) set_field_buffer (FIELD *,int,const char *); -extern NCURSES_EXPORT(int) set_field_status (FIELD *,bool); -extern NCURSES_EXPORT(int) set_field_userptr (FIELD *, void *); -extern NCURSES_EXPORT(int) set_field_opts (FIELD *,Field_Options); -extern NCURSES_EXPORT(int) field_opts_on (FIELD *,Field_Options); -extern NCURSES_EXPORT(int) field_opts_off (FIELD *,Field_Options); - -extern NCURSES_EXPORT(chtype) field_fore (const FIELD *); -extern NCURSES_EXPORT(chtype) field_back (const FIELD *); - -extern NCURSES_EXPORT(bool) new_page (const FIELD *); -extern NCURSES_EXPORT(bool) field_status (const FIELD *); - -extern NCURSES_EXPORT(void *) field_arg (const FIELD *); - -extern NCURSES_EXPORT(void *) field_userptr (const FIELD *); - -extern NCURSES_EXPORT(FIELDTYPE *) field_type (const FIELD *); - -extern NCURSES_EXPORT(char *) field_buffer (const FIELD *,int); - -extern NCURSES_EXPORT(Field_Options) field_opts (const FIELD *); +extern FORM_EXPORT(FIELD *) new_field (int,int,int,int,int,int); +extern FORM_EXPORT(FIELD *) dup_field (FIELD *,int,int); +extern FORM_EXPORT(FIELD *) link_field (FIELD *,int,int); + +extern FORM_EXPORT(int) free_field (FIELD *); +extern FORM_EXPORT(int) field_info (const FIELD *,int *,int *,int *,int *,int *,int *); +extern FORM_EXPORT(int) dynamic_field_info (const FIELD *,int *,int *,int *); +extern FORM_EXPORT(int) set_max_field ( FIELD *,int); +extern FORM_EXPORT(int) move_field (FIELD *,int,int); +extern FORM_EXPORT(int) set_field_type (FIELD *,FIELDTYPE *,...); +extern FORM_EXPORT(int) set_new_page (FIELD *,bool); +extern FORM_EXPORT(int) set_field_just (FIELD *,int); +extern FORM_EXPORT(int) field_just (const FIELD *); +extern FORM_EXPORT(int) set_field_fore (FIELD *,chtype); +extern FORM_EXPORT(int) set_field_back (FIELD *,chtype); +extern FORM_EXPORT(int) set_field_pad (FIELD *,int); +extern FORM_EXPORT(int) field_pad (const FIELD *); +extern FORM_EXPORT(int) set_field_buffer (FIELD *,int,const char *); +extern FORM_EXPORT(int) set_field_status (FIELD *,bool); +extern FORM_EXPORT(int) set_field_userptr (FIELD *, void *); +extern FORM_EXPORT(int) set_field_opts (FIELD *,Field_Options); +extern FORM_EXPORT(int) field_opts_on (FIELD *,Field_Options); +extern FORM_EXPORT(int) field_opts_off (FIELD *,Field_Options); + +extern FORM_EXPORT(chtype) field_fore (const FIELD *); +extern FORM_EXPORT(chtype) field_back (const FIELD *); + +extern FORM_EXPORT(bool) new_page (const FIELD *); +extern FORM_EXPORT(bool) field_status (const FIELD *); + +extern FORM_EXPORT(void *) field_arg (const FIELD *); + +extern FORM_EXPORT(void *) field_userptr (const FIELD *); + +extern FORM_EXPORT(FIELDTYPE *) field_type (const FIELD *); + +extern FORM_EXPORT(char *) field_buffer (const FIELD *,int); + +extern FORM_EXPORT(Field_Options) field_opts (const FIELD *); /****************** * FORM routines * ******************/ -extern NCURSES_EXPORT(FORM *) new_form (FIELD **); - -extern NCURSES_EXPORT(FIELD **) form_fields (const FORM *); -extern NCURSES_EXPORT(FIELD *) current_field (const FORM *); - -extern NCURSES_EXPORT(WINDOW *) form_win (const FORM *); -extern NCURSES_EXPORT(WINDOW *) form_sub (const FORM *); - -extern NCURSES_EXPORT(Form_Hook) form_init (const FORM *); -extern NCURSES_EXPORT(Form_Hook) form_term (const FORM *); -extern NCURSES_EXPORT(Form_Hook) field_init (const FORM *); -extern NCURSES_EXPORT(Form_Hook) field_term (const FORM *); - -extern NCURSES_EXPORT(int) free_form (FORM *); -extern NCURSES_EXPORT(int) set_form_fields (FORM *,FIELD **); -extern NCURSES_EXPORT(int) field_count (const FORM *); -extern NCURSES_EXPORT(int) set_form_win (FORM *,WINDOW *); -extern NCURSES_EXPORT(int) set_form_sub (FORM *,WINDOW *); -extern NCURSES_EXPORT(int) set_current_field (FORM *,FIELD *); -extern NCURSES_EXPORT(int) field_index (const FIELD *); -extern NCURSES_EXPORT(int) set_form_page (FORM *,int); -extern NCURSES_EXPORT(int) form_page (const FORM *); -extern NCURSES_EXPORT(int) scale_form (const FORM *,int *,int *); -extern NCURSES_EXPORT(int) set_form_init (FORM *,Form_Hook); -extern NCURSES_EXPORT(int) set_form_term (FORM *,Form_Hook); -extern NCURSES_EXPORT(int) set_field_init (FORM *,Form_Hook); -extern NCURSES_EXPORT(int) set_field_term (FORM *,Form_Hook); -extern NCURSES_EXPORT(int) post_form (FORM *); -extern NCURSES_EXPORT(int) unpost_form (FORM *); -extern NCURSES_EXPORT(int) pos_form_cursor (FORM *); -extern NCURSES_EXPORT(int) form_driver (FORM *,int); -extern NCURSES_EXPORT(int) set_form_userptr (FORM *,void *); -extern NCURSES_EXPORT(int) set_form_opts (FORM *,Form_Options); -extern NCURSES_EXPORT(int) form_opts_on (FORM *,Form_Options); -extern NCURSES_EXPORT(int) form_opts_off (FORM *,Form_Options); -extern NCURSES_EXPORT(int) form_request_by_name (const char *); - -extern NCURSES_EXPORT(const char *) form_request_name (int); - -extern NCURSES_EXPORT(void *) form_userptr (const FORM *); - -extern NCURSES_EXPORT(Form_Options) form_opts (const FORM *); - -extern NCURSES_EXPORT(bool) data_ahead (const FORM *); -extern NCURSES_EXPORT(bool) data_behind (const FORM *); +extern FORM_EXPORT(FORM *) new_form (FIELD **); + +extern FORM_EXPORT(FIELD **) form_fields (const FORM *); +extern FORM_EXPORT(FIELD *) current_field (const FORM *); + +extern FORM_EXPORT(WINDOW *) form_win (const FORM *); +extern FORM_EXPORT(WINDOW *) form_sub (const FORM *); + +extern FORM_EXPORT(Form_Hook) form_init (const FORM *); +extern FORM_EXPORT(Form_Hook) form_term (const FORM *); +extern FORM_EXPORT(Form_Hook) field_init (const FORM *); +extern FORM_EXPORT(Form_Hook) field_term (const FORM *); + +extern FORM_EXPORT(int) free_form (FORM *); +extern FORM_EXPORT(int) set_form_fields (FORM *,FIELD **); +extern FORM_EXPORT(int) field_count (const FORM *); +extern FORM_EXPORT(int) set_form_win (FORM *,WINDOW *); +extern FORM_EXPORT(int) set_form_sub (FORM *,WINDOW *); +extern FORM_EXPORT(int) set_current_field (FORM *,FIELD *); +extern FORM_EXPORT(int) unfocus_current_field (FORM *); +extern FORM_EXPORT(int) field_index (const FIELD *); +extern FORM_EXPORT(int) set_form_page (FORM *,int); +extern FORM_EXPORT(int) form_page (const FORM *); +extern FORM_EXPORT(int) scale_form (const FORM *,int *,int *); +extern FORM_EXPORT(int) set_form_init (FORM *,Form_Hook); +extern FORM_EXPORT(int) set_form_term (FORM *,Form_Hook); +extern FORM_EXPORT(int) set_field_init (FORM *,Form_Hook); +extern FORM_EXPORT(int) set_field_term (FORM *,Form_Hook); +extern FORM_EXPORT(int) post_form (FORM *); +extern FORM_EXPORT(int) unpost_form (FORM *); +extern FORM_EXPORT(int) pos_form_cursor (FORM *); +extern FORM_EXPORT(int) form_driver (FORM *,int); +# if NCURSES_WIDECHAR +extern FORM_EXPORT(int) form_driver_w (FORM *,int,wchar_t); +# endif +extern FORM_EXPORT(int) set_form_userptr (FORM *,void *); +extern FORM_EXPORT(int) set_form_opts (FORM *,Form_Options); +extern FORM_EXPORT(int) form_opts_on (FORM *,Form_Options); +extern FORM_EXPORT(int) form_opts_off (FORM *,Form_Options); +extern FORM_EXPORT(int) form_request_by_name (const char *); + +extern FORM_EXPORT(const char *) form_request_name (int); + +extern FORM_EXPORT(void *) form_userptr (const FORM *); + +extern FORM_EXPORT(Form_Options) form_opts (const FORM *); + +extern FORM_EXPORT(bool) data_ahead (const FORM *); +extern FORM_EXPORT(bool) data_behind (const FORM *); + +#if NCURSES_SP_FUNCS +extern FORM_EXPORT(FORM *) NCURSES_SP_NAME(new_form) (SCREEN*, FIELD **); +#endif #ifdef __cplusplus } #endif +/* *INDENT-ON*/ -#endif /* FORM_H */ +#endif /* FORM_H */ diff --git a/lib/libform/form.priv.h b/lib/libform/form.priv.h index 6e2b5906918..ad2d11128d5 100644 --- a/lib/libform/form.priv.h +++ b/lib/libform/form.priv.h @@ -1,6 +1,7 @@ -/* $OpenBSD: form.priv.h,v 1.8 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: form.priv.h,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. * + * Copyright 2018-2020,2021 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,12 +32,15 @@ * Author: Juergen Pfeifer, 1995,1997 * ****************************************************************************/ -/* $Id: form.priv.h,v 1.8 2015/01/23 22:48:51 krw Exp $ */ +/* $Id: form.priv.h,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ #ifndef FORM_PRIV_H #define FORM_PRIV_H 1 - +/* *INDENT-OFF*/ #include "curses.priv.h" + +#define NCURSES_OPAQUE_FORM 0 + #include "mf_common.h" #if USE_WIDEC_SUPPORT @@ -63,6 +67,13 @@ #include "form.h" + /*********************** + * Default objects * + ***********************/ +extern FORM_EXPORT_VAR(FORM *) _nc_Default_Form; +extern FORM_EXPORT_VAR(FIELD *) _nc_Default_Field; +extern FORM_EXPORT_VAR(FIELDTYPE *) _nc_Default_FieldType; + /* form status values */ #define _OVLMODE (0x04U) /* Form is in overlay mode */ #define _WINDOW_MODIFIED (0x10U) /* Current field window has been modified */ @@ -79,6 +90,7 @@ #define _HAS_ARGS (0x02U) /* Type has arguments */ #define _HAS_CHOICE (0x04U) /* Type has choice methods */ #define _RESIDENT (0x08U) /* Type is built-in */ +#define _GENERIC (0x10U) /* A generic field type */ /* This are the field options required to be a selectable field in field navigation requests */ @@ -92,21 +104,34 @@ #define Normalize_Field(field) \ ((field) = (field != 0) ? (field) : _nc_Default_Field) -/* Retrieve forms window */ +#if NCURSES_SP_FUNCS +#define Get_Form_Screen(form) \ + ((form)->win ? _nc_screen_of((form->win)):CURRENT_SCREEN) +#else +#define Get_Form_Screen(form) CURRENT_SCREEN +#endif + +/* Retrieve form's window */ #define Get_Form_Window(form) \ - ((form)->sub?(form)->sub:((form)->win?(form)->win:stdscr)) + ((form)->sub \ + ? (form)->sub \ + : ((form)->win \ + ? (form)->win \ + : StdScreen(Get_Form_Screen(form)))) /* Calculate the size for a single buffer for this field */ #define Buffer_Length(field) ((field)->drows * (field)->dcols) /* Calculate the total size of all buffers for this field */ #define Total_Buffer_Size(field) \ - ( (Buffer_Length(field) + 1) * (1+(field)->nbuf) * sizeof(FIELD_CELL) ) + ( (size_t)(Buffer_Length(field) + 1) * (size_t)(1+(field)->nbuf) * sizeof(FIELD_CELL) ) /* Logic to determine whether or not a field is single lined */ #define Single_Line_Field(field) \ (((field)->rows + (field)->nrow) == 1) +#define Field_Has_Option(f,o) ((((unsigned)(f)->opts) & o) != 0) + /* Logic to determine whether or not a field is selectable */ #define Field_Is_Selectable(f) (((unsigned)((f)->opts) & O_SELECTABLE)==O_SELECTABLE) #define Field_Is_Not_Selectable(f) (((unsigned)((f)->opts) & O_SELECTABLE)!=O_SELECTABLE) @@ -128,7 +153,7 @@ TypeArgument; O_NL_OVERLOAD |\ O_BS_OVERLOAD ) -#define ALL_FIELD_OPTS (Field_Options)( \ +#define STD_FIELD_OPTS (Field_Options)( \ O_VISIBLE |\ O_ACTIVE |\ O_PUBLIC |\ @@ -138,47 +163,83 @@ TypeArgument; O_AUTOSKIP|\ O_NULLOK |\ O_PASSOK |\ - O_STATIC ) + O_STATIC) + +#define ALL_FIELD_OPTS (Field_Options)( \ + STD_FIELD_OPTS |\ + O_DYNAMIC_JUSTIFY |\ + O_NO_LEFT_STRIP |\ + O_EDGE_INSERT_STAY |\ + O_INPUT_LIMIT) #define C_BLANK ' ' #define is_blank(c) ((c)==C_BLANK) #define C_ZEROS '\0' -extern NCURSES_EXPORT_VAR(const FIELDTYPE *) _nc_Default_FieldType; - -extern NCURSES_EXPORT(TypeArgument *) _nc_Make_Argument (const FIELDTYPE*, va_list*, int*); -extern NCURSES_EXPORT(TypeArgument *) _nc_Copy_Argument (const FIELDTYPE*, const TypeArgument*, int*); -extern NCURSES_EXPORT(void) _nc_Free_Argument (const FIELDTYPE*, TypeArgument*); -extern NCURSES_EXPORT(bool) _nc_Copy_Type (FIELD*, FIELD const *); -extern NCURSES_EXPORT(void) _nc_Free_Type (FIELD *); +extern FORM_EXPORT(TypeArgument *) _nc_Make_Argument (const FIELDTYPE*, va_list*, int*); +extern FORM_EXPORT(TypeArgument *) _nc_Copy_Argument (const FIELDTYPE*, const TypeArgument*, int*); +extern FORM_EXPORT(void) _nc_Free_Argument (const FIELDTYPE*, TypeArgument*); +extern FORM_EXPORT(bool) _nc_Copy_Type (FIELD*, FIELD const *); +extern FORM_EXPORT(void) _nc_Free_Type (FIELD *); + +extern FORM_EXPORT(int) _nc_Synchronize_Attributes (FIELD*); +extern FORM_EXPORT(int) _nc_Synchronize_Options (FIELD*, Field_Options); +extern FORM_EXPORT(int) _nc_Set_Form_Page (FORM*, int, FIELD*); +extern FORM_EXPORT(int) _nc_Refresh_Current_Field (FORM*); +extern FORM_EXPORT(FIELD *) _nc_First_Active_Field (FORM*); +extern FORM_EXPORT(bool) _nc_Internal_Validation (FORM*); +extern FORM_EXPORT(int) _nc_Set_Current_Field (FORM*, FIELD*); +extern FORM_EXPORT(int) _nc_Position_Form_Cursor (FORM*); +extern FORM_EXPORT(void) _nc_Unset_Current_Field(FORM *form); + +#if NCURSES_INTEROP_FUNCS +extern FORM_EXPORT(FIELDTYPE *) _nc_TYPE_INTEGER(void); +extern FORM_EXPORT(FIELDTYPE *) _nc_TYPE_ALNUM(void); +extern FORM_EXPORT(FIELDTYPE *) _nc_TYPE_ALPHA(void); +extern FORM_EXPORT(FIELDTYPE *) _nc_TYPE_ENUM(void); +extern FORM_EXPORT(FIELDTYPE *) _nc_TYPE_NUMERIC(void); +extern FORM_EXPORT(FIELDTYPE *) _nc_TYPE_REGEXP(void); +extern FORM_EXPORT(FIELDTYPE *) _nc_TYPE_IPV4(void); + +extern FORM_EXPORT(FIELDTYPE *) +_nc_generic_fieldtype(bool (*const field_check) (FORM*, + FIELD *, + const void *), + bool (*const char_check) (int, + FORM*, + FIELD*, + const void *), + bool (*const next)(FORM*,FIELD*,const void*), + bool (*const prev)(FORM*,FIELD*,const void*), + void (*freecallback)(void*)); +extern FORM_EXPORT(int) _nc_set_generic_fieldtype(FIELD*, FIELDTYPE*, int (*)(void**)); +extern FORM_EXPORT(WINDOW*) _nc_form_cursor(const FORM* , int* , int* ); + +#define INIT_FT_FUNC(func) {func} +#else +#define INIT_FT_FUNC(func) func +#endif -extern NCURSES_EXPORT(int) _nc_Synchronize_Attributes (FIELD*); -extern NCURSES_EXPORT(int) _nc_Synchronize_Options (FIELD*, Field_Options); -extern NCURSES_EXPORT(int) _nc_Set_Form_Page (FORM*, int, FIELD*); -extern NCURSES_EXPORT(int) _nc_Refresh_Current_Field (FORM*); -extern NCURSES_EXPORT(FIELD *) _nc_First_Active_Field (FORM*); -extern NCURSES_EXPORT(bool) _nc_Internal_Validation (FORM*); -extern NCURSES_EXPORT(int) _nc_Set_Current_Field (FORM*, FIELD*); -extern NCURSES_EXPORT(int) _nc_Position_Form_Cursor (FORM*); +extern FORM_EXPORT(void) _nc_get_fieldbuffer(FORM*, FIELD*, FIELD_CELL*); #if USE_WIDEC_SUPPORT -extern NCURSES_EXPORT(wchar_t *) _nc_Widen_String(char *, int *); +extern FORM_EXPORT(wchar_t *) _nc_Widen_String(char *, int *); #endif #ifdef TRACE -#define returnField(code) TRACE_RETURN(code,field) -#define returnFieldPtr(code) TRACE_RETURN(code,field_ptr) -#define returnForm(code) TRACE_RETURN(code,form) -#define returnFieldType(code) TRACE_RETURN(code,field_type) -#define returnFormHook(code) TRACE_RETURN(code,form_hook) +#define returnField(code) TRACE_RETURN1(code,field) +#define returnFieldPtr(code) TRACE_RETURN1(code,field_ptr) +#define returnForm(code) TRACE_RETURN1(code,form) +#define returnFieldType(code) TRACE_RETURN1(code,field_type) +#define returnFormHook(code) TRACE_RETURN1(code,form_hook) -extern NCURSES_EXPORT(FIELD **) _nc_retrace_field_ptr (FIELD **); -extern NCURSES_EXPORT(FIELD *) _nc_retrace_field (FIELD *); -extern NCURSES_EXPORT(FIELDTYPE *) _nc_retrace_field_type (FIELDTYPE *); -extern NCURSES_EXPORT(FORM *) _nc_retrace_form (FORM *); -extern NCURSES_EXPORT(Form_Hook) _nc_retrace_form_hook (Form_Hook); +extern FORM_EXPORT(FIELD **) _nc_retrace_field_ptr (FIELD **); +extern FORM_EXPORT(FIELD *) _nc_retrace_field (FIELD *); +extern FORM_EXPORT(FIELDTYPE *) _nc_retrace_field_type (FIELDTYPE *); +extern FORM_EXPORT(FORM *) _nc_retrace_form (FORM *); +extern FORM_EXPORT(Form_Hook) _nc_retrace_form_hook (Form_Hook); #else /* !TRACE */ @@ -247,5 +308,6 @@ extern NCURSES_EXPORT(Form_Hook) _nc_retrace_form_hook (Form_Hook); result = ((*buffer || (l < width)) ? FALSE : TRUE); \ } #endif +/* *INDENT-ON*/ #endif /* FORM_PRIV_H */ diff --git a/lib/libform/form_cursor.3 b/lib/libform/form_cursor.3 index 80c9be37193..4aea1cfdf29 100644 --- a/lib/libform/form_cursor.3 +++ b/lib/libform/form_cursor.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form_cursor.3,v 1.8 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_cursor.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,19 +30,19 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_cursor.3,v 1.8 2015/11/14 01:35:38 jmc Exp $ -.TH form_cursor 3 "" +.\" $Id: form_cursor.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ +.TH form_cursor 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBpos_form_cursor\fR - position a form window cursor +\fBpos_form_cursor\fP \- position a form window cursor .SH SYNOPSIS -\fB#include \fR -.br -int pos_form_cursor(FORM *form); -.br +\fB#include \fP +.sp +\fBint pos_form_cursor(FORM *\fIform\fB);\fR .SH DESCRIPTION -The function \fBpos_form_cursor\fR restores the cursor to the position required -for the forms driver to continue processing requests. This is useful after -\fBcurses\fR routines have been called to do screen-painting in response to a +The function \fBpos_form_cursor\fP restores the cursor to the position required +for the forms driver to continue processing requests. +This is useful after +\fBcurses\fP routines have been called to do screen-painting in response to a form operation. .SH RETURN VALUE This routine returns one of the following: @@ -56,22 +57,17 @@ Routine detected an incorrect or out-of-range argument. The form has not been posted. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). . .SH SEE ALSO -\fBcurses\fR(3), \fBform\fR(3). +\fBcurses\fP(3), \fBform\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_data.3 b/lib/libform/form_data.3 index 9cc41ff8289..d9d69dea192 100644 --- a/lib/libform/form_data.3 +++ b/lib/libform/form_data.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form_data.3,v 1.12 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_data.3,v 1.13 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,37 +30,34 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_data.3,v 1.12 2015/11/14 01:35:38 jmc Exp $ -.TH form_data 3 "" +.\" $Id: form_data.3,v 1.13 2023/10/17 09:52:10 nicm Exp $ +.TH form_data 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBdata_ahead\fR, \fBdata_behind\fR - test for off-screen data in given forms +\fBdata_ahead\fP, +\fBdata_behind\fP \- test for off-screen data in given forms .SH SYNOPSIS -\fB#include \fR -.br -bool data_ahead(const FORM *form); -.br -bool data_behind(const FORM *form); +\fB#include \fP +.sp +\fBbool data_ahead(const FORM *\fIform\fB);\fR .br +\fBbool data_behind(const FORM *\fIform\fB);\fR .SH DESCRIPTION -The function \fBdata_ahead\fR tests whether there is off-screen data -ahead in the given form. It returns TRUE (1) or FALSE (0). +The function \fBdata_ahead\fP tests whether there is off-screen data +ahead in the given form. +It returns TRUE (1) or FALSE (0). .PP -The function \fBdata_behind\fR tests whether there is off-screen data -behind in the given form. It returns TRUE (1) or FALSE (0). +The function \fBdata_behind\fP tests whether there is off-screen data +behind in the given form. +It returns TRUE (1) or FALSE (0). .SH SEE ALSO -\fBcurses\fR(3), \fBform\fR(3). +\fBcurses\fP(3), \fBform\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_driver.3 b/lib/libform/form_driver.3 index 48d371abe8d..22324800602 100644 --- a/lib/libform/form_driver.3 +++ b/lib/libform/form_driver.3 @@ -1,7 +1,9 @@ -.\" $OpenBSD: form_driver.3,v 1.8 2010/01/12 23:22:07 nicm Exp $ +'\" t +.\" $OpenBSD: form_driver.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2016,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,223 +30,150 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_driver.3,v 1.8 2010/01/12 23:22:07 nicm Exp $ -.TH form_driver 3 "" +.\" $Id: form_driver.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ +.TH form_driver 3 2023-08-19 "ncurses 6.4" "Library calls" +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .SH NAME -\fBform_driver\fR - command-processing loop of the form system +\fBform_driver\fP, +\fBform_driver_w\fP \- command-processing loop of the form system .SH SYNOPSIS -\fB#include \fR -.br -int form_driver(FORM *form, int c); +\fB#include \fP +.sp +\fBint form_driver(FORM *\fIform\fB, int \fIc\fB);\fR .br +\fBint form_driver_w(FORM *\fIform\fB, int \fIc\fB, wchar_t \fIwch\fB);\fR .SH DESCRIPTION +.SS form_driver Once a form has been posted (displayed), you should funnel input events to it -through \fBform_driver\fR. This routine has three major input cases: -.TP 3 -- +through \fBform_driver\fP. This routine has three major input cases: +.bP The input is a form navigation request. Navigation request codes are constants defined in \fB\fP, -which are distinct from the key- and character codes returned by \fBwgetch\fP. -.TP 3 -- +which are distinct from the key- and character codes returned +by \fBwgetch\fP(3). +.bP The input is a printable character. Printable characters (which must be positive, less than 256) are checked according to the program's locale settings. -.TP 3 -- +.bP The input is the KEY_MOUSE special key associated with an mouse event. -.PP +.SS form_driver_w +This extension simplifies the use of the forms library using wide characters. +The input is either a key code (a request) or a wide character +returned by \fBget_wch\fP(3). +The type must be passed as well, +to enable the library to determine whether the parameter +is a wide character or a request. +.SS Form-driver requests The form driver requests are as follows: -.TP 5 -REQ_NEXT_PAGE -Move to the next page. -.TP 5 -REQ_PREV_PAGE -Move to the previous page. -.TP 5 -REQ_FIRST_PAGE -Move to the first page. -.TP 5 -REQ_LAST_PAGE -Move to the last field. -.sp -.TP 5 -REQ_NEXT_FIELD -Move to the next field. -.TP 5 -REQ_PREV_FIELD -Move to the previous field. -.TP 5 -REQ_FIRST_FIELD -Move to the first field. -.TP 5 -REQ_LAST_FIELD -Move to the last field. -.TP 5 -REQ_SNEXT_FIELD -Move to the sorted next field. -.TP 5 -REQ_SPREV_FIELD -Move to the sorted previous field. -.TP 5 -REQ_SFIRST_FIELD -Move to the sorted first field. -.TP 5 -REQ_SLAST_FIELD -Move to the sorted last field. -.TP 5 -REQ_LEFT_FIELD -Move left to a field. -.TP 5 -REQ_RIGHT_FIELD -Move right to a field. -.TP 5 -REQ_UP_FIELD -Move up to a field. -.TP 5 -REQ_DOWN_FIELD -Move down to a field. -.sp -.TP 5 -REQ_NEXT_CHAR -Move to the next char. -.TP 5 -REQ_PREV_CHAR -Move to the previous char. -.TP 5 -REQ_NEXT_LINE -Move to the next line. -.TP 5 -REQ_PREV_LINE -Move to the previous line. -.TP 5 -REQ_NEXT_WORD -Move to the next word. -.TP 5 -REQ_PREV_WORD -Move to the previous word. -.TP 5 -REQ_BEG_FIELD -Move to the beginning of the field. -.TP 5 -REQ_END_FIELD -Move to the end of the field. -.TP 5 -REQ_BEG_LINE -Move to the beginning of the line. -.TP 5 -REQ_END_LINE -Move to the end of the line. -.TP 5 -REQ_LEFT_CHAR -Move left in the field. -.TP 5 -REQ_RIGHT_CHAR -Move right in the field. -.TP 5 -REQ_UP_CHAR -Move up in the field. -.TP 5 -REQ_DOWN_CHAR -Move down in the field. -.sp -.TP 5 -REQ_NEW_LINE -Insert or overlay a new line. -.TP 5 -REQ_INS_CHAR -Insert a blank at the cursor. -.TP 5 -REQ_INS_LINE -Insert a blank line at the cursor. -.TP 5 -REQ_DEL_CHAR -Delete character at the cursor. -.TP 5 -REQ_DEL_PREV -Delete character before the cursor. -.TP 5 -REQ_DEL_LINE -Delete line at the cursor. -.TP 5 -REQ_DEL_WORD -Delete blank-delimited word at the cursor. -.TP 5 -REQ_CLR_EOL -Clear to end of line from cursor. -.TP 5 -REQ_CLR_EOF -Clear to end of field from cursor. -.TP 5 -REQ_CLR_FIELD -Clear the entire field. -.TP 5 -REQ_OVL_MODE -Enter overlay mode. -.TP 5 -REQ_INS_MODE -Enter insert mode. -.sp -.TP 5 -REQ_SCR_FLINE -Scroll the field forward a line. -.TP 5 -REQ_SCR_BLINE -Scroll the field backward a line. -.TP 5 -REQ_SCR_FPAGE -Scroll the field forward a page. -.TP 5 -REQ_SCR_BPAGE -Scroll the field backward a page. -.TP 5 -REQ_SCR_FHPAGE -Scroll the field forward half a page. -.TP 5 -REQ_SCR_BHPAGE -Scroll the field backward half a page. -.sp -.TP 5 -REQ_SCR_FCHAR -Scroll the field forward a character. -.TP 5 -REQ_SCR_BCHAR -Scroll the field backward a character. -.TP 5 -REQ_SCR_HFLINE -Horizontal scroll the field forward a line. -.TP 5 -REQ_SCR_HBLINE -Horizontal scroll the field backward a line. -.TP 5 -REQ_SCR_HFHALF -Horizontal scroll the field forward half a line. -.TP 5 -REQ_SCR_HBHALF -Horizontal scroll the field backward half a line. -.sp -.TP -REQ_VALIDATION -Validate field. -.TP -REQ_NEXT_CHOICE -Display next field choice. -.TP -REQ_PREV_CHOICE -Display previous field choice. +.PP +.TS +l l +_ _ +l l. +\fBName\fP \fBDescription\fP +REQ_BEG_FIELD Move to the beginning of the field. +REQ_BEG_LINE Move to the beginning of the line. +REQ_CLR_EOF Clear to end of field from cursor. +REQ_CLR_EOL Clear to end of line from cursor. +REQ_CLR_FIELD Clear the entire field. +REQ_DEL_CHAR Delete character at the cursor. +REQ_DEL_LINE Delete line at the cursor. +REQ_DEL_PREV Delete character before the cursor. +REQ_DEL_WORD Delete blank-delimited word at the cursor. +REQ_DOWN_CHAR Move down in the field. +REQ_DOWN_FIELD Move down to a field. +REQ_END_FIELD Move to the end of the field. +REQ_END_LINE Move to the end of the line. +REQ_FIRST_FIELD Move to the first field. +REQ_FIRST_PAGE Move to the first page. +REQ_INS_CHAR Insert a blank at the cursor. +REQ_INS_LINE Insert a blank line at the cursor. +REQ_INS_MODE Enter insert mode. +REQ_LAST_FIELD Move to the last field. +REQ_LAST_PAGE Move to the last field. +REQ_LEFT_CHAR Move left in the field. +REQ_LEFT_FIELD Move left to a field. +REQ_NEW_LINE Insert or overlay a new line. +REQ_NEXT_CHAR Move to the next char. +REQ_NEXT_CHOICE Display next field choice. +REQ_NEXT_FIELD Move to the next field. +REQ_NEXT_LINE Move to the next line. +REQ_NEXT_PAGE Move to the next page. +REQ_NEXT_PAGE Move to the next page. +REQ_NEXT_WORD Move to the next word. +REQ_OVL_MODE Enter overlay mode. +REQ_PREV_CHAR Move to the previous char. +REQ_PREV_CHOICE Display previous field choice. +REQ_PREV_FIELD Move to the previous field. +REQ_PREV_LINE Move to the previous line. +REQ_PREV_PAGE Move to the previous page. +REQ_PREV_WORD Move to the previous word. +REQ_RIGHT_CHAR Move right in the field. +REQ_RIGHT_FIELD Move right to a field. +REQ_SCR_BCHAR Scroll the field backward a character. +REQ_SCR_BHPAGE Scroll the field backward half a page. +REQ_SCR_BLINE Scroll the field backward a line. +REQ_SCR_BPAGE Scroll the field backward a page. +REQ_SCR_FCHAR Scroll the field forward a character. +REQ_SCR_FHPAGE Scroll the field forward half a page. +REQ_SCR_FLINE Scroll the field forward a line. +REQ_SCR_FPAGE Scroll the field forward a page. +REQ_SCR_HBHALF Horizontal scroll the field backward half a line. +REQ_SCR_HBLINE Horizontal scroll the field backward a line. +REQ_SCR_HFHALF Horizontal scroll the field forward half a line. +REQ_SCR_HFLINE Horizontal scroll the field forward a line. +REQ_SFIRST_FIELD Move to the sorted first field. +REQ_SLAST_FIELD Move to the sorted last field. +REQ_SNEXT_FIELD Move to the sorted next field. +REQ_SPREV_FIELD Move to the sorted previous field. +REQ_UP_CHAR Move up in the field. +REQ_UP_FIELD Move up to a field. +REQ_VALIDATION Validate field. +.TE .PP If the second argument is a printable character, the driver places it -in the current position in the current field. If it is one of the forms +in the current position in the current field. +If it is one of the forms requests listed above, that request is executed. -.SS MOUSE HANDLING +.SS Field validation +The form library makes updates to the window associated +with form fields rather than directly to the field buffers. +.PP +The form driver provides low-level control over updates to the form fields. +The form driver also provides for validating modified fields +to ensure that the contents +meet whatever constraints an application may attach using \fBset_field_type\fP. .PP +You can validate a field without making any changes to it using +\fBREQ_VALIDATION\fP. +The form driver also validates a field in these cases: +.bP +a call to \fBset_current_field\fP attempts to move to a different field. +.bP +a call to \fBset_current_page\fP attempts to move +to a different page of the form. +.bP +a request attempts to move to a different field. +.bP +a request attempts to move to a different page of the form. +.PP +In each case, the move fails if the field is invalid. +.PP +If the modified field is valid, the form driver copies the modified +data from the window associated with the field +to the field buffer. +.SS Mouse handling If the second argument is the KEY_MOUSE special key, the associated mouse event is translated into one of the above pre-defined requests. -Currently only clicks in the user window (e.g. inside the form display +Currently only clicks in the user window (e.g., inside the form display area or the decoration window) are handled. .PP If you click above the display region of the form: -.RS +.RS 3 .TP a REQ_PREV_FIELD is generated for a single click, .TP @@ -254,7 +183,7 @@ a REQ_FIRST_FIELD is generated for a triple-click. .RE .PP If you click below the display region of the form: -.RS +.RS 3 .TP a REQ_NEXT_FIELD is generated for a single click, .TP @@ -264,37 +193,34 @@ a REQ_LAST_FIELD is generated for a triple-click. .RE .PP If you click at an field inside the display area of the form: -.RS -.TP 3 -- +.RS 3 +.bP the form cursor is positioned to that field. -.TP 3 -- +.bP If you double-click a field, the form cursor is positioned to that field -and \fBE_UNKNOWN_COMMAND\fR is returned. +and \fBE_UNKNOWN_COMMAND\fP is returned. This return value makes sense, because a double click usually means that an field-specific action should be returned. It is exactly the purpose of this return value to signal that an application specific command should be executed. -.TP 3 -- +.bP If a translation -into a request was done, \fBform_driver\fR returns the result of this request. +into a request was done, \fBform_driver\fP returns the result of this request. .RE .PP -If you clicked outside the user window or the mouse event could not be translated -into a form request an \fBE_REQUEST_DENIED\fR is returned. -.SS APPLICATION-DEFINED COMMANDS -.PP +If you clicked outside the user window +or the mouse event could not be translated +into a form request an \fBE_REQUEST_DENIED\fP is returned. +.SS Application-defined commands If the second argument is neither printable nor one of the above pre-defined form requests, the driver assumes it is an application-specific -command and returns \fBE_UNKNOWN_COMMAND\fR. Application-defined commands -should be defined relative to \fBMAX_COMMAND\fR, the maximum value of these +command and returns \fBE_UNKNOWN_COMMAND\fP. Application-defined commands +should be defined relative to \fBMAX_COMMAND\fP, the maximum value of these pre-defined requests. .SH RETURN VALUE -\fBform_driver\fR returns one of the following error codes: +\fBform_driver\fP returns one of the following error codes: .TP 5 .B E_OK The routine succeeded. @@ -311,31 +237,33 @@ The form has not been posted. .B E_INVALID_FIELD Contents of field is invalid. .TP 5 +.B E_NOT_CONNECTED +No fields are connected to the form. +.TP 5 .B E_REQUEST_DENIED The form driver could not process the request. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .TP 5 .B E_UNKNOWN_COMMAND The form driver code saw an unknown request code. . .SH SEE ALSO -\fBcurses\fR(3), -\fBform\fR(3), -\fBwgetch\fR(3). +\fBcurses\fP(3), +\fBform\fP(3), +\fBform_fieldtype\fP(3), +\fBform_field_buffer\fP(3), +\fBform_field_validation\fP(3), +\fBform_variables\fP(3), +\fBgetch\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header files -\fB\fR. +The header file \fB\fP automatically includes the header files +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_field.3 b/lib/libform/form_field.3 index 7821967c22d..0f38461196f 100644 --- a/lib/libform/form_field.3 +++ b/lib/libform/form_field.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form_field.3,v 1.10 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_field.3,v 1.11 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2003,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2012 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,41 +30,38 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_field.3,v 1.10 2015/11/14 01:35:38 jmc Exp $ -.TH form_field 3 "" +.\" $Id: form_field.3,v 1.11 2023/10/17 09:52:10 nicm Exp $ +.TH form_field 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBset_form_fields\fR, \fBform_fields\fR, -\fBfield_count\fR, \fBmove_field\fR -- make and break connections between fields and forms +\fBform_field\fP \- make and break connections between fields and forms .SH SYNOPSIS -\fB#include \fR +\fB#include \fP +.sp +\fBint set_form_fields(FORM *\fIform\fB, FIELD **\fIfields\fB);\fR .br -int set_form_fields(FORM *form, FIELD **fields); +\fBFIELD **form_fields(const FORM *\fIform\fB);\fR .br -FIELD **form_fields(const FORM *form); -.br -int field_count(const FORM *form); -.br -int move_field(FIELD *field, int frow, int fcol); +\fBint field_count(const FORM *\fIform\fB);\fR .br +\fBint move_field(FIELD *\fIfield\fB, int \fIfrow\fB, int \fIfcol\fB);\fR .SH DESCRIPTION -The function \fBset_form_fields\fR changes the field pointer array of -the given \fIform\fR. The array must be terminated by a \fBNULL\fR. +The function \fBset_form_fields\fP changes the field pointer array of +the given \fIform\fP. The array must be terminated by a \fBNULL\fP. .PP -The function \fBform_fields\fR returns the field array of the given form. +The function \fBform_fields\fP returns the field array of the given form. .PP -The function \fBfield_count\fR returns the count of fields in \fIform\fR. +The function \fBfield_count\fP returns the count of fields in \fIform\fP. .PP -The function \fBmove_field\fR moves the given field (which must be disconnected) +The function \fBmove_field\fP moves the given field (which must be disconnected) to a specified location on the screen. -.SH RETURN VALUES -The function \fBform_fields\fR returns a pointer (which may be \fBNULL\fR). -It does not set errno. +.SH RETURN VALUE +The function \fBform_fields\fP returns a pointer (which may be \fBNULL\fP). +It does not set \fBerrno\fP. .PP -The function \fBfield_count\fR returns \fBERR\fR if the \fIform\fP parameter +The function \fBfield_count\fP returns \fBERR\fP if the \fIform\fP parameter is \fBNULL\fP. .PP -The functions \fBset_form_fields\fR and \fBmove_field\fR return one of +The functions \fBset_form_fields\fP and \fBmove_field\fP return one of the following codes on error: .TP 5 .B E_OK @@ -79,24 +77,19 @@ The field is already connected to a form. The form is already posted. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .SH SEE ALSO -\fBcurses\fR(3), \fBform\fR(3). +\fBcurses\fP(3), \fBform\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. .PP -The SVr4 forms library documentation specifies the \fBfield_count\fR error value -as -1 (which is the value of \fBERR\fR). +The SVr4 forms library documentation specifies the \fBfield_count\fP error value +as \-1 (which is the value of \fBERR\fP). .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_field_attributes.3 b/lib/libform/form_field_attributes.3 index 1a8aa955021..062f64fffff 100644 --- a/lib/libform/form_field_attributes.3 +++ b/lib/libform/form_field_attributes.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form_field_attributes.3,v 1.9 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_field_attributes.3,v 1.10 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2002,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2006,2010 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,41 +30,45 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_field_attributes.3,v 1.9 2015/11/14 01:35:38 jmc Exp $ -.TH form_field_attributes 3 "" +.\" $Id: form_field_attributes.3,v 1.10 2023/10/17 09:52:10 nicm Exp $ +.TH form_field_attributes 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .SH NAME -\fBset_field_fore\fR, \fBfield_fore\fR, -\fBset_field_back\fR, \fBfield_back\fR, -\fBset_field_pad\fR, \fBfield_pad\fR -- color and attribute control for form fields +\fBform_field_attributes\fP \- color and attribute control for form fields .SH SYNOPSIS -\fB#include \fR +\fB#include \fP +.sp +\fBint set_field_fore(FIELD *\fIfield\fB, chtype \fIattr\fB);\fR .br -int set_field_fore(FIELD *field, chtype attr); +\fBchtype field_fore(const FIELD *\fIfield\fB);\fR +.sp +\fBint set_field_back(FIELD *\fIfield\fB, chtype \fIattr\fB);\fR .br -chtype field_fore(const FIELD *field); -.br -int set_field_back(FIELD *field, chtype attr); -.br -chtype field_back(const FIELD *field); -.br -int set_field_pad(FIELD *field, int pad); -.br -int field_pad(const FIELD *field); +\fBchtype field_back(const FIELD *\fIfield\fB);\fR +.sp +\fBint set_field_pad(FIELD *\fIfield\fB, int \fIpad\fB);\fR .br +\fBint field_pad(const FIELD *\fIfield\fB);\fR .SH DESCRIPTION -The function \fBset_field_fore\fR sets the foreground attribute of -\fIfield\fR. This is the highlight used to display the field contents. The -function \fBfield_fore\fR returns the foreground attribute. The default is -\fBA_STANDOUT\fR. +The function \fBset_field_fore\fP sets the foreground attribute of +\fIfield\fP. This is the highlight used to display the field contents. The +function \fBfield_fore\fP returns the foreground attribute. +The default is +\fBA_STANDOUT\fP. .PP -The function \fBset_field_back\fR sets the background attribute of -\fIform\fR. This is the highlight used to display the extent fields in the -form. The function \fBfield_back\fR returns the background attribute. The -default is \fBA_NORMAL\fR. +The function \fBset_field_back\fP sets the background attribute of +\fIform\fP. This is the highlight used to display the extent fields in the +form. +The function \fBfield_back\fP returns the background attribute. +The +default is \fBA_NORMAL\fP. .PP -The function \fBset_field_pad\fR sets the character used to fill the field. -The function \fBfield_pad\fR returns the given form's pad character. The +The function \fBset_field_pad\fP sets the character used to fill the field. +The function \fBfield_pad\fP returns the given form's pad character. +The default is a blank. .SH RETURN VALUE These routines return one of the following: @@ -75,23 +80,18 @@ The routine succeeded. Routine detected an incorrect or out-of-range argument. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). . .SH SEE ALSO -\fBcurses\fR(3) and related pages whose names begin "form_" for detailed +\fBcurses\fP(3) and related pages whose names begin \*(``form_\*('' for detailed descriptions of the entry points. .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_field_buffer.3 b/lib/libform/form_field_buffer.3 index 4686b66d33f..23f2df901a3 100644 --- a/lib/libform/form_field_buffer.3 +++ b/lib/libform/form_field_buffer.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form_field_buffer.3,v 1.13 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_field_buffer.3,v 1.14 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,78 +30,77 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_field_buffer.3,v 1.13 2015/11/14 01:35:38 jmc Exp $ -.TH form_field_buffer 3 "" +.\" $Id: form_field_buffer.3,v 1.14 2023/10/17 09:52:10 nicm Exp $ +.TH form_field_buffer 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .SH NAME -\fBset_field_buffer\fR, \fBfield_buffer\fR, -\fBset_field_status\fR, \fBfield_status\fR, -\fBset_max_field\fR - field buffer control +\fBform_field_buffer\fP \- field buffer control .SH SYNOPSIS -\fB#include \fR +\fB#include \fP +.sp +\fBint set_field_buffer(FIELD *\fIfield\fB, int \fIbuf\fB, const char *\fIvalue\fB);\fR .br -int set_field_buffer(FIELD *field, int buf, const char *value); -.br -char *field_buffer(const FIELD *field, int buffer); -.br -int set_field_status(FIELD *field, bool status); -.br -bool field_status(const FIELD *field); -.br -int set_max_field(FIELD *field, int max); +\fBchar *field_buffer(const FIELD *\fIfield\fB, int \fIbuffer\fB);\fR +.sp +\fBint set_field_status(FIELD *\fIfield\fB, bool \fIstatus\fB);\fR .br +\fBbool field_status(const FIELD *\fIfield\fB);\fR +.sp +\fBint set_max_field(FIELD *\fIfield\fB, int \fImax\fB);\fR .SH DESCRIPTION -The function \fBset_field_buffer\fR sets the numbered buffer of the given field +The function \fBset_field_buffer\fP sets the numbered buffer of the given field to contain a given string: .RS 3 -.TP 3 -- +.bP Buffer 0 is the displayed value of the field. -.TP 3 -- -Other numbered buffers may be allocated by applications through the \fBnbuf\fR -argument of (see \fBform_field_new\fR(3)) +.bP +Other numbered buffers may be allocated by applications through the \fBnbuf\fP +argument of (see \fBform_field_new\fP(3)) but are not manipulated by the forms library. .RE .PP -The function \fBfield_buffer\fR returns a pointer to +The function \fBfield_buffer\fP returns a pointer to the contents of the given numbered buffer: .RS 3 -.TP 3 -- +.bP The buffer contents always have the same length, and are padded with trailing spaces as needed to ensure this length is the same. -.TP 3 -- +.bP The buffer may contain leading spaces, depending on how it was set. -.TP 3 -- +.bP The buffer contents are set with \fBset_field_buffer\fP, or as a side effect of any editing operations on the corresponding field. -.TP 3 -- +.bP Editing operations are based on the \fIwindow\fP which displays the field, rather than a \fIstring\fP. The window contains only printable characters, and is filled with blanks. If you want the raw data, you must write your own routine that copies the value out of the buffer and removes the leading and trailing spaces. -.TP 3 -- +.bP Because editing operations change the content of the buffer to correspond to the window, you should not rely on using buffers for long-term storage of form data. .RE .PP -The function \fBset_field_status\fR sets the associated status flag of -\fIfield\fR; \fBfield_status\fR gets the current value. The status flag +The function \fBset_field_status\fP sets the associated status flag of +\fIfield\fP; \fBfield_status\fP gets the current value. +The status flag is set to a nonzero value whenever the field changes. .PP -The function \fBset_max_field\fR sets the maximum size for a dynamic field. +The function \fBset_max_field\fP sets the maximum size for a dynamic field. An argument of 0 turns off any maximum size threshold for that field. .SH RETURN VALUE -The \fBfield_buffer\fR function returns NULL on error. -It sets errno according to their success: +The \fBfield_buffer\fP function returns NULL on error. +It sets \fBerrno\fP according to their success: .TP 5 .B E_OK The routine succeeded. @@ -108,7 +108,7 @@ The routine succeeded. .B E_BAD_ARGUMENT Routine detected an incorrect or out-of-range argument. .PP -The \fBfield_status\fR function returns \fBTRUE\fR or \fBFALSE\fR. +The \fBfield_status\fP function returns \fBTRUE\fP or \fBFALSE\fP. .PP The remaining routines return one of the following: .TP 5 @@ -116,31 +116,30 @@ The remaining routines return one of the following: The routine succeeded. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .TP 5 .B E_BAD_ARGUMENT Routine detected an incorrect or out-of-range argument. .SH SEE ALSO -\fBcurses\fR(3) and related pages whose names begin "form_" for detailed +\fBcurses\fP(3) and related pages whose names begin \*(``form_\*('' for detailed descriptions of the entry points. .SH NOTES -The header file \fB\fR automatically includes the header file +The header file \fB\fP automatically includes the header file .PP -When configured for wide-characters, \fBfield_buffer\fP returns a pointer +When configured for wide characters, \fBfield_buffer\fP returns a pointer to temporary storage (allocated and freed by the library). The application should not attempt to modify the data. It will be freed on the next call to \fBfield_buffer\fP to return the same buffer. -\fB\fR. +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. +.PP +The \fBset_max_field\fP function checks for an ncurses extension +\fBO_INPUT_FIELD\fP which allows a dynamic field to shrink if the new +limit is smaller than the current field size. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_field_info.3 b/lib/libform/form_field_info.3 index b5c790726e0..529c4d129e1 100644 --- a/lib/libform/form_field_info.3 +++ b/lib/libform/form_field_info.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form_field_info.3,v 1.10 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_field_info.3,v 1.11 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2021,2022 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,29 +30,40 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_field_info.3,v 1.10 2015/11/14 01:35:38 jmc Exp $ -.TH form_field_info 3 "" +.\" $Id: form_field_info.3,v 1.11 2023/10/17 09:52:10 nicm Exp $ +.TH form_field_info 3 2022-02-12 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .SH NAME -\fBfield_info\fR, \fBdynamic_field_info\fR - retrieve field characteristics +\fBdynamic_field_info\fP, +\fBfield_info\fP \- retrieve field characteristics .SH SYNOPSIS -\fB#include \fR -.br -int field_info(const FIELD *field, int *rows, int *cols, - int *frow, int *fcol, int *nrow, int *nbuf); -.br -int dynamic_field_info(const FIELD *field, int *rows, int *cols, int *max); -.br +.nf +\fB#include \fP +.sp +\fBint field_info(const FIELD *\fIfield\fB,\fR + \fBint *\fIrows\fB, int *\fIcols\fB,\fR + \fBint *\fIfrow\fB, int *\fIfcol\fB,\fR + \fBint *\fInrow\fB, int *\fInbuf\fB);\fR +.sp +\fBint dynamic_field_info(const FIELD *\fIfield\fB,\fR + \fBint *\fIrows\fB, int *\fIcols\fB, int *\fImax\fB);\fR +.fi .SH DESCRIPTION -The function \fBfield_info\fR returns the sizes and other attributes passed in -to the field at its creation time. The attributes are: height, width, row of +The function \fBfield_info\fP returns the sizes and other attributes passed in +to the field at its creation time. +The attributes are: height, width, row of upper-left corner, column of upper-left corner, number off-screen rows, and number of working buffers. .PP -The function \fBdynamic_field_info\fR returns the actual size of the field, and -its maximum possible size. If the field has no size limit, the location +The function \fBdynamic_field_info\fP returns the actual size of the field, and +its maximum possible size. +If the field has no size limit, the location addressed by the third argument will be set to 0. A field can be made dynamic -by turning off the \fBO_STATIC\fR option with \fBfield_opts_off\fR. +by turning off the \fBO_STATIC\fP option with \fBfield_opts_off\fP. .SH RETURN VALUE These routines return one of the following: .TP 5 @@ -59,29 +71,24 @@ These routines return one of the following: The routine succeeded. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .TP 5 .B E_BAD_ARGUMENT Routine detected an incorrect or out-of-range argument. .SH SEE ALSO -\fBcurses\fR(3) and related pages whose names begin "form_" for detailed +\fBcurses\fP(3) and related pages whose names begin \*(``form_\*('' for detailed descriptions of the entry points. .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. .PP A null (zero pointer) is accepted for any of the return values, to ignore that value. Not all implementations allow this, e.g., Solaris 2.7 does not. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_field_just.3 b/lib/libform/form_field_just.3 index a19df8ea15c..9415e175f0f 100644 --- a/lib/libform/form_field_just.3 +++ b/lib/libform/form_field_just.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form_field_just.3,v 1.10 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_field_just.3,v 1.11 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2003,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,52 +30,51 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_field_just.3,v 1.10 2015/11/14 01:35:38 jmc Exp $ -.TH form_field_just 3 "" +.\" $Id: form_field_just.3,v 1.11 2023/10/17 09:52:10 nicm Exp $ +.TH form_field_just 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .SH NAME -\fBset_field_just\fR, \fBfield_just\fR - retrieve field characteristics +\fBset_field_just\fP, +\fBfield_just\fP \- retrieve field characteristics .SH SYNOPSIS -\fB#include \fR -.br -int set_field_just(FIELD *field, int justification); -.br -int field_just(const FIELD *field); +\fB#include \fP +.sp +\fBint set_field_just(FIELD *\fIfield\fB, int \fIjustification\fB);\fR .br +\fBint field_just(const FIELD *\fIfield\fB);\fR .SH DESCRIPTION -The function \fBset_field_just\fR sets the justification attribute of -a field; \fBfield_just\fR returns a field's justification attribute. +The function \fBset_field_just\fP sets the justification attribute of +a field; \fBfield_just\fP returns a field's justification attribute. The attribute may be one of NO_JUSTIFICATION, JUSTIFY_RIGHT, JUSTIFY_LEFT, or JUSTIFY_CENTER. . .SH RETURN VALUE -The function \fBfield_just\fR returns one of: NO_JUSTIFICATION, +The function \fBfield_just\fP returns one of: NO_JUSTIFICATION, JUSTIFY_RIGHT, JUSTIFY_LEFT, or JUSTIFY_CENTER. .PP -The function \fBset_field_just\fR returns one of the following: +The function \fBset_field_just\fP returns one of the following: .TP 5 .B E_OK The routine succeeded. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .TP 5 .B E_BAD_ARGUMENT Routine detected an incorrect or out-of-range argument. .SH SEE ALSO -\fBcurses\fR(3) and related pages whose names begin "form_" for detailed +\fBcurses\fP(3) and related pages whose names begin \*(``form_\*('' for detailed descriptions of the entry points. .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_field_new.3 b/lib/libform/form_field_new.3 index 6b7266d52ea..f349be6346a 100644 --- a/lib/libform/form_field_new.3 +++ b/lib/libform/form_field_new.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form_field_new.3,v 1.11 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_field_new.3,v 1.12 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,44 +30,47 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_field_new.3,v 1.11 2015/11/14 01:35:38 jmc Exp $ -.TH form_field_new 3 "" +.\" $Id: form_field_new.3,v 1.12 2023/10/17 09:52:10 nicm Exp $ +.TH form_field_new 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBnew_field\fR, \fBdup_field\fR, -\fBlink_field\fR, \fBfree_field\fR -- create and destroy form fields +\fBnew_field\fP, +\fBdup_field\fP, +\fBlink_field\fP, +\fBfree_field\fP \- create and destroy form fields .SH SYNOPSIS -\fB#include \fR +\fB#include \fP +.sp +\fBFIELD *new_field(int \fIheight\fB, int \fIwidth\fB,\fR + \fBint \fItoprow\fB, int \fIleftcol\fB,\fR + \fBint \fIoffscreen\fB, int \fInbuffers\fB);\fR .br -FIELD *new_field(int height, int width, - int toprow, int leftcol, - int offscreen, int nbuffers); +\fBFIELD *dup_field(FIELD *\fIfield\fB, int \fItoprow\fB, int \fIleftcol\fB);\fR .br -FIELD *dup_field(FIELD *field, int toprow, int leftcol); -.br -FIELD *link_field(FIELD *field, int toprow, int leftcol); -.br -int free_field(FIELD *field); +\fBFIELD *link_field(FIELD *\fIfield\fB, int \fItoprow\fB, int \fIleftcol\fB);\fR .br +\fBint free_field(FIELD *\fIfield\fB);\fR .SH DESCRIPTION -The function \fBnew_field\fR allocates a new field and initializes it from the +The function \fBnew_field\fP allocates a new field and initializes it from the parameters given: height, width, row of upper-left corner, column of upper-left corner, number off-screen rows, and number of additional working buffers. .PP -The function \fBdup_field\fR duplicates a field at a new location. Most +The function \fBdup_field\fP duplicates a field at a new location. +Most attributes (including current contents, size, validation type, buffer count, growth threshold, justification, foreground, background, pad character, -options, and user pointer) are copied. Field status and the field page bit are +options, and user pointer) are copied. +Field status and the field page bit are not copied. .PP -The function \fBlink_field\fR acts like \fBdup_field\fR, but the new field -shares buffers with its parent. Attribute data is separate. +The function \fBlink_field\fP acts like \fBdup_field\fP, but the new field +shares buffers with its parent. +Attribute data is separate. .PP -The function \fBfree_field\fR de-allocates storage associated with a field. +The function \fBfree_field\fP de-allocates storage associated with a field. .SH RETURN VALUE -The function, \fBnew_field\fR, \fBdup_field\fR, \fBlink_field\fR return -\fBNULL\fR on error. -They set errno according to their success: +The functions \fBnew_field\fP, \fBdup_field\fP, \fBlink_field\fP return +\fBNULL\fP on error. +They set \fBerrno\fP according to their success: .TP 5 .B E_OK The routine succeeded. @@ -77,7 +81,7 @@ Routine detected an incorrect or out-of-range argument. .B E_SYSTEM_ERROR System error occurred, e.g., malloc failure. .PP -The function \fBfree_field\fR returns one of the following: +The function \fBfree_field\fP returns one of the following: .TP 5 .B E_OK The routine succeeded. @@ -88,23 +92,18 @@ Routine detected an incorrect or out-of-range argument. .B E_CONNECTED field is connected. .SH SEE ALSO -\fBcurses\fR(3), \fBform\fR(3). +\fBcurses\fP(3), \fBform\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. .PP It may be unwise to count on the set of attributes copied by -\fBdup_field\fR being portable; the System V forms library documents are +\fBdup_field\fP being portable; the System V forms library documents are not very explicit about what gets copied and what does not. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_field_opts.3 b/lib/libform/form_field_opts.3 index 7936d8b9f6b..1f156eb58d6 100644 --- a/lib/libform/form_field_opts.3 +++ b/lib/libform/form_field_opts.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form_field_opts.3,v 1.12 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_field_opts.3,v 1.13 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2014,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,73 +30,99 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_field_opts.3,v 1.12 2015/11/14 01:35:38 jmc Exp $ -.TH form_field_opts 3 "" +.\" $Id: form_field_opts.3,v 1.13 2023/10/17 09:52:10 nicm Exp $ +.TH form_field_opts 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBset_field_opts\fR, \fBfield_opts_on\fR, -\fBfield_opts_off\fR, \fBfield_opts\fR -- set and get field options +\fBset_field_opts\fP, +\fBfield_opts_on\fP, +\fBfield_opts_off\fP, +\fBfield_opts\fP \- set and get field options .SH SYNOPSIS -\fB#include \fR +\fB#include \fP +.sp +\fBint set_field_opts(FIELD *\fIfield\fB, Field_Options \fIopts\fB);\fR .br -int set_field_opts(FIELD *field, Field_Options opts); -.br -int field_opts_on(FIELD *field, Field_Options opts); -.br -int field_opts_off(FIELD *field, Field_Options opts); -.br -Field_Options field_opts(const FIELD *field); +\fBField_Options field_opts(const FIELD *\fIfield\fB);\fR +.sp +\fBint field_opts_on(FIELD *\fIfield\fB, Field_Options \fIopts\fB);\fR .br +\fBint field_opts_off(FIELD *\fIfield\fB, Field_Options \fIopts\fB);\fR .SH DESCRIPTION -The function \fBset_field_opts\fR sets all the given field's option bits (field -option bits may be logically OR'ed together). +The function \fBset_field_opts\fP sets all the given field's option bits (field +option bits may be logically-OR'ed together). .PP -The function \fBfield_opts_on\fR turns on the given option bits, and leaves +The function \fBfield_opts_on\fP turns on the given option bits, and leaves others alone. .PP -The function \fBfield_opts_off\fR turns off the given option bits, and leaves +The function \fBfield_opts_off\fP turns off the given option bits, and leaves others alone. .PP -The function \fBfield_opts\fR returns the field's current option bits. +The function \fBfield_opts\fP returns the field's current option bits. .PP -The following options are defined (all are on by default): -.TP 5 -O_VISIBLE -The field is displayed. If this option is off, display of the field is -suppressed. +The following standard options are defined (all are on by default): .TP 5 O_ACTIVE -The field is visited during processing. If this option is off, the field will -not be reachable by navigation keys. Please notice that an invisible field +The field is visited during processing. +If this option is off, the field will +not be reachable by navigation keys. +Please notice that an invisible field appears to be inactive also. .TP 5 -O_PUBLIC -The field contents are displayed as data is entered. -.TP 5 -O_EDIT -The field can be edited. -.TP 5 -O_WRAP -Words that do not fit on a line are wrapped to the next line. Words are -blank-separated. +O_AUTOSKIP +Skip to the next field when this one fills. .TP 5 O_BLANK The field is cleared whenever a character is entered at the first position. .TP 5 -O_AUTOSKIP -Skip to the next field when this one fills. +O_EDIT +The field can be edited. .TP 5 O_NULLOK Allow a blank field. .TP 5 +O_PASSOK +Validate field only if modified by user. +.TP 5 +O_PUBLIC +The field contents are displayed as data is entered. +.TP 5 O_STATIC Field buffers are fixed to field's original size. Turn this option off to create a dynamic field. .TP 5 -O_PASSOK -Validate field only if modified by user. +O_VISIBLE +The field is displayed. +If this option is off, display of the field is +suppressed. +.TP 5 +O_WRAP +Words that do not fit on a line are wrapped to the next line. +Words are +blank-separated. +.PP +These extension options are defined (extensions are off by default): +.TP 5 +O_DYNAMIC_JUSTIFY +Permit dynamic fields to be justified, like static fields. +.TP 5 +O_NO_LEFT_STRIP +Preserve leading whitespace in the field buffer, which is normally discarded. +.TP 5 +O_EDGE_INSERT_STAY +When inserting into a field up to the boundary position, +optionally delay the scrolling, +so that the last inserted character remains visible, +but advance the cursor to reflect the insertion. +This allows the form library to display the +inserted character in one-character fields +as well as allowing the library to maintain consistent state. +.TP 5 +O_INPUT_FIELD +The \fBset_max_field\fP function checks for this extension, +which allows a dynamic field to shrink if the new +limit is smaller than the current field size. .SH RETURN VALUE -Except for \fBfield_opts\fR, each routine returns one of the following: +Except for \fBfield_opts\fP, each routine returns one of the following: .TP 5 .B E_OK The routine succeeded. @@ -107,21 +134,18 @@ Routine detected an incorrect or out-of-range argument. The field is the current field. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .SH SEE ALSO -\fBcurses\fR(3), \fBform\fR(3). +\fBcurses\fP(3), +\fBform\fP(3). +\fBform_field_just\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_field_userptr.3 b/lib/libform/form_field_userptr.3 index 6cbb483d29b..83e54b58bc9 100644 --- a/lib/libform/form_field_userptr.3 +++ b/lib/libform/form_field_userptr.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form_field_userptr.3,v 1.9 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_field_userptr.3,v 1.10 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2021,2022 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,44 +30,39 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_field_userptr.3,v 1.9 2015/11/14 01:35:38 jmc Exp $ -.TH form_field_userptr 3 "" +.\" $Id: form_field_userptr.3,v 1.10 2023/10/17 09:52:10 nicm Exp $ +.TH form_field_userptr 3 2022-02-12 "ncurses 6.4" "Library calls" .SH NAME -\fBset_field_userptr\fR, \fBfield_userptr\fR -- associate application data with a form field +\fBset_field_userptr\fP, +\fBfield_userptr\fP \- associate application data with a form field .SH SYNOPSIS -\fB#include \fR -.br -int set_field_userptr(FIELD *field, void*userptr); -.br -void *field_userptr(const FIELD *field); +\fB#include \fP +.sp +\fBint set_field_userptr(FIELD *\fIfield\fB, void *\fIuserptr\fB);\fR .br +\fBvoid *field_userptr(const FIELD *\fIfield\fB);\fR .SH DESCRIPTION Every form field has a field that can be used to hold application-specific data -(that is, the form-driver code leaves it alone). These functions get and set +(that is, the form-driver code leaves it alone). +These functions get and set that field. .SH RETURN VALUE -The function \fBfield_userptr\fR returns a pointer (which may be \fBNULL\fR). -It does not set errno. +The function \fBfield_userptr\fP returns a pointer (which may be \fBNULL\fP). +It does not set \fBerrno\fP. .PP -The function \fBset_field_userptr\fR returns \fBE_OK\fP (success). +The function \fBset_field_userptr\fP returns \fBE_OK\fP (success). .SH SEE ALSO -\fBcurses\fR(3), \fBform\fR(3). +\fBcurses\fP(3), \fBform\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. .PP The user pointer is a void pointer. We chose not to leave it as a char pointer for SVr4 compatibility. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_field_validation.3 b/lib/libform/form_field_validation.3 index f196f792f4e..7b43ea69f50 100644 --- a/lib/libform/form_field_validation.3 +++ b/lib/libform/form_field_validation.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: form_field_validation.3,v 1.10 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_field_validation.3,v 1.11 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2003,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,120 +29,206 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_field_validation.3,v 1.10 2015/11/14 01:35:38 jmc Exp $ -.TH form_field_validation 3 "" +.\" $Id: form_field_validation.3,v 1.11 2023/10/17 09:52:10 nicm Exp $ +.TH form_field_validation 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .SH NAME -\fBset_field_type\fR, \fBfield_type\fR, -\fBfield_arg\fR - data type validation for fields +\fBform_field_validation\fP \- data type validation for fields .SH SYNOPSIS -\fB#include \fR -.br -int set_field_type(FIELD *field, FIELDTYPE *type, ...); +\fB#include \fP +.sp +\fBvoid *field_arg(const FIELD *\fIfield\fB);\fR .br -FIELDTYPE *field_type(const FIELD *field); +\fBFIELDTYPE *field_type(const FIELD *\fIfield\fB);\fR .br -void *field_arg(const FIELD *field); +\fBint set_field_type(FIELD *\fIfield\fB, FIELDTYPE *\fItype\fB, ...);\fR .sp -FIELDTYPE *TYPE_ALNUM; +/* predefined field types */ .br -FIELDTYPE *TYPE_ALPHA; +\fBFIELDTYPE *TYPE_ALNUM;\fP .br -FIELDTYPE *TYPE_ENUM; +\fBFIELDTYPE *TYPE_ALPHA;\fP .br -FIELDTYPE *TYPE_INTEGER; +\fBFIELDTYPE *TYPE_ENUM;\fP .br -FIELDTYPE *TYPE_NUMERIC; +\fBFIELDTYPE *TYPE_INTEGER;\fP .br -FIELDTYPE *TYPE_REGEXP; +\fBFIELDTYPE *TYPE_NUMERIC;\fP .br -FIELDTYPE *TYPE_IPV4; +\fBFIELDTYPE *TYPE_REGEXP;\fP .br +\fBFIELDTYPE *TYPE_IPV4;\fP .SH DESCRIPTION -The function \fBset_field_type\fR declares a data type for a given form field. +By default, no validation is done on form fields. +You can associate a form with with a \fIfield type\fP, +making the form library validate input. +.SS field_arg +Returns a pointer to the field's argument block. +The \fIargument block\fP is an opaque structure containing +a copy of the arguments provided in a \fBset_field_type\fP call. +.SS field_type +Returns a pointer to the \fIfield type\fP associated with the form field, +i.e., by calling \fBset_field_type\fP. +.SS set_field_type +The function \fBset_field_type\fP associates +a field type with a given form field. This is the type checked by validation functions. +Most field types are configurable, +via arguments which the caller provides when calling \fBset_field_type\fP. +.PP +Several field types are predefined by the form library. +.SS Predefined types +It is possible to set up new programmer-defined field types. +Field types are implemented via the \fBFIELDTYPE\fP data +structure, which contains several pointers to functions. +.PP +See the \fBform_fieldtype\fP(3) manual page, +which describes functions which can be used to construct +a field-type dynamically. +.PP The predefined types are as follows: .TP 5 TYPE_ALNUM -Alphanumeric data. Requires a third \fBint\fR argument, a minimum field width. +Alphanumeric data. +Required parameter: +.RS +.bP +a third \fBint\fP argument, a minimum field width. +.RE .TP 5 TYPE_ALPHA -Character data. Requires a third \fBint\fR argument, a minimum field width. +Character data. +Required parameter: +.RS +.bP +a third \fBint\fP argument, a minimum field width. +.RE .TP 5 TYPE_ENUM -Accept one of a specified set of strings. Requires a third \fB(char **)\fR -argument pointing to a string list; a fourth \fBint\fR flag argument to enable -case-sensitivity; and a fifth \fBint\fR flag argument specifying whether a partial -match must be a unique one (if this flag is off, a prefix matches the first -of any set of more than one list elements with that prefix). Please notice -that the string list is not copied, only a reference to it is stored in the -field. So you should avoid using a list that lives in automatic variables -on the stack. +Accept one of a specified set of strings. +Required parameters: +.RS +.bP +a third \fB(char **)\fP argument pointing to a string list; +.bP +a fourth \fBint\fP flag argument to enable case-sensitivity; +.bP +a fifth \fBint\fP flag argument specifying whether a partial +match must be a unique one. +If this flag is off, a prefix matches the first +of any set of more than one list elements with that prefix. +.RE +.IP +The library copies the string list, +so you may use a list that lives in automatic variables on the stack. .TP 5 TYPE_INTEGER -Integer data, parsable to an integer by \fBatoi(3)\fR. Requires a third -\fBint\fR argument controlling the precision, a fourth \fBlong\fR argument -constraining minimum value, and a fifth \fBlong\fR constraining maximum value. +Integer data, parsable to an integer by \fBatoi\fP(3). +Required parameters: +.RS +.bP +a third \fBint\fP argument controlling the precision, +.bP +a fourth \fBlong\fP argument constraining minimum value, +.bP +a fifth \fBlong\fP constraining maximum value. If the maximum value is less than or equal to the minimum value, the range is -simply ignored. On return the field buffer is formatted according to the -\fBprintf\fR format specification ".*ld", where the '*' is replaced by the -precision argument. -For details of the precision handling see \fBprintf's\fR man-page. +simply ignored. +.RE +.IP +On return, the field buffer is formatted according to the +\fBprintf\fP format specification \*(``.*ld\*('', +where the \*(``*\*('' is replaced by the precision argument. +.IP +For details of the precision handling see \fBprintf\fP(3). .TP 5 TYPE_NUMERIC -Numeric data (may have a decimal-point part). Requires a third -\fBint\fR argument controlling the precision, a fourth \fBdouble\fR -argument constraining minimum value, and a fifth \fBdouble\fR constraining -maximum value. If your system supports locales, the decimal point character -to be used must be the one specified by your locale. -If the maximum value is less than or equal to the minimum value, the range is -simply ignored. On return the field buffer is formatted according to the -\fBprintf\fR format specification ".*f", where the '*' is replaced by the -precision argument. -For details of the precision handling see \fBprintf's\fR man-page. +Numeric data (may have a decimal-point part). +Required parameters: +.RS +.bP +a third \fBint\fP argument controlling the precision, +.bP +a fourth \fBdouble\fP argument constraining minimum value, +.bP +and a fifth \fBdouble\fP constraining maximum value. +If your system supports locales, +the decimal point character must be the one specified by your locale. +If the maximum value is less than or equal to the minimum value, +the range is simply ignored. +.RE +.IP +On return, the field buffer is formatted according to the +\fBprintf\fP format specification \*(``.*f\*('', +where the \*(``*\*('' is replaced by the precision argument. +.IP +For details of the precision handling see \fBprintf\fP(3). .TP 5 TYPE_REGEXP -Regular expression data. Requires a regular expression \fB(char *)\fR third argument; -the data is valid if the regular expression matches it. Regular expressions -are in the format of \fBregcomp\fR and \fBregexec\fR. Please notice -that the regular expression must match the whole field. If you have for -example an eight character wide field, a regular expression "^[0-9]*$" always -means that you have to fill all eight positions with digits. If you want to -allow fewer digits, you may use for example "^[0-9]* *$" which is good for -trailing spaces (up to an empty field), or "^ *[0-9]* *$" which is good for +Regular expression data. +Required parameter: +.RS +.bP +a third argument, a regular expression \fB(char *)\fP string. +The data is valid if the regular expression matches it. +.RE +.IP +Regular expressions +are in the format of \fBregcomp\fP and \fBregexec\fP. +.IP +The regular expression must match the whole field. +If you have for example, an eight character wide field, +a regular expression "^[0\-9]*$" always +means that you have to fill all eight positions with digits. +If you want to allow fewer digits, +you may use for example "^[0\-9]* *$" which is good for +trailing spaces (up to an empty field), +or "^ *[0\-9]* *$" which is good for leading and trailing spaces around the digits. .TP 5 TYPE_IPV4 -An Internet Protocol Version 4 address. This requires no additional argument. It -is checked whether or not the buffer has the form a.b.c.d, where a,b,c and d are -numbers between 0 and 255. Trailing blanks in the buffer are ignored. The address -itself is not validated. Please note that this is an ncurses extension. This -field type may not be available in other curses implementations. -.PP -It is possible to set up new programmer-defined field types. See the -\fBform_fieldtype\fR(3) manual page. +An Internet Protocol Version 4 address. +Required parameter: +.RS +.bP +none +.RE +.IP +The form library checks whether or not the buffer has the form \fIa.b.c.d\fP, +where \fIa\fP, \fIb\fP, \fIc\fP, and \fId\fP are numbers in the range 0 to 255. +Trailing blanks in the buffer are ignored. +The address itself is not validated. +.IP +This is an ncurses extension; +this field type may not be available in other curses implementations. .SH RETURN VALUE -The functions \fBfield_type\fR and \fBfield_arg\fR return \fBNULL\fR on -error. The function \fBset_field_type\fR returns one of the following: +The functions \fBfield_type\fP and \fBfield_arg\fP return \fBNULL\fP on error. +The function \fBset_field_type\fP returns one of the following: .TP 5 .B E_OK The routine succeeded. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .SH SEE ALSO -\fBcurses\fR(3), \fBform\fR(3). +\fBcurses\fP(3), +\fBform\fP(3), +\fBform_fieldtype\fP(3), +\fBform_variables\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_fieldtype.3 b/lib/libform/form_fieldtype.3 index b2956a41ed3..fa33369b842 100644 --- a/lib/libform/form_fieldtype.3 +++ b/lib/libform/form_fieldtype.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form_fieldtype.3,v 1.12 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_fieldtype.3,v 1.13 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2003,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2006,2010 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,79 +30,101 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_fieldtype.3,v 1.12 2015/11/14 01:35:38 jmc Exp $ -.TH form_fieldtype 3 "" +.\" $Id: form_fieldtype.3,v 1.13 2023/10/17 09:52:10 nicm Exp $ +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.TH form_fieldtype 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBnew_fieldtype\fR, \fBfree_fieldtype\fR, -\fBset_fieldtype_arg\fR, \fBset_fieldtype_choice\fR, -\fBlink_fieldtype\fR - define validation-field types +\fBform_fieldtype\fP \- define validation-field types .SH SYNOPSIS -\fB#include \fR +\fB#include \fP +.sp +\fBFIELDTYPE *new_fieldtype(\fP + \fBbool (* const \fIfield_check\fB)(FIELD *, const void *),\fR + \fBbool (* const \fIchar_check\fB)(int, const void *));\fR .br -FIELDTYPE *new_fieldtype( - bool (* const field_check)(FIELD *, const void *), - bool (* const char_check)(int, const void *)); -.br -int free_fieldtype(FIELDTYPE *fieldtype); -.br -int set_fieldtype_arg( - FIELDTYPE *fieldtype, - void *(* const make_arg)(va_list *), - void *(* const copy_arg)(const void *), - void (* const free_arg)(void *)); -.br -int set_fieldtype_choice( - FIELDTYPE *fieldtype, - bool (* const next_choice)(FIELD *, const void *), - bool (* const prev_choice)(FIELD *, const void *)); -.br -FIELDTYPE *link_fieldtype(FIELDTYPE *type1, - FIELDTYPE *type2); +\fBint free_fieldtype(FIELDTYPE *\fIfieldtype\fB);\fR +.sp +\fBint set_fieldtype_arg(\fP + \fBFIELDTYPE *\fIfieldtype\fB,\fR + \fBvoid *(* const \fImake_arg\fB)(va_list *),\fR + \fBvoid *(* const \fIcopy_arg\fB)(const void *),\fR + \fBvoid (* const \fIfree_arg\fB)(void *));\fR .br +\fBint set_fieldtype_choice(\fP + \fBFIELDTYPE *\fIfieldtype\fB,\fR + \fBbool (* const \fInext_choice\fB)(FIELD *, const void *),\fR + \fBbool (* const \fIprev_choice\fB)(FIELD *, const void *));\fR +.sp +\fBFIELDTYPE *link_fieldtype(FIELDTYPE *\fItype1\fB,\fR + \fBFIELDTYPE *\fItype2\fB);\fR .SH DESCRIPTION -The function \fBnew_fieldtype\fR creates a new field type usable for data -validation. You supply it with \fIfield_check\fR, a predicate to check the +.SS new_fieldtype +The function \fBnew_fieldtype\fP creates a new field type usable for data +validation. +Its parameters are function pointers: +.TP 5 +\fIfield_check\fP +This function checks the validity of an entered data string whenever the user attempts to leave a field. +It has two arguments: +.RS +.bP The (FIELD *) argument is passed in so the validation predicate can see the -field's buffer, sizes and other attributes; the second argument is an +field's buffer, sizes and other attributes. +.bP +The second argument is an argument-block structure, about which more below. +.RE +.TP 5 +\fIchar_check\fP +This function validates input characters as they are entered. +The form library passes it the character to be checked +and a pointer to an argument-block structure. +.SS free_fieldtype +The \fBfree_fieldtype\fP function +frees the space allocated for a given validation type by \fBnew_fieldtype\fP. +.SS set_fieldtype_arg +The function \fBset_fieldtype_arg\fP associates +three storage-management functions with a field type: +.TP 5 +\fImake_arg\fP +This function is automatically applied to the +list of arguments you give \fBset_field_type\fP when attaching validation +to a field. +It stores the arguments in an allocated argument-block +object which is used when validating input. +.TP 5 +\fIcopy_arg\fP +This function may be used by applications to copy argument-blocks. +.TP 5 +\fIfree_arg\fP +Frees an argument-block structure. .PP -You also supply \fBnew_fieldtype\fR with \fIchar_check\fR, -a function to validate input characters as they are entered; it will be passed -the character to be checked and a pointer to an argument-block structure. -.PP -The function \fBfree_fieldtype\fR frees the space allocated for a given -validation type. -.PP -The function \fBset_fieldtype_arg\fR associates three storage-management functions -with a field type. -The \fImake_arg\fR function is automatically applied to the -list of arguments you give \fBset_field_type\fR when attaching validation -to a field; its job is to bundle these into an allocated argument-block -object which can later be passed to validation predicated. -The other two hook arguments should copy and free argument-block structures. -They will be used by the forms-driver code. -You must supply the \fImake_arg\fR function, -the other two are optional, you may supply NULL for them. -In this case it is assumed -that \fImake_arg\fR does not allocate memory but simply loads the +You must supply the \fImake_arg\fP function. +The other two are optional: you may supply NULL for them. +In this case, the form library assumes +that \fImake_arg\fP does not allocate memory but simply loads the argument into a single scalar value. -.PP -The function \fBlink_fieldtype\fR creates -a new field type from the two given types. -They are connected by an logical 'OR'. -.PP -The form driver requests \fBREQ_NEXT_CHOICE\fR and \fBREQ_PREV_CHOICE\fR assume +.SS set_fieldtype_choice +The form driver requests \fBREQ_NEXT_CHOICE\fP and \fBREQ_PREV_CHOICE\fP assume that the possible values of a field form an ordered set, and provide the forms user with a way to move through the set. -The \fBset_fieldtype_choice\fR +.PP +The \fBset_fieldtype_choice\fP function allows forms programmers to define successor and predecessor functions for the field type. These functions take the field pointer and an argument-block structure as arguments. +.SS link_fieldtype +The function \fBlink_fieldtype\fP creates +a new field type from the two given types. +They are connected by an logical 'OR'. .SH RETURN VALUE The pointer-valued routines return NULL on error. -They set errno according to their success: +They set \fBerrno\fP according to their success: .TP 5 .B E_OK The routine succeeded. @@ -128,25 +151,18 @@ The field is already connected to a form. The field is the current field. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .SH SEE ALSO -\fBcurses\fR(3), \fBform\fR(3). +\fBcurses\fP(3), +\fBform\fP(3), +\fBform_field_validation\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. -.PP -All of the \fB(char *)\fR arguments of these functions should actually be -\fB(void *)\fR. The type has been left uncorrected for strict compatibility -with System V. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_hook.3 b/lib/libform/form_hook.3 index 20686a7d4ea..d4e35752f72 100644 --- a/lib/libform/form_hook.3 +++ b/lib/libform/form_hook.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form_hook.3,v 1.11 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_hook.3,v 1.12 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2007,2010 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,78 +30,73 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_hook.3,v 1.11 2015/11/14 01:35:38 jmc Exp $ -.TH form_hook 3 "" +.\" $Id: form_hook.3,v 1.12 2023/10/17 09:52:10 nicm Exp $ +.TH form_hook 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBset_field_init\fR, \fBfield_init\fR, -\fBset_field_term\fR, \fBfield_term\fR, -\fBset_form_init\fR, \fBform_init\fR, -\fBset_form_term\fR, \fBform_term\fR -- set hooks for automatic invocation by applications +\fBform_hook\fP \- set hooks for automatic invocation by applications .SH SYNOPSIS -\fB#include \fR +\fB#include \fP +.sp +\fBint set_field_init(FORM *\fIform\fB, Form_Hook \fIfunc\fB);\fR .br -int set_field_init(FORM *form, Form_Hook func); +\fBForm_Hook field_init(const FORM *\fIform\fB);\fR +.sp +\fBint set_field_term(FORM *\fIform\fB, Form_Hook \fIfunc\fB);\fR .br -Form_Hook field_init(const FORM *form); +\fBForm_Hook field_term(const FORM *\fIform\fB);\fR +.sp +\fBint set_form_init(FORM *\fIform\fB, Form_Hook \fIfunc\fB);\fR .br -int set_field_term(FORM *form, Form_Hook func); -.br -Form_Hook field_term(const FORM *form); -.br -int set_form_init(FORM *form, Form_Hook func); -.br -Form_Hook form_init(const FORM *form); -.br -int set_form_term(FORM *form, Form_Hook func); -.br -Form_Hook form_term(const FORM *form); +\fBForm_Hook form_init(const FORM *\fIform\fB);\fR +.sp +\fBint set_form_term(FORM *\fIform\fB, Form_Hook \fIfunc\fB);\fR .br +\fBForm_Hook form_term(const FORM *\fIform\fB);\fR .SH DESCRIPTION These functions make it possible to set hook functions to be called at various -points in the automatic processing of input event codes by \fBform_driver\fR. +points in the automatic processing of input event codes by \fBform_driver\fP. .PP -The function \fBset_field_init\fR sets a hook to be called at form-post time -and each time the selected field changes (after the change). \fBfield_init\fR -returns the current field init hook, if any (\fBNULL\fR if there is no such +The function \fBset_field_init\fP sets a hook to be called at form-post time +and each time the selected field changes (after the change). +\fBfield_init\fP +returns the current field init hook, if any (\fBNULL\fP if there is no such hook). .PP -The function \fBset_field_term\fR sets a hook to be called at form-unpost time -and each time the selected field changes (before the change). \fBfield_term\fR -returns the current field term hook, if any (\fBNULL\fR if there is no such +The function \fBset_field_term\fP sets a hook to be called at form-unpost time +and each time the selected field changes (before the change). +\fBfield_term\fP +returns the current field term hook, if any (\fBNULL\fP if there is no such hook). .PP -The function \fBset_form_init\fR sets a hook to be called at form-post time and -just after a page change once it is posted. \fBform_init\fR returns the -current form init hook, if any (\fBNULL\fR if there is no such hook). +The function \fBset_form_init\fP sets a hook to be called at form-post time and +just after a page change once it is posted. +\fBform_init\fP returns the +current form init hook, if any (\fBNULL\fP if there is no such hook). .PP -The function \fBset_form_term\fR sets a hook to be called at form-unpost time -and just before a page change once it is posted. \fBform_init\fR -returns the current form term hook, if any (\fBNULL\fR if there is no such +The function \fBset_form_term\fP sets a hook to be called at form-unpost time +and just before a page change once it is posted. +\fBform_init\fP +returns the current form term hook, if any (\fBNULL\fP if there is no such hook). .SH RETURN VALUE -Routines that return pointers return \fBNULL\fR on error. Other routines +Routines that return pointers return \fBNULL\fP on error. +Other routines return one of the following: .TP 5 .B E_OK The routine succeeded. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .SH SEE ALSO -\fBcurses\fR(3), \fBform\fR(3). +\fBcurses\fP(3), \fBform\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_new.3 b/lib/libform/form_new.3 index b79e8d60172..1f7630f5039 100644 --- a/lib/libform/form_new.3 +++ b/lib/libform/form_new.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form_new.3,v 1.9 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_new.3,v 1.10 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,26 +30,26 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_new.3,v 1.9 2015/11/14 01:35:38 jmc Exp $ -.TH form_new 3 "" +.\" $Id: form_new.3,v 1.10 2023/10/17 09:52:10 nicm Exp $ +.TH form_new 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBnew_form\fR, \fBfree_form\fR - create and destroy forms +\fBnew_form\fP, +\fBfree_form\fP \- create and destroy forms .SH SYNOPSIS -\fB#include \fR -.br -FORM *new_form(FIELD **fields); -.br -int free_form(FORM *form); +\fB#include \fP +.sp +\fBFORM *new_form(FIELD **\fIfields\fB);\fR .br +\fBint free_form(FORM *\fIform\fB);\fR .SH DESCRIPTION -The function \fBnew_form\fR creates a new form connected to a specified field -pointer array (which must be \fBNULL\fR-terminated). +The function \fBnew_form\fP creates a new form connected to a specified field +pointer array (which must be \fBNULL\fP-terminated). .PP -The function \fBfree_form\fR disconnects \fIform\fR from its field array +The function \fBfree_form\fP disconnects \fIform\fP from its field array and frees the storage allocated for the form. .SH RETURN VALUE -The function \fBnew_form\fR returns \fBNULL\fR on error. -It sets errno according to the function's success: +The function \fBnew_form\fP returns \fBNULL\fP on error. +It sets \fBerrno\fP according to the function's success: .TP 5 .B E_OK The routine succeeded. @@ -62,7 +63,7 @@ The field is already connected to a form. .B E_SYSTEM_ERROR System error occurred, e.g., malloc failure. .PP -The function \fBfree_form\fR returns one of the following: +The function \fBfree_form\fP returns one of the following: .TP 5 .B E_OK The routine succeeded. @@ -73,19 +74,14 @@ Routine detected an incorrect or out-of-range argument. .B E_POSTED The form has already been posted. .SH SEE ALSO -\fBcurses\fR(3), \fBform\fR(3). +\fBcurses\fP(3), \fBform\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_new_page.3 b/lib/libform/form_new_page.3 index ab686716952..e5f3976029c 100644 --- a/lib/libform/form_new_page.3 +++ b/lib/libform/form_new_page.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form_new_page.3,v 1.9 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_new_page.3,v 1.10 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2002,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,51 +30,47 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_new_page.3,v 1.9 2015/11/14 01:35:38 jmc Exp $ -.TH form_new_page 3 "" +.\" $Id: form_new_page.3,v 1.10 2023/10/17 09:52:10 nicm Exp $ +.TH form_new_page 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .SH NAME -\fBset_new_page\fR, \fBnew_page\fR - form pagination functions +\fBset_new_page\fP, +\fBnew_page\fP \- form pagination functions .SH SYNOPSIS -\fB#include \fR -.br -int set_new_page(FIELD *field, bool new_page_flag); -.br -bool new_page(const FIELD *field); +\fB#include \fP +.sp +\fBint set_new_page(FIELD *\fIfield\fB, bool \fInew_page_flag\fB);\fR .br +\fBbool new_page(const FIELD *\fIfield\fB);\fR .SH DESCRIPTION -The function \fBset_new_page\fR sets or resets a flag marking the given field +The function \fBset_new_page\fP sets or resets a flag marking the given field as the beginning of a new page on its form. .PP -The function \fBnew_page\fR is a predicate which tests if a given field marks +The function \fBnew_page\fP is a predicate which tests if a given field marks a page beginning on its form. .SH RETURN VALUE -The function \fBnew_page\fR returns \fBTRUE\fR or \fBFALSE\fR. +The function \fBnew_page\fP returns \fBTRUE\fP or \fBFALSE\fP. .PP -The function \fBset_new_page\fR return one of the following: +The function \fBset_new_page\fP returns one of the following: .TP 5 .B E_OK The routine succeeded. .TP 5 -.B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). -.TP 5 .B E_CONNECTED The given field is already connected to a form. .SH SEE ALSO -\fBcurses\fR(3) and related pages whose names begin "form_" for detailed +\fBcurses\fP(3) and related pages whose names begin \*(``form_\*('' for detailed descriptions of the entry points. .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_opts.3 b/lib/libform/form_opts.3 index b42bc78d889..5e6cc7060a0 100644 --- a/lib/libform/form_opts.3 +++ b/lib/libform/form_opts.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form_opts.3,v 1.10 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_opts.3,v 1.11 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,66 +30,61 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_opts.3,v 1.10 2015/11/14 01:35:38 jmc Exp $ -.TH form_opts 3 "" +.\" $Id: form_opts.3,v 1.11 2023/10/17 09:52:10 nicm Exp $ +.TH form_opts 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBset_form_opts\fR, \fBform_opts_on\fR, -\fBform_opts_off\fR, \fBform_opts\fR -- set and get form options +\fBset_form_opts\fP, +\fBform_opts_on\fP, +\fBform_opts_off\fP, +\fBform_opts\fP \- set and get form options .SH SYNOPSIS -\fB#include \fR +\fB#include \fP +.sp +\fBint set_form_opts(FORM *\fIform\fB, Field_Options \fIopts\fB);\fR .br -int set_form_opts(FORM *form, Field_Options opts); -.br -int form_opts_on(FORM *form, Field_Options opts); -.br -int form_opts_off(FORM *form, Field_Options opts); -.br -Field_Options form_opts(const FORM *form); +\fBField_Options form_opts(const FORM *\fIform\fB);\fR +.sp +\fBint form_opts_on(FORM *\fIform\fB, Field_Options \fIopts\fB);\fR .br +\fBint form_opts_off(FORM *\fIform\fB, Field_Options \fIopts\fB);\fR .SH DESCRIPTION -The function \fBset_form_opts\fR sets all the given form's option bits (form -option bits may be logically OR'ed together). +The function \fBset_form_opts\fP sets all the given form's option bits (form +option bits may be logically-OR'ed together). .PP -The function \fBform_opts_on\fR turns on the given option bits, and leaves +The function \fBform_opts_on\fP turns on the given option bits, and leaves others alone. .PP -The function \fBform_opts_off\fR turns off the given option bits, and leaves +The function \fBform_opts_off\fP turns off the given option bits, and leaves others alone. .PP -The function \fBform_opts\fR returns the form's current option bits. +The function \fBform_opts\fP returns the form's current option bits. .PP The following options are defined (all are on by default): .TP 5 O_NL_OVERLOAD -Overload the \fBREQ_NEW_LINE\fR forms driver request so that calling it at the +Overload the \fBREQ_NEW_LINE\fP forms driver request so that calling it at the end of a field goes to the next field. .TP 5 O_BS_OVERLOAD -Overload the \fBREQ_DEL_PREV\fR forms driver request so that calling it at the +Overload the \fBREQ_DEL_PREV\fP forms driver request so that calling it at the beginning of a field goes to the previous field. .SH RETURN VALUE -Except for \fBform_opts\fR, each routine returns one of the following: +Except for \fBform_opts\fP, each routine returns one of the following: .TP 5 .B E_OK The routine succeeded. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .SH SEE ALSO -\fBcurses\fR(3), \fBform\fR(3). +\fBcurses\fP(3), \fBform\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_page.3 b/lib/libform/form_page.3 index 3c9cb017ae5..efb07b8e57e 100644 --- a/lib/libform/form_page.3 +++ b/lib/libform/form_page.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form_page.3,v 1.9 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_page.3,v 1.10 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2016 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,39 +30,43 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_page.3,v 1.9 2015/11/14 01:35:38 jmc Exp $ -.TH form_page 3 "" +.\" $Id: form_page.3,v 1.10 2023/10/17 09:52:10 nicm Exp $ +.TH form_page 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBset_current_field\fR, \fBcurrent_field\fR, -\fBset_form_page\fR, \fBform_page\fR, -\fBfield_index\fR - set and get form page number +\fBform_page\fP \- set and get form page number .SH SYNOPSIS -\fB#include \fR +\fB#include \fP +.sp +\fBint set_current_field(FORM *\fIform\fB, FIELD *\fIfield\fB);\fR .br -int set_current_field(FORM *form, FIELD *field); -.br -FIELD *current_field(const FORM *); -.br -int set_form_page(FORM *form, int n); -.br -int form_page(const FORM *form); -.br -int field_index(const FIELD *field); +\fBFIELD *current_field(const FORM *\fIform\fB);\fR +.sp +\fBint unfocus_current_field(FORM *\fIform\fB);\fR +.sp +\fBint set_form_page(FORM *\fIform\fB, int \fIn\fB);\fR .br +\fBint form_page(const FORM *\fIform\fB);\fR +.sp +\fBint field_index(const FIELD *\fIfield\fB);\fR .SH DESCRIPTION -The function \fBset_current field\fR sets the current field of the given -form; \fBcurrent_field\fR returns the current field of the given form. +The function \fBset_current_field\fP sets the current field of the given +form; \fBcurrent_field\fP returns the current field of the given form. +.PP +The function \fBunfocus_current_field\fP removes the focus from the current +field of the form. +In such state, inquiries via \fBcurrent_field\fP shall return a NULL pointer. .PP -The function \fBset_form_page\fR sets the form's page number (goes to page -\fIn\fR of the form). +The function \fBset_form_page\fP sets the form's page number (goes to page +\fIn\fP of the form). .PP -The function \fBform_page\fR returns the form's current page number. +The function \fBform_page\fP returns the form's current page number. .PP -The function \fBfield_index\fR returns the index of the field in the -field array of the form it is connected to. It returns \fBERR\fR if +The function \fBfield_index\fP returns the index of the field in the +field array of the form it is connected to. +It returns \fBERR\fP if the argument is the null pointer or the field is not connected. .SH RETURN VALUE -Except for \fBform_page\fR, each routine returns one of the following: +Except for \fBform_page\fP, each routine returns one of the following: .TP 5 .B E_OK The routine succeeded. @@ -79,22 +84,19 @@ Contents of a field are not valid. The form driver could not process the request. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). . .SH SEE ALSO -\fBcurses\fR(3), \fBform\fR(3). +\fBcurses\fP(3), \fBform\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. +.PP +The \fBunfocus_current_field\fP function is an ncurses extension. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_post.3 b/lib/libform/form_post.3 index ca29a6a4698..f7d8a63f4c7 100644 --- a/lib/libform/form_post.3 +++ b/lib/libform/form_post.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form_post.3,v 1.8 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_post.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2015,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,25 +30,25 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_post.3,v 1.8 2015/11/14 01:35:38 jmc Exp $ -.TH form_post 3 "" +.\" $Id: form_post.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ +.TH form_post 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBpost_form\fR, \fBunpost_form\fR -- write or erase forms from associated subwindows +\fBpost_form\fP, +\fBunpost_form\fP \- write or erase forms from associated subwindows .SH SYNOPSIS -\fB#include \fR -.br -int post_form(FORM *form); -.br -int unpost_form(FORM *form); +\fB#include \fP +.sp +\fBint post_form(FORM *\fIform\fB);\fR .br +\fBint unpost_form(FORM *\fIform\fB);\fR .SH DESCRIPTION -The function \fBpost_form\fR displays a form to its associated subwindow. To -trigger physical display of the subwindow, use \fBrefresh\fR or some equivalent -\fBcurses\fR routine (the implicit \fBdoupdate\fR triggered by an \fBcurses\fR +The function \fBpost_form\fP displays a form to its associated subwindow. +To trigger physical display of the subwindow, +use \fBrefresh\fP(3) or some equivalent +\fBcurses\fP routine (the implicit \fBdoupdate\fP triggered by an \fBcurses\fP input request will do). .PP -The function \fBunpost_form\fR erases form from its associated subwindow. +The function \fBunpost_form\fP erases form from its associated subwindow. .SH RETURN VALUE These routines return one of the following: .TP 5 @@ -73,22 +74,17 @@ Form is too large for its window. The form has already been posted. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). . .SH SEE ALSO -\fBcurses\fR(3), \fBform\fR(3). +\fBcurses\fP(3), \fBform\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_requestname.3 b/lib/libform/form_requestname.3 index f8e441ee8d3..ac887ce6be2 100644 --- a/lib/libform/form_requestname.3 +++ b/lib/libform/form_requestname.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form_requestname.3,v 1.8 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_requestname.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,46 +30,42 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_requestname.3,v 1.8 2015/11/14 01:35:38 jmc Exp $ -.TH form_requestname 3 "" +.\" $Id: form_requestname.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ +.TH form_requestname 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBform_request_name\fR, -\fBform_request_by_name\fR -- handle printable form request names +\fBform_request_by_name\fP, +\fBform_request_name\fP \- handle printable form request names .SH SYNOPSIS -\fB#include \fR -.br -const char *form_request_name(int request); -.br -int form_request_by_name(const char *name); +\fB#include \fP +.sp +\fBconst char *form_request_name(int \fIrequest\fB);\fR .br +\fBint form_request_by_name(const char *\fIname\fB);\fR .SH DESCRIPTION -The function \fBform_request_name\fR returns the printable name of a form +.SS form_request_name +The function \fBform_request_name\fP returns the printable name of a form request code. -.br -The function \fBform_request_by_name\fR searches in the name-table for a request -with the given name and returns its request code. Otherwise E_NO_MATCH is returned. +.SS form_request_name_by_name +The function \fBform_request_by_name\fP searches in the name-table for a request +with the given name and returns its request code. +Otherwise E_NO_MATCH is returned. .SH RETURN VALUE -\fBform_request_name\fR returns \fBNULL\fR on error and sets errno -to \fBE_BAD_ARGUMENT\fR. -.br -\fBform_request_by_name\fR returns \fBE_NO_MATCH\fR on error. -It does not set errno. +\fBform_request_name\fP returns \fBNULL\fP on error and sets \fBerrno\fP +to \fBE_BAD_ARGUMENT\fP. +.PP +\fBform_request_by_name\fP returns \fBE_NO_MATCH\fP on error. +It does not set \fBerrno\fP. .SH SEE ALSO -\fBcurses\fR(3), \fBform\fR(3). +\fBcurses\fP(3), \fBform\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines are specific to ncurses. They were not supported on -Version 7, BSD or System V implementations. It is recommended that +These routines are specific to ncurses. +They were not supported on +Version 7, BSD or System V implementations. +It is recommended that any code depending on them be conditioned using NCURSES_VERSION. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_userptr.3 b/lib/libform/form_userptr.3 index 3b4be2e3c64..bfd6fb283c6 100644 --- a/lib/libform/form_userptr.3 +++ b/lib/libform/form_userptr.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form_userptr.3,v 1.9 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_userptr.3,v 1.10 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,44 +30,38 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_userptr.3,v 1.9 2015/11/14 01:35:38 jmc Exp $ -.TH form_userptr 3 "" +.\" $Id: form_userptr.3,v 1.10 2023/10/17 09:52:10 nicm Exp $ +.TH form_userptr 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBset_form_userptr\fR, \fBform_userptr\fR -- associate application data with a form item +\fBset_form_userptr\fP, +\fBform_userptr\fP \- associate application data with a form item .SH SYNOPSIS -\fB#include \fR -.br -int set_form_userptr(FORM *form, void *userptr); -.br -void* form_userptr(const FORM *form); +\fB#include \fP +.sp +\fBint set_form_userptr(FORM *\fIform\fB, void *\fIuserptr\fB);\fR .br +\fBvoid* form_userptr(const FORM *\fIform\fB);\fR .SH DESCRIPTION Every form and every form item has a field that can be used to hold application-specific data (that is, the form-driver code leaves it alone). These functions get and set the form user pointer field. .SH RETURN VALUE -The function \fBform_userptr\fR returns a pointer (which may be \fBNULL\fR). -It does not set errno. +The function \fBform_userptr\fP returns a pointer (which may be \fBNULL\fP). +It does not set \fBerrno\fP. .PP -The function \fBset_form_userptr\fR returns \fBE_OK\fP (success). +The function \fBset_form_userptr\fP returns \fBE_OK\fP (success). .SH SEE ALSO -\fBcurses\fR(3), \fBform\fR(3). +\fBcurses\fP(3), \fBform\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. .PP The user pointer is a void pointer. We chose not to leave it as a char pointer for SVr4 compatibility. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/form_variables.3 b/lib/libform/form_variables.3 new file mode 100644 index 00000000000..4ff571a2c59 --- /dev/null +++ b/lib/libform/form_variables.3 @@ -0,0 +1,81 @@ +.\"*************************************************************************** +.\" Copyright 2020,2021 Thomas E. Dickey * +.\" Copyright 2010-2013,2017 Free Software Foundation, Inc. * +.\" * +.\" Permission is hereby granted, free of charge, to any person obtaining a * +.\" copy of this software and associated documentation files (the * +.\" "Software"), to deal in the Software without restriction, including * +.\" without limitation the rights to use, copy, modify, merge, publish, * +.\" distribute, distribute with modifications, sublicense, and/or sell * +.\" copies of the Software, and to permit persons to whom the Software is * +.\" furnished to do so, subject to the following conditions: * +.\" * +.\" The above copyright notice and this permission notice shall be included * +.\" in all copies or substantial portions of the Software. * +.\" * +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * +.\" IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * +.\" DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * +.\" OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * +.\" THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +.\" * +.\" Except as contained in this notice, the name(s) of the above copyright * +.\" holders shall not be used in advertising or otherwise to promote the * +.\" sale, use or other dealings in this Software without prior written * +.\" authorization. * +.\"*************************************************************************** +.\" +.\" $Id: form_variables.3,v 1.1 2023/10/17 09:52:10 nicm Exp $ +.TH form_variables 3 2021-12-25 "ncurses 6.4" "Library calls" +.na +.hy 0 +.SH NAME +\fBTYPE_ALNUM\fP, +\fBTYPE_ALPHA\fP, +\fBTYPE_ENUM\fP, +\fBTYPE_INTEGER\fP, +\fBTYPE_IPV4\fP, +\fBTYPE_NUMERIC\fP, +\fBTYPE_REGEXP\fP +\- form system global variables +.ad +.hy +.SH SYNOPSIS +.nf +\fB#include \fP +.PP +\fBFIELDTYPE * TYPE_ALNUM;\fP +\fBFIELDTYPE * TYPE_ALPHA;\fP +\fBFIELDTYPE * TYPE_ENUM;\fP +\fBFIELDTYPE * TYPE_INTEGER;\fP +\fBFIELDTYPE * TYPE_IPV4;\fP +\fBFIELDTYPE * TYPE_NUMERIC;\fP +\fBFIELDTYPE * TYPE_REGEXP;\fP +.fi +.SH DESCRIPTION +These are building blocks for the form library, +defining fields that can be created using +the \fBform_fieldtype\fP(3) functions. +Each provides functions for field- and character-validation, +according to the given datatype. +.SS TYPE_ALNUM +This holds alphanumeric data. +.SS TYPE_ALPHA +This holds alphabetic data. +.SS TYPE_ENUM +This holds an enumerated type. +.SS TYPE_INTEGER +This holds a decimal integer. +.SS TYPE_IPV4 +This holds an IPv4 internet address, e.g., "127.0.0.1". +.SS TYPE_NUMERIC +This holds a decimal number, with optional sign and decimal point. +.SS TYPE_REGEXP +This holds a regular expression. +.SH PORTABILITY +The \fBTYPE_IPV4\fP variable is an extension not provided by older +implementations of the form library. +.SH SEE ALSO +\fBform\fP(3). diff --git a/lib/libform/form_win.3 b/lib/libform/form_win.3 index 798fe2ef210..d0fc36a3aea 100644 --- a/lib/libform/form_win.3 +++ b/lib/libform/form_win.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: form_win.3,v 1.10 2015/11/14 01:35:38 jmc Exp $ +.\" $OpenBSD: form_win.3,v 1.11 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2006,2010 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,48 +30,48 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: form_win.3,v 1.10 2015/11/14 01:35:38 jmc Exp $ -.TH form_win 3 "" +.\" $Id: form_win.3,v 1.11 2023/10/17 09:52:10 nicm Exp $ +.TH form_win 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBset_form_win\fR, \fBform_win\fR, -\fBset_form_sub\fR, \fBform_sub\fR, -\fBscale_form\fR - make and break form window and subwindow associations +\fBform_win\fP \- make and break form window and subwindow associations .SH SYNOPSIS -\fB#include \fR +\fB#include \fP +.sp +\fBint set_form_win(FORM *\fIform\fB, WINDOW *\fIwin\fB);\fR .br -int set_form_win(FORM *form, WINDOW *win); -.br -WINDOW *form_win(const FORM *form); -.br -int set_form_sub(FORM *form, WINDOW *sub); -.br -WINDOW *form_sub(const FORM *form); -.br -int scale_form(const FORM *form, int *rows, int *columns); +\fBWINDOW *form_win(const FORM *\fIform\fB);\fR +.sp +\fBint set_form_sub(FORM *\fIform\fB, WINDOW *\fIsub\fB);\fR .br +\fBWINDOW *form_sub(const FORM *\fIform\fB);\fR +.sp +\fBint scale_form(const FORM *\fIform\fB, int *\fIrows\fB, int *\fIcolumns\fB);\fR .SH DESCRIPTION -Every form has an associated pair of \fBcurses\fR windows. The form window +Every form has an associated pair of \fBcurses\fP windows. +The form window displays any title and border associated with the window; the form subwindow displays the items of the form that are currently available for selection. .PP -The first four functions get and set those windows. It is not necessary to set -either window; by default, the driver code uses \fBstdscr\fR for both. +The first four functions get and set those windows. +It is not necessary to set +either window; by default, the driver code uses \fBstdscr\fP for both. .PP -In the \fBset_\fR functions, window argument of \fBNULL\fR is treated as though -it were \fBstsdcr\fR. A form argument of \fBNULL\fR is treated as a request +In the \fBset_\fP functions, window argument of \fBNULL\fP is treated as though +it were \fBstsdcr\fP. A form argument of \fBNULL\fP is treated as a request to change the system default form window or subwindow. .PP -The function \fBscale_form\fR returns the minimum size required for the -subwindow of \fIform\fR. +The function \fBscale_form\fP returns the minimum size required for the +subwindow of \fIform\fP. .SH RETURN VALUE -Routines that return pointers return \fBNULL\fR on error. Routines that return +Routines that return pointers return \fBNULL\fP on error. +Routines that return an integer return one of the following error codes: .TP 5 .B E_OK The routine succeeded. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .TP 5 .B E_BAD_ARGUMENT Routine detected an incorrect or out-of-range argument. @@ -81,19 +82,16 @@ The form has already been posted. .B E_NOT_CONNECTED No items are connected to the form. .SH SEE ALSO -\fBcurses\fR(3), \fBform\fR(3). +\fBcurses\fP(3), +\fBcurs_variables\fP(3), +\fBform\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V forms library. They were not supported on +These routines emulate the System V forms library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libform/frm_cursor.c b/lib/libform/frm_cursor.c index 3e12e809f91..161c90c73fd 100644 --- a/lib/libform/frm_cursor.c +++ b/lib/libform/frm_cursor.c @@ -1,6 +1,7 @@ -/* $OpenBSD: frm_cursor.c,v 1.6 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: frm_cursor.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2004,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,12 +34,12 @@ #include "form.priv.h" -MODULE_ID("$Id: frm_cursor.c,v 1.6 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: frm_cursor.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int pos_form_cursor(FORM * form) -| +| | Description : Moves the form window cursor to the location required | by the form driver to resume form processing. This may | be needed after the application calls a curses library @@ -49,12 +50,12 @@ MODULE_ID("$Id: frm_cursor.c,v 1.6 2015/01/23 22:48:51 krw Exp $") | E_BAD_ARGUMENT - Invalid form pointer | E_NOT_POSTED - Form is not posted +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) pos_form_cursor(FORM *form) { int res; - T((T_CALLED("pos_form_cursor(%p)"), form)); + T((T_CALLED("pos_form_cursor(%p)"), (void *)form)); if (!form) res = E_BAD_ARGUMENT; diff --git a/lib/libform/frm_data.c b/lib/libform/frm_data.c index 90c1c673546..24c380d4f6d 100644 --- a/lib/libform/frm_data.c +++ b/lib/libform/frm_data.c @@ -1,6 +1,7 @@ -/* $OpenBSD: frm_data.c,v 1.8 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: frm_data.c,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2004,2005 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2010,2013 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,24 +34,24 @@ #include "form.priv.h" -MODULE_ID("$Id: frm_data.c,v 1.8 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: frm_data.c,v 1.9 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : bool data_behind(const FORM *form) -| +| | Description : Check for off-screen data behind. This is nearly trivial | because the beginning of a field is fixed. | | Return Values : TRUE - there are off-screen data behind | FALSE - there are no off-screen data behind +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(bool) +FORM_EXPORT(bool) data_behind(const FORM *form) { bool result = FALSE; - T((T_CALLED("data_behind(%p)"), form)); + T((T_CALLED("data_behind(%p)"), (const void *)form)); if (form && (form->status & _POSTED) && form->current) { @@ -70,12 +71,12 @@ data_behind(const FORM *form) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : static char * Only_Padding( | WINDOW *w, | int len, | int pad) -| +| | Description : Test if 'length' cells starting at the current position | contain a padding character. | @@ -104,7 +105,7 @@ Only_Padding(WINDOW *w, int len, int pad) } } #else - cell = winch(w); + cell = (FIELD_CELL)winch(w); if (ChCharOf(cell) != ChCharOf(pad)) { result = FALSE; @@ -123,21 +124,21 @@ Only_Padding(WINDOW *w, int len, int pad) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : bool data_ahead(const FORM *form) -| +| | Description : Check for off-screen data ahead. This is more difficult -| because a dynamic field has a variable end. +| because a dynamic field has a variable end. | | Return Values : TRUE - there are off-screen data ahead | FALSE - there are no off-screen data ahead +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(bool) +FORM_EXPORT(bool) data_ahead(const FORM *form) { bool result = FALSE; - T((T_CALLED("data_ahead(%p)"), form)); + T((T_CALLED("data_ahead(%p)"), (const void *)form)); if (form && (form->status & _POSTED) && form->current) { @@ -150,12 +151,11 @@ data_ahead(const FORM *form) if (Single_Line_Field(field)) { - int check_len; - pos = form->begincol + field->cols; while (pos < field->dcols) { - check_len = field->dcols - pos; + int check_len = field->dcols - pos; + if (check_len >= field->cols) check_len = field->cols; cursor_moved = TRUE; diff --git a/lib/libform/frm_def.c b/lib/libform/frm_def.c index 3fe20191b08..7653cf582b6 100644 --- a/lib/libform/frm_def.c +++ b/lib/libform/frm_def.c @@ -1,6 +1,7 @@ -/* $OpenBSD: frm_def.c,v 1.8 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: frm_def.c,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,7 +34,7 @@ #include "form.priv.h" -MODULE_ID("$Id: frm_def.c,v 1.8 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: frm_def.c,v 1.9 2023/10/17 09:52:10 nicm Exp $") /* this can't be readonly */ static FORM default_form = @@ -62,14 +63,14 @@ static FORM default_form = NULL /* fieldterm */ }; -NCURSES_EXPORT_VAR(FORM *) _nc_Default_Form = &default_form; - +FORM_EXPORT_VAR(FORM *) _nc_Default_Form = &default_form; + /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : static FIELD *Insert_Field_By_Position( -| FIELD *new_field, +| FIELD *new_field, | FIELD *head ) -| +| | Description : Insert new_field into sorted fieldlist with head "head" | and return new head of sorted fieldlist. Sorting | criteria is (row,column). This is a circular list. @@ -113,9 +114,9 @@ Insert_Field_By_Position(FIELD *newfield, FIELD *head) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : static void Disconnect_Fields(FORM *form) -| +| | Description : Break association between form and array of fields. | | Return Values : - @@ -143,9 +144,9 @@ Disconnect_Fields(FORM *form) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : static int Connect_Fields(FORM *form, FIELD **fields) -| +| | Description : Set association between form and array of fields. | | Return Values : E_OK - no error @@ -158,10 +159,9 @@ Connect_Fields(FORM *form, FIELD **fields) { int field_cnt, j; int page_nr; - int maximum_row_in_field, maximum_col_in_field; _PAGE *pg; - T((T_CALLED("Connect_Fields(%p,%p)"), form, fields)); + T((T_CALLED("Connect_Fields(%p,%p)"), (void *)form, (void *)fields)); assert(form); @@ -189,7 +189,7 @@ Connect_Fields(FORM *form, FIELD **fields) /* allocate page structures */ if ((pg = typeMalloc(_PAGE, page_nr)) != (_PAGE *) 0) { - T((T_CREATE("_PAGE %p"), pg)); + T((T_CREATE("_PAGE %p"), (void *)pg)); form->page = pg; } else @@ -199,15 +199,18 @@ Connect_Fields(FORM *form, FIELD **fields) size of the form */ for (j = 0; j < field_cnt; j++) { + int maximum_row_in_field; + int maximum_col_in_field; + if (j == 0) - pg->pmin = j; + pg->pmin = (short)j; else { if (fields[j]->status & _NEWPAGE) { - pg->pmax = j - 1; + pg->pmax = (short)(j - 1); pg++; - pg->pmin = j; + pg->pmin = (short)j; } } @@ -215,14 +218,14 @@ Connect_Fields(FORM *form, FIELD **fields) maximum_col_in_field = fields[j]->fcol + fields[j]->cols; if (form->rows < maximum_row_in_field) - form->rows = maximum_row_in_field; + form->rows = (short)maximum_row_in_field; if (form->cols < maximum_col_in_field) - form->cols = maximum_col_in_field; + form->cols = (short)maximum_col_in_field; } - pg->pmax = field_cnt - 1; - form->maxfield = field_cnt; - form->maxpage = page_nr; + pg->pmax = (short)(field_cnt - 1); + form->maxfield = (short)field_cnt; + form->maxpage = (short)page_nr; /* Sort fields on form pages */ for (page_nr = 0; page_nr < form->maxpage; page_nr++) @@ -231,8 +234,8 @@ Connect_Fields(FORM *form, FIELD **fields) for (j = form->page[page_nr].pmin; j <= form->page[page_nr].pmax; j++) { - fields[j]->index = j; - fields[j]->page = page_nr; + fields[j]->index = (short)j; + fields[j]->page = (short)page_nr; fld = Insert_Field_By_Position(fields[j], fld); } if (fld) @@ -250,10 +253,10 @@ Connect_Fields(FORM *form, FIELD **fields) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : static int Associate_Fields(FORM *form, FIELD **fields) -| -| Description : Set association between form and array of fields. +| +| Description : Set association between form and array of fields. | If there are fields, position to first active field. | | Return Values : E_OK - success @@ -283,9 +286,9 @@ Associate_Fields(FORM *form, FIELD **fields) } /*--------------------------------------------------------------------------- -| Facility : libnform -| Function : FORM *new_form( FIELD **fields ) -| +| Facility : libnform +| Function : FORM *new_form_sp(SCREEN* sp, FIELD** fields ) +| | Description : Create new form with given array of fields. | | Return Values : Pointer to form. NULL if error occurred. @@ -295,22 +298,32 @@ Associate_Fields(FORM *form, FIELD **fields) | E_CONNECTED - a field is already connected | E_SYSTEM_ERROR - not enough memory +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(FORM *) -new_form(FIELD **fields) +FORM_EXPORT(FORM *) +NCURSES_SP_NAME(new_form) (NCURSES_SP_DCLx FIELD **fields) { int err = E_SYSTEM_ERROR; + FORM *form = (FORM *)0; - FORM *form = typeMalloc(FORM, 1); + T((T_CALLED("new_form(%p,%p)"), (void *)SP_PARM, (void *)fields)); - T((T_CALLED("new_form(%p)"), fields)); - if (form) + if (IsValidScreen(SP_PARM)) { - T((T_CREATE("form %p"), form)); - *form = *_nc_Default_Form; - if ((err = Associate_Fields(form, fields)) != E_OK) + form = typeMalloc(FORM, 1); + + if (form) { - free_form(form); - form = (FORM *)0; + T((T_CREATE("form %p"), (void *)form)); + *form = *_nc_Default_Form; + /* This ensures win and sub are always non-null, + so we can derive always the SCREEN that this form is + running on. */ + form->win = StdScreen(SP_PARM); + form->sub = StdScreen(SP_PARM); + if ((err = Associate_Fields(form, fields)) != E_OK) + { + free_form(form); + form = (FORM *)0; + } } } @@ -321,19 +334,40 @@ new_form(FIELD **fields) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform +| Function : FORM* new_form(FIELD** fields ) +| +| Description : Create new form with given array of fields. +| +| Return Values : Pointer to form. NULL if error occurred. +! Set errno: +| E_OK - success +| E_BAD_ARGUMENT - Invalid form pointer or field array +| E_CONNECTED - a field is already connected +| E_SYSTEM_ERROR - not enough memory ++--------------------------------------------------------------------------*/ +#if NCURSES_SP_FUNCS +FORM_EXPORT(FORM *) +new_form(FIELD **fields) +{ + return NCURSES_SP_NAME(new_form) (CURRENT_SCREEN, fields); +} +#endif + +/*--------------------------------------------------------------------------- +| Facility : libnform | Function : int free_form( FORM *form ) -| +| | Description : Release internal memory associated with form. | | Return Values : E_OK - no error | E_BAD_ARGUMENT - invalid form pointer | E_POSTED - form is posted +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) free_form(FORM *form) { - T((T_CALLED("free_form(%p)"), form)); + T((T_CALLED("free_form(%p)"), (void *)form)); if (!form) RETURN(E_BAD_ARGUMENT); @@ -350,9 +384,9 @@ free_form(FORM *form) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int set_form_fields( FORM *form, FIELD **fields ) -| +| | Description : Set a new association of an array of fields to a form | | Return Values : E_OK - no error @@ -361,13 +395,13 @@ free_form(FORM *form) | E_POSTED - form is posted | E_SYSTEM_ERROR - not enough memory +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) set_form_fields(FORM *form, FIELD **fields) { FIELD **old; int res; - T((T_CALLED("set_form_fields(%p,%p)"), form, fields)); + T((T_CALLED("set_form_fields(%p,%p)"), (void *)form, (void *)fields)); if (!form) RETURN(E_BAD_ARGUMENT); @@ -385,32 +419,32 @@ set_form_fields(FORM *form, FIELD **fields) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : FIELD **form_fields( const FORM *form ) -| +| | Description : Retrieve array of fields | | Return Values : Pointer to field array +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(FIELD **) +FORM_EXPORT(FIELD **) form_fields(const FORM *form) { - T((T_CALLED("form_field(%p)"), form)); + T((T_CALLED("form_field(%p)"), (const void *)form)); returnFieldPtr(Normalize_Form(form)->field); } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int field_count( const FORM *form ) -| +| | Description : Retrieve number of fields | | Return Values : Number of fields, -1 if none are defined +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) field_count(const FORM *form) { - T((T_CALLED("field_count(%p)"), form)); + T((T_CALLED("field_count(%p)"), (const void *)form)); returnCode(Normalize_Form(form)->maxfield); } diff --git a/lib/libform/frm_driver.c b/lib/libform/frm_driver.c index 154056d8cf8..29749bbe5f3 100644 --- a/lib/libform/frm_driver.c +++ b/lib/libform/frm_driver.c @@ -1,6 +1,7 @@ -/* $OpenBSD: frm_driver.c,v 1.12 2017/07/29 07:18:32 florian Exp $ */ +/* $OpenBSD: frm_driver.c,v 1.13 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2020,2021 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,7 +34,7 @@ #include "form.priv.h" -MODULE_ID("$Id: frm_driver.c,v 1.12 2017/07/29 07:18:32 florian Exp $") +MODULE_ID("$Id: frm_driver.c,v 1.13 2023/10/17 09:52:10 nicm Exp $") /*---------------------------------------------------------------------------- This is the core module of the form library. It contains the majority @@ -100,9 +101,9 @@ Perhaps at some time we will make this configurable at runtime. #define GROW_IF_NAVIGATE (1) #if USE_WIDEC_SUPPORT -#define myADDNSTR(w, s, n) wadd_wchnstr(w, s, n) -#define myINSNSTR(w, s, n) wins_wchnstr(w, s, n) -#define myINNSTR(w, s, n) fix_wchnstr(w, s, n) +#define myADDNSTR(w, s, n) wide_waddnstr(w, s, n) +#define myINSNSTR(w, s, n) wide_winsnstr(w, s, n) +#define myINNSTR(w, s, n) wide_winnstr(w, s, n) #define myWCWIDTH(w, y, x) cell_width(w, y, x) #else #define myADDNSTR(w, s, n) waddnstr(w, s, n) @@ -131,34 +132,34 @@ static int FE_Delete_Previous(FORM *); /* Calculate the position of a single row in a field buffer */ #define Position_Of_Row_In_Buffer(field,row) ((row)*(field)->dcols) -/* Calculate start address for the fields buffer# N */ +/* Calculate start address for the field's buffer# N */ #define Address_Of_Nth_Buffer(field,N) \ ((field)->buf + (N)*(1+Buffer_Length(field))) -/* Calculate the start address of the row in the fields specified buffer# N */ +/* Calculate the start address of the row in the field's specified buffer# N */ #define Address_Of_Row_In_Nth_Buffer(field,N,row) \ (Address_Of_Nth_Buffer(field,N) + Position_Of_Row_In_Buffer(field,row)) -/* Calculate the start address of the row in the fields primary buffer */ +/* Calculate the start address of the row in the field's primary buffer */ #define Address_Of_Row_In_Buffer(field,row) \ Address_Of_Row_In_Nth_Buffer(field,0,row) -/* Calculate the start address of the row in the forms current field +/* Calculate the start address of the row in the form's current field buffer# N */ #define Address_Of_Current_Row_In_Nth_Buffer(form,N) \ Address_Of_Row_In_Nth_Buffer((form)->current,N,(form)->currow) -/* Calculate the start address of the row in the forms current field +/* Calculate the start address of the row in the form's current field primary buffer */ #define Address_Of_Current_Row_In_Buffer(form) \ Address_Of_Current_Row_In_Nth_Buffer(form,0) -/* Calculate the address of the cursor in the forms current field +/* Calculate the address of the cursor in the form's current field primary buffer */ #define Address_Of_Current_Position_In_Nth_Buffer(form,N) \ (Address_Of_Current_Row_In_Nth_Buffer(form,N) + (form)->curcol) -/* Calculate the address of the cursor in the forms current field +/* Calculate the address of the cursor in the form's current field buffer# N */ #define Address_Of_Current_Position_In_Buffer(form) \ Address_Of_Current_Position_In_Nth_Buffer(form,0) @@ -173,29 +174,30 @@ static int FE_Delete_Previous(FORM *); instead of a derived window because it contains invisible parts. This is true for non-public fields and for scrollable fields. */ #define Has_Invisible_Parts(field) \ - (!((field)->opts & O_PUBLIC) || \ + (!(Field_Has_Option(field, O_PUBLIC)) || \ Is_Scroll_Field(field)) /* Logic to decide whether or not a field needs justification */ #define Justification_Allowed(field) \ (((field)->just != NO_JUSTIFICATION) && \ (Single_Line_Field(field)) && \ - (((field)->dcols == (field)->cols) && \ - ((field)->opts & O_STATIC)) ) + ((Field_Has_Option(field, O_STATIC) && \ + ((field)->dcols == (field)->cols)) || \ + Field_Has_Option(field, O_DYNAMIC_JUSTIFY))) /* Logic to determine whether or not a dynamic field may still grow */ #define Growable(field) ((field)->status & _MAY_GROW) -/* Macro to set the attributes for a fields window */ +/* Macro to set the attributes for a field's window */ #define Set_Field_Window_Attributes(field,win) \ -( wbkgdset((win),(chtype)((field)->pad | (field)->back)), \ - wattrset((win),(field)->fore) ) +( wbkgdset((win),(chtype)((chtype)((field)->pad) | (field)->back)), \ + (void) wattrset((win), (int)(field)->fore) ) /* Logic to decide whether or not a field really appears on the form */ #define Field_Really_Appears(field) \ ((field->form) &&\ (field->form->status & _POSTED) &&\ - (field->opts & O_VISIBLE) &&\ + (Field_Has_Option(field, O_VISIBLE)) &&\ (field->page == field->form->curpage)) /* Logic to determine whether or not we are on the first position in the @@ -216,10 +218,10 @@ static FIELD_CELL myZEROS; static void check_pos(FORM *form, int lineno) { - int y, x; - if (form && form->w) { + int y, x; + getyx(form->w, y, x); if (y != form->currow || x != form->curcol) { @@ -239,15 +241,36 @@ check_pos(FORM *form, int lineno) Wide-character special functions --------------------------------------------------------------------------*/ #if USE_WIDEC_SUPPORT -/* like winsnstr */ +/* add like waddnstr, but using cchar_t* rather than char* + */ +static int +wide_waddnstr(WINDOW *w, const cchar_t *s, int n) +{ + int rc = OK; + + while (n-- > 0) + { + if ((rc = wadd_wch(w, s)) != OK) + break; + ++s; + } + return rc; +} + +/* insert like winsnstr, but using cchar_t* rather than char* + * + * X/Open Curses has no close equivalent; inserts are done only with wchar_t + * strings. + */ static int -wins_wchnstr(WINDOW *w, cchar_t *s, int n) +wide_winsnstr(WINDOW *w, const cchar_t *s, int n) { int code = ERR; - int y, x; while (n-- > 0) { + int y, x; + getyx(w, y, x); if ((code = wins_wch(w, s++)) != OK) break; @@ -257,11 +280,13 @@ wins_wchnstr(WINDOW *w, cchar_t *s, int n) return code; } -/* win_wchnstr is inconsistent with winnstr, since it returns OK rather than - * the number of items transferred. +/* retrieve like winnstr, but using cchar_t*, rather than char*. + * + * X/Open Curses' closest equivalent, win_wchnstr(), is inconsistent with + * winnstr(), since it returns OK rather than the number of items transferred. */ static int -fix_wchnstr(WINDOW *w, cchar_t *s, int n) +wide_winnstr(WINDOW *w, cchar_t *s, int n) { int x; @@ -488,7 +513,6 @@ Buffer_To_Window(const FIELD *field, WINDOW *win) { int width, height; int y, x; - int len; int row; FIELD_CELL *pBuffer; @@ -502,6 +526,8 @@ Buffer_To_Window(const FIELD *field, WINDOW *win) row < height; row++, pBuffer += width) { + int len; + if ((len = (int)(After_End_Of_Data(pBuffer, width) - pBuffer)) > 0) { wmove(win, row, 0); @@ -513,9 +539,10 @@ Buffer_To_Window(const FIELD *field, WINDOW *win) /*--------------------------------------------------------------------------- | Facility : libnform -| Function : static void Window_To_Buffer( +| Function : void _nc_get_fieldbuffer( | WINDOW * win, -| FIELD * field) +| FIELD * field, +| FIELD_CELL * buf) | | Description : Copy the content of the window into the buffer. | The multiple lines of a window are simply @@ -524,18 +551,22 @@ Buffer_To_Window(const FIELD *field, WINDOW *win) | | Return Values : - +--------------------------------------------------------------------------*/ -static void -Window_To_Buffer(WINDOW *win, FIELD *field) +FORM_EXPORT(void) +_nc_get_fieldbuffer(FORM *form, FIELD *field, FIELD_CELL *buf) { int pad; int len = 0; FIELD_CELL *p; int row, height; + WINDOW *win; + + assert(form && field && buf); - assert(win && field && field->buf); + win = form->w; + assert(win); pad = field->pad; - p = field->buf; + p = buf; height = getmaxy(win); for (row = 0; (row < height) && (row < field->drows); row++) @@ -562,6 +593,25 @@ Window_To_Buffer(WINDOW *win, FIELD *field) } } +/*--------------------------------------------------------------------------- +| Facility : libnform +| Function : static void Window_To_Buffer( +| FORM * form, +| FIELD * field) +| +| Description : Copy the content of the window into the buffer. +| The multiple lines of a window are simply +| concatenated into the buffer. Pad characters in +| the window will be replaced by blanks in the buffer. +| +| Return Values : - ++--------------------------------------------------------------------------*/ +static void +Window_To_Buffer(FORM *form, FIELD *field) +{ + _nc_get_fieldbuffer(form, field, field->buf); +} + /*--------------------------------------------------------------------------- | Facility : libnform | Function : static void Synchronize_Buffer(FORM * form) @@ -578,9 +628,9 @@ Synchronize_Buffer(FORM *form) { if (form->status & _WINDOW_MODIFIED) { - form->status &= ~_WINDOW_MODIFIED; - form->status |= _FCHECK_REQUIRED; - Window_To_Buffer(form->w, form->current); + ClrStatus(form, _WINDOW_MODIFIED); + SetStatus(form, _FCHECK_REQUIRED); + Window_To_Buffer(form, form->current); wmove(form->w, form->currow, form->curcol); } } @@ -630,7 +680,7 @@ Field_Grown(FIELD *field, int amount) growth = Minimum(field->maxgrow - field->dcols, growth); field->dcols += growth; if (field->dcols == field->maxgrow) - field->status &= ~_MAY_GROW; + ClrStatus(field, _MAY_GROW); } else { @@ -639,7 +689,7 @@ Field_Grown(FIELD *field, int amount) growth = Minimum(field->maxgrow - field->drows, growth); field->drows += growth; if (field->drows == field->maxgrow) - field->status &= ~_MAY_GROW; + ClrStatus(field, _MAY_GROW); } /* drows, dcols changed, so we get really the new buffer length */ new_buflen = Buffer_Length(field); @@ -651,7 +701,7 @@ Field_Grown(FIELD *field, int amount) field->drows = old_drows; if ((single_line_field && (field->dcols != field->maxgrow)) || (!single_line_field && (field->drows != field->maxgrow))) - field->status |= _MAY_GROW; + SetStatus(field, _MAY_GROW); } else { @@ -659,17 +709,16 @@ Field_Grown(FIELD *field, int amount) * realloc(). */ int i, j; - FIELD_CELL *old_bp; - FIELD_CELL *new_bp; result = TRUE; /* allow sharing of recovery on failure */ - T((T_CREATE("fieldcell %p"), newbuf)); + T((T_CREATE("fieldcell %p"), (void *)newbuf)); field->buf = newbuf; for (i = 0; i <= field->nbuf; i++) { - new_bp = Address_Of_Nth_Buffer(field, i); - old_bp = oldbuf + i * (1 + old_buflen); + FIELD_CELL *new_bp = Address_Of_Nth_Buffer(field, i); + FIELD_CELL *old_bp = oldbuf + i * (1 + old_buflen); + for (j = 0; j < old_buflen; ++j) new_bp[j] = old_bp[j]; while (j < new_buflen) @@ -730,7 +779,7 @@ Field_Grown(FIELD *field, int amount) (field->dcols != field->maxgrow)) || (!single_line_field && (field->drows != field->maxgrow))) - field->status |= _MAY_GROW; + SetStatus(field, _MAY_GROW); free(newbuf); } } @@ -753,7 +802,7 @@ Field_Grown(FIELD *field, int amount) static int Field_encloses(FIELD *field, int ry, int rx) { - T((T_CALLED("Field_encloses(%p)"), field)); + T((T_CALLED("Field_encloses(%p)"), (void *)field)); if (field != 0 && field->frow <= ry && (field->frow + field->rows) > ry @@ -779,7 +828,7 @@ Field_encloses(FIELD *field, int ry, int rx) | E_SYSTEM_ERROR - form has no current field or | field-window +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) _nc_Position_Form_Cursor(FORM *form) { FIELD *field; @@ -813,20 +862,22 @@ _nc_Position_Form_Cursor(FORM *form) | Facility : libnform | Function : int _nc_Refresh_Current_Field(FORM * form) | -| Description : Propagate the changes in the fields window to the +| Description : Propagate the changes in the field's window to the | window of the form. | | Return Values : E_OK - on success | E_BAD_ARGUMENT - invalid form pointer | E_SYSTEM_ERROR - general error +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +static bool move_after_insert = TRUE; +FORM_EXPORT(int) _nc_Refresh_Current_Field(FORM *form) { WINDOW *formwin; FIELD *field; + bool is_public; - T((T_CALLED("_nc_Refresh_Current_Field(%p)"), form)); + T((T_CALLED("_nc_Refresh_Current_Field(%p)"), (void *)form)); if (!form) RETURN(E_BAD_ARGUMENT); @@ -837,102 +888,106 @@ _nc_Refresh_Current_Field(FORM *form) field = form->current; formwin = Get_Form_Window(form); - if (field->opts & O_PUBLIC) + is_public = Field_Has_Option(field, O_PUBLIC); + + if (Is_Scroll_Field(field)) { - if (Is_Scroll_Field(field)) + /* Again, in this case the fieldwin isn't derived from formwin, + so we have to perform a copy operation. */ + if (Single_Line_Field(field)) { - /* Again, in this case the fieldwin isn't derived from formwin, - so we have to perform a copy operation. */ - if (Single_Line_Field(field)) + /* horizontal scrolling */ + if (form->curcol < form->begincol) + form->begincol = form->curcol; + else { - /* horizontal scrolling */ - if (form->curcol < form->begincol) - form->begincol = form->curcol; - else - { - if (form->curcol >= (form->begincol + field->cols)) - form->begincol = form->curcol - field->cols + 1; - } - copywin(form->w, - formwin, - 0, - form->begincol, - field->frow, - field->fcol, - field->frow, - field->cols + field->fcol - 1, - 0); + if (form->curcol >= (form->begincol + field->cols)) + form->begincol = form->curcol - field->cols + + (move_after_insert ? 1 : 0); } - else + if (is_public) + copywin(form->w, + formwin, + 0, + form->begincol, + field->frow, + field->fcol, + field->frow, + field->cols + field->fcol - 1, + 0); + } + else + { + /* A multi-line, i.e. vertical scrolling field */ + int first_modified_row, first_unmodified_row; + + if (field->drows > field->rows) { - /* A multi-line, i.e. vertical scrolling field */ - int row_after_bottom, first_modified_row, first_unmodified_row; + int row_after_bottom = form->toprow + field->rows; - if (field->drows > field->rows) + if (form->currow < form->toprow) { - row_after_bottom = form->toprow + field->rows; - if (form->currow < form->toprow) - { - form->toprow = form->currow; - field->status |= _NEWTOP; - } - if (form->currow >= row_after_bottom) - { - form->toprow = form->currow - field->rows + 1; - field->status |= _NEWTOP; - } - if (field->status & _NEWTOP) - { - /* means we have to copy whole range */ - first_modified_row = form->toprow; - first_unmodified_row = first_modified_row + field->rows; - field->status &= ~_NEWTOP; - } - else - { - /* we try to optimize : finding the range of touched - lines */ - first_modified_row = form->toprow; - while (first_modified_row < row_after_bottom) - { - if (is_linetouched(form->w, first_modified_row)) - break; - first_modified_row++; - } - first_unmodified_row = first_modified_row; - while (first_unmodified_row < row_after_bottom) - { - if (!is_linetouched(form->w, first_unmodified_row)) - break; - first_unmodified_row++; - } - } + form->toprow = form->currow; + SetStatus(field, _NEWTOP); } - else + if (form->currow >= row_after_bottom) { + form->toprow = form->currow - field->rows + 1; + SetStatus(field, _NEWTOP); + } + if (field->status & _NEWTOP) + { + /* means we have to copy whole range */ first_modified_row = form->toprow; first_unmodified_row = first_modified_row + field->rows; + ClrStatus(field, _NEWTOP); + } + else + { + /* we try to optimize : finding the range of touched + lines */ + first_modified_row = form->toprow; + while (first_modified_row < row_after_bottom) + { + if (is_linetouched(form->w, first_modified_row)) + break; + first_modified_row++; + } + first_unmodified_row = first_modified_row; + while (first_unmodified_row < row_after_bottom) + { + if (!is_linetouched(form->w, first_unmodified_row)) + break; + first_unmodified_row++; + } } - if (first_unmodified_row != first_modified_row) - copywin(form->w, - formwin, - first_modified_row, - 0, - field->frow + first_modified_row - form->toprow, - field->fcol, - field->frow + first_unmodified_row - form->toprow - 1, - field->cols + field->fcol - 1, - 0); } - wsyncup(formwin); - } - else - { - /* if the field-window is simply a derived window, i.e. contains no - * invisible parts, the whole thing is trivial - */ - wsyncup(form->w); + else + { + first_modified_row = form->toprow; + first_unmodified_row = first_modified_row + field->rows; + } + if (first_unmodified_row != first_modified_row && is_public) + copywin(form->w, + formwin, + first_modified_row, + 0, + field->frow + first_modified_row - form->toprow, + field->fcol, + field->frow + first_unmodified_row - form->toprow - 1, + field->cols + field->fcol - 1, + 0); } + if (is_public) + wsyncup(formwin); + } + else + { + /* if the field-window is simply a derived window, i.e. contains no + * invisible parts, the whole thing is trivial + */ + if (is_public) + wsyncup(form->w); } untouchwin(form->w); returnCode(_nc_Position_Form_Cursor(form)); @@ -953,28 +1008,32 @@ Perform_Justification(FIELD *field, WINDOW *win) { FIELD_CELL *bp; int len; - int col = 0; - bp = Get_Start_Of_Data(field->buf, Buffer_Length(field)); + bp = (Field_Has_Option(field, O_NO_LEFT_STRIP) + ? field->buf + : Get_Start_Of_Data(field->buf, Buffer_Length(field))); len = (int)(After_End_Of_Data(field->buf, Buffer_Length(field)) - bp); if (len > 0) { - assert(win && (field->drows == 1) && (field->dcols == field->cols)); + int col = 0; - switch (field->just) - { - case JUSTIFY_LEFT: - break; - case JUSTIFY_CENTER: - col = (field->cols - len) / 2; - break; - case JUSTIFY_RIGHT: - col = field->cols - len; - break; - default: - break; - } + assert(win && (field->drows == 1)); + + if (field->cols - len >= 0) + switch (field->just) + { + case JUSTIFY_LEFT: + break; + case JUSTIFY_CENTER: + col = (field->cols - len) / 2; + break; + case JUSTIFY_RIGHT: + col = field->cols - len; + break; + default: + break; + } wmove(win, 0, col); myADDNSTR(win, bp, len); @@ -996,9 +1055,14 @@ static void Undo_Justification(FIELD *field, WINDOW *win) { FIELD_CELL *bp; + int y, x; int len; - bp = Get_Start_Of_Data(field->buf, Buffer_Length(field)); + getyx(win, y, x); + + bp = (Field_Has_Option(field, O_NO_LEFT_STRIP) + ? field->buf + : Get_Start_Of_Data(field->buf, Buffer_Length(field))); len = (int)(After_End_Of_Data(field->buf, Buffer_Length(field)) - bp); if (len > 0) @@ -1007,11 +1071,13 @@ Undo_Justification(FIELD *field, WINDOW *win) wmove(win, 0, 0); myADDNSTR(win, bp, len); } + wmove(win, y, x); } /*--------------------------------------------------------------------------- | Facility : libnform -| Function : static bool Check_Char( +| Function : static bool Check_Char(FORM *form, +| FIELD *field, | FIELDTYPE * typ, | int ch, | TypeArgument *argp) @@ -1023,7 +1089,11 @@ Undo_Justification(FIELD *field, WINDOW *win) | FALSE - Character is invalid +--------------------------------------------------------------------------*/ static bool -Check_Char(FIELDTYPE *typ, int ch, TypeArgument *argp) +Check_Char(FORM *form, + FIELD *field, + FIELDTYPE *typ, + int ch, + TypeArgument *argp) { if (typ) { @@ -1031,13 +1101,23 @@ Check_Char(FIELDTYPE *typ, int ch, TypeArgument *argp) { assert(argp); return ( - Check_Char(typ->left, ch, argp->left) || - Check_Char(typ->right, ch, argp->right)); + Check_Char(form, field, typ->left, ch, argp->left) || + Check_Char(form, field, typ->right, ch, argp->right)); } else { +#if NCURSES_INTEROP_FUNCS + if (typ->charcheck.occheck) + { + if (typ->status & _GENERIC) + return typ->charcheck.gccheck(ch, form, field, (void *)argp); + else + return typ->charcheck.occheck(ch, (void *)argp); + } +#else if (typ->ccheck) return typ->ccheck(ch, (void *)argp); +#endif } } return (!iscntrl(UChar(ch)) ? TRUE : FALSE); @@ -1073,23 +1153,27 @@ Display_Or_Erase_Field(FIELD *field, bool bEraseFlag) return E_SYSTEM_ERROR; else { - if (field->opts & O_VISIBLE) - Set_Field_Window_Attributes(field, win); + if (Field_Has_Option(field, O_VISIBLE)) + { + Set_Field_Window_Attributes(field, win); + } else - wattrset(win, WINDOW_ATTRS(fwin)); + { + (void)wattrset(win, (int)WINDOW_ATTRS(fwin)); + } werase(win); } if (!bEraseFlag) { - if (field->opts & O_PUBLIC) + if (Field_Has_Option(field, O_PUBLIC)) { if (Justification_Allowed(field)) Perform_Justification(field, win); else Buffer_To_Window(field, win); } - field->status &= ~_NEWTOP; + ClrStatus(field, _NEWTOP); } wsyncup(win); delwin(win); @@ -1128,18 +1212,18 @@ Synchronize_Field(FIELD *field) form->currow = form->curcol = form->toprow = form->begincol = 0; werase(form->w); - if ((field->opts & O_PUBLIC) && Justification_Allowed(field)) + if ((Field_Has_Option(field, O_PUBLIC)) && Justification_Allowed(field)) Undo_Justification(field, form->w); else Buffer_To_Window(field, form->w); - field->status |= _NEWTOP; + SetStatus(field, _NEWTOP); res = _nc_Refresh_Current_Field(form); } else res = Display_Field(field); } - field->status |= _CHANGED; + SetStatus(field, _CHANGED); return (res); } @@ -1160,7 +1244,6 @@ Synchronize_Linked_Fields(FIELD *field) { FIELD *linked_field; int res = E_OK; - int syncres; if (!field) return (E_BAD_ARGUMENT); @@ -1169,9 +1252,11 @@ Synchronize_Linked_Fields(FIELD *field) return (E_SYSTEM_ERROR); for (linked_field = field->link; - linked_field != field; + (linked_field != field) && (linked_field != 0); linked_field = linked_field->link) { + int syncres; + if (((syncres = Synchronize_Field(linked_field)) != E_OK) && (res == E_OK)) res = syncres; @@ -1183,7 +1268,7 @@ Synchronize_Linked_Fields(FIELD *field) | Facility : libnform | Function : int _nc_Synchronize_Attributes(FIELD * field) | -| Description : If a fields visual attributes have changed, this +| Description : If a field's visual attributes have changed, this | routine is called to propagate those changes to the | screen. | @@ -1191,14 +1276,13 @@ Synchronize_Linked_Fields(FIELD *field) | E_BAD_ARGUMENT - invalid field pointer | E_SYSTEM_ERROR - some severe basic error +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) _nc_Synchronize_Attributes(FIELD *field) { FORM *form; int res = E_OK; - WINDOW *formwin; - T((T_CALLED("_nc_Synchronize_Attributes(%p)"), field)); + T((T_CALLED("_nc_Synchronize_Attributes(%p)"), (void *)field)); if (!field) returnCode(E_BAD_ARGUMENT); @@ -1214,7 +1298,7 @@ _nc_Synchronize_Attributes(FIELD *field) werase(form->w); wmove(form->w, form->currow, form->curcol); - if (field->opts & O_PUBLIC) + if (Field_Has_Option(field, O_PUBLIC)) { if (Justification_Allowed(field)) Undo_Justification(field, form->w); @@ -1223,14 +1307,16 @@ _nc_Synchronize_Attributes(FIELD *field) } else { - formwin = Get_Form_Window(form); + WINDOW *formwin = Get_Form_Window(form); + copywin(form->w, formwin, 0, 0, field->frow, field->fcol, - field->rows - 1, field->cols - 1, 0); + field->frow + field->rows - 1, + field->fcol + field->cols - 1, 0); wsyncup(formwin); Buffer_To_Window(field, form->w); - field->status |= _NEWTOP; /* fake refresh to paint all */ + SetStatus(field, _NEWTOP); /* fake refresh to paint all */ _nc_Refresh_Current_Field(form); } } @@ -1248,7 +1334,7 @@ _nc_Synchronize_Attributes(FIELD *field) | Function : int _nc_Synchronize_Options(FIELD * field, | Field_Options newopts) | -| Description : If a fields options have changed, this routine is +| Description : If a field's options have changed, this routine is | called to propagate these changes to the screen and | to really change the behavior of the field. | @@ -1257,7 +1343,7 @@ _nc_Synchronize_Attributes(FIELD *field) | E_CURRENT - field is the current one | E_SYSTEM_ERROR - some severe basic error +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) _nc_Synchronize_Options(FIELD *field, Field_Options newopts) { Field_Options oldopts; @@ -1265,7 +1351,7 @@ _nc_Synchronize_Options(FIELD *field, Field_Options newopts) FORM *form; int res = E_OK; - T((T_CALLED("_nc_Synchronize_Options(%p,%#x)"), field, newopts)); + T((T_CALLED("_nc_Synchronize_Options(%p,%#x)"), (void *)field, newopts)); if (!field) returnCode(E_BAD_ARGUMENT); @@ -1277,42 +1363,41 @@ _nc_Synchronize_Options(FIELD *field, Field_Options newopts) if (form) { - if (form->current == field) - { - field->opts = oldopts; - returnCode(E_CURRENT); - } - if (form->status & _POSTED) { + if (form->current == field) + { + field->opts = oldopts; + returnCode(E_CURRENT); + } if (form->curpage == field->page) { - if (changed_opts & O_VISIBLE) + if ((unsigned)changed_opts & O_VISIBLE) { - if (newopts & O_VISIBLE) + if ((unsigned)newopts & O_VISIBLE) res = Display_Field(field); else res = Erase_Field(field); } else { - if ((changed_opts & O_PUBLIC) && - (newopts & O_VISIBLE)) + if (((unsigned)changed_opts & O_PUBLIC) && + ((unsigned)newopts & O_VISIBLE)) res = Display_Field(field); } } } } - if (changed_opts & O_STATIC) + if ((unsigned)changed_opts & O_STATIC) { bool single_line_field = Single_Line_Field(field); int res2 = E_OK; - if (newopts & O_STATIC) + if ((unsigned)newopts & O_STATIC) { /* the field becomes now static */ - field->status &= ~_MAY_GROW; + ClrStatus(field, _MAY_GROW); /* if actually we have no hidden columns, justification may occur again */ if (single_line_field && @@ -1330,7 +1415,7 @@ _nc_Synchronize_Options(FIELD *field, Field_Options newopts) (single_line_field && (field->dcols < field->maxgrow)) || (!single_line_field && (field->drows < field->maxgrow))) { - field->status |= _MAY_GROW; + SetStatus(field, _MAY_GROW); /* a field with justification now changes its behavior, so we must redisplay it */ if (single_line_field && @@ -1348,6 +1433,57 @@ _nc_Synchronize_Options(FIELD *field, Field_Options newopts) returnCode(res); } +/* + * Removes the focus from the current field of the form. + */ +void +_nc_Unset_Current_Field(FORM *form) +{ + FIELD *field = form->current; + + _nc_Refresh_Current_Field(form); + if (Field_Has_Option(field, O_PUBLIC)) + { + if (field->drows > field->rows) + { + if (form->toprow == 0) + ClrStatus(field, _NEWTOP); + else + SetStatus(field, _NEWTOP); + } + else + { + if (Justification_Allowed(field)) + { + Window_To_Buffer(form, field); + werase(form->w); + Perform_Justification(field, form->w); + if (Field_Has_Option(field, O_DYNAMIC_JUSTIFY) && + (form->w->_parent == 0)) + { + copywin(form->w, + Get_Form_Window(form), + 0, + 0, + field->frow, + field->fcol, + field->frow, + field->cols + field->fcol - 1, + 0); + wsyncup(Get_Form_Window(form)); + } + else + { + wsyncup(form->w); + } + } + } + } + delwin(form->w); + form->w = (WINDOW *)0; + form->current = 0; +} + /*--------------------------------------------------------------------------- | Facility : libnform | Function : int _nc_Set_Current_Field(FORM * form, @@ -1360,15 +1496,15 @@ _nc_Synchronize_Options(FIELD *field, Field_Options newopts) | E_SYSTEM_ERROR - some severe basic error | E_NOT_CONNECTED - no fields are connected to the form +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) _nc_Set_Current_Field(FORM *form, FIELD *newfield) { FIELD *field; WINDOW *new_window; - T((T_CALLED("_nc_Set_Current_Field(%p,%p)"), form, newfield)); + T((T_CALLED("_nc_Set_Current_Field(%p,%p)"), (void *)form, (void *)newfield)); - if (!form || !newfield || !form->current || (newfield->form != form)) + if (!form || !newfield || (newfield->form != form)) returnCode(E_BAD_ARGUMENT); if ((form->status & _IN_DRIVER)) @@ -1382,34 +1518,10 @@ _nc_Set_Current_Field(FORM *form, FIELD *newfield) if ((field != newfield) || !(form->status & _POSTED)) { - if ((form->w) && - (field->opts & O_VISIBLE) && + if (field && (form->w) && + (Field_Has_Option(field, O_VISIBLE)) && (field->form->curpage == field->page)) - { - _nc_Refresh_Current_Field(form); - if (field->opts & O_PUBLIC) - { - if (field->drows > field->rows) - { - if (form->toprow == 0) - field->status &= ~_NEWTOP; - else - field->status |= _NEWTOP; - } - else - { - if (Justification_Allowed(field)) - { - Window_To_Buffer(form->w, field); - werase(form->w); - Perform_Justification(field, form->w); - wsyncup(form->w); - } - } - } - delwin(form->w); - form->w = (WINDOW *)0; - } + _nc_Unset_Current_Field(form); field = newfield; @@ -1428,7 +1540,7 @@ _nc_Set_Current_Field(FORM *form, FIELD *newfield) delwin(form->w); form->w = new_window; - form->status &= ~_WINDOW_MODIFIED; + ClrStatus(form, _WINDOW_MODIFIED); Set_Field_Window_Attributes(field, form->w); if (Has_Invisible_Parts(field)) @@ -1473,7 +1585,7 @@ IFN_Next_Character(FORM *form) FIELD *field = form->current; int step = myWCWIDTH(form->w, form->currow, form->curcol); - T((T_CALLED("IFN_Next_Character(%p)"), form)); + T((T_CALLED("IFN_Next_Character(%p)"), (void *)form)); if ((form->curcol += step) == field->dcols) { if ((++(form->currow)) == field->drows) @@ -1515,7 +1627,7 @@ IFN_Previous_Character(FORM *form) int amount = myWCWIDTH(form->w, form->currow, form->curcol - 1); int oldcol = form->curcol; - T((T_CALLED("IFN_Previous_Character(%p)"), form)); + T((T_CALLED("IFN_Previous_Character(%p)"), (void *)form)); if ((form->curcol -= amount) < 0) { if ((--(form->currow)) < 0) @@ -1543,7 +1655,7 @@ IFN_Next_Line(FORM *form) { FIELD *field = form->current; - T((T_CALLED("IFN_Next_Line(%p)"), form)); + T((T_CALLED("IFN_Next_Line(%p)"), (void *)form)); if ((++(form->currow)) == field->drows) { #if GROW_IF_NAVIGATE @@ -1569,7 +1681,7 @@ IFN_Next_Line(FORM *form) static int IFN_Previous_Line(FORM *form) { - T((T_CALLED("IFN_Previous_Line(%p)"), form)); + T((T_CALLED("IFN_Previous_Line(%p)"), (void *)form)); if ((--(form->currow)) < 0) { form->currow++; @@ -1596,7 +1708,7 @@ IFN_Next_Word(FORM *form) FIELD_CELL *s; FIELD_CELL *t; - T((T_CALLED("IFN_Next_Word(%p)"), form)); + T((T_CALLED("IFN_Next_Word(%p)"), (void *)form)); /* We really need access to the data, so we have to synchronize */ Synchronize_Buffer(form); @@ -1639,7 +1751,7 @@ IFN_Previous_Word(FORM *form) FIELD_CELL *t; bool again = FALSE; - T((T_CALLED("IFN_Previous_Word(%p)"), form)); + T((T_CALLED("IFN_Previous_Word(%p)"), (void *)form)); /* We really need access to the data, so we have to synchronize */ Synchronize_Buffer(form); @@ -1689,7 +1801,7 @@ IFN_Beginning_Of_Field(FORM *form) { FIELD *field = form->current; - T((T_CALLED("IFN_Beginning_Of_Field(%p)"), form)); + T((T_CALLED("IFN_Beginning_Of_Field(%p)"), (void *)form)); Synchronize_Buffer(form); Adjust_Cursor_Position(form, Get_Start_Of_Data(field->buf, Buffer_Length(field))); @@ -1713,7 +1825,7 @@ IFN_End_Of_Field(FORM *form) FIELD *field = form->current; FIELD_CELL *pos; - T((T_CALLED("IFN_End_Of_Field(%p)"), form)); + T((T_CALLED("IFN_End_Of_Field(%p)"), (void *)form)); Synchronize_Buffer(form); pos = After_End_Of_Data(field->buf, Buffer_Length(field)); if (pos == (field->buf + Buffer_Length(field))) @@ -1736,7 +1848,7 @@ IFN_Beginning_Of_Line(FORM *form) { FIELD *field = form->current; - T((T_CALLED("IFN_Beginning_Of_Line(%p)"), form)); + T((T_CALLED("IFN_Beginning_Of_Line(%p)"), (void *)form)); Synchronize_Buffer(form); Adjust_Cursor_Position(form, Get_Start_Of_Data(Address_Of_Current_Row_In_Buffer(form), @@ -1762,7 +1874,7 @@ IFN_End_Of_Line(FORM *form) FIELD_CELL *pos; FIELD_CELL *bp; - T((T_CALLED("IFN_End_Of_Line(%p)"), form)); + T((T_CALLED("IFN_End_Of_Line(%p)"), (void *)form)); Synchronize_Buffer(form); bp = Address_Of_Current_Row_In_Buffer(form); pos = After_End_Of_Data(bp, field->dcols); @@ -1788,7 +1900,7 @@ IFN_Left_Character(FORM *form) int amount = myWCWIDTH(form->w, form->currow, form->curcol - 1); int oldcol = form->curcol; - T((T_CALLED("IFN_Left_Character(%p)"), form)); + T((T_CALLED("IFN_Left_Character(%p)"), (void *)form)); if ((form->curcol -= amount) < 0) { form->curcol = oldcol; @@ -1813,7 +1925,7 @@ IFN_Right_Character(FORM *form) int amount = myWCWIDTH(form->w, form->currow, form->curcol); int oldcol = form->curcol; - T((T_CALLED("IFN_Right_Character(%p)"), form)); + T((T_CALLED("IFN_Right_Character(%p)"), (void *)form)); if ((form->curcol += amount) >= form->current->dcols) { #if GROW_IF_NAVIGATE @@ -1841,7 +1953,7 @@ IFN_Right_Character(FORM *form) static int IFN_Up_Character(FORM *form) { - T((T_CALLED("IFN_Up_Character(%p)"), form)); + T((T_CALLED("IFN_Up_Character(%p)"), (void *)form)); if ((--(form->currow)) < 0) { form->currow++; @@ -1865,7 +1977,7 @@ IFN_Down_Character(FORM *form) { FIELD *field = form->current; - T((T_CALLED("IFN_Down_Character(%p)"), form)); + T((T_CALLED("IFN_Down_Character(%p)"), (void *)form)); if ((++(form->currow)) == field->drows) { #if GROW_IF_NAVIGATE @@ -1957,7 +2069,7 @@ Vertical_Scrolling(int (*const fct) (FORM *), FORM *form) { res = fct(form); if (res == E_OK) - form->current->status |= _NEWTOP; + SetStatus(form->current, _NEWTOP); } return (res); } @@ -1974,7 +2086,7 @@ Vertical_Scrolling(int (*const fct) (FORM *), FORM *form) static int VSC_Scroll_Line_Forward(FORM *form) { - T((T_CALLED("VSC_Scroll_Line_Forward(%p)"), form)); + T((T_CALLED("VSC_Scroll_Line_Forward(%p)"), (void *)form)); returnCode(VSC_Generic(form, 1)); } @@ -1990,7 +2102,7 @@ VSC_Scroll_Line_Forward(FORM *form) static int VSC_Scroll_Line_Backward(FORM *form) { - T((T_CALLED("VSC_Scroll_Line_Backward(%p)"), form)); + T((T_CALLED("VSC_Scroll_Line_Backward(%p)"), (void *)form)); returnCode(VSC_Generic(form, -1)); } @@ -2006,7 +2118,7 @@ VSC_Scroll_Line_Backward(FORM *form) static int VSC_Scroll_Page_Forward(FORM *form) { - T((T_CALLED("VSC_Scroll_Page_Forward(%p)"), form)); + T((T_CALLED("VSC_Scroll_Page_Forward(%p)"), (void *)form)); returnCode(VSC_Generic(form, form->current->rows)); } @@ -2022,7 +2134,7 @@ VSC_Scroll_Page_Forward(FORM *form) static int VSC_Scroll_Half_Page_Forward(FORM *form) { - T((T_CALLED("VSC_Scroll_Half_Page_Forward(%p)"), form)); + T((T_CALLED("VSC_Scroll_Half_Page_Forward(%p)"), (void *)form)); returnCode(VSC_Generic(form, (form->current->rows + 1) / 2)); } @@ -2038,7 +2150,7 @@ VSC_Scroll_Half_Page_Forward(FORM *form) static int VSC_Scroll_Page_Backward(FORM *form) { - T((T_CALLED("VSC_Scroll_Page_Backward(%p)"), form)); + T((T_CALLED("VSC_Scroll_Page_Backward(%p)"), (void *)form)); returnCode(VSC_Generic(form, -(form->current->rows))); } @@ -2054,7 +2166,7 @@ VSC_Scroll_Page_Backward(FORM *form) static int VSC_Scroll_Half_Page_Backward(FORM *form) { - T((T_CALLED("VSC_Scroll_Half_Page_Backward(%p)"), form)); + T((T_CALLED("VSC_Scroll_Half_Page_Backward(%p)"), (void *)form)); returnCode(VSC_Generic(form, -((form->current->rows + 1) / 2))); } /*---------------------------------------------------------------------------- @@ -2148,7 +2260,7 @@ Horizontal_Scrolling(int (*const fct) (FORM *), FORM *form) static int HSC_Scroll_Char_Forward(FORM *form) { - T((T_CALLED("HSC_Scroll_Char_Forward(%p)"), form)); + T((T_CALLED("HSC_Scroll_Char_Forward(%p)"), (void *)form)); returnCode(HSC_Generic(form, 1)); } @@ -2164,7 +2276,7 @@ HSC_Scroll_Char_Forward(FORM *form) static int HSC_Scroll_Char_Backward(FORM *form) { - T((T_CALLED("HSC_Scroll_Char_Backward(%p)"), form)); + T((T_CALLED("HSC_Scroll_Char_Backward(%p)"), (void *)form)); returnCode(HSC_Generic(form, -1)); } @@ -2180,7 +2292,7 @@ HSC_Scroll_Char_Backward(FORM *form) static int HSC_Horizontal_Line_Forward(FORM *form) { - T((T_CALLED("HSC_Horizontal_Line_Forward(%p)"), form)); + T((T_CALLED("HSC_Horizontal_Line_Forward(%p)"), (void *)form)); returnCode(HSC_Generic(form, form->current->cols)); } @@ -2196,7 +2308,7 @@ HSC_Horizontal_Line_Forward(FORM *form) static int HSC_Horizontal_Half_Line_Forward(FORM *form) { - T((T_CALLED("HSC_Horizontal_Half_Line_Forward(%p)"), form)); + T((T_CALLED("HSC_Horizontal_Half_Line_Forward(%p)"), (void *)form)); returnCode(HSC_Generic(form, (form->current->cols + 1) / 2)); } @@ -2212,7 +2324,7 @@ HSC_Horizontal_Half_Line_Forward(FORM *form) static int HSC_Horizontal_Line_Backward(FORM *form) { - T((T_CALLED("HSC_Horizontal_Line_Backward(%p)"), form)); + T((T_CALLED("HSC_Horizontal_Line_Backward(%p)"), (void *)form)); returnCode(HSC_Generic(form, -(form->current->cols))); } @@ -2228,7 +2340,7 @@ HSC_Horizontal_Line_Backward(FORM *form) static int HSC_Horizontal_Half_Line_Backward(FORM *form) { - T((T_CALLED("HSC_Horizontal_Half_Line_Backward(%p)"), form)); + T((T_CALLED("HSC_Horizontal_Half_Line_Backward(%p)"), (void *)form)); returnCode(HSC_Generic(form, -((form->current->cols + 1) / 2))); } @@ -2315,7 +2427,6 @@ Insert_String(FORM *form, int row, FIELD_CELL *txt, int len) int datalen = (int)(After_End_Of_Data(bp, field->dcols) - bp); int freelen = field->dcols - datalen; int requiredlen = len + 1; - FIELD_CELL *split; int result = E_REQUEST_DENIED; if (freelen >= requiredlen) @@ -2324,7 +2435,7 @@ Insert_String(FORM *form, int row, FIELD_CELL *txt, int len) myINSNSTR(form->w, txt, len); wmove(form->w, row, len); myINSNSTR(form->w, &myBLANK, 1); - return E_OK; + result = E_OK; } else { @@ -2340,6 +2451,8 @@ Insert_String(FORM *form, int row, FIELD_CELL *txt, int len) if (row < (field->drows - 1)) { + FIELD_CELL *split; + split = After_Last_Whitespace_Character(bp, (int)(Get_Start_Of_Data(bp @@ -2363,8 +2476,8 @@ Insert_String(FORM *form, int row, FIELD_CELL *txt, int len) return E_OK; } } - return (result); } + return (result); } /*--------------------------------------------------------------------------- @@ -2389,7 +2502,7 @@ Wrapping_Not_Necessary_Or_Wrapping_Ok(FORM *form) int result = E_REQUEST_DENIED; bool Last_Row = ((field->drows - 1) == form->currow); - if ((field->opts & O_WRAP) && /* wrapping wanted */ + if ((Field_Has_Option(field, O_WRAP)) && /* wrapping wanted */ (!Single_Line_Field(field)) && /* must be multi-line */ (There_Is_No_Room_For_A_Char_In_Line(form)) && /* line is full */ (!Last_Row || Growable(field))) /* there are more lines */ @@ -2407,7 +2520,7 @@ Wrapping_Not_Necessary_Or_Wrapping_Ok(FORM *form) return E_SYSTEM_ERROR; } bp = Address_Of_Current_Row_In_Buffer(form); - Window_To_Buffer(form->w, field); + Window_To_Buffer(form, field); split = After_Last_Whitespace_Character(bp, field->dcols); /* split points to the first character of the sequence to be brought on the next line */ @@ -2433,7 +2546,7 @@ Wrapping_Not_Necessary_Or_Wrapping_Ok(FORM *form) if (result != E_OK) { DeleteChar(form); - Window_To_Buffer(form->w, field); + Window_To_Buffer(form, field); result = E_REQUEST_DENIED; } } @@ -2472,7 +2585,7 @@ Field_Editing(int (*const fct) (FORM *), FORM *form) editable fields. */ if ((fct == FE_Delete_Previous) && - (form->opts & O_BS_OVERLOAD) && + ((unsigned)form->opts & O_BS_OVERLOAD) && First_Position_In_Current_Field(form)) { res = Inter_Field_Navigation(FN_Previous_Field, form); @@ -2481,7 +2594,7 @@ Field_Editing(int (*const fct) (FORM *), FORM *form) { if (fct == FE_New_Line) { - if ((form->opts & O_NL_OVERLOAD) && + if (((unsigned)form->opts & O_NL_OVERLOAD) && First_Position_In_Current_Field(form)) { res = Inter_Field_Navigation(FN_Next_Field, form); @@ -2493,11 +2606,11 @@ Field_Editing(int (*const fct) (FORM *), FORM *form) else { /* From now on, everything must be editable */ - if (form->current->opts & O_EDIT) + if ((unsigned)form->current->opts & O_EDIT) { res = fct(form); if (res == E_OK) - form->status |= _WINDOW_MODIFIED; + SetStatus(form, _WINDOW_MODIFIED); } } } @@ -2524,13 +2637,13 @@ FE_New_Line(FORM *form) FIELD_CELL *bp, *t; bool Last_Row = ((field->drows - 1) == form->currow); - T((T_CALLED("FE_New_Line(%p)"), form)); + T((T_CALLED("FE_New_Line(%p)"), (void *)form)); if (form->status & _OVLMODE) { if (Last_Row && (!(Growable(field) && !Single_Line_Field(field)))) { - if (!(form->opts & O_NL_OVERLOAD)) + if (!((unsigned)form->opts & O_NL_OVERLOAD)) returnCode(E_REQUEST_DENIED); wmove(form->w, form->currow, form->curcol); wclrtoeol(form->w); @@ -2538,7 +2651,7 @@ FE_New_Line(FORM *form) handled in the generic routine. The reason is, that FN_Next_Field may fail, but the form is definitively changed */ - form->status |= _WINDOW_MODIFIED; + SetStatus(form, _WINDOW_MODIFIED); returnCode(Inter_Field_Navigation(FN_Next_Field, form)); } else @@ -2554,7 +2667,7 @@ FE_New_Line(FORM *form) wclrtoeol(form->w); form->currow++; form->curcol = 0; - form->status |= _WINDOW_MODIFIED; + SetStatus(form, _WINDOW_MODIFIED); returnCode(E_OK); } } @@ -2564,7 +2677,7 @@ FE_New_Line(FORM *form) if (Last_Row && !(Growable(field) && !Single_Line_Field(field))) { - if (!(form->opts & O_NL_OVERLOAD)) + if (!((unsigned)form->opts & O_NL_OVERLOAD)) returnCode(E_REQUEST_DENIED); returnCode(Inter_Field_Navigation(FN_Next_Field, form)); } @@ -2586,7 +2699,7 @@ FE_New_Line(FORM *form) wmove(form->w, form->currow, form->curcol); winsertln(form->w); myADDNSTR(form->w, bp, (int)(t - bp)); - form->status |= _WINDOW_MODIFIED; + SetStatus(form, _WINDOW_MODIFIED); returnCode(E_OK); } } @@ -2607,8 +2720,9 @@ FE_Insert_Character(FORM *form) FIELD *field = form->current; int result = E_REQUEST_DENIED; - T((T_CALLED("FE_Insert_Character(%p)"), form)); - if (Check_Char(field->type, (int)C_BLANK, (TypeArgument *)(field->arg))) + T((T_CALLED("FE_Insert_Character(%p)"), (void *)form)); + if (Check_Char(form, field, field->type, (int)C_BLANK, + (TypeArgument *)(field->arg))) { bool There_Is_Room = Is_There_Room_For_A_Char_In_Line(form); @@ -2642,8 +2756,9 @@ FE_Insert_Line(FORM *form) FIELD *field = form->current; int result = E_REQUEST_DENIED; - T((T_CALLED("FE_Insert_Line(%p)"), form)); - if (Check_Char(field->type, (int)C_BLANK, (TypeArgument *)(field->arg))) + T((T_CALLED("FE_Insert_Line(%p)"), (void *)form)); + if (Check_Char(form, field, + field->type, (int)C_BLANK, (TypeArgument *)(field->arg))) { bool Maybe_Done = (form->currow != (field->drows - 1)) && Is_There_Room_For_A_Line(form); @@ -2675,7 +2790,7 @@ FE_Insert_Line(FORM *form) static int FE_Delete_Character(FORM *form) { - T((T_CALLED("FE_Delete_Character(%p)"), form)); + T((T_CALLED("FE_Delete_Character(%p)"), (void *)form)); DeleteChar(form); returnCode(E_OK); } @@ -2698,7 +2813,7 @@ FE_Delete_Previous(FORM *form) { FIELD *field = form->current; - T((T_CALLED("FE_Delete_Previous(%p)"), form)); + T((T_CALLED("FE_Delete_Previous(%p)"), (void *)form)); if (First_Position_In_Current_Field(form)) returnCode(E_REQUEST_DENIED); @@ -2766,7 +2881,7 @@ FE_Delete_Previous(FORM *form) static int FE_Delete_Line(FORM *form) { - T((T_CALLED("FE_Delete_Line(%p)"), form)); + T((T_CALLED("FE_Delete_Line(%p)"), (void *)form)); form->curcol = 0; wdeleteln(form->w); returnCode(E_OK); @@ -2790,7 +2905,7 @@ FE_Delete_Word(FORM *form) FIELD_CELL *cp = bp + form->curcol; FIELD_CELL *s; - T((T_CALLED("FE_Delete_Word(%p)"), form)); + T((T_CALLED("FE_Delete_Word(%p)"), (void *)form)); Synchronize_Buffer(form); if (ISBLANK(*cp)) returnCode(E_REQUEST_DENIED); /* not in word */ @@ -2824,7 +2939,7 @@ FE_Delete_Word(FORM *form) static int FE_Clear_To_End_Of_Line(FORM *form) { - T((T_CALLED("FE_Clear_To_End_Of_Line(%p)"), form)); + T((T_CALLED("FE_Clear_To_End_Of_Line(%p)"), (void *)form)); wmove(form->w, form->currow, form->curcol); wclrtoeol(form->w); returnCode(E_OK); @@ -2841,7 +2956,7 @@ FE_Clear_To_End_Of_Line(FORM *form) static int FE_Clear_To_End_Of_Field(FORM *form) { - T((T_CALLED("FE_Clear_To_End_Of_Field(%p)"), form)); + T((T_CALLED("FE_Clear_To_End_Of_Field(%p)"), (void *)form)); wmove(form->w, form->currow, form->curcol); wclrtobot(form->w); returnCode(E_OK); @@ -2858,7 +2973,7 @@ FE_Clear_To_End_Of_Field(FORM *form) static int FE_Clear_Field(FORM *form) { - T((T_CALLED("FE_Clear_Field(%p)"), form)); + T((T_CALLED("FE_Clear_Field(%p)"), (void *)form)); form->currow = form->curcol = 0; werase(form->w); returnCode(E_OK); @@ -2882,8 +2997,8 @@ FE_Clear_Field(FORM *form) static int EM_Overlay_Mode(FORM *form) { - T((T_CALLED("EM_Overlay_Mode(%p)"), form)); - form->status |= _OVLMODE; + T((T_CALLED("EM_Overlay_Mode(%p)"), (void *)form)); + SetStatus(form, _OVLMODE); returnCode(E_OK); } @@ -2898,8 +3013,8 @@ EM_Overlay_Mode(FORM *form) static int EM_Insert_Mode(FORM *form) { - T((T_CALLED("EM_Insert_Mode(%p)"), form)); - form->status &= ~_OVLMODE; + T((T_CALLED("EM_Insert_Mode(%p)"), (void *)form)); + ClrStatus(form, _OVLMODE); returnCode(E_OK); } @@ -2913,7 +3028,7 @@ EM_Insert_Mode(FORM *form) /*--------------------------------------------------------------------------- | Facility : libnform -| Function : static bool Next_Choice( +| Function : static bool Next_Choice(FORM * form, | FIELDTYPE * typ, | FIELD * field, | TypeArgument *argp) @@ -2925,7 +3040,7 @@ EM_Insert_Mode(FORM *form) | FALSE - couldn't retrieve next choice +--------------------------------------------------------------------------*/ static bool -Next_Choice(FIELDTYPE *typ, FIELD *field, TypeArgument *argp) +Next_Choice(FORM *form, FIELDTYPE *typ, FIELD *field, TypeArgument *argp) { if (!typ || !(typ->status & _HAS_CHOICE)) return FALSE; @@ -2934,19 +3049,27 @@ Next_Choice(FIELDTYPE *typ, FIELD *field, TypeArgument *argp) { assert(argp); return ( - Next_Choice(typ->left, field, argp->left) || - Next_Choice(typ->right, field, argp->right)); + Next_Choice(form, typ->left, field, argp->left) || + Next_Choice(form, typ->right, field, argp->right)); } else { +#if NCURSES_INTEROP_FUNCS + assert(typ->enum_next.onext); + if (typ->status & _GENERIC) + return typ->enum_next.gnext(form, field, (void *)argp); + else + return typ->enum_next.onext(field, (void *)argp); +#else assert(typ->next); return typ->next(field, (void *)argp); +#endif } } /*--------------------------------------------------------------------------- | Facility : libnform -| Function : static bool Previous_Choice( +| Function : static bool Previous_Choice(FORM * form, | FIELDTYPE * typ, | FIELD * field, | TypeArgument *argp) @@ -2958,7 +3081,7 @@ Next_Choice(FIELDTYPE *typ, FIELD *field, TypeArgument *argp) | FALSE - couldn't retrieve previous choice +--------------------------------------------------------------------------*/ static bool -Previous_Choice(FIELDTYPE *typ, FIELD *field, TypeArgument *argp) +Previous_Choice(FORM *form, FIELDTYPE *typ, FIELD *field, TypeArgument *argp) { if (!typ || !(typ->status & _HAS_CHOICE)) return FALSE; @@ -2967,13 +3090,21 @@ Previous_Choice(FIELDTYPE *typ, FIELD *field, TypeArgument *argp) { assert(argp); return ( - Previous_Choice(typ->left, field, argp->left) || - Previous_Choice(typ->right, field, argp->right)); + Previous_Choice(form, typ->left, field, argp->left) || + Previous_Choice(form, typ->right, field, argp->right)); } else { +#if NCURSES_INTEROP_FUNCS + assert(typ->enum_prev.oprev); + if (typ->status & _GENERIC) + return typ->enum_prev.gprev(form, field, (void *)argp); + else + return typ->enum_prev.oprev(field, (void *)argp); +#else assert(typ->prev); return typ->prev(field, (void *)argp); +#endif } } /*---------------------------------------------------------------------------- @@ -2998,9 +3129,9 @@ CR_Next_Choice(FORM *form) { FIELD *field = form->current; - T((T_CALLED("CR_Next_Choice(%p)"), form)); + T((T_CALLED("CR_Next_Choice(%p)"), (void *)form)); Synchronize_Buffer(form); - returnCode((Next_Choice(field->type, field, (TypeArgument *)(field->arg))) + returnCode((Next_Choice(form, field->type, field, (TypeArgument *)(field->arg))) ? E_OK : E_REQUEST_DENIED); } @@ -3019,9 +3150,9 @@ CR_Previous_Choice(FORM *form) { FIELD *field = form->current; - T((T_CALLED("CR_Previous_Choice(%p)"), form)); + T((T_CALLED("CR_Previous_Choice(%p)"), (void *)form)); Synchronize_Buffer(form); - returnCode((Previous_Choice(field->type, field, (TypeArgument *)(field->arg))) + returnCode((Previous_Choice(form, field->type, field, (TypeArgument *)(field->arg))) ? E_OK : E_REQUEST_DENIED); } @@ -3035,7 +3166,7 @@ CR_Previous_Choice(FORM *form) /*--------------------------------------------------------------------------- | Facility : libnform -| Function : static bool Check_Field( +| Function : static bool Check_Field(FORM* form, | FIELDTYPE * typ, | FIELD * field, | TypeArgument * argp) @@ -3048,11 +3179,11 @@ CR_Previous_Choice(FORM *form) | FALSE - field is invalid. +--------------------------------------------------------------------------*/ static bool -Check_Field(FIELDTYPE *typ, FIELD *field, TypeArgument *argp) +Check_Field(FORM *form, FIELDTYPE *typ, FIELD *field, TypeArgument *argp) { if (typ) { - if (field->opts & O_NULLOK) + if (Field_Has_Option(field, O_NULLOK)) { FIELD_CELL *bp = field->buf; @@ -3069,13 +3200,23 @@ Check_Field(FIELDTYPE *typ, FIELD *field, TypeArgument *argp) { assert(argp); return ( - Check_Field(typ->left, field, argp->left) || - Check_Field(typ->right, field, argp->right)); + Check_Field(form, typ->left, field, argp->left) || + Check_Field(form, typ->right, field, argp->right)); } else { +#if NCURSES_INTEROP_FUNCS + if (typ->fieldcheck.ofcheck) + { + if (typ->status & _GENERIC) + return typ->fieldcheck.gfcheck(form, field, (void *)argp); + else + return typ->fieldcheck.ofcheck(field, (void *)argp); + } +#else if (typ->fcheck) return typ->fcheck(field, (void *)argp); +#endif } } return TRUE; @@ -3090,7 +3231,7 @@ Check_Field(FIELDTYPE *typ, FIELD *field, TypeArgument *argp) | Return Values : TRUE - field is valid | FALSE - field is invalid +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(bool) +FORM_EXPORT(bool) _nc_Internal_Validation(FORM *form) { FIELD *field; @@ -3099,12 +3240,12 @@ _nc_Internal_Validation(FORM *form) Synchronize_Buffer(form); if ((form->status & _FCHECK_REQUIRED) || - (!(field->opts & O_PASSOK))) + (!(Field_Has_Option(field, O_PASSOK)))) { - if (!Check_Field(field->type, field, (TypeArgument *)(field->arg))) + if (!Check_Field(form, field->type, field, (TypeArgument *)(field->arg))) return FALSE; - form->status &= ~_FCHECK_REQUIRED; - field->status |= _CHANGED; + ClrStatus(form, _FCHECK_REQUIRED); + SetStatus(field, _CHANGED); Synchronize_Linked_Fields(field); } return TRUE; @@ -3129,7 +3270,7 @@ _nc_Internal_Validation(FORM *form) static int FV_Validation(FORM *form) { - T((T_CALLED("FV_Validation(%p)"), form)); + T((T_CALLED("FV_Validation(%p)"), (void *)form)); if (_nc_Internal_Validation(form)) returnCode(E_OK); else @@ -3149,7 +3290,7 @@ FV_Validation(FORM *form) | | Description : Get the next field after the given field on the current | page. The order of fields is the one defined by the -| fields array. Only visible and active fields are +| field's array. Only visible and active fields are | counted. | | Return Values : Pointer to the next field. @@ -3184,7 +3325,7 @@ Next_Field_On_Page(FIELD *field) | | Return Values : Pointer to calculated field. +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(FIELD *) +FORM_EXPORT(FIELD *) _nc_First_Active_Field(FORM *form) { FIELD **last_on_page = &form->field[form->page[form->curpage].pmax]; @@ -3204,14 +3345,15 @@ _nc_First_Active_Field(FORM *form) do { field = (field == last_on_page) ? first : field + 1; - if (((*field)->opts & O_VISIBLE)) + if (Field_Has_Option(*field, O_VISIBLE)) break; } while (proposed != (*field)); proposed = *field; - if ((proposed == *last_on_page) && !(proposed->opts & O_VISIBLE)) + if ((proposed == *last_on_page) && + !((unsigned)proposed->opts & O_VISIBLE)) { /* This means, there is also no visible field on the page. So we propose the first one and hope the very best... @@ -3231,7 +3373,7 @@ _nc_First_Active_Field(FORM *form) | | Description : Get the previous field before the given field on the | current page. The order of fields is the one defined by -| the fields array. Only visible and active fields are +| the field's array. Only visible and active fields are | counted. | | Return Values : Pointer to the previous field. @@ -3365,10 +3507,10 @@ Right_Neighbor_Field(FIELD *field) | Function : static FIELD *Upper_Neighbor_Field(FIELD * field) | | Description : Because of the row-major nature of sorting the fields, -| it is more difficult to define whats the upper neighbor +| it is more difficult to define what the upper neighbor | field really means. We define that it must be on a | 'previous' line (cyclic order!) and is the rightmost -| field laying on the left side of the given field. If +| field lying on the left side of the given field. If | this set is empty, we take the first field on the line. | | Return Values : Pointer to the upper neighbor field. @@ -3415,7 +3557,7 @@ Upper_Neighbor_Field(FIELD *field) | Function : static FIELD *Down_Neighbor_Field(FIELD * field) | | Description : Because of the row-major nature of sorting the fields, -| its more difficult to define whats the down neighbor +| it is more difficult to define what the down neighbor | field really means. We define that it must be on a | 'next' line (cyclic order!) and is the leftmost | field laying on the right side of the given field. If @@ -3507,7 +3649,7 @@ Inter_Field_Navigation(int (*const fct) (FORM *), FORM *form) static int FN_Next_Field(FORM *form) { - T((T_CALLED("FN_Next_Field(%p)"), form)); + T((T_CALLED("FN_Next_Field(%p)"), (void *)form)); returnCode(_nc_Set_Current_Field(form, Next_Field_On_Page(form->current))); } @@ -3525,7 +3667,7 @@ FN_Next_Field(FORM *form) static int FN_Previous_Field(FORM *form) { - T((T_CALLED("FN_Previous_Field(%p)"), form)); + T((T_CALLED("FN_Previous_Field(%p)"), (void *)form)); returnCode(_nc_Set_Current_Field(form, Previous_Field_On_Page(form->current))); } @@ -3542,7 +3684,7 @@ FN_Previous_Field(FORM *form) static int FN_First_Field(FORM *form) { - T((T_CALLED("FN_First_Field(%p)"), form)); + T((T_CALLED("FN_First_Field(%p)"), (void *)form)); returnCode(_nc_Set_Current_Field(form, Next_Field_On_Page(form->field[form->page[form->curpage].pmax]))); } @@ -3559,7 +3701,7 @@ FN_First_Field(FORM *form) static int FN_Last_Field(FORM *form) { - T((T_CALLED("FN_Last_Field(%p)"), form)); + T((T_CALLED("FN_Last_Field(%p)"), (void *)form)); returnCode( _nc_Set_Current_Field(form, Previous_Field_On_Page(form->field[form->page[form->curpage].pmin]))); @@ -3578,7 +3720,7 @@ FN_Last_Field(FORM *form) static int FN_Sorted_Next_Field(FORM *form) { - T((T_CALLED("FN_Sorted_Next_Field(%p)"), form)); + T((T_CALLED("FN_Sorted_Next_Field(%p)"), (void *)form)); returnCode(_nc_Set_Current_Field(form, Sorted_Next_Field(form->current))); } @@ -3596,7 +3738,7 @@ FN_Sorted_Next_Field(FORM *form) static int FN_Sorted_Previous_Field(FORM *form) { - T((T_CALLED("FN_Sorted_Previous_Field(%p)"), form)); + T((T_CALLED("FN_Sorted_Previous_Field(%p)"), (void *)form)); returnCode(_nc_Set_Current_Field(form, Sorted_Previous_Field(form->current))); } @@ -3614,7 +3756,7 @@ FN_Sorted_Previous_Field(FORM *form) static int FN_Sorted_First_Field(FORM *form) { - T((T_CALLED("FN_Sorted_First_Field(%p)"), form)); + T((T_CALLED("FN_Sorted_First_Field(%p)"), (void *)form)); returnCode(_nc_Set_Current_Field(form, Sorted_Next_Field(form->field[form->page[form->curpage].smax]))); } @@ -3632,7 +3774,7 @@ FN_Sorted_First_Field(FORM *form) static int FN_Sorted_Last_Field(FORM *form) { - T((T_CALLED("FN_Sorted_Last_Field(%p)"), form)); + T((T_CALLED("FN_Sorted_Last_Field(%p)"), (void *)form)); returnCode(_nc_Set_Current_Field(form, Sorted_Previous_Field(form->field[form->page[form->curpage].smin]))); } @@ -3650,7 +3792,7 @@ FN_Sorted_Last_Field(FORM *form) static int FN_Left_Field(FORM *form) { - T((T_CALLED("FN_Left_Field(%p)"), form)); + T((T_CALLED("FN_Left_Field(%p)"), (void *)form)); returnCode(_nc_Set_Current_Field(form, Left_Neighbor_Field(form->current))); } @@ -3668,7 +3810,7 @@ FN_Left_Field(FORM *form) static int FN_Right_Field(FORM *form) { - T((T_CALLED("FN_Right_Field(%p)"), form)); + T((T_CALLED("FN_Right_Field(%p)"), (void *)form)); returnCode(_nc_Set_Current_Field(form, Right_Neighbor_Field(form->current))); } @@ -3688,7 +3830,7 @@ FN_Right_Field(FORM *form) static int FN_Up_Field(FORM *form) { - T((T_CALLED("FN_Up_Field(%p)"), form)); + T((T_CALLED("FN_Up_Field(%p)"), (void *)form)); returnCode(_nc_Set_Current_Field(form, Upper_Neighbor_Field(form->current))); } @@ -3708,7 +3850,7 @@ FN_Up_Field(FORM *form) static int FN_Down_Field(FORM *form) { - T((T_CALLED("FN_Down_Field(%p)"), form)); + T((T_CALLED("FN_Down_Field(%p)"), (void *)form)); returnCode(_nc_Set_Current_Field(form, Down_Neighbor_Field(form->current))); } @@ -3737,7 +3879,7 @@ FN_Down_Field(FORM *form) | E_BAD_ARGUMENT - invalid field pointer | E_SYSTEM_ERROR - some severe basic error +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) _nc_Set_Form_Page(FORM *form, int page, FIELD *field) { int res = E_OK; @@ -3747,11 +3889,11 @@ _nc_Set_Form_Page(FORM *form, int page, FIELD *field) FIELD *last_field, *field_on_page; werase(Get_Form_Window(form)); - form->curpage = page; + form->curpage = (short)page; last_field = field_on_page = form->field[form->page[page].smin]; do { - if (field_on_page->opts & O_VISIBLE) + if ((unsigned)field_on_page->opts & O_VISIBLE) if ((res = Display_Field(field_on_page)) != E_OK) return (res); field_on_page = field_on_page->snext; @@ -3816,7 +3958,7 @@ Previous_Page_Number(const FORM *form) | that the field is left and a new field is entered. | So the field must be validated and the field init/term | hooks must be called. Because also the page is changed, -| the forms init/term hooks must be called also. +| the form's init/term hooks must be called also. | | Return Values : E_OK - success | E_INVALID_FIELD - field is invalid @@ -3852,7 +3994,7 @@ Page_Navigation(int (*const fct) (FORM *), FORM *form) static int PN_Next_Page(FORM *form) { - T((T_CALLED("PN_Next_Page(%p)"), form)); + T((T_CALLED("PN_Next_Page(%p)"), (void *)form)); returnCode(_nc_Set_Form_Page(form, Next_Page_Number(form), (FIELD *)0)); } @@ -3868,7 +4010,7 @@ PN_Next_Page(FORM *form) static int PN_Previous_Page(FORM *form) { - T((T_CALLED("PN_Previous_Page(%p)"), form)); + T((T_CALLED("PN_Previous_Page(%p)"), (void *)form)); returnCode(_nc_Set_Form_Page(form, Previous_Page_Number(form), (FIELD *)0)); } @@ -3884,7 +4026,7 @@ PN_Previous_Page(FORM *form) static int PN_First_Page(FORM *form) { - T((T_CALLED("PN_First_Page(%p)"), form)); + T((T_CALLED("PN_First_Page(%p)"), (void *)form)); returnCode(_nc_Set_Form_Page(form, 0, (FIELD *)0)); } @@ -3900,7 +4042,7 @@ PN_First_Page(FORM *form) static int PN_Last_Page(FORM *form) { - T((T_CALLED("PN_Last_Page(%p)"), form)); + T((T_CALLED("PN_Last_Page(%p)"), (void *)form)); returnCode(_nc_Set_Form_Page(form, form->maxpage - 1, (FIELD *)0)); } @@ -3912,6 +4054,94 @@ PN_Last_Page(FORM *form) Helper routines for the core form driver. --------------------------------------------------------------------------*/ +# if USE_WIDEC_SUPPORT +/*--------------------------------------------------------------------------- +| Facility : libnform +| Function : static int Data_Entry_w(FORM * form, wchar_t c) +| +| Description : Enter the wide character c into at the current +| position of the current field of the form. +| +| Return Values : E_OK - success +| E_REQUEST_DENIED - driver could not process the request +| E_SYSTEM_ERROR - ++--------------------------------------------------------------------------*/ +static int +Data_Entry_w(FORM *form, wchar_t c) +{ + FIELD *field = form->current; + int result = E_REQUEST_DENIED; + + T((T_CALLED("Data_Entry(%p,%s)"), (void *)form, _tracechtype((chtype)c))); + if ((Field_Has_Option(field, O_EDIT)) +#if FIX_FORM_INACTIVE_BUG + && (Field_Has_Option(field, O_ACTIVE)) +#endif + ) + { + wchar_t given[2]; + cchar_t temp_ch; + + given[0] = c; + given[1] = 0; + setcchar(&temp_ch, given, 0, 0, (void *)0); + if ((Field_Has_Option(field, O_BLANK)) && + First_Position_In_Current_Field(form) && + !(form->status & _FCHECK_REQUIRED) && + !(form->status & _WINDOW_MODIFIED)) + werase(form->w); + + if (form->status & _OVLMODE) + { + wadd_wch(form->w, &temp_ch); + } + else + /* no _OVLMODE */ + { + bool There_Is_Room = Is_There_Room_For_A_Char_In_Line(form); + + if (!(There_Is_Room || + ((Single_Line_Field(field) && Growable(field))))) + RETURN(E_REQUEST_DENIED); + + if (!There_Is_Room && !Field_Grown(field, 1)) + RETURN(E_SYSTEM_ERROR); + + wins_wch(form->w, &temp_ch); + } + + if ((result = Wrapping_Not_Necessary_Or_Wrapping_Ok(form)) == E_OK) + { + bool End_Of_Field = (((field->drows - 1) == form->currow) && + ((field->dcols - 1) == form->curcol)); + + form->status |= _WINDOW_MODIFIED; + if (End_Of_Field && !Growable(field) && (Field_Has_Option(field, O_AUTOSKIP))) + result = Inter_Field_Navigation(FN_Next_Field, form); + else + { + if (End_Of_Field && Growable(field) && !Field_Grown(field, 1)) + result = E_SYSTEM_ERROR; + else + { + /* + * We have just added a byte to the form field. It may have + * been part of a multibyte character. If it was, the + * addch_used field is nonzero and we should not try to move + * to a new column. + */ + if (WINDOW_EXT(form->w, addch_used) == 0) + IFN_Next_Character(form); + + result = E_OK; + } + } + } + } + RETURN(result); +} +# endif + /*--------------------------------------------------------------------------- | Facility : libnform | Function : static int Data_Entry(FORM * form,int c) @@ -3929,14 +4159,14 @@ Data_Entry(FORM *form, int c) FIELD *field = form->current; int result = E_REQUEST_DENIED; - T((T_CALLED("Data_Entry(%p,%s)"), form, _tracechtype((chtype)c))); - if ((field->opts & O_EDIT) + T((T_CALLED("Data_Entry(%p,%s)"), (void *)form, _tracechtype((chtype)c))); + if ((Field_Has_Option(field, O_EDIT)) #if FIX_FORM_INACTIVE_BUG - && (field->opts & O_ACTIVE) + && (Field_Has_Option(field, O_ACTIVE)) #endif ) { - if ((field->opts & O_BLANK) && + if ((Field_Has_Option(field, O_BLANK)) && First_Position_In_Current_Field(form) && !(form->status & _FCHECK_REQUIRED) && !(form->status & _WINDOW_MODIFIED)) @@ -3966,8 +4196,14 @@ Data_Entry(FORM *form, int c) bool End_Of_Field = (((field->drows - 1) == form->currow) && ((field->dcols - 1) == form->curcol)); - form->status |= _WINDOW_MODIFIED; - if (End_Of_Field && !Growable(field) && (field->opts & O_AUTOSKIP)) + if (Field_Has_Option(field, O_EDGE_INSERT_STAY)) + move_after_insert = !!(form->curcol + - form->begincol + - field->cols + + 1); + + SetStatus(form, _WINDOW_MODIFIED); + if (End_Of_Field && !Growable(field) && (Field_Has_Option(field, O_AUTOSKIP))) result = Inter_Field_Navigation(FN_Next_Field, form); else { @@ -4124,18 +4360,20 @@ static const Binding_Info bindings[MAX_FORM_COMMAND - MIN_FORM_COMMAND + 1] = | E_NOT_CONNECTED - no fields are connected to the form | E_UNKNOWN_COMMAND - command not known +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) form_driver(FORM *form, int c) { - const Binding_Info *BI = (Binding_Info *) 0; + const Binding_Info *BI = (Binding_Info *)0; int res = E_UNKNOWN_COMMAND; - T((T_CALLED("form_driver(%p,%d)"), form, c)); + move_after_insert = TRUE; + + T((T_CALLED("form_driver(%p,%d)"), (void *)form, c)); if (!form) RETURN(E_BAD_ARGUMENT); - if (!(form->field)) + if (!(form->field) || !(form->current)) RETURN(E_NOT_CONNECTED); assert(form->page); @@ -4159,7 +4397,10 @@ form_driver(FORM *form, int c) if ((c >= MIN_FORM_COMMAND && c <= MAX_FORM_COMMAND) && ((bindings[c - MIN_FORM_COMMAND].keycode & Key_Mask) == c)) - BI = &(bindings[c - MIN_FORM_COMMAND]); + { + TR(TRACE_CALLS, ("form_request %s", form_request_name(c))); + BI = &(bindings[c - MIN_FORM_COMMAND]); + } if (BI) { @@ -4177,7 +4418,7 @@ form_driver(FORM *form, int c) NULL /* Choice Request is generic */ }; size_t nMethods = (sizeof(Generic_Methods) / sizeof(Generic_Methods[0])); - size_t method = (BI->keycode >> ID_Shft) & 0xffff; /* see ID_Mask */ + size_t method = (size_t)((BI->keycode >> ID_Shft) & 0xffff); /* see ID_Mask */ if ((method >= nMethods) || !(BI->cmd)) res = E_SYSTEM_ERROR; @@ -4186,16 +4427,20 @@ form_driver(FORM *form, int c) Generic_Method fct = Generic_Methods[method]; if (fct) - res = fct(BI->cmd, form); + { + res = fct(BI->cmd, form); + } else - res = (BI->cmd) (form); + { + res = (BI->cmd) (form); + } } } #ifdef NCURSES_MOUSE_VERSION else if (KEY_MOUSE == c) { MEVENT event; - WINDOW *win = form->win ? form->win : stdscr; + WINDOW *win = form->win ? form->win : StdScreen(Get_Form_Screen(form)); WINDOW *sub = form->sub ? form->sub : win; getmouse(&event); @@ -4235,14 +4480,13 @@ form_driver(FORM *form, int c) } else if (wenclose(sub, event.y, event.x)) { /* Inside the area we try to find the hit item */ - int i; - ry = event.y; rx = event.x; if (wmouse_trafo(sub, &ry, &rx, FALSE)) { int min_field = form->page[form->curpage].pmin; int max_field = form->page[form->curpage].pmax; + int i; for (i = min_field; i <= max_field; ++i) { @@ -4282,7 +4526,7 @@ form_driver(FORM *form, int c) if (!iscntrl(UChar(c))) #else if (isprint(UChar(c)) && - Check_Char(form->current->type, c, + Check_Char(form, form->current, form->current->type, c, (TypeArgument *)(form->current->arg))) #endif res = Data_Entry(form, c); @@ -4291,6 +4535,194 @@ form_driver(FORM *form, int c) RETURN(res); } +# if USE_WIDEC_SUPPORT +/*--------------------------------------------------------------------------- +| Facility : libnform +| Function : int form_driver_w(FORM * form,int type,wchar_t c) +| +| Description : This is the workhorse of the forms system. +| +| Input is either a key code (request) or a wide char +| returned by e.g. get_wch (). The type must be passed +| as well,so that we are able to determine whether the char +| is a multibyte char or a request. + +| If it is a request, the form driver executes +| the request and returns the result. If it is data +| (printable character), it enters the data into the +| current position in the current field. If it is not +| recognized, the form driver assumes it is an application +| defined command and returns E_UNKNOWN_COMMAND. +| Application defined command should be defined relative +| to MAX_FORM_COMMAND, the maximum value of a request. +| +| Return Values : E_OK - success +| E_SYSTEM_ERROR - system error +| E_BAD_ARGUMENT - an argument is incorrect +| E_NOT_POSTED - form is not posted +| E_INVALID_FIELD - field contents are invalid +| E_BAD_STATE - called from inside a hook routine +| E_REQUEST_DENIED - request failed +| E_NOT_CONNECTED - no fields are connected to the form +| E_UNKNOWN_COMMAND - command not known ++--------------------------------------------------------------------------*/ +FORM_EXPORT(int) +form_driver_w(FORM *form, int type, wchar_t c) +{ + const Binding_Info *BI = (Binding_Info *)0; + int res = E_UNKNOWN_COMMAND; + + T((T_CALLED("form_driver(%p,%d)"), (void *)form, (int)c)); + + if (!form) + RETURN(E_BAD_ARGUMENT); + + if (!(form->field)) + RETURN(E_NOT_CONNECTED); + + assert(form->page); + + if (c == (wchar_t)FIRST_ACTIVE_MAGIC) + { + form->current = _nc_First_Active_Field(form); + RETURN(E_OK); + } + + assert(form->current && + form->current->buf && + (form->current->form == form) + ); + + if (form->status & _IN_DRIVER) + RETURN(E_BAD_STATE); + + if (!(form->status & _POSTED)) + RETURN(E_NOT_POSTED); + + /* check if this is a keycode or a (wide) char */ + if (type == KEY_CODE_YES) + { + if ((c >= MIN_FORM_COMMAND && c <= MAX_FORM_COMMAND) && + ((bindings[c - MIN_FORM_COMMAND].keycode & Key_Mask) == c)) + BI = &(bindings[c - MIN_FORM_COMMAND]); + } + + if (BI) + { + typedef int (*Generic_Method) (int (*const) (FORM *), FORM *); + static const Generic_Method Generic_Methods[] = + { + Page_Navigation, /* overloaded to call field&form hooks */ + Inter_Field_Navigation, /* overloaded to call field hooks */ + NULL, /* Intra-Field is generic */ + Vertical_Scrolling, /* Overloaded to check multi-line */ + Horizontal_Scrolling, /* Overloaded to check single-line */ + Field_Editing, /* Overloaded to mark modification */ + NULL, /* Edit Mode is generic */ + NULL, /* Field Validation is generic */ + NULL /* Choice Request is generic */ + }; + size_t nMethods = (sizeof(Generic_Methods) / sizeof(Generic_Methods[0])); + size_t method = (size_t)(BI->keycode >> ID_Shft) & 0xffff; /* see ID_Mask */ + + if ((method >= nMethods) || !(BI->cmd)) + res = E_SYSTEM_ERROR; + else + { + Generic_Method fct = Generic_Methods[method]; + + if (fct) + res = fct(BI->cmd, form); + else + res = (BI->cmd) (form); + } + } +#ifdef NCURSES_MOUSE_VERSION + else if (KEY_MOUSE == c) + { + MEVENT event; + WINDOW *win = form->win ? form->win : StdScreen(Get_Form_Screen(form)); + WINDOW *sub = form->sub ? form->sub : win; + + getmouse(&event); + if ((event.bstate & (BUTTON1_CLICKED | + BUTTON1_DOUBLE_CLICKED | + BUTTON1_TRIPLE_CLICKED)) + && wenclose(win, event.y, event.x)) + { /* we react only if the click was in the userwin, that means + * inside the form display area or at the decoration window. + */ + int ry = event.y, rx = event.x; /* screen coordinates */ + + res = E_REQUEST_DENIED; + if (mouse_trafo(&ry, &rx, FALSE)) + { /* rx, ry are now "curses" coordinates */ + if (ry < sub->_begy) + { /* we clicked above the display region; this is + * interpreted as "scroll up" request + */ + if (event.bstate & BUTTON1_CLICKED) + res = form_driver(form, REQ_PREV_FIELD); + else if (event.bstate & BUTTON1_DOUBLE_CLICKED) + res = form_driver(form, REQ_PREV_PAGE); + else if (event.bstate & BUTTON1_TRIPLE_CLICKED) + res = form_driver(form, REQ_FIRST_FIELD); + } + else if (ry > sub->_begy + sub->_maxy) + { /* we clicked below the display region; this is + * interpreted as "scroll down" request + */ + if (event.bstate & BUTTON1_CLICKED) + res = form_driver(form, REQ_NEXT_FIELD); + else if (event.bstate & BUTTON1_DOUBLE_CLICKED) + res = form_driver(form, REQ_NEXT_PAGE); + else if (event.bstate & BUTTON1_TRIPLE_CLICKED) + res = form_driver(form, REQ_LAST_FIELD); + } + else if (wenclose(sub, event.y, event.x)) + { /* Inside the area we try to find the hit item */ + ry = event.y; + rx = event.x; + if (wmouse_trafo(sub, &ry, &rx, FALSE)) + { + int min_field = form->page[form->curpage].pmin; + int max_field = form->page[form->curpage].pmax; + int i; + + for (i = min_field; i <= max_field; ++i) + { + FIELD *field = form->field[i]; + + if (Field_Is_Selectable(field) + && Field_encloses(field, ry, rx) == E_OK) + { + res = _nc_Set_Current_Field(form, field); + if (res == E_OK) + res = _nc_Position_Form_Cursor(form); + if (res == E_OK + && (event.bstate & BUTTON1_DOUBLE_CLICKED)) + res = E_UNKNOWN_COMMAND; + break; + } + } + } + } + } + } + else + res = E_REQUEST_DENIED; + } +#endif /* NCURSES_MOUSE_VERSION */ + else if (type == OK) + { + res = Data_Entry_w(form, c); + } + + _nc_Refresh_Current_Field(form); + RETURN(res); +} +# endif /* USE_WIDEC_SUPPORT */ + /*---------------------------------------------------------------------------- Field-Buffer manipulation routines. The effects of setting a buffer are tightly coupled to the core of the form @@ -4308,26 +4740,26 @@ form_driver(FORM *form, int c) | For dynamic fields this may grow the fieldbuffers if | the length of the value exceeds the current buffer | length. For buffer 0 only printable values are allowed. -| For static fields, the value needs not to be zero ter- -| minated. It is copied up to the length of the buffer. +| For static fields, the value must not be zero terminated. +| It is copied up to the length of the buffer. | | Return Values : E_OK - success | E_BAD_ARGUMENT - invalid argument | E_SYSTEM_ERROR - system error +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) set_field_buffer(FIELD *field, int buffer, const char *value) { FIELD_CELL *p; int res = E_OK; - unsigned int i; - unsigned int len; + int i; + int len; #if USE_WIDEC_SUPPORT FIELD_CELL *widevalue = 0; #endif - T((T_CALLED("set_field_buffer(%p,%d,%s)"), field, buffer, _nc_visbuf(value))); + T((T_CALLED("set_field_buffer(%p,%d,%s)"), (void *)field, buffer, _nc_visbuf(value))); if (!field || !value || ((buffer < 0) || (buffer > field->nbuf))) RETURN(E_BAD_ARGUMENT); @@ -4339,7 +4771,7 @@ set_field_buffer(FIELD *field, int buffer, const char *value) /* for a growable field we must assume zero terminated strings, because somehow we have to detect the length of what should be copied. */ - unsigned int vlen = strlen(value); + int vlen = (int)strlen(value); if (vlen > len) { @@ -4363,15 +4795,15 @@ set_field_buffer(FIELD *field, int buffer, const char *value) * and other special cases that we really do not want to handle here. */ #if NCURSES_EXT_FUNCS - if (wresize(field->working, field->drows, field->dcols) == ERR) + if (wresize(field->working, 1, Buffer_Length(field) + 1) == ERR) #endif { delwin(field->working); - field->working = newpad(field->drows, field->dcols); + field->working = newpad(1, Buffer_Length(field) + 1); } len = Buffer_Length(field); wclear(field->working); - mvwaddstr(field->working, 0, 0, value); + (void)mvwaddstr(field->working, 0, 0, value); if ((widevalue = typeCalloc(FIELD_CELL, len + 1)) == 0) { @@ -4379,11 +4811,11 @@ set_field_buffer(FIELD *field, int buffer, const char *value) } else { - for (i = 0; i < (unsigned)field->drows; ++i) + for (i = 0; i < field->drows; ++i) { - mvwin_wchnstr(field->working, i, 0, - widevalue + (i * field->dcols), - field->dcols); + (void)mvwin_wchnstr(field->working, 0, (int)i * field->dcols, + widevalue + ((int)i * field->dcols), + field->dcols); } for (i = 0; i < len; ++i) { @@ -4432,32 +4864,32 @@ set_field_buffer(FIELD *field, int buffer, const char *value) | | Return Values : Pointer to buffer or NULL if arguments were invalid. +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(char *) +FORM_EXPORT(char *) field_buffer(const FIELD *field, int buffer) { char *result = 0; - T((T_CALLED("field_buffer(%p,%d)"), field, buffer)); + T((T_CALLED("field_buffer(%p,%d)"), (const void *)field, buffer)); if (field && (buffer >= 0) && (buffer <= field->nbuf)) { #if USE_WIDEC_SUPPORT FIELD_CELL *data = Address_Of_Nth_Buffer(field, buffer); - unsigned need = 0; + size_t need = 0; int size = Buffer_Length(field); int n; /* determine the number of bytes needed to store the expanded string */ for (n = 0; n < size; ++n) { - if (!isWidecExt(data[n])) + if (!isWidecExt(data[n]) && data[n].chars[0] != L'\0') { mbstate_t state; size_t next; init_mb(state); next = _nc_wcrtomb(0, data[n].chars[0], &state); - if (!isEILSEQ(next)) + if (next > 0) need += next; } } @@ -4467,12 +4899,25 @@ field_buffer(const FIELD *field, int buffer) free(field->expanded[buffer]); field->expanded[buffer] = typeMalloc(char, need + 1); - /* expand the multibyte data */ + /* + * Expand the multibyte data. + * + * It may also be multi-column data. In that case, the data for a row + * may be null-padded to align to the dcols/drows layout (or it may + * contain embedded wide-character extensions). Change the null-padding + * to blanks as needed. + */ if ((result = field->expanded[buffer]) != 0) { wclear(field->working); - mvwadd_wchnstr(field->working, 0, 0, data, size); - mvwinnstr(field->working, 0, 0, result, (int)need); + wmove(field->working, 0, 0); + for (n = 0; n < size; ++n) + { + if (!isWidecExt(data[n]) && data[n].chars[0] != L'\0') + wadd_wch(field->working, &data[n]); + } + wmove(field->working, 0, 0); + winnstr(field->working, result, (int)need); } #else result = Address_Of_Nth_Buffer(field, buffer); @@ -4483,27 +4928,11 @@ field_buffer(const FIELD *field, int buffer) #if USE_WIDEC_SUPPORT -/* FIXME: see lib_get_wch.c */ -#if HAVE_MBTOWC && HAVE_MBLEN -#define reset_mbytes(state) mblen(NULL, 0), mbtowc(NULL, NULL, 0) -#define count_mbytes(buffer,length,state) mblen(buffer,length) -#define trans_mbytes(wch,buffer,length,state) \ - (int) mbtowc(&wch, buffer, length) -#elif HAVE_MBRTOWC && HAVE_MBRLEN -#define NEED_STATE -#define reset_mbytes(state) init_mb(state) -#define count_mbytes(buffer,length,state) mbrlen(buffer,length,&state) -#define trans_mbytes(wch,buffer,length,state) \ - (int) mbrtowc(&wch, buffer, length, &state) -#else -make an error -#endif - /*--------------------------------------------------------------------------- | Convert a multibyte string to a wide-character string. The result must be | freed by the caller. +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(wchar_t *) +FORM_EXPORT(wchar_t *) _nc_Widen_String(char *source, int *lengthp) { wchar_t *result = 0; @@ -4513,7 +4942,7 @@ _nc_Widen_String(char *source, int *lengthp) int pass; int status; -#ifdef NEED_STATE +#ifndef state_unused mbstate_t state; #endif @@ -4532,8 +4961,8 @@ _nc_Widen_String(char *source, int *lengthp) source[passed + tries] = 0; reset_mbytes(state); - status = trans_mbytes(wch, source + passed, tries, state); - source[passed + tries] = save; + status = check_mbytes(wch, source + passed, tries, state); + source[passed + tries] = (char)save; if (status > 0) { @@ -4547,14 +4976,14 @@ _nc_Widen_String(char *source, int *lengthp) { result[need] = wch; } - passed += status; + passed += (size_t)status; ++need; } else { if (pass) { - result[need] = source[passed]; + result[need] = (wchar_t)source[passed]; } ++need; ++passed; @@ -4567,7 +4996,7 @@ _nc_Widen_String(char *source, int *lengthp) break; result = typeCalloc(wchar_t, need); - *lengthp = need; + *lengthp = (int)need; if (result == 0) break; } diff --git a/lib/libform/frm_hook.c b/lib/libform/frm_hook.c index f3fd4d48d22..3714ac77ee3 100644 --- a/lib/libform/frm_hook.c +++ b/lib/libform/frm_hook.c @@ -1,6 +1,7 @@ -/* $OpenBSD: frm_hook.c,v 1.8 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: frm_hook.c,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2018,2020 Thomas E. Dickey * + * Copyright 1998-2012,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,22 +34,23 @@ #include "form.priv.h" -MODULE_ID("$Id: frm_hook.c,v 1.8 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: frm_hook.c,v 1.9 2023/10/17 09:52:10 nicm Exp $") /* "Template" macro to generate function to set application specific hook */ #define GEN_HOOK_SET_FUNCTION( typ, name ) \ -NCURSES_IMPEXP int NCURSES_API set_ ## typ ## _ ## name (FORM *form, Form_Hook func)\ +FORM_IMPEXP int NCURSES_API set_ ## typ ## _ ## name (FORM *form, Form_Hook func)\ {\ - T((T_CALLED("set_" #typ"_"#name"(%p,%p)"), form, func));\ + TR_FUNC_BFR(1); \ + T((T_CALLED("set_" #typ"_"#name"(%p,%s)"), (void *) form, TR_FUNC_ARG(0, func)));\ (Normalize_Form( form ) -> typ ## name) = func ;\ RETURN(E_OK);\ } /* "Template" macro to generate function to get application specific hook */ #define GEN_HOOK_GET_FUNCTION( typ, name ) \ -NCURSES_IMPEXP Form_Hook NCURSES_API typ ## _ ## name ( const FORM *form )\ +FORM_IMPEXP Form_Hook NCURSES_API typ ## _ ## name ( const FORM *form )\ {\ - T((T_CALLED(#typ "_" #name "(%p)"), form));\ + T((T_CALLED(#typ "_" #name "(%p)"), (const void *) form));\ returnFormHook( Normalize_Form( form ) -> typ ## name );\ } diff --git a/lib/libform/frm_opts.c b/lib/libform/frm_opts.c index a3d7cba32b4..94776d0cd3e 100644 --- a/lib/libform/frm_opts.c +++ b/lib/libform/frm_opts.c @@ -1,6 +1,7 @@ -/* $OpenBSD: frm_opts.c,v 1.9 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: frm_opts.c,v 1.10 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2004,2005 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2012,2013 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,25 +34,25 @@ #include "form.priv.h" -MODULE_ID("$Id: frm_opts.c,v 1.9 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: frm_opts.c,v 1.10 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int set_form_opts(FORM *form, Form_Options opts) -| +| | Description : Turns on the named options and turns off all the | remaining options for that form. | | Return Values : E_OK - success | E_BAD_ARGUMENT - invalid options +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) set_form_opts(FORM *form, Form_Options opts) { - T((T_CALLED("set_form_opts(%p,%d)"), form, opts)); + T((T_CALLED("set_form_opts(%p,%d)"), (void *)form, opts)); - opts &= ALL_FORM_OPTS; - if (opts & ~ALL_FORM_OPTS) + opts &= (Form_Options)ALL_FORM_OPTS; + if ((unsigned)opts & ~ALL_FORM_OPTS) RETURN(E_BAD_ARGUMENT); else { @@ -61,37 +62,37 @@ set_form_opts(FORM *form, Form_Options opts) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : Form_Options form_opts(const FORM *) -| +| | Description : Retrieves the current form options. | | Return Values : The option flags. +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(Form_Options) +FORM_EXPORT(Form_Options) form_opts(const FORM *form) { - T((T_CALLED("form_opts(%p)"), form)); - returnCode((int)(Normalize_Form(form)->opts & ALL_FORM_OPTS)); + T((T_CALLED("form_opts(%p)"), (const void *)form)); + returnCode((Form_Options)((unsigned)Normalize_Form(form)->opts & ALL_FORM_OPTS)); } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int form_opts_on(FORM *form, Form_Options opts) -| -| Description : Turns on the named options; no other options are +| +| Description : Turns on the named options; no other options are | changed. | -| Return Values : E_OK - success +| Return Values : E_OK - success | E_BAD_ARGUMENT - invalid options +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) form_opts_on(FORM *form, Form_Options opts) { - T((T_CALLED("form_opts_on(%p,%d)"), form, opts)); + T((T_CALLED("form_opts_on(%p,%d)"), (void *)form, opts)); - opts &= ALL_FORM_OPTS; - if (opts & ~ALL_FORM_OPTS) + opts &= (Form_Options)ALL_FORM_OPTS; + if ((unsigned)opts & ~ALL_FORM_OPTS) RETURN(E_BAD_ARGUMENT); else { @@ -101,22 +102,22 @@ form_opts_on(FORM *form, Form_Options opts) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int form_opts_off(FORM *form, Form_Options opts) -| -| Description : Turns off the named options; no other options are +| +| Description : Turns off the named options; no other options are | changed. | -| Return Values : E_OK - success +| Return Values : E_OK - success | E_BAD_ARGUMENT - invalid options +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) form_opts_off(FORM *form, Form_Options opts) { - T((T_CALLED("form_opts_off(%p,%d)"), form, opts)); + T((T_CALLED("form_opts_off(%p,%d)"), (void *)form, opts)); - opts &= ALL_FORM_OPTS; - if (opts & ~ALL_FORM_OPTS) + opts &= (Form_Options)ALL_FORM_OPTS; + if ((unsigned)opts & ~ALL_FORM_OPTS) RETURN(E_BAD_ARGUMENT); else { diff --git a/lib/libform/frm_page.c b/lib/libform/frm_page.c index d2e78410abf..9490e99be6a 100644 --- a/lib/libform/frm_page.c +++ b/lib/libform/frm_page.c @@ -1,6 +1,7 @@ -/* $OpenBSD: frm_page.c,v 1.6 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: frm_page.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,12 +34,12 @@ #include "form.priv.h" -MODULE_ID("$Id: frm_page.c,v 1.6 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: frm_page.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int set_form_page(FORM * form,int page) -| +| | Description : Set the page number of the form. | | Return Values : E_OK - success @@ -47,19 +48,19 @@ MODULE_ID("$Id: frm_page.c,v 1.6 2015/01/23 22:48:51 krw Exp $") | E_INVALID_FIELD - current field can't be left | E_SYSTEM_ERROR - system error +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) set_form_page(FORM *form, int page) { int err = E_OK; - T((T_CALLED("set_form_page(%p,%d)"), form, page)); + T((T_CALLED("set_form_page(%p,%d)"), (void *)form, page)); if (!form || (page < 0) || (page >= form->maxpage)) RETURN(E_BAD_ARGUMENT); if (!(form->status & _POSTED)) { - form->curpage = page; + form->curpage = (short)page; form->current = _nc_First_Active_Field(form); } else @@ -88,18 +89,18 @@ set_form_page(FORM *form, int page) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int form_page(const FORM * form) -| +| | Description : Return the current page of the form. | | Return Values : >= 0 : current page number | -1 : invalid form pointer +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) form_page(const FORM *form) { - T((T_CALLED("form_page(%p)"), form)); + T((T_CALLED("form_page(%p)"), (const void *)form)); returnCode(Normalize_Form(form)->curpage); } diff --git a/lib/libform/frm_post.c b/lib/libform/frm_post.c index d1d238fa4bb..bfee635c03a 100644 --- a/lib/libform/frm_post.c +++ b/lib/libform/frm_post.c @@ -1,6 +1,7 @@ -/* $OpenBSD: frm_post.c,v 1.6 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: frm_post.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,12 +34,12 @@ #include "form.priv.h" -MODULE_ID("$Id: frm_post.c,v 1.6 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: frm_post.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int post_form(FORM * form) -| +| | Description : Writes the form into its associated subwindow. | | Return Values : E_OK - success @@ -48,14 +49,14 @@ MODULE_ID("$Id: frm_post.c,v 1.6 2015/01/23 22:48:51 krw Exp $") | E_NO_ROOM - form doesn't fit into subwindow | E_SYSTEM_ERROR - system error +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) post_form(FORM *form) { WINDOW *formwin; int err; int page; - T((T_CALLED("post_form(%p)"), form)); + T((T_CALLED("post_form(%p)"), (void *)form)); if (!form) RETURN(E_BAD_ARGUMENT); @@ -70,7 +71,7 @@ post_form(FORM *form) if ((form->cols > getmaxx(formwin)) || (form->rows > getmaxy(formwin))) RETURN(E_NO_ROOM); - /* reset form->curpage to an invald value. This forces Set_Form_Page + /* reset form->curpage to an invalid value. This forces Set_Form_Page to do the page initialization which is required by post_form. */ page = form->curpage; @@ -78,7 +79,7 @@ post_form(FORM *form) if ((err = _nc_Set_Form_Page(form, page, form->current)) != E_OK) RETURN(err); - form->status |= _POSTED; + SetStatus(form, _POSTED); Call_Hook(form, forminit); Call_Hook(form, fieldinit); @@ -88,9 +89,9 @@ post_form(FORM *form) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int unpost_form(FORM * form) -| +| | Description : Erase form from its associated subwindow. | | Return Values : E_OK - success @@ -98,10 +99,10 @@ post_form(FORM *form) | E_NOT_POSTED - form isn't posted | E_BAD_STATE - called from a hook routine +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) unpost_form(FORM *form) { - T((T_CALLED("unpost_form(%p)"), form)); + T((T_CALLED("unpost_form(%p)"), (void *)form)); if (!form) RETURN(E_BAD_ARGUMENT); @@ -118,7 +119,7 @@ unpost_form(FORM *form) werase(Get_Form_Window(form)); delwin(form->w); form->w = (WINDOW *)0; - form->status &= ~_POSTED; + ClrStatus(form, _POSTED); RETURN(E_OK); } diff --git a/lib/libform/frm_req_name.c b/lib/libform/frm_req_name.c index 1909c795136..3129fb6e0c1 100644 --- a/lib/libform/frm_req_name.c +++ b/lib/libform/frm_req_name.c @@ -1,6 +1,7 @@ -/* $OpenBSD: frm_req_name.c,v 1.7 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: frm_req_name.c,v 1.8 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2008 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2012,2015 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -38,85 +39,89 @@ #include "form.priv.h" -MODULE_ID("$Id: frm_req_name.c,v 1.7 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: frm_req_name.c,v 1.8 2023/10/17 09:52:10 nicm Exp $") -static const char *request_names[MAX_FORM_COMMAND - MIN_FORM_COMMAND + 1] = +#define DATA(s) { s } + +static const char request_names[MAX_FORM_COMMAND - MIN_FORM_COMMAND + 1][13] = { - "NEXT_PAGE", - "PREV_PAGE", - "FIRST_PAGE", - "LAST_PAGE", - - "NEXT_FIELD", - "PREV_FIELD", - "FIRST_FIELD", - "LAST_FIELD", - "SNEXT_FIELD", - "SPREV_FIELD", - "SFIRST_FIELD", - "SLAST_FIELD", - "LEFT_FIELD", - "RIGHT_FIELD", - "UP_FIELD", - "DOWN_FIELD", - - "NEXT_CHAR", - "PREV_CHAR", - "NEXT_LINE", - "PREV_LINE", - "NEXT_WORD", - "PREV_WORD", - "BEG_FIELD", - "END_FIELD", - "BEG_LINE", - "END_LINE", - "LEFT_CHAR", - "RIGHT_CHAR", - "UP_CHAR", - "DOWN_CHAR", - - "NEW_LINE", - "INS_CHAR", - "INS_LINE", - "DEL_CHAR", - "DEL_PREV", - "DEL_LINE", - "DEL_WORD", - "CLR_EOL", - "CLR_EOF", - "CLR_FIELD", - "OVL_MODE", - "INS_MODE", - "SCR_FLINE", - "SCR_BLINE", - "SCR_FPAGE", - "SCR_BPAGE", - "SCR_FHPAGE", - "SCR_BHPAGE", - "SCR_FCHAR", - "SCR_BCHAR", - "SCR_HFLINE", - "SCR_HBLINE", - "SCR_HFHALF", - "SCR_HBHALF", - - "VALIDATION", - "NEXT_CHOICE", - "PREV_CHOICE" + DATA("NEXT_PAGE"), + DATA("PREV_PAGE"), + DATA("FIRST_PAGE"), + DATA("LAST_PAGE"), + + DATA("NEXT_FIELD"), + DATA("PREV_FIELD"), + DATA("FIRST_FIELD"), + DATA("LAST_FIELD"), + DATA("SNEXT_FIELD"), + DATA("SPREV_FIELD"), + DATA("SFIRST_FIELD"), + DATA("SLAST_FIELD"), + DATA("LEFT_FIELD"), + DATA("RIGHT_FIELD"), + DATA("UP_FIELD"), + DATA("DOWN_FIELD"), + + DATA("NEXT_CHAR"), + DATA("PREV_CHAR"), + DATA("NEXT_LINE"), + DATA("PREV_LINE"), + DATA("NEXT_WORD"), + DATA("PREV_WORD"), + DATA("BEG_FIELD"), + DATA("END_FIELD"), + DATA("BEG_LINE"), + DATA("END_LINE"), + DATA("LEFT_CHAR"), + DATA("RIGHT_CHAR"), + DATA("UP_CHAR"), + DATA("DOWN_CHAR"), + + DATA("NEW_LINE"), + DATA("INS_CHAR"), + DATA("INS_LINE"), + DATA("DEL_CHAR"), + DATA("DEL_PREV"), + DATA("DEL_LINE"), + DATA("DEL_WORD"), + DATA("CLR_EOL"), + DATA("CLR_EOF"), + DATA("CLR_FIELD"), + DATA("OVL_MODE"), + DATA("INS_MODE"), + DATA("SCR_FLINE"), + DATA("SCR_BLINE"), + DATA("SCR_FPAGE"), + DATA("SCR_BPAGE"), + DATA("SCR_FHPAGE"), + DATA("SCR_BHPAGE"), + DATA("SCR_FCHAR"), + DATA("SCR_BCHAR"), + DATA("SCR_HFLINE"), + DATA("SCR_HBLINE"), + DATA("SCR_HFHALF"), + DATA("SCR_HBHALF"), + + DATA("VALIDATION"), + DATA("NEXT_CHOICE"), + DATA("PREV_CHOICE") }; +#undef DATA + #define A_SIZE (sizeof(request_names)/sizeof(request_names[0])) /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : const char * form_request_name (int request); -| +| | Description : Get the external name of a form request. | | Return Values : Pointer to name - on success | NULL - on invalid request code +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(const char *) +FORM_EXPORT(const char *) form_request_name(int request) { T((T_CALLED("form_request_name(%d)"), request)); @@ -131,38 +136,42 @@ form_request_name(int request) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int form_request_by_name (const char *str); -| +| | Description : Search for a request with this name. | | Return Values : Request Id - on success | E_NO_MATCH - request not found +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) form_request_by_name(const char *str) { /* because the table is so small, it doesn't really hurt to run sequentially through it. */ - unsigned int i = 0; - char buf[16]; + size_t i = 0; T((T_CALLED("form_request_by_name(%s)"), _nc_visbuf(str))); - if (str) + if (str != 0 && (i = strlen(str)) != 0) { - strncpy(buf, str, sizeof(buf)); - while ((i < sizeof(buf)) && (buf[i] != '\0')) + char buf[16]; /* longest name is 10 chars */ + + if (i > sizeof(buf) - 2) + i = sizeof(buf) - 2; + memcpy(buf, str, i); + buf[i] = '\0'; + + for (i = 0; buf[i] != '\0'; ++i) { - buf[i] = toupper(UChar(buf[i])); - i++; + buf[i] = (char)toupper(UChar(buf[i])); } for (i = 0; i < A_SIZE; i++) { - if (strncmp(request_names[i], buf, sizeof(buf)) == 0) - returnCode(MIN_FORM_COMMAND + (int) i); + if (strcmp(request_names[i], buf) == 0) + returnCode(MIN_FORM_COMMAND + (int)i); } } RETURN(E_NO_MATCH); diff --git a/lib/libform/frm_scale.c b/lib/libform/frm_scale.c index e87e0470646..f494e8bf40f 100644 --- a/lib/libform/frm_scale.c +++ b/lib/libform/frm_scale.c @@ -1,6 +1,7 @@ -/* $OpenBSD: frm_scale.c,v 1.6 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: frm_scale.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2004,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,22 +34,25 @@ #include "form.priv.h" -MODULE_ID("$Id: frm_scale.c,v 1.6 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: frm_scale.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int scale_form( const FORM *form, int *rows, int *cols ) -| +| | Description : Retrieve size of form | | Return Values : E_OK - no error | E_BAD_ARGUMENT - invalid form pointer | E_NOT_CONNECTED - no fields connected to form +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) scale_form(const FORM *form, int *rows, int *cols) { - T((T_CALLED("scale_form(%p,%p,%p)"), form, rows, cols)); + T((T_CALLED("scale_form(%p,%p,%p)"), + (const void *)form, + (void *)rows, + (void *)cols)); if (!form) RETURN(E_BAD_ARGUMENT); diff --git a/lib/libform/frm_sub.c b/lib/libform/frm_sub.c index 6da286675f7..911cf211d55 100644 --- a/lib/libform/frm_sub.c +++ b/lib/libform/frm_sub.c @@ -1,6 +1,7 @@ -/* $OpenBSD: frm_sub.c,v 1.6 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: frm_sub.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -28,48 +29,57 @@ ****************************************************************************/ /**************************************************************************** - * Author: Juergen Pfeifer, 1995,1997 * + * Author: Juergen Pfeifer, 1995-1997,2009 * ****************************************************************************/ #include "form.priv.h" -MODULE_ID("$Id: frm_sub.c,v 1.6 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: frm_sub.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int set_form_sub(FORM *form, WINDOW *win) -| -| Description : Set the subwindow of the form to win. +| +| Description : Set the subwindow of the form to win. | | Return Values : E_OK - success | E_POSTED - form is posted +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) set_form_sub(FORM *form, WINDOW *win) { - T((T_CALLED("set_form_sub(%p,%p)"), form, win)); + T((T_CALLED("set_form_sub(%p,%p)"), (void *)form, (void *)win)); if (form && (form->status & _POSTED)) RETURN(E_POSTED); + else + { +#if NCURSES_SP_FUNCS + FORM *f = Normalize_Form(form); - Normalize_Form(form)->sub = win; - RETURN(E_OK); + f->sub = win ? win : StdScreen(Get_Form_Screen(f)); + RETURN(E_OK); +#else + Normalize_Form(form)->sub = win; + RETURN(E_OK); +#endif + } } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : WINDOW *form_sub(const FORM *) -| +| | Description : Retrieve the window of the form. | | Return Values : The pointer to the Subwindow. +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(WINDOW *) +FORM_EXPORT(WINDOW *) form_sub(const FORM *form) { const FORM *f; - T((T_CALLED("form_sub(%p)"), form)); + T((T_CALLED("form_sub(%p)"), (const void *)form)); f = Normalize_Form(form); returnWin(Get_Form_Window(f)); diff --git a/lib/libform/frm_user.c b/lib/libform/frm_user.c index 365493ce2bd..bf6c566073f 100644 --- a/lib/libform/frm_user.c +++ b/lib/libform/frm_user.c @@ -1,6 +1,7 @@ -/* $OpenBSD: frm_user.c,v 1.8 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: frm_user.c,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2004,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,40 +34,40 @@ #include "form.priv.h" -MODULE_ID("$Id: frm_user.c,v 1.8 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: frm_user.c,v 1.9 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int set_form_userptr(FORM *form, void *usrptr) -| +| | Description : Set the pointer that is reserved in any form to store -| application relevant informations +| application relevant information. | | Return Values : E_OK - on success +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) set_form_userptr(FORM *form, void *usrptr) { - T((T_CALLED("set_form_userptr(%p,%p)"), form, usrptr)); + T((T_CALLED("set_form_userptr(%p,%p)"), (void *)form, (void *)usrptr)); Normalize_Form(form)->usrptr = usrptr; RETURN(E_OK); } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : void *form_userptr(const FORM *form) -| +| | Description : Return the pointer that is reserved in any form to -| store application relevant informations. +| store application relevant information. | | Return Values : Value of pointer. If no such pointer has been set, | NULL is returned +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(void *) +FORM_EXPORT(void *) form_userptr(const FORM *form) { - T((T_CALLED("form_userptr(%p)"), form)); + T((T_CALLED("form_userptr(%p)"), (const void *)form)); returnVoidPtr(Normalize_Form(form)->usrptr); } diff --git a/lib/libform/frm_win.c b/lib/libform/frm_win.c index d1df86d8711..6f9c721abb0 100644 --- a/lib/libform/frm_win.c +++ b/lib/libform/frm_win.c @@ -1,6 +1,7 @@ -/* $OpenBSD: frm_win.c,v 1.8 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: frm_win.c,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -33,46 +34,61 @@ #include "form.priv.h" -MODULE_ID("$Id: frm_win.c,v 1.8 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: frm_win.c,v 1.9 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : int set_form_win(FORM *form,WINDOW *win) -| -| Description : Set the window of the form to win. +| +| Description : Set the window of the form to win. | | Return Values : E_OK - success | E_POSTED - form is posted +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +FORM_EXPORT(int) set_form_win(FORM *form, WINDOW *win) { - T((T_CALLED("set_form_win(%p,%p)"), form, win)); + T((T_CALLED("set_form_win(%p,%p)"), (void *)form, (void *)win)); if (form && (form->status & _POSTED)) RETURN(E_POSTED); + else + { +#if NCURSES_SP_FUNCS + FORM *f = Normalize_Form(form); - Normalize_Form(form)->win = win; - RETURN(E_OK); + f->win = win ? win : StdScreen(Get_Form_Screen(f)); + RETURN(E_OK); +#else + Normalize_Form(form)->win = win; + RETURN(E_OK); +#endif + } } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : WINDOW *form_win(const FORM *) -| +| | Description : Retrieve the window of the form. | | Return Values : The pointer to the Window or stdscr if there is none. +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(WINDOW *) +FORM_EXPORT(WINDOW *) form_win(const FORM *form) { + WINDOW *result; const FORM *f; - T((T_CALLED("form_win(%p)"), form)); + T((T_CALLED("form_win(%p)"), (const void *)form)); f = Normalize_Form(form); - returnWin(f->win ? f->win : stdscr); +#if NCURSES_SP_FUNCS + result = (f->win ? f->win : StdScreen(Get_Form_Screen(f))); +#else + result = (f->win ? f->win : stdscr); +#endif + returnWin(result); } /* frm_win.c ends here */ diff --git a/lib/libform/fty_alnum.c b/lib/libform/fty_alnum.c index 6d37b736f34..9689b8b689d 100644 --- a/lib/libform/fty_alnum.c +++ b/lib/libform/fty_alnum.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fty_alnum.c,v 1.9 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fty_alnum.c,v 1.10 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -35,7 +36,7 @@ #include "form.priv.h" -MODULE_ID("$Id: fty_alnum.c,v 1.9 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fty_alnum.c,v 1.10 2023/10/17 09:52:10 nicm Exp $") #define thisARG alnumARG @@ -47,26 +48,46 @@ thisARG; /*--------------------------------------------------------------------------- | Facility : libnform -| Function : static void *Make_This_Type(va_list *ap) +| Function : static void *Generic_This_Type(void *arg) | | Description : Allocate structure for alphanumeric type argument. | | Return Values : Pointer to argument structure or NULL on error +--------------------------------------------------------------------------*/ static void * -Make_This_Type(va_list *ap) +Generic_This_Type(void *arg) { - thisARG *argp = typeMalloc(thisARG, 1); + thisARG *argp = (thisARG *)0; - if (argp) + if (arg) { - T((T_CREATE("thisARG %p"), argp)); - argp->width = va_arg(*ap, int); - } + argp = typeMalloc(thisARG, 1); + if (argp) + { + T((T_CREATE("thisARG %p"), (void *)argp)); + argp->width = *((int *)arg); + } + } return ((void *)argp); } +/*--------------------------------------------------------------------------- +| Facility : libnform +| Function : static void *Make_This_Type(va_list *ap) +| +| Description : Allocate structure for alphanumeric type argument. +| +| Return Values : Pointer to argument structure or NULL on error ++--------------------------------------------------------------------------*/ +static void * +Make_This_Type(va_list *ap) +{ + int w = va_arg(*ap, int); + + return Generic_This_Type((void *)&w); +} + /*--------------------------------------------------------------------------- | Facility : libnform | Function : static void *Copy_ThisType(const void *argp) @@ -83,7 +104,7 @@ Copy_This_Type(const void *argp) if (result) { - T((T_CREATE("thisARG %p"), result)); + T((T_CREATE("thisARG %p"), (void *)result)); *result = *ap; } @@ -120,7 +141,7 @@ static bool Check_This_Character(int c, const void *argp GCC_UNUSED) { #if USE_WIDEC_SUPPORT - if (iswalnum((wint_t) c)) + if (iswalnum((wint_t)c)) return TRUE; #endif return (isalnum(UChar(c)) ? TRUE : FALSE); @@ -157,12 +178,27 @@ static FIELDTYPE typeTHIS = Make_This_Type, Copy_This_Type, Free_This_Type, - Check_This_Field, - Check_This_Character, - NULL, - NULL + INIT_FT_FUNC(Check_This_Field), + INIT_FT_FUNC(Check_This_Character), + INIT_FT_FUNC(NULL), + INIT_FT_FUNC(NULL), +#if NCURSES_INTEROP_FUNCS + Generic_This_Type +#endif }; -NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_ALNUM = &typeTHIS; +FORM_EXPORT_VAR(FIELDTYPE *) TYPE_ALNUM = &typeTHIS; + +#if NCURSES_INTEROP_FUNCS +/* The next routines are to simplify the use of ncurses from + programming languages with restrictions on interop with C level + constructs (e.g. variable access or va_list + ellipsis constructs) +*/ +FORM_EXPORT(FIELDTYPE *) +_nc_TYPE_ALNUM(void) +{ + return TYPE_ALNUM; +} +#endif /* fty_alnum.c ends here */ diff --git a/lib/libform/fty_alpha.c b/lib/libform/fty_alpha.c index fa1bf2c88c0..c11b1c512c6 100644 --- a/lib/libform/fty_alpha.c +++ b/lib/libform/fty_alpha.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fty_alpha.c,v 1.9 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fty_alpha.c,v 1.10 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -35,7 +36,7 @@ #include "form.priv.h" -MODULE_ID("$Id: fty_alpha.c,v 1.9 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fty_alpha.c,v 1.10 2023/10/17 09:52:10 nicm Exp $") #define thisARG alphaARG @@ -47,26 +48,46 @@ thisARG; /*--------------------------------------------------------------------------- | Facility : libnform -| Function : static void *Make_This_Type(va_list *ap) +| Function : static void *Generic_This_Type(va_list *ap) | | Description : Allocate structure for alpha type argument. | | Return Values : Pointer to argument structure or NULL on error +--------------------------------------------------------------------------*/ static void * -Make_This_Type(va_list *ap) +Generic_This_Type(void *arg) { - thisARG *argp = typeMalloc(thisARG, 1); + thisARG *argp = (thisARG *)0; - if (argp) + if (arg) { - T((T_CREATE("thisARG %p"), argp)); - argp->width = va_arg(*ap, int); - } + argp = typeMalloc(thisARG, 1); + if (argp) + { + T((T_CREATE("thisARG %p"), (void *)argp)); + argp->width = *((int *)arg); + } + } return ((void *)argp); } +/*--------------------------------------------------------------------------- +| Facility : libnform +| Function : static void *Make_This_Type(va_list *ap) +| +| Description : Allocate structure for alpha type argument. +| +| Return Values : Pointer to argument structure or NULL on error ++--------------------------------------------------------------------------*/ +static void * +Make_This_Type(va_list *ap) +{ + int w = va_arg(*ap, int); + + return Generic_This_Type((void *)&w); +} + /*--------------------------------------------------------------------------- | Facility : libnform | Function : static void *Copy_This_Type(const void * argp) @@ -83,7 +104,7 @@ Copy_This_Type(const void *argp) if (result) { - T((T_CREATE("thisARG %p"), result)); + T((T_CREATE("thisARG %p"), (void *)result)); *result = *ap; } @@ -120,7 +141,7 @@ static bool Check_This_Character(int c, const void *argp GCC_UNUSED) { #if USE_WIDEC_SUPPORT - if (iswalpha((wint_t) c)) + if (iswalpha((wint_t)c)) return TRUE; #endif return (isalpha(UChar(c)) ? TRUE : FALSE); @@ -157,12 +178,27 @@ static FIELDTYPE typeTHIS = Make_This_Type, Copy_This_Type, Free_This_Type, - Check_This_Field, - Check_This_Character, - NULL, - NULL + INIT_FT_FUNC(Check_This_Field), + INIT_FT_FUNC(Check_This_Character), + INIT_FT_FUNC(NULL), + INIT_FT_FUNC(NULL), +#if NCURSES_INTEROP_FUNCS + Generic_This_Type +#endif }; -NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_ALPHA = &typeTHIS; +FORM_EXPORT_VAR(FIELDTYPE *) TYPE_ALPHA = &typeTHIS; + +#if NCURSES_INTEROP_FUNCS +/* The next routines are to simplify the use of ncurses from + programming languages with restrictions on interop with C level + constructs (e.g. variable access or va_list + ellipsis constructs) +*/ +FORM_EXPORT(FIELDTYPE *) +_nc_TYPE_ALPHA(void) +{ + return TYPE_ALPHA; +} +#endif /* fty_alpha.c ends here */ diff --git a/lib/libform/fty_enum.c b/lib/libform/fty_enum.c index bcd6bbf5f33..f31b3f920cb 100644 --- a/lib/libform/fty_enum.c +++ b/lib/libform/fty_enum.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fty_enum.c,v 1.11 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fty_enum.c,v 1.12 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -35,7 +36,7 @@ #include "form.priv.h" -MODULE_ID("$Id: fty_enum.c,v 1.11 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fty_enum.c,v 1.12 2023/10/17 09:52:10 nicm Exp $") typedef struct { @@ -46,46 +47,103 @@ typedef struct } enumARG; +typedef struct + { + char **kwds; + int ccase; + int cunique; + } +enumParams; + /*--------------------------------------------------------------------------- -| Facility : libnform -| Function : static void *Make_Enum_Type( va_list * ap ) -| +| Facility : libnform +| Function : static void *Generic_Enum_Type(void * arg) +| | Description : Allocate structure for enumeration type argument. | | Return Values : Pointer to argument structure or NULL on error +--------------------------------------------------------------------------*/ static void * -Make_Enum_Type(va_list *ap) +Generic_Enum_Type(void *arg) { - enumARG *argp = typeMalloc(enumARG, 1); + enumARG *argp = (enumARG *)0; + enumParams *params = (enumParams *)arg; - if (argp) + if (params) { - int cnt = 0; - char **kp = (char **)0; - int ccase, cunique; - - T((T_CREATE("enumARG %p"), argp)); - argp->kwds = va_arg(*ap, char **); - ccase = va_arg(*ap, int); - cunique = va_arg(*ap, int); - - argp->checkcase = ccase ? TRUE : FALSE; - argp->checkunique = cunique ? TRUE : FALSE; - - kp = argp->kwds; - while (kp && (*kp++)) - cnt++; - argp->count = cnt; + argp = typeMalloc(enumARG, 1); + + if (argp) + { + int cnt = 0; + char **kp = (char **)0; + char **kwds = (char **)0; + int ccase, cunique; + + T((T_CREATE("enumARG %p"), (void *)argp)); + kwds = params->kwds; + ccase = params->ccase; + cunique = params->cunique; + + argp->checkcase = ccase ? TRUE : FALSE; + argp->checkunique = cunique ? TRUE : FALSE; + argp->kwds = (char **)0; + + kp = kwds; + while (kp && (*kp++)) + cnt++; + argp->count = cnt; + + if (cnt > 0) + { + char **kptarget; + + /* We copy the keywords, because we can't rely on the fact + that the caller doesn't relocate or free the memory used + for the keywords (maybe he has GC) + */ + argp->kwds = typeMalloc(char *, cnt + 1); + + kp = kwds; + if ((kptarget = argp->kwds) != 0) + { + while (kp && (*kp)) + { + (*kptarget++) = strdup(*kp++); + } + *kptarget = (char *)0; + } + } + } } return (void *)argp; } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform +| Function : static void *Make_Enum_Type( va_list * ap ) +| +| Description : Allocate structure for enumeration type argument. +| +| Return Values : Pointer to argument structure or NULL on error ++--------------------------------------------------------------------------*/ +static void * +Make_Enum_Type(va_list *ap) +{ + enumParams params; + + params.kwds = va_arg(*ap, char **); + params.ccase = va_arg(*ap, int); + params.cunique = va_arg(*ap, int); + + return Generic_Enum_Type((void *)¶ms); +} + +/*--------------------------------------------------------------------------- +| Facility : libnform | Function : static void *Copy_Enum_Type( const void * argp ) -| -| Description : Copy structure for enumeration type argument. +| +| Description : Copy structure for enumeration type argument. | | Return Values : Pointer to argument structure or NULL on error. +--------------------------------------------------------------------------*/ @@ -102,17 +160,33 @@ Copy_Enum_Type(const void *argp) if (result) { - T((T_CREATE("enumARG %p"), result)); + T((T_CREATE("enumARG %p"), (void *)result)); *result = *ap; + + if (ap->count > 0) + { + char **kptarget; + char **kp = ap->kwds; + result->kwds = typeMalloc(char *, 1 + ap->count); + + if ((kptarget = result->kwds) != 0) + { + while (kp && (*kp)) + { + (*kptarget++) = strdup(*kp++); + } + *kptarget = (char *)0; + } + } } } return (void *)result; } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : static void Free_Enum_Type( void * argp ) -| +| | Description : Free structure for enumeration type argument. | | Return Values : - @@ -121,7 +195,24 @@ static void Free_Enum_Type(void *argp) { if (argp) - free(argp); + { + const enumARG *ap = (const enumARG *)argp; + + if (ap->kwds && ap->count > 0) + { + char **kp = ap->kwds; + int cnt = 0; + + while (kp && (*kp)) + { + free(*kp++); + cnt++; + } + assert(cnt == ap->count); + free(ap->kwds); + } + free(argp); + } } #define SKIP_SPACE(x) while(((*(x))!='\0') && (is_blank(*(x)))) (x)++ @@ -130,11 +221,11 @@ Free_Enum_Type(void *argp) #define EXACT 2 /*--------------------------------------------------------------------------- -| Facility : libnform -| Function : static int Compare(const unsigned char * s, +| Facility : libnform +| Function : static int Compare(const unsigned char * s, | const unsigned char * buf, | bool ccase ) -| +| | Description : Check whether or not the text in 'buf' matches the | text in 's', at least partial. | @@ -185,11 +276,11 @@ Compare(const unsigned char *s, const unsigned char *buf, } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : static bool Check_Enum_Field( | FIELD * field, | const void * argp) -| +| | Description : Validate buffer content to be a valid enumeration value | | Return Values : TRUE - field is valid @@ -203,10 +294,11 @@ Check_Enum_Field(FIELD *field, const void *argp) bool unique = ((const enumARG *)argp)->checkunique; unsigned char *bp = (unsigned char *)field_buffer(field, 0); char *s, *t, *p; - int res; while (kwds && (s = (*kwds++))) { + int res; + if ((res = Compare((unsigned char *)s, bp, ccase)) != NOMATCH) { p = t = s; /* t is at least a partial match */ @@ -242,10 +334,10 @@ static const char *dummy[] = {(char *)0}; /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : static bool Next_Enum(FIELD * field, | const void * argp) -| +| | Description : Check for the next enumeration value | | Return Values : TRUE - next value found and loaded @@ -279,11 +371,11 @@ Next_Enum(FIELD *field, const void *argp) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : static bool Previous_Enum( | FIELD * field, | const void * argp) -| +| | Description : Check for the previous enumeration value | | Return Values : TRUE - previous value found and loaded @@ -327,13 +419,27 @@ static FIELDTYPE typeENUM = Make_Enum_Type, Copy_Enum_Type, Free_Enum_Type, - Check_Enum_Field, - NULL, - Next_Enum, - Previous_Enum + INIT_FT_FUNC(Check_Enum_Field), + INIT_FT_FUNC(NULL), + INIT_FT_FUNC(Next_Enum), + INIT_FT_FUNC(Previous_Enum), +#if NCURSES_INTEROP_FUNCS + Generic_Enum_Type +#endif }; -NCURSES_EXPORT_VAR(FIELDTYPE *) -TYPE_ENUM = &typeENUM; +FORM_EXPORT_VAR(FIELDTYPE *) TYPE_ENUM = &typeENUM; + +#if NCURSES_INTEROP_FUNCS +/* The next routines are to simplify the use of ncurses from + programming languages with restrictions on interop with C level + constructs (e.g. variable access or va_list + ellipsis constructs) +*/ +FORM_EXPORT(FIELDTYPE *) +_nc_TYPE_ENUM(void) +{ + return TYPE_ENUM; +} +#endif /* fty_enum.c ends here */ diff --git a/lib/libform/fty_generic.c b/lib/libform/fty_generic.c new file mode 100644 index 00000000000..c505df1bd61 --- /dev/null +++ b/lib/libform/fty_generic.c @@ -0,0 +1,305 @@ +/**************************************************************************** + * Copyright 2018-2020,2021 Thomas E. Dickey * + * Copyright 2008-2012,2016 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/*************************************************************************** +* * +* Author : Juergen Pfeifer * +* * +***************************************************************************/ + +#include "form.priv.h" + +MODULE_ID("$Id: fty_generic.c,v 1.1 2023/10/17 09:52:10 nicm Exp $") + +/* + * This is not a full implementation of a field type, but adds some + * support for higher level languages with some restrictions to interop + * with C language. In particular, the collection of arguments for the + * various fieldtypes is not based on the vararg C mechanism, but on a + * iterator based callback mechanism that allows the high level language + * to provide the arguments as a structure. Most languages have mechanisms + * to layout structures so that they can be passed to C. + * + * The languages can register a new generic fieldtype dynamically and store + * a handle (key) to the calling object as an argument. Together with that + * it can register a freearg callback, so that the high level language + * remains in control of the memory management of the arguments they pass. + * The design idea is, that the high-level language - typically a OO + * language like C# or Java, uses its own dispatching mechanisms + * (polymorphism) to call the proper check routines responsible for the + * argument type. So these language implement typically only one generic + * fieldtype they register with the forms library using this call. + * + * For that purpose we have extended the fieldtype structure by a new element + * that gets the arguments from a single struct passed by the caller. + * + */ +#if NCURSES_INTEROP_FUNCS + +/*--------------------------------------------------------------------------- +| Facility : libnform +| Function : static void *Generic_This_Type( void * arg ) +| +| Description : We interpret the passed arg just as a handle the +| calling language uses to keep track of its allocated +| argument structures. We can simply copy it back. +| +| Return Values : Pointer to argument structure ++--------------------------------------------------------------------------*/ +static void * +Generic_This_Type(void *arg) +{ + return (arg); +} + +/*--------------------------------------------------------------------------- +| Facility : libnform +| Function : FIELDTYPE *_nc_generic_fieldtype( +| bool (* const field_check)(FIELD *,const void *), +| bool (* const char_check) (int, const void *), +| bool (*const next)(FORM*,FIELD*,const void*), +| bool (*const prev)(FORM*,FIELD*,const void*), +| void (*freecallback)(void*)) +| +| Description : Create a new fieldtype. The application programmer must +| write a field_check and a char_check function and give +| them as input to this call. A callback to allow the +| release of the allocated memory must also be provided. +| For generic field types, we provide some more +| information about the field as parameters. +| +| If an error occurs, errno is set to +| E_BAD_ARGUMENT - invalid arguments +| E_SYSTEM_ERROR - system error (no memory) +| +| Return Values : Fieldtype pointer or NULL if error occurred ++--------------------------------------------------------------------------*/ +FORM_EXPORT(FIELDTYPE *) +_nc_generic_fieldtype(bool (*const field_check) (FORM *, FIELD *, const void *), + bool (*const char_check) (int, FORM *, FIELD *, const + void *), + bool (*const next) (FORM *, FIELD *, const void *), + bool (*const prev) (FORM *, FIELD *, const void *), + void (*freecallback) (void *)) +{ + int code = E_SYSTEM_ERROR; + FIELDTYPE *res = (FIELDTYPE *)0; + + TR_FUNC_BFR(5); + + T((T_CALLED("_nc_generic_fieldtype(%s,%s,%s,%s,%s)"), + TR_FUNC_ARG(0, field_check), + TR_FUNC_ARG(1, char_check), + TR_FUNC_ARG(2, next), + TR_FUNC_ARG(3, prev), + TR_FUNC_ARG(4, freecallback))); + + if (field_check || char_check) + { + res = typeMalloc(FIELDTYPE, 1); + + if (res) + { + *res = *_nc_Default_FieldType; + SetStatus(res, (_HAS_ARGS | _GENERIC)); + res->fieldcheck.gfcheck = field_check; + res->charcheck.gccheck = char_check; + res->genericarg = Generic_This_Type; + res->freearg = freecallback; + res->enum_next.gnext = next; + res->enum_prev.gprev = prev; + code = E_OK; + } + } + else + code = E_BAD_ARGUMENT; + + if (E_OK != code) + SET_ERROR(code); + + returnFieldType(res); +} + +/*--------------------------------------------------------------------------- +| Facility : libnform +| Function : static TypeArgument *GenericArgument( +| const FIELDTYPE* typ, +| int (*argiterator)(void**), +| int* err) +| +| Description : The iterator callback must browse through all fieldtype +| parameters that have an argument associated with the +| type. The iterator returns 1 if the operation to get +| the next element was successful, 0 otherwise. If the +| iterator could move to the next argument, it fills +| the void* pointer representing the argument into the +| location provided as argument to the iterator. +| The err reference is used to keep track of errors. +| +| Return Values : Pointer to argument structure ++--------------------------------------------------------------------------*/ +static TypeArgument * +GenericArgument(const FIELDTYPE *typ, + int (*argiterator) (void **), int *err) +{ + TypeArgument *res = (TypeArgument *)0; + + if (typ != 0 && (typ->status & _HAS_ARGS) != 0 && err != 0 && argiterator != 0) + { + if (typ->status & _LINKED_TYPE) + { + /* Composite fieldtypes keep track internally of their own memory */ + TypeArgument *p = typeMalloc(TypeArgument, 1); + + if (p) + { + p->left = GenericArgument(typ->left, argiterator, err); + p->right = GenericArgument(typ->right, argiterator, err); + return p; + } + else + *err += 1; + } + else + { + assert(typ->genericarg != (void *)0); + if (typ->genericarg == 0) + *err += 1; + else + { + void *argp; + int valid = argiterator(&argp); + + if (valid == 0 || argp == 0 || + !(res = (TypeArgument *)typ->genericarg(argp))) + { + *err += 1; + } + } + } + } + return res; +} + +/*--------------------------------------------------------------------------- +| Facility : libnform +| Function : int _nc_set_generic_fieldtype( +| FIELD* field, +| FIELDTYPE* ftyp, +| int (*argiterator)(void**)) +| +| Description : Assign the fieldtype to the field and use the iterator +| mechanism to get the arguments when a check is +| performed. +| +| Return Values : E_OK if all went well +| E_SYSTEM_ERROR if an error occurred ++--------------------------------------------------------------------------*/ +FORM_EXPORT(int) +_nc_set_generic_fieldtype(FIELD *field, + FIELDTYPE *ftyp, + int (*argiterator) (void **)) +{ + int code = E_SYSTEM_ERROR; + int err = 0; + + if (field) + { + if (field && field->type) + _nc_Free_Type(field); + + field->type = ftyp; + if (ftyp) + { + if (argiterator) + { + /* The precondition is that the iterator is reset */ + field->arg = (void *)GenericArgument(field->type, argiterator, &err); + + if (err) + { + _nc_Free_Argument(field->type, (TypeArgument *)(field->arg)); + field->type = (FIELDTYPE *)0; + field->arg = (void *)0; + } + else + { + code = E_OK; + if (field->type) + field->type->ref++; + } + } + } + else + { + field->arg = (void *)0; + code = E_OK; + } + } + return code; +} + +/*--------------------------------------------------------------------------- +| Facility : libnform +| Function : WINDOW* _nc_form_cursor( +| FORM* form, +| int *pRow, int *pCol) +| +| Description : Get the current position of the form cursor position +| We also return the field window +| +| Return Values : The field's Window or NULL on error ++--------------------------------------------------------------------------*/ +FORM_EXPORT(WINDOW *) +_nc_form_cursor(const FORM *form, int *pRow, int *pCol) +{ + int code = E_SYSTEM_ERROR; + WINDOW *res = (WINDOW *)0; + + if (form != 0 && pRow != 0 && pCol != 0) + { + *pRow = form->currow; + *pCol = form->curcol; + res = form->w; + code = E_OK; + } + if (code != E_OK) + SET_ERROR(code); + return res; +} + +#else +extern void _nc_fty_generic(void); +void +_nc_fty_generic(void) +{ +} +#endif + +/* fty_generic.c ends here */ diff --git a/lib/libform/fty_int.c b/lib/libform/fty_int.c index dfc2bd894f4..1378b6766df 100644 --- a/lib/libform/fty_int.c +++ b/lib/libform/fty_int.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fty_int.c,v 1.9 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fty_int.c,v 1.10 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -35,7 +36,7 @@ #include "form.priv.h" -MODULE_ID("$Id: fty_int.c,v 1.9 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fty_int.c,v 1.10 2023/10/17 09:52:10 nicm Exp $") #if USE_WIDEC_SUPPORT #define isDigit(c) (iswdigit((wint_t)(c)) || isdigit(UChar(c))) @@ -53,34 +54,66 @@ typedef struct } thisARG; +typedef struct + { + int precision; + long low; + long high; + } +integerPARM; + /*--------------------------------------------------------------------------- -| Facility : libnform -| Function : static void *Make_This_Type( va_list * ap ) -| +| Facility : libnform +| Function : static void *Generic_This_Type( void * arg ) +| | Description : Allocate structure for integer type argument. | | Return Values : Pointer to argument structure or NULL on error +--------------------------------------------------------------------------*/ static void * -Make_This_Type(va_list *ap) +Generic_This_Type(void *arg) { - thisARG *argp = typeMalloc(thisARG, 1); + thisARG *argp = (thisARG *)0; + thisARG *param = (thisARG *)arg; - if (argp) + if (param) { - T((T_CREATE("thisARG %p"), argp)); - argp->precision = va_arg(*ap, int); - argp->low = va_arg(*ap, long); - argp->high = va_arg(*ap, long); + argp = typeMalloc(thisARG, 1); + + if (argp) + { + T((T_CREATE("thisARG %p"), (void *)argp)); + *argp = *param; + } } return (void *)argp; } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform +| Function : static void *Make_This_Type( va_list * ap ) +| +| Description : Allocate structure for integer type argument. +| +| Return Values : Pointer to argument structure or NULL on error ++--------------------------------------------------------------------------*/ +static void * +Make_This_Type(va_list *ap) +{ + thisARG arg; + + arg.precision = va_arg(*ap, int); + arg.low = va_arg(*ap, long); + arg.high = va_arg(*ap, long); + + return Generic_This_Type((void *)&arg); +} + +/*--------------------------------------------------------------------------- +| Facility : libnform | Function : static void *Copy_This_Type(const void * argp) -| -| Description : Copy structure for integer type argument. +| +| Description : Copy structure for integer type argument. | | Return Values : Pointer to argument structure or NULL on error. +--------------------------------------------------------------------------*/ @@ -88,14 +121,15 @@ static void * Copy_This_Type(const void *argp) { const thisARG *ap = (const thisARG *)argp; - thisARG *result = (thisARG *) 0; + thisARG *result = (thisARG *)0; if (argp) { result = typeMalloc(thisARG, 1); + if (result) { - T((T_CREATE("thisARG %p"), result)); + T((T_CREATE("thisARG %p"), (void *)result)); *result = *ap; } } @@ -103,9 +137,9 @@ Copy_This_Type(const void *argp) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : static void Free_This_Type(void * argp) -| +| | Description : Free structure for integer type argument. | | Return Values : - @@ -118,11 +152,11 @@ Free_This_Type(void *argp) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : static bool Check_This_Field( | FIELD * field, | const void * argp) -| +| | Description : Validate buffer content to be a valid integer value | | Return Values : TRUE - field is valid @@ -137,11 +171,9 @@ Check_This_Field(FIELD *field, const void *argp) int prec = argi->precision; unsigned char *bp = (unsigned char *)field_buffer(field, 0); char *s = (char *)bp; - long val; - char buf[100]; bool result = FALSE; - while (*bp && *bp == ' ') + while (*bp == ' ') bp++; if (*bp) { @@ -150,13 +182,14 @@ Check_This_Field(FIELD *field, const void *argp) #if USE_WIDEC_SUPPORT if (*bp) { - bool blank = FALSE; int len; - int n; wchar_t *list = _nc_Widen_String((char *)bp, &len); if (list != 0) { + bool blank = FALSE; + int n; + result = TRUE; for (n = 0; n < len; ++n) { @@ -194,7 +227,8 @@ Check_This_Field(FIELD *field, const void *argp) #endif if (result) { - val = atol(s); + long val = atol(s); + if (low < high) { if (val < low || val > high) @@ -202,7 +236,10 @@ Check_This_Field(FIELD *field, const void *argp) } if (result) { - snprintf(buf, sizeof(buf), "%.*ld", (prec > 0 ? prec : 0), val); + char buf[100]; + + _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf)) + "%.*ld", (prec > 0 ? prec : 0), val); set_field_buffer(field, 0, buf); } } @@ -211,11 +248,11 @@ Check_This_Field(FIELD *field, const void *argp) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : static bool Check_This_Character( | int c, | const void * argp) -| +| | Description : Check a character for the integer type. | | Return Values : TRUE - character is valid @@ -236,12 +273,27 @@ static FIELDTYPE typeTHIS = Make_This_Type, Copy_This_Type, Free_This_Type, - Check_This_Field, - Check_This_Character, - NULL, - NULL + INIT_FT_FUNC(Check_This_Field), + INIT_FT_FUNC(Check_This_Character), + INIT_FT_FUNC(NULL), + INIT_FT_FUNC(NULL), +#if NCURSES_INTEROP_FUNCS + Generic_This_Type +#endif }; -NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_INTEGER = &typeTHIS; +FORM_EXPORT_VAR(FIELDTYPE *) TYPE_INTEGER = &typeTHIS; + +#if NCURSES_INTEROP_FUNCS +/* The next routines are to simplify the use of ncurses from + programming languages with restrictions on interop with C level + constructs (e.g. variable access or va_list + ellipsis constructs) +*/ +FORM_EXPORT(FIELDTYPE *) +_nc_TYPE_INTEGER(void) +{ + return TYPE_INTEGER; +} +#endif /* fty_int.c ends here */ diff --git a/lib/libform/fty_ipv4.c b/lib/libform/fty_ipv4.c index 8c5bbf46f2c..19f400cae1c 100644 --- a/lib/libform/fty_ipv4.c +++ b/lib/libform/fty_ipv4.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fty_ipv4.c,v 1.7 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fty_ipv4.c,v 1.8 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2004,2006 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2006,2009 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -35,14 +36,14 @@ #include "form.priv.h" -MODULE_ID("$Id: fty_ipv4.c,v 1.7 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fty_ipv4.c,v 1.8 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : static bool Check_IPV4_Field( | FIELD * field, | const void * argp) -| +| | Description : Validate buffer content to be a valid IP number (Ver. 4) | | Return Values : TRUE - field is valid @@ -53,7 +54,7 @@ Check_IPV4_Field(FIELD *field, const void *argp GCC_UNUSED) { char *bp = field_buffer(field, 0); int num = 0, len; - unsigned int d1, d2, d3, d4; + unsigned int d1 = 0, d2 = 0, d3 = 0, d4 = 0; if (isdigit(UChar(*bp))) /* Must start with digit */ { @@ -70,11 +71,11 @@ Check_IPV4_Field(FIELD *field, const void *argp GCC_UNUSED) } /*--------------------------------------------------------------------------- -| Facility : libnform +| Facility : libnform | Function : static bool Check_IPV4_Character( -| int c, +| int c, | const void *argp ) -| +| | Description : Check a character for unsigned type or period. | | Return Values : TRUE - character is valid @@ -95,12 +96,27 @@ static FIELDTYPE typeIPV4 = NULL, NULL, NULL, - Check_IPV4_Field, - Check_IPV4_Character, - NULL, + INIT_FT_FUNC(Check_IPV4_Field), + INIT_FT_FUNC(Check_IPV4_Character), + INIT_FT_FUNC(NULL), + INIT_FT_FUNC(NULL), +#if NCURSES_INTEROP_FUNCS NULL +#endif }; -NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_IPV4 = &typeIPV4; +FORM_EXPORT_VAR(FIELDTYPE *) TYPE_IPV4 = &typeIPV4; + +#if NCURSES_INTEROP_FUNCS +/* The next routines are to simplify the use of ncurses from + programming languages with restrictions on interop with C level + constructs (e.g. variable access or va_list + ellipsis constructs) +*/ +FORM_EXPORT(FIELDTYPE *) +_nc_TYPE_IPV4(void) +{ + return TYPE_IPV4; +} +#endif /* fty_ipv4.c ends here */ diff --git a/lib/libform/fty_num.c b/lib/libform/fty_num.c index 06ef8201c11..09aac0a606a 100644 --- a/lib/libform/fty_num.c +++ b/lib/libform/fty_num.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fty_num.c,v 1.9 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fty_num.c,v 1.10 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * + * Copyright 2019-2020,2021 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -35,13 +36,13 @@ #include "form.priv.h" -MODULE_ID("$Id: fty_num.c,v 1.9 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fty_num.c,v 1.10 2023/10/17 09:52:10 nicm Exp $") #if HAVE_LOCALE_H #include #endif -#if HAVE_LOCALE_H +#if HAVE_LOCALE_H && HAVE_LOCALECONV #define isDecimalPoint(c) ((c) == ((L && L->decimal_point) ? *(L->decimal_point) : '.')) #else #define isDecimalPoint(c) ((c) == '.') @@ -64,35 +65,69 @@ typedef struct } thisARG; +typedef struct + { + int precision; + double low; + double high; + } +thisPARM; + /*--------------------------------------------------------------------------- | Facility : libnform -| Function : static void *Make_This_Type(va_list * ap) +| Function : static void *Generic_This_Type(void * arg) | | Description : Allocate structure for numeric type argument. | | Return Values : Pointer to argument structure or NULL on error +--------------------------------------------------------------------------*/ static void * -Make_This_Type(va_list *ap) +Generic_This_Type(void *arg) { - thisARG *argn = typeMalloc(thisARG, 1); + thisARG *argn = (thisARG *)0; + thisPARM *args = (thisPARM *)arg; - if (argn) + if (args) { - T((T_CREATE("thisARG %p"), argn)); - argn->precision = va_arg(*ap, int); - argn->low = va_arg(*ap, double); - argn->high = va_arg(*ap, double); + argn = typeMalloc(thisARG, 1); -#if HAVE_LOCALE_H - argn->L = localeconv(); + if (argn) + { + T((T_CREATE("thisARG %p"), (void *)argn)); + argn->precision = args->precision; + argn->low = args->low; + argn->high = args->high; + +#if HAVE_LOCALE_H && HAVE_LOCALECONV + argn->L = localeconv(); #else - argn->L = NULL; + argn->L = NULL; #endif + } } return (void *)argn; } +/*--------------------------------------------------------------------------- +| Facility : libnform +| Function : static void *Make_This_Type(va_list * ap) +| +| Description : Allocate structure for numeric type argument. +| +| Return Values : Pointer to argument structure or NULL on error ++--------------------------------------------------------------------------*/ +static void * +Make_This_Type(va_list *ap) +{ + thisPARM arg; + + arg.precision = va_arg(*ap, int); + arg.low = va_arg(*ap, double); + arg.high = va_arg(*ap, double); + + return Generic_This_Type((void *)&arg); +} + /*--------------------------------------------------------------------------- | Facility : libnform | Function : static void *Copy_This_Type(const void * argp) @@ -105,14 +140,15 @@ static void * Copy_This_Type(const void *argp) { const thisARG *ap = (const thisARG *)argp; - thisARG *result = (thisARG *) 0; + thisARG *result = (thisARG *)0; if (argp) { result = typeMalloc(thisARG, 1); + if (result) { - T((T_CREATE("thisARG %p"), result)); + T((T_CREATE("thisARG %p"), (void *)result)); *result = *ap; } } @@ -153,12 +189,10 @@ Check_This_Field(FIELD *field, const void *argp) int prec = argn->precision; unsigned char *bp = (unsigned char *)field_buffer(field, 0); char *s = (char *)bp; - double val = 0.0; struct lconv *L = argn->L; - char buf[64]; bool result = FALSE; - while (*bp && *bp == ' ') + while (*bp == ' ') bp++; if (*bp) { @@ -167,14 +201,15 @@ Check_This_Field(FIELD *field, const void *argp) #if USE_WIDEC_SUPPORT if (*bp) { - bool blank = FALSE; - int state = 0; int len; - int n; wchar_t *list = _nc_Widen_String((char *)bp, &len); if (list != 0) { + bool blank = FALSE; + int state = 0; + int n; + result = TRUE; for (n = 0; n < len; ++n) { @@ -230,7 +265,8 @@ Check_This_Field(FIELD *field, const void *argp) #endif if (result) { - val = atof(s); + double val = atof(s); + if (low < high) { if (val < low || val > high) @@ -238,7 +274,10 @@ Check_This_Field(FIELD *field, const void *argp) } if (result) { - snprintf(buf, sizeof(buf), "%.*f", (prec > 0 ? prec : 0), val); + char buf[64]; + + _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf)) + "%.*f", (prec > 0 ? prec : 0), val); set_field_buffer(field, 0, buf); } } @@ -280,12 +319,27 @@ static FIELDTYPE typeTHIS = Make_This_Type, Copy_This_Type, Free_This_Type, - Check_This_Field, - Check_This_Character, - NULL, - NULL + INIT_FT_FUNC(Check_This_Field), + INIT_FT_FUNC(Check_This_Character), + INIT_FT_FUNC(NULL), + INIT_FT_FUNC(NULL), +#if NCURSES_INTEROP_FUNCS + Generic_This_Type +#endif }; -NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_NUMERIC = &typeTHIS; +FORM_EXPORT_VAR(FIELDTYPE *) TYPE_NUMERIC = &typeTHIS; + +#if NCURSES_INTEROP_FUNCS +/* The next routines are to simplify the use of ncurses from + programming languages with restrictions on interop with C level + constructs (e.g. variable access or va_list + ellipsis constructs) +*/ +FORM_EXPORT(FIELDTYPE *) +_nc_TYPE_NUMERIC(void) +{ + return TYPE_NUMERIC; +} +#endif /* fty_num.c ends here */ diff --git a/lib/libform/fty_regex.c b/lib/libform/fty_regex.c index f2688892efe..9ee371e861b 100644 --- a/lib/libform/fty_regex.c +++ b/lib/libform/fty_regex.c @@ -1,6 +1,7 @@ -/* $OpenBSD: fty_regex.c,v 1.9 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: fty_regex.c,v 1.10 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * + * Copyright 2018-2020,2021 Thomas E. Dickey * + * Copyright 1998-2012,2015 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -35,10 +36,48 @@ #include "form.priv.h" -MODULE_ID("$Id: fty_regex.c,v 1.9 2015/01/23 22:48:51 krw Exp $") +MODULE_ID("$Id: fty_regex.c,v 1.10 2023/10/17 09:52:10 nicm Exp $") -#if HAVE_REGEX_H_FUNCS /* We prefer POSIX regex */ +#if HAVE_REGEX_H_FUNCS || HAVE_LIB_PCRE2 /* We prefer POSIX regex */ + +#if HAVE_PCRE2POSIX_H +#include + +/* pcre2 used to provide its "POSIX" entrypoints using the same names as the + * standard ones in the C runtime, but that never worked because the linker + * would use the C runtime. Debian patched the library to fix this symbol + * conflict, but overlooked the header file, and Debian's patch was made + * obsolete when pcre2 was changed early in 2019 to provide different names. + * + * Here is a workaround to make the older version of Debian's package work. + */ +#if !defined(PCRE2regcomp) && defined(HAVE_PCRE2REGCOMP) + +#undef regcomp +#undef regexec +#undef regfree + +#ifdef __cplusplus +extern "C" +{ +#endif + PCRE2POSIX_EXP_DECL int PCRE2regcomp(regex_t *, const char *, int); + PCRE2POSIX_EXP_DECL int PCRE2regexec(const regex_t *, const char *, size_t, + regmatch_t *, int); + PCRE2POSIX_EXP_DECL void PCRE2regfree(regex_t *); +#ifdef __cplusplus +} /* extern "C" */ +#endif +#define regcomp(r,s,n) PCRE2regcomp(r,s,n) +#define regexec(r,s,n,m,x) PCRE2regexec(r,s,n,m,x) +#define regfree(r) PCRE2regfree(r) +#endif +/* end workaround... */ +#elif HAVE_PCREPOSIX_H +#include +#else #include +#endif typedef struct { @@ -91,97 +130,107 @@ RegExp_Arg; #endif +#if HAVE_REGEX_H_FUNCS | HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS +# define MAYBE_UNUSED +#else +# define MAYBE_UNUSED GCC_UNUSED +#endif + /*--------------------------------------------------------------------------- | Facility : libnform -| Function : static void *Make_RegularExpression_Type(va_list * ap) +| Function : static void *Generic_RegularExpression_Type(void * arg) | | Description : Allocate structure for regex type argument. | | Return Values : Pointer to argument structure or NULL on error +--------------------------------------------------------------------------*/ static void * -Make_RegularExpression_Type(va_list *ap) +Generic_RegularExpression_Type(void *arg MAYBE_UNUSED) { #if HAVE_REGEX_H_FUNCS - char *rx = va_arg(*ap, char *); - RegExp_Arg *preg; + char *rx = (char *)arg; + RegExp_Arg *preg = (RegExp_Arg *)0; - preg = typeMalloc(RegExp_Arg, 1); - - if (preg) + if (rx) { - T((T_CREATE("RegExp_Arg %p"), preg)); - if (((preg->pRegExp = typeMalloc(regex_t, 1)) != 0) - && !regcomp(preg->pRegExp, rx, - (REG_EXTENDED | REG_NOSUB | REG_NEWLINE))) - { - T((T_CREATE("regex_t %p"), preg->pRegExp)); - preg->refCount = typeMalloc(unsigned long, 1); + preg = typeCalloc(RegExp_Arg, 1); - *(preg->refCount) = 1; - } - else + if (preg) { - if (preg->pRegExp) - free(preg->pRegExp); - free(preg); - preg = (RegExp_Arg *)0; + T((T_CREATE("RegExp_Arg %p"), (void *)preg)); + if (((preg->pRegExp = typeMalloc(regex_t, 1)) != 0) + && !regcomp(preg->pRegExp, rx, + (REG_EXTENDED | REG_NOSUB | REG_NEWLINE))) + { + T((T_CREATE("regex_t %p"), (void *)preg->pRegExp)); + if ((preg->refCount = typeMalloc(unsigned long, 1)) != 0) + *(preg->refCount) = 1; + } + else + { + if (preg->pRegExp) + free(preg->pRegExp); + free(preg); + preg = (RegExp_Arg *)0; + } } } return ((void *)preg); #elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS - char *rx = va_arg(*ap, char *); - RegExp_Arg *pArg; + char *rx = (char *)arg; + RegExp_Arg *pArg = (RegExp_Arg *)0; - pArg = typeMalloc(RegExp_Arg, 1); - - if (pArg) + if (rx) { - int blen = RX_INCREMENT; - - T((T_CREATE("RegExp_Arg %p"), pArg)); - pArg->compiled_expression = NULL; - pArg->refCount = typeMalloc(unsigned long, 1); + pArg = typeMalloc(RegExp_Arg, 1); - *(pArg->refCount) = 1; - - do + if (pArg) { - char *buf = typeMalloc(char, blen); + int blen = RX_INCREMENT; + + T((T_CREATE("RegExp_Arg %p"), pArg)); + pArg->compiled_expression = NULL; + if ((pArg->refCount = typeMalloc(unsigned long, 1)) != 0) + *(pArg->refCount) = 1; - if (buf) + do { + char *buf = typeMalloc(char, blen); + + if (buf) + { #if HAVE_REGEXP_H_FUNCS - char *last_pos = compile(rx, buf, &buf[blen], '\0'); + char *last_pos = compile(rx, buf, &buf[blen], '\0'); #else /* HAVE_REGEXPR_H_FUNCS */ - char *last_pos = compile(rx, buf, &buf[blen]); + char *last_pos = compile(rx, buf, &buf[blen]); #endif - if (reg_errno) - { - free(buf); - if (reg_errno == 50) - blen += RX_INCREMENT; + if (reg_errno) + { + free(buf); + if (reg_errno == 50) + blen += RX_INCREMENT; + else + { + free(pArg); + pArg = NULL; + break; + } + } else { - free(pArg); - pArg = NULL; + pArg->compiled_expression = buf; break; } } - else - { - pArg->compiled_expression = buf; - break; - } } + while (blen <= MAX_RX_LEN); + } + if (pArg && !pArg->compiled_expression) + { + free(pArg); + pArg = NULL; } - while (blen <= MAX_RX_LEN); - } - if (pArg && !pArg->compiled_expression) - { - free(pArg); - pArg = NULL; } return (void *)pArg; #else @@ -189,6 +238,22 @@ Make_RegularExpression_Type(va_list *ap) #endif } +/*--------------------------------------------------------------------------- +| Facility : libnform +| Function : static void *Make_RegularExpression_Type(va_list * ap) +| +| Description : Allocate structure for regex type argument. +| +| Return Values : Pointer to argument structure or NULL on error ++--------------------------------------------------------------------------*/ +static void * +Make_RegularExpression_Type(va_list *ap) +{ + char *rx = va_arg(*ap, char *); + + return Generic_RegularExpression_Type((void *)rx); +} + /*--------------------------------------------------------------------------- | Facility : libnform | Function : static void *Copy_RegularExpression_Type( @@ -199,7 +264,7 @@ Make_RegularExpression_Type(va_list *ap) | Return Values : Pointer to argument structure or NULL on error. +--------------------------------------------------------------------------*/ static void * -Copy_RegularExpression_Type(const void *argp) +Copy_RegularExpression_Type(const void *argp MAYBE_UNUSED) { #if (HAVE_REGEX_H_FUNCS | HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS) const RegExp_Arg *ap = (const RegExp_Arg *)argp; @@ -225,7 +290,7 @@ Copy_RegularExpression_Type(const void *argp) | Return Values : - +--------------------------------------------------------------------------*/ static void -Free_RegularExpression_Type(void *argp) +Free_RegularExpression_Type(void *argp MAYBE_UNUSED) { #if HAVE_REGEX_H_FUNCS | HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS RegExp_Arg *ap = (RegExp_Arg *)argp; @@ -239,6 +304,7 @@ Free_RegularExpression_Type(void *argp) { free(ap->refCount); regfree(ap->pRegExp); + free(ap->pRegExp); } #elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS if (ap->compiled_expression) @@ -265,7 +331,8 @@ Free_RegularExpression_Type(void *argp) | FALSE - field is invalid +--------------------------------------------------------------------------*/ static bool -Check_RegularExpression_Field(FIELD *field, const void *argp) +Check_RegularExpression_Field(FIELD *field MAYBE_UNUSED, + const void *argp MAYBE_UNUSED) { bool match = FALSE; @@ -296,12 +363,27 @@ static FIELDTYPE typeREGEXP = Make_RegularExpression_Type, Copy_RegularExpression_Type, Free_RegularExpression_Type, - Check_RegularExpression_Field, - NULL, - NULL, - NULL + INIT_FT_FUNC(Check_RegularExpression_Field), + INIT_FT_FUNC(NULL), + INIT_FT_FUNC(NULL), + INIT_FT_FUNC(NULL), +#if NCURSES_INTEROP_FUNCS + Generic_RegularExpression_Type +#endif }; -NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_REGEXP = &typeREGEXP; +FORM_EXPORT_VAR(FIELDTYPE *) TYPE_REGEXP = &typeREGEXP; + +#if NCURSES_INTEROP_FUNCS +/* The next routines are to simplify the use of ncurses from + programming languages with restrictions on interop with C level + constructs (e.g. variable access or va_list + ellipsis constructs) +*/ +FORM_EXPORT(FIELDTYPE *) +_nc_TYPE_REGEXP(void) +{ + return TYPE_REGEXP; +} +#endif /* fty_regex.c ends here */ diff --git a/lib/libform/shlib_version b/lib/libform/shlib_version index 9c1551636c5..5b844bbf422 100644 --- a/lib/libform/shlib_version +++ b/lib/libform/shlib_version @@ -1,2 +1,2 @@ -major=6 +major=7 minor=0 diff --git a/lib/libmenu/Makefile b/lib/libmenu/Makefile index 8d9ddda6ace..b5308721aa0 100644 --- a/lib/libmenu/Makefile +++ b/lib/libmenu/Makefile @@ -1,13 +1,13 @@ -# $OpenBSD: Makefile,v 1.19 2019/02/13 15:10:40 nicm Exp $ +# $OpenBSD: Makefile,v 1.20 2023/10/17 09:52:10 nicm Exp $ LIB= menu -SRCS= m_attribs.c m_cursor.c m_driver.c m_format.c \ - m_global.c m_hook.c m_item_cur.c m_item_nam.c m_item_new.c \ - m_item_opt.c m_item_top.c m_item_use.c m_item_val.c m_item_vis.c \ - m_items.c m_new.c m_opts.c m_pad.c m_pattern.c m_post.c \ - m_req_name.c m_scale.c m_spacing.c m_sub.c m_trace.c m_userptr.c m_win.c -HDRS= menu.h eti.h -CFLAGS+=-I${.CURDIR} -I${.CURDIR}/../libcurses -DHAVE_CONFIG_H +SRCS= m_attribs.c m_cursor.c m_driver.c m_format.c m_global.c m_hook.c \ + m_item_cur.c m_item_nam.c m_item_new.c m_item_opt.c m_item_top.c \ + m_item_use.c m_item_val.c m_item_vis.c m_items.c m_new.c m_opts.c \ + m_pad.c m_pattern.c m_post.c m_req_name.c m_scale.c m_spacing.c \ + m_sub.c m_userptr.c m_win.c +HDRS= eti.h menu.h +CFLAGS+=-I${.CURDIR}/../libcurses -D_XOPEN_SOURCE_EXTENDED -DNDEBUG MAN= menu.3 menu_attributes.3 menu_cursor.3 menu_driver.3 menu_format.3 \ menu_hook.3 menu_items.3 menu_mark.3 menu_new.3 menu_opts.3 \ menu_pattern.3 menu_post.3 menu_requestname.3 menu_spacing.3 \ diff --git a/lib/libmenu/READ.ME b/lib/libmenu/READ.ME index 56f1715cc04..e88f98560b9 100644 --- a/lib/libmenu/READ.ME +++ b/lib/libmenu/READ.ME @@ -1,5 +1,6 @@ ------------------------------------------------------------------------------- --- Copyright (c) 1998-2003,2006 Free Software Foundation, Inc. -- +-- Copyright 2020,2021 Thomas E. Dickey -- +-- Copyright 1998-2003,2006 Free Software Foundation, Inc. -- -- -- -- Permission is hereby granted, free of charge, to any person obtaining a -- -- copy of this software and associated documentation files (the -- @@ -25,7 +26,7 @@ -- sale, use or other dealings in this Software without prior written -- -- authorization. -- ------------------------------------------------------------------------------- --- $Id: READ.ME,v 1.4 2010/01/12 23:22:07 nicm Exp $ +-- $Id: READ.ME,v 1.5 2023/10/17 09:52:10 nicm Exp $ ------------------------------------------------------------------------------- This is a clone of the menu library that is available with typical @@ -36,7 +37,7 @@ a 386 based SVR4 implementation (ESIX). The development environment was and is an ELF based Linux system. -For things that still need doing, see the TO-DO file in the top-level +For things that still need doing, see the TO-DO file in the top-level directory. Juergen Pfeifer diff --git a/lib/libmenu/eti.h b/lib/libmenu/eti.h index d0df2de14be..968db48ada0 100644 --- a/lib/libmenu/eti.h +++ b/lib/libmenu/eti.h @@ -1,7 +1,8 @@ -/* $OpenBSD: eti.h,v 1.6 2010/01/12 23:22:07 nicm Exp $ */ +/* $OpenBSD: eti.h,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2002,2003 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2002,2003 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,7 +33,7 @@ * Author: Juergen Pfeifer, 1995,1997 * ****************************************************************************/ -/* $Id: eti.h,v 1.6 2010/01/12 23:22:07 nicm Exp $ */ +/* $Id: eti.h,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ #ifndef NCURSES_ETI_H_incl #define NCURSES_ETI_H_incl 1 diff --git a/lib/libmenu/m_attribs.c b/lib/libmenu/m_attribs.c index 6b7f56f038f..8f6e0028780 100644 --- a/lib/libmenu/m_attribs.c +++ b/lib/libmenu/m_attribs.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_attribs.c,v 1.7 2010/01/12 23:22:07 nicm Exp $ */ +/* $OpenBSD: m_attribs.c,v 1.8 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,7 +40,7 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_attribs.c,v 1.7 2010/01/12 23:22:07 nicm Exp $") +MODULE_ID("$Id: m_attribs.c,v 1.8 2023/10/17 09:52:10 nicm Exp $") /* Macro to redraw menu if it is posted and changed */ #define Refresh_Menu(menu) \ @@ -51,9 +52,9 @@ MODULE_ID("$Id: m_attribs.c,v 1.7 2010/01/12 23:22:07 nicm Exp $") /* "Template" macro to generate a function to set a menus attribute */ #define GEN_MENU_ATTR_SET_FCT( name ) \ -NCURSES_IMPEXP int NCURSES_API set_menu_ ## name (MENU * menu, chtype attr)\ +MENU_EXPORT(int) NCURSES_API set_menu_ ## name (MENU* menu, chtype attr) \ {\ - T((T_CALLED("set_menu_" #name "(%p,%s)"), menu, _traceattr(attr)));\ + T((T_CALLED("set_menu_" #name "(%p,%s)"), (void *) menu, _traceattr(attr))); \ if (!(attr==A_NORMAL || (attr & A_ATTRIBUTES)==attr))\ RETURN(E_BAD_ARGUMENT);\ if (menu && ( menu -> name != attr))\ @@ -67,79 +68,80 @@ NCURSES_IMPEXP int NCURSES_API set_menu_ ## name (MENU * menu, chtype attr)\ /* "Template" macro to generate a function to get a menu's attribute */ #define GEN_MENU_ATTR_GET_FCT( name ) \ -NCURSES_IMPEXP chtype NCURSES_API menu_ ## name (const MENU * menu)\ +MENU_EXPORT(chtype) NCURSES_API menu_ ## name (const MENU * menu)\ {\ - T((T_CALLED("menu_" #name "(%p)"), menu));\ + T((T_CALLED("menu_" #name "(%p)"), (const void *) menu));\ returnAttr(Normalize_Menu( menu ) -> name);\ } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int set_menu_fore(MENU *menu, chtype attr) -| +| | Description : Set the attribute for selectable items. In single- | valued menus this is used to highlight the current | item ((i.e. where the cursor is), in multi-valued | menus this is used to highlight the selected items. | | Return Values : E_OK - success -| E_BAD_ARGUMENT - an invalid value has been passed +| E_BAD_ARGUMENT - an invalid value has been passed +--------------------------------------------------------------------------*/ GEN_MENU_ATTR_SET_FCT(fore) /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : chtype menu_fore(const MENU* menu) -| +| | Description : Return the attribute used for selectable items that | are current (single-valued menu) or selected (multi- -| valued menu). +| valued menu). | | Return Values : Attribute value +--------------------------------------------------------------------------*/ GEN_MENU_ATTR_GET_FCT(fore) /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int set_menu_back(MENU *menu, chtype attr) -| +| | Description : Set the attribute for selectable but not yet selected | items. | -| Return Values : E_OK - success +| Return Values : E_OK - success | E_BAD_ARGUMENT - an invalid value has been passed +--------------------------------------------------------------------------*/ GEN_MENU_ATTR_SET_FCT(back) /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : chtype menu_back(const MENU *menu) -| +| | Description : Return the attribute used for selectable but not yet -| selected items. +| selected items. | | Return Values : Attribute value +--------------------------------------------------------------------------*/ GEN_MENU_ATTR_GET_FCT(back) /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int set_menu_grey(MENU *menu, chtype attr) -| +| | Description : Set the attribute for unselectable items. | | Return Values : E_OK - success -| E_BAD_ARGUMENT - an invalid value has been passed +| E_BAD_ARGUMENT - an invalid value has been passed +--------------------------------------------------------------------------*/ GEN_MENU_ATTR_SET_FCT(grey) /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : chtype menu_grey(const MENU *menu) -| +| | Description : Return the attribute used for non-selectable items | | Return Values : Attribute value +--------------------------------------------------------------------------*/ GEN_MENU_ATTR_GET_FCT(grey) + /* m_attribs.c ends here */ diff --git a/lib/libmenu/m_cursor.c b/lib/libmenu/m_cursor.c index a9bf98c5172..b1e4bfa04bf 100644 --- a/lib/libmenu/m_cursor.c +++ b/lib/libmenu/m_cursor.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_cursor.c,v 1.8 2010/01/12 23:22:07 nicm Exp $ */ +/* $OpenBSD: m_cursor.c,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2004,2005 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,7 +40,7 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_cursor.c,v 1.8 2010/01/12 23:22:07 nicm Exp $") +MODULE_ID("$Id: m_cursor.c,v 1.9 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- | Facility : libnmenu @@ -51,16 +52,16 @@ MODULE_ID("$Id: m_cursor.c,v 1.8 2010/01/12 23:22:07 nicm Exp $") | E_BAD_ARGUMENT - invalid menu | E_NOT_POSTED - Menu is not posted +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -_nc_menu_cursor_pos(const MENU * menu, const ITEM * item, int *pY, int *pX) +MENU_EXPORT(int) +_nc_menu_cursor_pos(const MENU *menu, const ITEM *item, int *pY, int *pX) { if (!menu || !pX || !pY) return (E_BAD_ARGUMENT); else { - if ((ITEM *) 0 == item) + if ((ITEM *)0 == item) item = menu->curitem; - assert(item != (ITEM *) 0); + assert(item != (ITEM *)0); if (!(menu->status & _POSTED)) return (E_NOT_POSTED); @@ -81,19 +82,19 @@ _nc_menu_cursor_pos(const MENU * menu, const ITEM * item, int *pY, int *pX) | E_BAD_ARGUMENT - invalid menu | E_NOT_POSTED - Menu is not posted +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -pos_menu_cursor(const MENU * menu) +MENU_EXPORT(int) +pos_menu_cursor(const MENU *menu) { - WINDOW *win, *sub; int x = 0, y = 0; - int err = _nc_menu_cursor_pos(menu, (ITEM *) 0, &y, &x); + int err = _nc_menu_cursor_pos(menu, (ITEM *)0, &y, &x); - T((T_CALLED("pos_menu_cursor(%p)"), menu)); + T((T_CALLED("pos_menu_cursor(%p)"), (const void *)menu)); if (E_OK == err) { - win = menu->userwin ? menu->userwin : stdscr; - sub = menu->usersub ? menu->usersub : win; + WINDOW *win = Get_Menu_UserWin(menu); + WINDOW *sub = menu->usersub ? menu->usersub : win; + assert(win && sub); if ((menu->opt & O_SHOWMATCH) && (menu->pindex > 0)) diff --git a/lib/libmenu/m_driver.c b/lib/libmenu/m_driver.c index 6e08249575b..353e3beeac4 100644 --- a/lib/libmenu/m_driver.c +++ b/lib/libmenu/m_driver.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_driver.c,v 1.8 2010/01/12 23:22:07 nicm Exp $ */ +/* $OpenBSD: m_driver.c,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2008 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2012,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,7 +40,7 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_driver.c,v 1.8 2010/01/12 23:22:07 nicm Exp $") +MODULE_ID("$Id: m_driver.c,v 1.9 2023/10/17 09:52:10 nicm Exp $") /* Macros */ @@ -49,7 +50,7 @@ MODULE_ID("$Id: m_driver.c,v 1.8 2010/01/12 23:22:07 nicm Exp $") /* Add a new character to the match pattern buffer */ #define Add_Character_To_Pattern(menu,ch) \ - { (menu)->pattern[((menu)->pindex)++] = (ch);\ + { (menu)->pattern[((menu)->pindex)++] = (char) (ch);\ (menu)->pattern[(menu)->pindex] = '\0'; } /*--------------------------------------------------------------------------- @@ -116,14 +117,15 @@ Is_Sub_String( | Return Values : E_OK - an item matching the pattern was found | E_NO_MATCH - nothing found +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +MENU_EXPORT(int) _nc_Match_Next_Character_In_Item_Name -(MENU * menu, int ch, ITEM ** item) +(MENU *menu, int ch, ITEM **item) { bool found = FALSE, passed = FALSE; int idx, last; - T((T_CALLED("_nc_Match_Next_Character(%p,%d,%p)"), menu, ch, item)); + T((T_CALLED("_nc_Match_Next_Character(%p,%d,%p)"), + (void *)menu, ch, (void *)item)); assert(menu && item && *item); idx = (*item)->index; @@ -139,7 +141,7 @@ _nc_Match_Next_Character_In_Item_Name /* we artificially position one item back, because in the do...while loop we start with the next item. This means, that with a new pattern search we always start the scan with the actual item. If - we do a NEXT_PATTERN oder PREV_PATTERN search, we start with the + we do a NEXT_PATTERN or PREV_PATTERN search, we start with the one after or before the actual item. */ if (--idx < 0) idx = menu->nitems - 1; @@ -199,7 +201,7 @@ _nc_Match_Next_Character_In_Item_Name /*--------------------------------------------------------------------------- | Facility : libnmenu -| Function : int menu_driver(MENU *menu, int c) +| Function : int menu_driver(MENU* menu, int c) | | Description : Central dispatcher for the menu. Translates the logical | request 'c' into a menu action. @@ -209,8 +211,8 @@ _nc_Match_Next_Character_In_Item_Name | E_BAD_STATE - menu is in user hook routine | E_NOT_POSTED - menu is not posted +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -menu_driver(MENU * menu, int c) +MENU_EXPORT(int) +menu_driver(MENU *menu, int c) { #define NAVIGATE(dir) \ if (!item->dir)\ @@ -220,9 +222,9 @@ menu_driver(MENU * menu, int c) int result = E_OK; ITEM *item; - int my_top_row, rdiff; + int my_top_row; - T((T_CALLED("menu_driver(%p,%d)"), menu, c)); + T((T_CALLED("menu_driver(%p,%d)"), (void *)menu, c)); if (!menu) RETURN(E_BAD_ARGUMENT); @@ -239,6 +241,8 @@ menu_driver(MENU * menu, int c) if ((c > KEY_MAX) && (c <= MAX_MENU_COMMAND)) { + int rdiff; + if (!((c == REQ_BACK_PATTERN) || (c == REQ_NEXT_MATCH) || (c == REQ_PREV_MATCH))) { @@ -489,16 +493,20 @@ menu_driver(MENU * menu, int c) } else if (wenclose(sub, event.y, event.x)) { /* Inside the area we try to find the hit item */ - int i, x, y, err; + int x, y; ry = event.y; rx = event.x; if (wmouse_trafo(sub, &ry, &rx, FALSE)) { + int i; + for (i = 0; i < menu->nitems; i++) { - err = _nc_menu_cursor_pos(menu, menu->items[i], - &y, &x); + int err = _nc_menu_cursor_pos(menu, + menu->items[i], + &y, &x); + if (E_OK == err) { if ((ry == y) && @@ -531,14 +539,22 @@ menu_driver(MENU * menu, int c) } } else - result = E_REQUEST_DENIED; + { + if (menu->opt & O_MOUSE_MENU) + ungetmouse(&event); /* let someone else handle this */ + result = E_REQUEST_DENIED; + } } #endif /* NCURSES_MOUSE_VERSION */ else result = E_UNKNOWN_COMMAND; } - if (E_OK == result) + if (item == 0) + { + result = E_BAD_STATE; + } + else if (E_OK == result) { /* Adjust the top row if it turns out that the current item unfortunately doesn't appear in the menu window */ diff --git a/lib/libmenu/m_format.c b/lib/libmenu/m_format.c index 3a5fd3ab6dd..3e0bda7b94e 100644 --- a/lib/libmenu/m_format.c +++ b/lib/libmenu/m_format.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_format.c,v 1.7 2010/01/12 23:22:07 nicm Exp $ */ +/* $OpenBSD: m_format.c,v 1.8 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,7 +40,7 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_format.c,v 1.7 2010/01/12 23:22:07 nicm Exp $") +MODULE_ID("$Id: m_format.c,v 1.8 2023/10/17 09:52:10 nicm Exp $") #define minimum(a,b) ((a)<(b) ? (a): (b)) @@ -57,18 +58,19 @@ MODULE_ID("$Id: m_format.c,v 1.7 2010/01/12 23:22:07 nicm Exp $") | E_NOT_CONNECTED - there are no items connected | E_POSTED - the menu is already posted +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -set_menu_format(MENU * menu, int rows, int cols) +MENU_EXPORT(int) +set_menu_format(MENU *menu, int rows, int cols) { - int total_rows, total_cols; - T((T_CALLED("set_menu_format(%p,%d,%d)"), menu, rows, cols)); + T((T_CALLED("set_menu_format(%p,%d,%d)"), (void *)menu, rows, cols)); if (rows < 0 || cols < 0) RETURN(E_BAD_ARGUMENT); if (menu) { + int total_rows, total_cols; + if (menu->status & _POSTED) RETURN(E_POSTED); @@ -83,8 +85,8 @@ set_menu_format(MENU * menu, int rows, int cols) if (menu->pattern) Reset_Pattern(menu); - menu->frows = rows; - menu->fcols = cols; + menu->frows = (short)rows; + menu->fcols = (short)cols; assert(rows > 0 && cols > 0); total_rows = (menu->nitems - 1) / cols + 1; @@ -92,21 +94,21 @@ set_menu_format(MENU * menu, int rows, int cols) minimum(menu->nitems, cols) : (menu->nitems - 1) / total_rows + 1; - menu->rows = total_rows; - menu->cols = total_cols; - menu->arows = minimum(total_rows, rows); + menu->rows = (short)total_rows; + menu->cols = (short)total_cols; + menu->arows = (short)minimum(total_rows, rows); menu->toprow = 0; menu->curitem = *(menu->items); assert(menu->curitem); - menu->status |= _LINK_NEEDED; + SetStatus(menu, _LINK_NEEDED); _nc_Calculate_Item_Length_and_Width(menu); } else { if (rows > 0) - _nc_Default_Menu.frows = rows; + _nc_Default_Menu.frows = (short)rows; if (cols > 0) - _nc_Default_Menu.fcols = cols; + _nc_Default_Menu.fcols = (short)cols; } RETURN(E_OK); @@ -121,8 +123,8 @@ set_menu_format(MENU * menu, int rows, int cols) | | Return Values : - +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(void) -menu_format(const MENU * menu, int *rows, int *cols) +MENU_EXPORT(void) +menu_format(const MENU *menu, int *rows, int *cols) { if (rows) *rows = Normalize_Menu(menu)->frows; diff --git a/lib/libmenu/m_global.c b/lib/libmenu/m_global.c index af6fa156924..2ad54fa5618 100644 --- a/lib/libmenu/m_global.c +++ b/lib/libmenu/m_global.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_global.c,v 1.8 2010/01/12 23:22:07 nicm Exp $ */ +/* $OpenBSD: m_global.c,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2004,2005 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2012,2014 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,11 +40,11 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_global.c,v 1.8 2010/01/12 23:22:07 nicm Exp $") +MODULE_ID("$Id: m_global.c,v 1.9 2023/10/17 09:52:10 nicm Exp $") static char mark[] = "-"; /* *INDENT-OFF* */ -NCURSES_EXPORT_VAR(MENU) _nc_Default_Menu = { +MENU_EXPORT_VAR(MENU) _nc_Default_Menu = { 16, /* Nr. of chars high */ 1, /* Nr. of chars wide */ 16, /* Nr. of items high */ @@ -55,7 +56,7 @@ NCURSES_EXPORT_VAR(MENU) _nc_Default_Menu = { 0, /* length of widest description */ 1, /* length of mark */ 1, /* length of one item */ - 1, /* Spacing for descriptor */ + 1, /* Spacing for descriptor */ 1, /* Spacing for columns */ 1, /* Spacing for rows */ (char *)0, /* buffer used to store match chars */ @@ -70,7 +71,7 @@ NCURSES_EXPORT_VAR(MENU) _nc_Default_Menu = { 0, /* Top row of menu */ (chtype)A_REVERSE, /* Attribute for selection */ (chtype)A_NORMAL, /* Attribute for nonselection */ - (chtype)A_UNDERLINE, /* Attribute for inactive */ + (chtype)A_UNDERLINE, /* Attribute for inactive */ ' ', /* Pad character */ (Menu_Hook)0, /* Menu init */ (Menu_Hook)0, /* Menu term */ @@ -79,10 +80,10 @@ NCURSES_EXPORT_VAR(MENU) _nc_Default_Menu = { (void *)0, /* userptr */ mark, /* mark */ ALL_MENU_OPTS, /* options */ - 0 /* status */ + 0 /* status */ }; -NCURSES_EXPORT_VAR(ITEM) _nc_Default_Item = { +MENU_EXPORT_VAR(ITEM) _nc_Default_Item = { { (char *)0, 0 }, /* name */ { (char *)0, 0 }, /* description */ (MENU *)0, /* Pointer to parent menu */ @@ -100,50 +101,50 @@ NCURSES_EXPORT_VAR(ITEM) _nc_Default_Item = { /* *INDENT-ON* */ /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : static void ComputeMaximum_NameDesc_Lenths(MENU *menu) -| +| | Description : Calculates the maximum name and description lengths | of the items connected to the menu | | Return Values : - +--------------------------------------------------------------------------*/ NCURSES_INLINE static void -ComputeMaximum_NameDesc_Lengths(MENU * menu) +ComputeMaximum_NameDesc_Lengths(MENU *menu) { unsigned MaximumNameLength = 0; unsigned MaximumDescriptionLength = 0; ITEM **items; - unsigned check; assert(menu && menu->items); for (items = menu->items; *items; items++) { - check = _nc_Calculate_Text_Width(&((*items)->name)); + unsigned check = (unsigned)_nc_Calculate_Text_Width(&((*items)->name)); + if (check > MaximumNameLength) MaximumNameLength = check; - check = _nc_Calculate_Text_Width(&((*items)->description)); + check = (unsigned)_nc_Calculate_Text_Width(&((*items)->description)); if (check > MaximumDescriptionLength) MaximumDescriptionLength = check; } - menu->namelen = MaximumNameLength; - menu->desclen = MaximumDescriptionLength; + menu->namelen = (short)MaximumNameLength; + menu->desclen = (short)MaximumDescriptionLength; T(("ComputeMaximum_NameDesc_Lengths %d,%d", menu->namelen, menu->desclen)); } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : static void ResetConnectionInfo(MENU *, ITEM **) -| -| Description : Reset all informations in the menu and the items in +| +| Description : Reset all information in the menu and the items in | the item array that indicates a connection | | Return Values : - +--------------------------------------------------------------------------*/ NCURSES_INLINE static void -ResetConnectionInfo(MENU * menu, ITEM ** items) +ResetConnectionInfo(MENU *menu, ITEM **items) { ITEM **item; @@ -151,18 +152,18 @@ ResetConnectionInfo(MENU * menu, ITEM ** items) for (item = items; *item; item++) { (*item)->index = 0; - (*item)->imenu = (MENU *) 0; + (*item)->imenu = (MENU *)0; } if (menu->pattern) free(menu->pattern); menu->pattern = (char *)0; menu->pindex = 0; - menu->items = (ITEM **) 0; + menu->items = (ITEM **)0; menu->nitems = 0; } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : bool _nc_Connect_Items(MENU *menu, ITEM **items) | | Description : Connect the items in the item array to the menu. @@ -172,14 +173,15 @@ ResetConnectionInfo(MENU * menu, ITEM ** items) | Return Values : TRUE - successful connection | FALSE - connection failed +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(bool) -_nc_Connect_Items(MENU * menu, ITEM ** items) +MENU_EXPORT(bool) +_nc_Connect_Items(MENU *menu, ITEM **items) { - ITEM **item; unsigned int ItemCount = 0; if (menu && items) { + ITEM **item; + for (item = items; *item; item++) { if ((*item)->imenu) @@ -197,7 +199,7 @@ _nc_Connect_Items(MENU * menu, ITEM ** items) { (*item)->value = FALSE; } - (*item)->index = ItemCount++; + (*item)->index = (short)ItemCount++; (*item)->imenu = menu; } } @@ -208,7 +210,7 @@ _nc_Connect_Items(MENU * menu, ITEM ** items) if (ItemCount != 0) { menu->items = items; - menu->nitems = ItemCount; + menu->nitems = (short)ItemCount; ComputeMaximum_NameDesc_Lengths(menu); if ((menu->pattern = typeMalloc(char, (unsigned)(1 + menu->namelen)))) { @@ -220,45 +222,45 @@ _nc_Connect_Items(MENU * menu, ITEM ** items) } } - /* If we fall through to this point, we have to reset all items connection + /* If we fall through to this point, we have to reset all items connection and inform about a reject connection */ ResetConnectionInfo(menu, items); return (FALSE); } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : void _nc_Disconnect_Items(MENU *menu) -| +| | Description : Disconnect the menus item array from the menu | | Return Values : - +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(void) -_nc_Disconnect_Items(MENU * menu) +MENU_EXPORT(void) +_nc_Disconnect_Items(MENU *menu) { if (menu && menu->items) ResetConnectionInfo(menu, menu->items); } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int _nc_Calculate_Text_Width(const TEXT * item) -| +| | Description : Calculate the number of columns for a TEXT. | | Return Values : the width +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -_nc_Calculate_Text_Width(const TEXT * item /*FIXME: limit length */ ) +MENU_EXPORT(int) +_nc_Calculate_Text_Width(const TEXT *item /*FIXME: limit length */ ) { #if USE_WIDEC_SUPPORT int result = item->length; - T((T_CALLED("_nc_menu_text_width(%p)"), item)); + T((T_CALLED("_nc_menu_text_width(%p)"), (const void *)item)); if (result != 0 && item->str != 0) { - int count = mbstowcs(0, item->str, 0); + int count = (int)mbstowcs(0, item->str, 0); wchar_t *temp = 0; if (count > 0 @@ -290,26 +292,22 @@ _nc_Calculate_Text_Width(const TEXT * item /*FIXME: limit length */ ) */ #if USE_WIDEC_SUPPORT static int -calculate_actual_width(MENU * menu, bool name) +calculate_actual_width(MENU *menu, bool name) { int width = 0; - int check = 0; - ITEM **items; assert(menu && menu->items); if (menu->items != 0) { + ITEM **items; + for (items = menu->items; *items; items++) { - if (name) - { - check = _nc_Calculate_Text_Width(&((*items)->name)); - } - else - { - check = _nc_Calculate_Text_Width(&((*items)->description)); - } + int check = (name + ? _nc_Calculate_Text_Width(&((*items)->name)) + : _nc_Calculate_Text_Width(&((*items)->description))); + if (check > width) width = check; } @@ -330,22 +328,22 @@ calculate_actual_width(MENU * menu, bool name) #endif /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : void _nc_Calculate_Item_Length_and_Width(MENU *menu) -| +| | Description : Calculate the length of an item and the width of the | whole menu. | | Return Values : - +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(void) -_nc_Calculate_Item_Length_and_Width(MENU * menu) +MENU_EXPORT(void) +_nc_Calculate_Item_Length_and_Width(MENU *menu) { int l; assert(menu); - menu->height = 1 + menu->spc_rows * (menu->arows - 1); + menu->height = (short)(1 + menu->spc_rows * (menu->arows - 1)); l = calculate_actual_width(menu, TRUE); l += menu->marklen; @@ -356,10 +354,10 @@ _nc_Calculate_Item_Length_and_Width(MENU * menu) l += menu->spc_desc; } - menu->itemlen = l; + menu->itemlen = (short)l; l *= menu->cols; l += (menu->cols - 1) * menu->spc_cols; /* for the padding between the columns */ - menu->width = l; + menu->width = (short)l; T(("_nc_CalculateItem_Length_and_Width columns %d, item %d, width %d", menu->cols, @@ -368,21 +366,21 @@ _nc_Calculate_Item_Length_and_Width(MENU * menu) } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : void _nc_Link_Item(MENU *menu) -| +| | Description : Statically calculate for every item its four neighbors. | This depends on the orientation of the menu. This | static approach simplifies navigation in the menu a lot. | | Return Values : - +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(void) -_nc_Link_Items(MENU * menu) +MENU_EXPORT(void) +_nc_Link_Items(MENU *menu) { if (menu && menu->items && *(menu->items)) { - int i, j; + int i; ITEM *item; int Number_Of_Items = menu->nitems; int col = 0, row = 0; @@ -390,7 +388,7 @@ _nc_Link_Items(MENU * menu) int Last_in_Column; bool cycle = (menu->opt & O_NONCYCLIC) ? FALSE : TRUE; - menu->status &= ~_LINK_NEEDED; + ClrStatus(menu, _LINK_NEEDED); if (menu->opt & O_ROWMAJOR) { @@ -409,14 +407,14 @@ _nc_Link_Items(MENU * menu) (cycle ? menu->items[(Last_in_Row >= Number_Of_Items) ? Number_Of_Items - 1 : Last_in_Row] : - (ITEM *) 0); + (ITEM *)0); item->right = ((col < (Number_Of_Columns - 1)) && ((i + 1) < Number_Of_Items) )? menu->items[i + 1] : (cycle ? menu->items[row * Number_Of_Columns] : - (ITEM *) 0 + (ITEM *)0 ); Last_in_Column = (menu->rows - 1) * Number_Of_Columns + col; @@ -425,16 +423,16 @@ _nc_Link_Items(MENU * menu) (cycle ? menu->items[(Last_in_Column >= Number_Of_Items) ? Number_Of_Items - 1 : Last_in_Column] : - (ITEM *) 0); + (ITEM *)0); item->down = ((i + Number_Of_Columns) < Number_Of_Items) ? menu->items[i + Number_Of_Columns] : (cycle ? menu->items[(row + 1) < menu->rows ? Number_Of_Items - 1 : col] : - (ITEM *) 0); - item->x = col; - item->y = row; + (ITEM *)0); + item->x = (short)col; + item->y = (short)row; if (++col == Number_Of_Columns) { row++; @@ -445,6 +443,7 @@ _nc_Link_Items(MENU * menu) else { int Number_Of_Rows = menu->rows; + int j; for (j = 0; j < Number_Of_Items; j++) { @@ -457,12 +456,12 @@ _nc_Link_Items(MENU * menu) (cycle ? (Last_in_Column >= Number_Of_Items) ? menu->items[Last_in_Column - Number_Of_Rows] : menu->items[Last_in_Column] : - (ITEM *) 0); + (ITEM *)0); item->right = ((i + Number_Of_Rows) < Number_Of_Items) ? menu->items[i + Number_Of_Rows] : - (cycle ? menu->items[row] : (ITEM *) 0); + (cycle ? menu->items[row] : (ITEM *)0); Last_in_Row = col * Number_Of_Rows + (Number_Of_Rows - 1); @@ -472,7 +471,7 @@ _nc_Link_Items(MENU * menu) menu->items[(Last_in_Row >= Number_Of_Items) ? Number_Of_Items - 1 : Last_in_Row] : - (ITEM *) 0); + (ITEM *)0); item->down = (row < (Number_Of_Rows - 1)) ? @@ -481,11 +480,11 @@ _nc_Link_Items(MENU * menu) (col - 1) * Number_Of_Rows + row + 1]) : (cycle ? menu->items[col * Number_Of_Rows] : - (ITEM *) 0 + (ITEM *)0 ); - item->x = col; - item->y = row; + item->x = (short)col; + item->y = (short)row; if ((++row) == Number_Of_Rows) { col++; @@ -497,22 +496,22 @@ _nc_Link_Items(MENU * menu) } /*--------------------------------------------------------------------------- -| Facility : libnmenu -| Function : void _nc_Show_Menu(const MENU *menu) -| +| Facility : libnmenu +| Function : void _nc_Show_Menu(const MENU* menu) +| | Description : Update the window that is associated with the menu | | Return Values : - +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(void) -_nc_Show_Menu(const MENU * menu) +MENU_EXPORT(void) +_nc_Show_Menu(const MENU *menu) { - WINDOW *win; - int maxy, maxx; - assert(menu); if ((menu->status & _POSTED) && !(menu->status & _IN_DRIVER)) { + WINDOW *win; + int maxy, maxx; + /* adjust the internal subwindow to start on the current top */ assert(menu->sub); mvderwin(menu->sub, menu->spc_rows * menu->toprow, 0); @@ -532,29 +531,31 @@ _nc_Show_Menu(const MENU * menu) } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : void _nc_New_TopRow_and_CurrentItem( -| MENU *menu, -| int new_toprow, +| MENU *menu, +| int new_toprow, | ITEM *new_current_item) -| +| | Description : Redisplay the menu so that the given row becomes the | top row and the given item becomes the new current | item. | | Return Values : - +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(void) - _nc_New_TopRow_and_CurrentItem - (MENU * menu, int new_toprow, ITEM * new_current_item) +MENU_EXPORT(void) +_nc_New_TopRow_and_CurrentItem( + MENU *menu, + int new_toprow, + ITEM *new_current_item) { - ITEM *cur_item; - bool mterm_called = FALSE; - bool iterm_called = FALSE; - assert(menu); if (menu->status & _POSTED) { + ITEM *cur_item; + bool mterm_called = FALSE; + bool iterm_called = FALSE; + if (new_current_item != menu->curitem) { Call_Hook(menu, itemterm); @@ -568,7 +569,9 @@ NCURSES_EXPORT(void) cur_item = menu->curitem; assert(cur_item); - menu->toprow = new_toprow; + menu->toprow = (short)(((menu->rows - menu->frows) >= 0) + ? min(menu->rows - menu->frows, new_toprow) + : 0); menu->curitem = new_current_item; if (mterm_called) @@ -590,7 +593,9 @@ NCURSES_EXPORT(void) } else { /* if we are not posted, this is quite simple */ - menu->toprow = new_toprow; + menu->toprow = (short)(((menu->rows - menu->frows) >= 0) + ? min(menu->rows - menu->frows, new_toprow) + : 0); menu->curitem = new_current_item; } } diff --git a/lib/libmenu/m_hook.c b/lib/libmenu/m_hook.c index cab55c10ba8..f144e8084fa 100644 --- a/lib/libmenu/m_hook.c +++ b/lib/libmenu/m_hook.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_hook.c,v 1.7 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_hook.c,v 1.8 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2018-2020,2021 Thomas E. Dickey * + * Copyright 1998-2012,2016 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,29 +40,30 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_hook.c,v 1.7 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_hook.c,v 1.8 2023/10/17 09:52:10 nicm Exp $") /* "Template" macro to generate function to set application specific hook */ #define GEN_HOOK_SET_FUNCTION( typ, name ) \ -NCURSES_IMPEXP int NCURSES_API set_ ## typ ## _ ## name (MENU *menu, Menu_Hook func )\ +MENU_EXPORT(int) NCURSES_API set_ ## typ ## _ ## name (MENU *menu, Menu_Hook func )\ {\ - T((T_CALLED("set_" #typ "_" #name "(%p,%p)"), menu, func));\ + TR_FUNC_BFR(1);\ + T((T_CALLED("set_" #typ "_" #name "(%p,%s)"), (void *) menu, TR_FUNC_ARG(0, func)));\ (Normalize_Menu(menu) -> typ ## name = func );\ RETURN(E_OK);\ } /* "Template" macro to generate function to get application specific hook */ #define GEN_HOOK_GET_FUNCTION( typ, name ) \ -NCURSES_IMPEXP Menu_Hook NCURSES_API typ ## _ ## name ( const MENU *menu )\ +MENU_EXPORT(Menu_Hook) NCURSES_API typ ## _ ## name ( const MENU *menu )\ {\ - T((T_CALLED(#typ "_" #name "(%p)"), menu));\ + T((T_CALLED(#typ "_" #name "(%p)"), (const void *) menu));\ returnMenuHook(Normalize_Menu(menu) -> typ ## name);\ } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int set_menu_init(MENU *menu, void (*f)(MENU *)) -| +| | Description : Set user-exit which is called when menu is posted | or just after the top row changes. | @@ -70,11 +72,11 @@ NCURSES_IMPEXP Menu_Hook NCURSES_API typ ## _ ## name ( const MENU *menu )\ GEN_HOOK_SET_FUNCTION(menu, init) /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : void (*)(MENU *) menu_init(const MENU *menu) -| +| | Description : Return address of user-exit function which is called -| when a menu is posted or just after the top row +| when a menu is posted or just after the top row | changes. | | Return Values : Menu init function address or NULL @@ -82,9 +84,9 @@ GEN_HOOK_SET_FUNCTION(menu, init) GEN_HOOK_GET_FUNCTION(menu, init) /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int set_menu_term (MENU *menu, void (*f)(MENU *)) -| +| | Description : Set user-exit which is called when menu is unposted | or just before the top row changes. | @@ -93,11 +95,11 @@ GEN_HOOK_GET_FUNCTION(menu, init) GEN_HOOK_SET_FUNCTION(menu, term) /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : void (*)(MENU *) menu_term(const MENU *menu) -| +| | Description : Return address of user-exit function which is called -| when a menu is unposted or just before the top row +| when a menu is unposted or just before the top row | changes. | | Return Values : Menu finalization function address or NULL @@ -105,9 +107,9 @@ GEN_HOOK_SET_FUNCTION(menu, term) GEN_HOOK_GET_FUNCTION(menu, term) /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int set_item_init (MENU *menu, void (*f)(MENU *)) -| +| | Description : Set user-exit which is called when menu is posted | or just after the current item changes. | @@ -116,11 +118,11 @@ GEN_HOOK_GET_FUNCTION(menu, term) GEN_HOOK_SET_FUNCTION(item, init) /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : void (*)(MENU *) item_init (const MENU *menu) -| +| | Description : Return address of user-exit function which is called -| when a menu is posted or just after the current item +| when a menu is posted or just after the current item | changes. | | Return Values : Item init function address or NULL @@ -128,9 +130,9 @@ GEN_HOOK_SET_FUNCTION(item, init) GEN_HOOK_GET_FUNCTION(item, init) /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int set_item_term (MENU *menu, void (*f)(MENU *)) -| +| | Description : Set user-exit which is called when menu is unposted | or just before the current item changes. | @@ -139,11 +141,11 @@ GEN_HOOK_GET_FUNCTION(item, init) GEN_HOOK_SET_FUNCTION(item, term) /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : void (*)(MENU *) item_init (const MENU *menu) -| +| | Description : Return address of user-exit function which is called -| when a menu is unposted or just before the current item +| when a menu is unposted or just before the current item | changes. | | Return Values : Item finalization function address or NULL diff --git a/lib/libmenu/m_item_cur.c b/lib/libmenu/m_item_cur.c index af3e26d1cdc..16d9a421c35 100644 --- a/lib/libmenu/m_item_cur.c +++ b/lib/libmenu/m_item_cur.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_item_cur.c,v 1.7 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_item_cur.c,v 1.8 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2004,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,20 +40,20 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_item_cur.c,v 1.7 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_item_cur.c,v 1.8 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int set_current_item(MENU *menu, const ITEM *item) -| +| | Description : Make the item the current item | | Return Values : E_OK - success +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -set_current_item(MENU * menu, ITEM * item) +MENU_EXPORT(int) +set_current_item(MENU *menu, ITEM *item) { - T((T_CALLED("set_current_item(%p,%p)"), menu, item)); + T((T_CALLED("set_current_item(%p,%p)"), (void *)menu, (void *)item)); if (menu && item && (item->imenu == menu)) { @@ -83,32 +84,32 @@ set_current_item(MENU * menu, ITEM * item) } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : ITEM *current_item(const MENU *menu) -| +| | Description : Return the menus current item | | Return Values : Item pointer or NULL if failure +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(ITEM *) -current_item(const MENU * menu) +MENU_EXPORT(ITEM *) +current_item(const MENU *menu) { - T((T_CALLED("current_item(%p)"), menu)); - returnItem((menu && menu->items) ? menu->curitem : (ITEM *) 0); + T((T_CALLED("current_item(%p)"), (const void *)menu)); + returnItem((menu && menu->items) ? menu->curitem : (ITEM *)0); } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int item_index(const ITEM *) -| +| | Description : Return the logical index of this item. | | Return Values : The index or ERR if this is an invalid item pointer +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -item_index(const ITEM * item) +MENU_EXPORT(int) +item_index(const ITEM *item) { - T((T_CALLED("item_index(%p)"), item)); + T((T_CALLED("item_index(%p)"), (const void *)item)); returnCode((item && item->imenu) ? item->index : ERR); } diff --git a/lib/libmenu/m_item_nam.c b/lib/libmenu/m_item_nam.c index 9d1bebfb2ee..74171c754e9 100644 --- a/lib/libmenu/m_item_nam.c +++ b/lib/libmenu/m_item_nam.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_item_nam.c,v 1.7 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_item_nam.c,v 1.8 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2004,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,35 +40,35 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_item_nam.c,v 1.7 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_item_nam.c,v 1.8 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : char *item_name(const ITEM *item) -| +| | Description : Return name of menu item | | Return Values : See above; returns NULL if item is invalid +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(const char *) -item_name(const ITEM * item) +MENU_EXPORT(const char *) +item_name(const ITEM *item) { - T((T_CALLED("item_name(%p)"), item)); + T((T_CALLED("item_name(%p)"), (const void *)item)); returnCPtr((item) ? item->name.str : (char *)0); } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : char *item_description(const ITEM *item) -| +| | Description : Returns description of item | | Return Values : See above; Returns NULL if item is invalid +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(const char *) -item_description(const ITEM * item) +MENU_EXPORT(const char *) +item_description(const ITEM *item) { - T((T_CALLED("item_description(%p)"), item)); + T((T_CALLED("item_description(%p)"), (const void *)item)); returnCPtr((item) ? item->description.str : (char *)0); } diff --git a/lib/libmenu/m_item_new.c b/lib/libmenu/m_item_new.c index 85bb38b7187..3fd00bce23b 100644 --- a/lib/libmenu/m_item_new.c +++ b/lib/libmenu/m_item_new.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_item_new.c,v 1.9 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_item_new.c,v 1.10 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * + * Copyright 2020-2021 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -46,12 +47,12 @@ #endif #endif -MODULE_ID("$Id: m_item_new.c,v 1.9 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_item_new.c,v 1.10 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : bool Is_Printable_String(const char *s) -| +| | Description : Checks whether or not the string contains only printable | characters. | @@ -64,7 +65,7 @@ Is_Printable_String(const char *s) int result = TRUE; #if USE_WIDEC_SUPPORT - int count = mbstowcs(0, s, 0); + int count = (int)mbstowcs(0, s, 0); wchar_t *temp = 0; assert(s); @@ -76,7 +77,7 @@ Is_Printable_String(const char *s) mbstowcs(temp, s, (unsigned)count); for (n = 0; n < count; ++n) - if (!iswprint((wint_t) temp[n])) + if (!iswprint((wint_t)temp[n])) { result = FALSE; break; @@ -99,16 +100,16 @@ Is_Printable_String(const char *s) } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : ITEM *new_item(char *name, char *description) -| +| | Description : Create a new item with name and description. Return | a pointer to this new item. | N.B.: an item must(!) have a name. | | Return Values : The item pointer or NULL if creation failed. +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(ITEM *) +MENU_EXPORT(ITEM *) new_item(const char *name, const char *description) { ITEM *item; @@ -119,23 +120,25 @@ new_item(const char *name, const char *description) if (!name || (*name == '\0') || !Is_Printable_String(name)) { - item = (ITEM *) 0; + item = (ITEM *)0; SET_ERROR(E_BAD_ARGUMENT); } else { - item = (ITEM *) calloc(1, sizeof(ITEM)); + item = typeCalloc(ITEM, 1); + if (item) { + T((T_CREATE("item %p"), (void *)item)); *item = _nc_Default_Item; /* hope we have struct assignment */ - item->name.length = strlen(name); + item->name.length = (unsigned short)strlen(name); item->name.str = name; if (description && (*description != '\0') && Is_Printable_String(description)) { - item->description.length = strlen(description); + item->description.length = (unsigned short)strlen(description); item->description.str = description; } else @@ -151,20 +154,20 @@ new_item(const char *name, const char *description) } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int free_item(ITEM *item) -| -| Description : Free the allocated storage for this item. +| +| Description : Free the allocated storage for this item. | N.B.: a connected item can't be freed. | | Return Values : E_OK - success | E_BAD_ARGUMENT - invalid value has been passed -| E_CONNECTED - item is still connected to a menu +| E_CONNECTED - item is still connected to a menu +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -free_item(ITEM * item) +MENU_EXPORT(int) +free_item(ITEM *item) { - T((T_CALLED("free_item(%p)"), item)); + T((T_CALLED("free_item(%p)"), (void *)item)); if (!item) RETURN(E_BAD_ARGUMENT); @@ -178,31 +181,31 @@ free_item(ITEM * item) } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int set_menu_mark( MENU *menu, const char *mark ) -| +| | Description : Set the mark string used to indicate the current | item (single-valued menu) or the selected items | (multi-valued menu). -| The mark argument may be NULL, in which case no +| The mark argument may be NULL, in which case no | marker is used. -| This might be a little bit tricky, because this may -| affect the geometry of the menu, which we don't allow +| This might be a little bit tricky, because this may +| affect the geometry of the menu, which we don't allow | if it is already posted. | | Return Values : E_OK - success | E_BAD_ARGUMENT - an invalid value has been passed | E_SYSTEM_ERROR - no memory to store mark +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -set_menu_mark(MENU * menu, const char *mark) +MENU_EXPORT(int) +set_menu_mark(MENU *menu, const char *mark) { - unsigned l; + short l; - T((T_CALLED("set_menu_mark(%p,%s)"), menu, _nc_visbuf(mark))); + T((T_CALLED("set_menu_mark(%p,%s)"), (void *)menu, _nc_visbuf(mark))); if (mark && (*mark != '\0') && Is_Printable_String(mark)) - l = strlen(mark); + l = (short)strlen(mark); else l = 0; @@ -215,22 +218,22 @@ set_menu_mark(MENU * menu, const char *mark) { /* If the menu is already posted, the geometry is fixed. Then we can only accept a mark with exactly the same length */ - if (menu->marklen != (int)l) + if (menu->marklen != l) RETURN(E_BAD_ARGUMENT); } menu->marklen = l; if (l) { - menu->mark = (char *)malloc(l + 1); + menu->mark = strdup(mark); if (menu->mark) { - strlcpy(menu->mark, mark, l+1); if (menu != &_nc_Default_Menu) - menu->status |= _MARK_ALLOCATED; + SetStatus(menu, _MARK_ALLOCATED); } else { menu->mark = old_mark; + menu->marklen = (short)((old_mark != 0) ? strlen(old_mark) : 0); RETURN(E_SYSTEM_ERROR); } } @@ -259,17 +262,17 @@ set_menu_mark(MENU * menu, const char *mark) } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : char *menu_mark(const MENU *menu) -| +| | Description : Return a pointer to the marker string | | Return Values : The marker string pointer or NULL if no marker defined +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(const char *) -menu_mark(const MENU * menu) +MENU_EXPORT(const char *) +menu_mark(const MENU *menu) { - T((T_CALLED("menu_mark(%p)"), menu)); + T((T_CALLED("menu_mark(%p)"), (const void *)menu)); returnPtr(Normalize_Menu(menu)->mark); } diff --git a/lib/libmenu/m_item_opt.c b/lib/libmenu/m_item_opt.c index 8dc31abbff0..fe9522e9869 100644 --- a/lib/libmenu/m_item_opt.c +++ b/lib/libmenu/m_item_opt.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_item_opt.c,v 1.9 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_item_opt.c,v 1.10 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2004,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,12 +40,12 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_item_opt.c,v 1.9 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_item_opt.c,v 1.10 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnmenu -| Function : int set_item_opts(ITEM *item, Item_Options opts) -| +| Facility : libnmenu +| Function : int set_item_opts(ITEM *item, Item_Options opts) +| | Description : Set the options of the item. If there are relevant | changes, the item is connected and the menu is posted, | the menu will be redisplayed. @@ -52,10 +53,10 @@ MODULE_ID("$Id: m_item_opt.c,v 1.9 2010/01/12 23:22:08 nicm Exp $") | Return Values : E_OK - success | E_BAD_ARGUMENT - invalid item options +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -set_item_opts(ITEM * item, Item_Options opts) +MENU_EXPORT(int) +set_item_opts(ITEM *item, Item_Options opts) { - T((T_CALLED("set_menu_opts(%p,%d)"), item, opts)); + T((T_CALLED("set_menu_opts(%p,%d)"), (void *)item, opts)); opts &= ALL_ITEM_OPTS; @@ -87,22 +88,22 @@ set_item_opts(ITEM * item, Item_Options opts) } /*--------------------------------------------------------------------------- -| Facility : libnmenu -| Function : int item_opts_off(ITEM *item, Item_Options opts) -| +| Facility : libnmenu +| Function : int item_opts_off(ITEM *item, Item_Options opts) +| | Description : Switch of the options for this item. | | Return Values : E_OK - success | E_BAD_ARGUMENT - invalid options +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -item_opts_off(ITEM * item, Item_Options opts) +MENU_EXPORT(int) +item_opts_off(ITEM *item, Item_Options opts) { ITEM *citem = item; /* use a copy because set_item_opts must detect NULL item itself to adjust its behavior */ - T((T_CALLED("item_opts_off(%p,%d)"), item, opts)); + T((T_CALLED("item_opts_off(%p,%d)"), (void *)item, opts)); if (opts & ~ALL_ITEM_OPTS) RETURN(E_BAD_ARGUMENT); @@ -115,22 +116,22 @@ item_opts_off(ITEM * item, Item_Options opts) } /*--------------------------------------------------------------------------- -| Facility : libnmenu -| Function : int item_opts_on(ITEM *item, Item_Options opts) -| +| Facility : libnmenu +| Function : int item_opts_on(ITEM *item, Item_Options opts) +| | Description : Switch on the options for this item. | | Return Values : E_OK - success | E_BAD_ARGUMENT - invalid options +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -item_opts_on(ITEM * item, Item_Options opts) +MENU_EXPORT(int) +item_opts_on(ITEM *item, Item_Options opts) { ITEM *citem = item; /* use a copy because set_item_opts must detect NULL item itself to adjust its behavior */ - T((T_CALLED("item_opts_on(%p,%d)"), item, opts)); + T((T_CALLED("item_opts_on(%p,%d)"), (void *)item, opts)); opts &= ALL_ITEM_OPTS; if (opts & ~ALL_ITEM_OPTS) @@ -144,17 +145,17 @@ item_opts_on(ITEM * item, Item_Options opts) } /*--------------------------------------------------------------------------- -| Facility : libnmenu -| Function : Item_Options item_opts(const ITEM *item) -| +| Facility : libnmenu +| Function : Item_Options item_opts(const ITEM *item) +| | Description : Switch of the options for this item. | | Return Values : Items options +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(Item_Options) -item_opts(const ITEM * item) +MENU_EXPORT(Item_Options) +item_opts(const ITEM *item) { - T((T_CALLED("item_opts(%p)"), item)); + T((T_CALLED("item_opts(%p)"), (const void *)item)); returnItemOpts(ALL_ITEM_OPTS & Normalize_Item(item)->opt); } diff --git a/lib/libmenu/m_item_top.c b/lib/libmenu/m_item_top.c index d17c1d48744..74d55371276 100644 --- a/lib/libmenu/m_item_top.c +++ b/lib/libmenu/m_item_top.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_item_top.c,v 1.5 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_item_top.c,v 1.6 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2004,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,30 +40,28 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_item_top.c,v 1.5 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_item_top.c,v 1.6 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int set_top_row(MENU *menu, int row) -| +| | Description : Makes the specified row the top row in the menu | | Return Values : E_OK - success | E_BAD_ARGUMENT - not a menu pointer or invalid row | E_NOT_CONNECTED - there are no items for the menu +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -set_top_row(MENU * menu, int row) +MENU_EXPORT(int) +set_top_row(MENU *menu, int row) { - ITEM *item; - - T((T_CALLED("set_top_row(%p,%d)"), menu, row)); + T((T_CALLED("set_top_row(%p,%d)"), (void *)menu, row)); if (menu) { if (menu->status & _IN_DRIVER) RETURN(E_BAD_STATE); - if (menu->items == (ITEM **) 0) + if (menu->items == (ITEM **)0) RETURN(E_NOT_CONNECTED); if ((row < 0) || (row > (menu->rows - menu->arows))) @@ -73,6 +72,8 @@ set_top_row(MENU * menu, int row) if (row != menu->toprow) { + ITEM *item; + if (menu->status & _LINK_NEEDED) _nc_Link_Items(menu); @@ -86,17 +87,17 @@ set_top_row(MENU * menu, int row) } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int top_row(const MENU *) -| +| | Description : Return the top row of the menu | | Return Values : The row number or ERR if there is no row +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -top_row(const MENU * menu) +MENU_EXPORT(int) +top_row(const MENU *menu) { - T((T_CALLED("top_row(%p)"), menu)); + T((T_CALLED("top_row(%p)"), (const void *)menu)); if (menu && menu->items && *(menu->items)) { assert((menu->toprow >= 0) && (menu->toprow < menu->rows)); diff --git a/lib/libmenu/m_item_use.c b/lib/libmenu/m_item_use.c index 68313046aa4..de7ec2e1bd3 100644 --- a/lib/libmenu/m_item_use.c +++ b/lib/libmenu/m_item_use.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_item_use.c,v 1.7 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_item_use.c,v 1.8 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2004,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,39 +40,39 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_item_use.c,v 1.7 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_item_use.c,v 1.8 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int set_item_userptr(ITEM *item, void *userptr) -| +| | Description : Set the pointer that is reserved in any item to store -| application relevant informations. +| application relevant information. | | Return Values : E_OK - success +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -set_item_userptr(ITEM * item, void *userptr) +MENU_EXPORT(int) +set_item_userptr(ITEM *item, void *userptr) { - T((T_CALLED("set_item_userptr(%p,%p)"), item, userptr)); + T((T_CALLED("set_item_userptr(%p,%p)"), (void *)item, (void *)userptr)); Normalize_Item(item)->userptr = userptr; RETURN(E_OK); } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : void *item_userptr(const ITEM *item) -| +| | Description : Return the pointer that is reserved in any item to store -| application relevant informations. +| application relevant information. | | Return Values : Value of the pointer. If no such pointer has been set, | NULL is returned. +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(void *) -item_userptr(const ITEM * item) +MENU_EXPORT(void *) +item_userptr(const ITEM *item) { - T((T_CALLED("item_userptr(%p)"), item)); + T((T_CALLED("item_userptr(%p)"), (const void *)item)); returnVoidPtr(Normalize_Item(item)->userptr); } diff --git a/lib/libmenu/m_item_val.c b/lib/libmenu/m_item_val.c index 9d4b69c79ce..c0123583436 100644 --- a/lib/libmenu/m_item_val.c +++ b/lib/libmenu/m_item_val.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_item_val.c,v 1.7 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_item_val.c,v 1.8 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2004,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,30 +40,28 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_item_val.c,v 1.7 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_item_val.c,v 1.8 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int set_item_value(ITEM *item, int value) -| +| | Description : Programmatically set the item's selection value. This is | only allowed if the item is selectable at all and if | it is not connected to a single-valued menu. | If the item is connected to a posted menu, the menu -| will be redisplayed. +| will be redisplayed. | | Return Values : E_OK - success | E_REQUEST_DENIED - not selectable or single valued menu +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -set_item_value(ITEM * item, bool value) +MENU_EXPORT(int) +set_item_value(ITEM *item, bool value) { - MENU *menu; - - T((T_CALLED("set_item_value(%p,%d)"), item, value)); + T((T_CALLED("set_item_value(%p,%d)"), (void *)item, value)); if (item) { - menu = item->imenu; + MENU *menu = item->imenu; if ((!(item->opt & O_SELECTABLE)) || (menu && (menu->opt & O_ONEVALUE))) @@ -88,18 +87,18 @@ set_item_value(ITEM * item, bool value) } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : bool item_value(const ITEM *item) -| +| | Description : Return the selection value of the item | | Return Values : TRUE - if item is selected | FALSE - if item is not selected +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(bool) -item_value(const ITEM * item) +MENU_EXPORT(bool) +item_value(const ITEM *item) { - T((T_CALLED("item_value(%p)"), item)); + T((T_CALLED("item_value(%p)"), (const void *)item)); returnBool((Normalize_Item(item)->value) ? TRUE : FALSE); } diff --git a/lib/libmenu/m_item_vis.c b/lib/libmenu/m_item_vis.c index 9297c6c46f2..dd2ccf0ec5f 100644 --- a/lib/libmenu/m_item_vis.c +++ b/lib/libmenu/m_item_vis.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_item_vis.c,v 1.7 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_item_vis.c,v 1.8 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2004,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,24 +40,24 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_item_vis.c,v 1.7 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_item_vis.c,v 1.8 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : bool item_visible(const ITEM *item) -| +| | Description : A item is visible if it currently appears in the | subwindow of a posted menu. | | Return Values : TRUE if visible | FALSE if invisible +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(bool) -item_visible(const ITEM * item) +MENU_EXPORT(bool) +item_visible(const ITEM *item) { MENU *menu; - T((T_CALLED("item_visible(%p)"), item)); + T((T_CALLED("item_visible(%p)"), (const void *)item)); if (item && (menu = item->imenu) && (menu->status & _POSTED) && diff --git a/lib/libmenu/m_items.c b/lib/libmenu/m_items.c index 991d0229838..8734fa5aff9 100644 --- a/lib/libmenu/m_items.c +++ b/lib/libmenu/m_items.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_items.c,v 1.7 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_items.c,v 1.8 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2004,2005 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2005,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,12 +40,12 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_items.c,v 1.7 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_items.c,v 1.8 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int set_menu_items(MENU *menu, ITEM **items) -| +| | Description : Sets the item pointer array connected to menu. | | Return Values : E_OK - success @@ -54,10 +55,10 @@ MODULE_ID("$Id: m_items.c,v 1.7 2010/01/12 23:22:08 nicm Exp $") | E_BAD_ARGUMENT - An incorrect menu or item array was | passed to the function +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -set_menu_items(MENU * menu, ITEM ** items) +MENU_EXPORT(int) +set_menu_items(MENU *menu, ITEM **items) { - T((T_CALLED("set_menu_items(%p,%p)"), menu, items)); + T((T_CALLED("set_menu_items(%p,%p)"), (void *)menu, (void *)items)); if (!menu || (items && !(*items))) RETURN(E_BAD_ARGUMENT); @@ -79,33 +80,33 @@ set_menu_items(MENU * menu, ITEM ** items) } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : ITEM **menu_items(const MENU *menu) -| +| | Description : Returns a pointer to the item pointer array of the menu | | Return Values : NULL on error +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(ITEM **) -menu_items(const MENU * menu) +MENU_EXPORT(ITEM **) +menu_items(const MENU *menu) { - T((T_CALLED("menu_items(%p)"), menu)); - returnItemPtr(menu ? menu->items : (ITEM **) 0); + T((T_CALLED("menu_items(%p)"), (const void *)menu)); + returnItemPtr(menu ? menu->items : (ITEM **)0); } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int item_count(const MENU *menu) -| +| | Description : Get the number of items connected to the menu. If the -| menu pointer is NULL we return -1. +| menu pointer is NULL we return -1. | | Return Values : Number of items or -1 to indicate error. +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -item_count(const MENU * menu) +MENU_EXPORT(int) +item_count(const MENU *menu) { - T((T_CALLED("item_count(%p)"), menu)); + T((T_CALLED("item_count(%p)"), (const void *)menu)); returnCode(menu ? menu->nitems : -1); } diff --git a/lib/libmenu/m_new.c b/lib/libmenu/m_new.c index ce9ece3d4e9..a4d8e293cf4 100644 --- a/lib/libmenu/m_new.c +++ b/lib/libmenu/m_new.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_new.c,v 1.8 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_new.c,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2004,2006 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,12 +40,12 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_new.c,v 1.8 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_new.c,v 1.9 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnmenu -| Function : MENU *new_menu(ITEM **items) -| +| Facility : libnmenu +| Function : MENU* _nc_new_menu(SCREEN*, ITEM **items) +| | Description : Creates a new menu connected to the item pointer | array items and returns a pointer to the new menu. | The new menu is initialized with the values from the @@ -52,27 +53,37 @@ MODULE_ID("$Id: m_new.c,v 1.8 2010/01/12 23:22:08 nicm Exp $") | | Return Values : NULL on error +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(MENU *) -new_menu(ITEM ** items) +MENU_EXPORT(MENU *) +NCURSES_SP_NAME(new_menu) (NCURSES_SP_DCLx ITEM **items) { int err = E_SYSTEM_ERROR; - MENU *menu = (MENU *) calloc(1, sizeof(MENU)); + MENU *menu = typeCalloc(MENU, 1); - T((T_CALLED("new_menu(%p)"), items)); + T((T_CALLED("new_menu(%p,%p)"), (void *)SP_PARM, (void *)items)); if (menu) { + T((T_CREATE("menu %p"), (void *)menu)); *menu = _nc_Default_Menu; menu->status = 0; menu->rows = menu->frows; menu->cols = menu->fcols; +#if NCURSES_SP_FUNCS + /* This ensures userwin and usersub are always non-null, + so we can derive always the SCREEN that this menu is + running on. */ + menu->userwin = SP_PARM->_stdscr; + menu->usersub = SP_PARM->_stdscr; +#endif if (items && *items) { if (!_nc_Connect_Items(menu, items)) { err = E_NOT_CONNECTED; free(menu); - menu = (MENU *) 0; + menu = (MENU *)0; } + else + err = E_OK; } } @@ -83,20 +94,39 @@ new_menu(ITEM ** items) } /*--------------------------------------------------------------------------- -| Facility : libnmenu -| Function : int free_menu(MENU *menu) -| -| Description : Disconnects menu from its associated item pointer +| Facility : libnmenu +| Function : MENU *new_menu(ITEM **items) +| +| Description : Creates a new menu connected to the item pointer +| array items and returns a pointer to the new menu. +| The new menu is initialized with the values from the +| default menu. +| +| Return Values : NULL on error ++--------------------------------------------------------------------------*/ +#if NCURSES_SP_FUNCS +MENU_EXPORT(MENU *) +new_menu(ITEM **items) +{ + return NCURSES_SP_NAME(new_menu) (CURRENT_SCREEN, items); +} +#endif + +/*--------------------------------------------------------------------------- +| Facility : libnmenu +| Function : int free_menu(MENU *menu) +| +| Description : Disconnects menu from its associated item pointer | array and frees the storage allocated for the menu. | | Return Values : E_OK - success | E_BAD_ARGUMENT - Invalid menu pointer passed | E_POSTED - Menu is already posted +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -free_menu(MENU * menu) +MENU_EXPORT(int) +free_menu(MENU *menu) { - T((T_CALLED("free_menu(%p)"), menu)); + T((T_CALLED("free_menu(%p)"), (void *)menu)); if (!menu) RETURN(E_BAD_ARGUMENT); diff --git a/lib/libmenu/m_opts.c b/lib/libmenu/m_opts.c index ce7600244b1..8e168445af4 100644 --- a/lib/libmenu/m_opts.c +++ b/lib/libmenu/m_opts.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_opts.c,v 1.8 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_opts.c,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2004,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,7 +40,7 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_opts.c,v 1.8 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_opts.c,v 1.9 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- | Facility : libnmenu @@ -54,10 +55,10 @@ MODULE_ID("$Id: m_opts.c,v 1.8 2010/01/12 23:22:08 nicm Exp $") | E_BAD_ARGUMENT - invalid menu options | E_POSTED - menu is already posted +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -set_menu_opts(MENU * menu, Menu_Options opts) +MENU_EXPORT(int) +set_menu_opts(MENU *menu, Menu_Options opts) { - T((T_CALLED("set_menu_opts(%p,%d)"), menu, opts)); + T((T_CALLED("set_menu_opts(%p,%d)"), (void *)menu, opts)); opts &= ALL_MENU_OPTS; @@ -87,7 +88,7 @@ set_menu_opts(MENU * menu, Menu_Options opts) { ITEM **item; - if (((item = menu->items) != (ITEM **) 0)) + if (((item = menu->items) != (ITEM **)0)) for (; *item; item++) (*item)->value = FALSE; } @@ -114,14 +115,14 @@ set_menu_opts(MENU * menu, Menu_Options opts) | E_BAD_ARGUMENT - invalid options | E_POSTED - menu is already posted +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -menu_opts_off(MENU * menu, Menu_Options opts) +MENU_EXPORT(int) +menu_opts_off(MENU *menu, Menu_Options opts) { MENU *cmenu = menu; /* use a copy because set_menu_opts must detect NULL menu itself to adjust its behavior */ - T((T_CALLED("menu_opts_off(%p,%d)"), menu, opts)); + T((T_CALLED("menu_opts_off(%p,%d)"), (void *)menu, opts)); opts &= ALL_MENU_OPTS; if (opts & ~ALL_MENU_OPTS) @@ -147,14 +148,14 @@ menu_opts_off(MENU * menu, Menu_Options opts) | E_BAD_ARGUMENT - invalid menu options | E_POSTED - menu is already posted +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -menu_opts_on(MENU * menu, Menu_Options opts) +MENU_EXPORT(int) +menu_opts_on(MENU *menu, Menu_Options opts) { MENU *cmenu = menu; /* use a copy because set_menu_opts must detect NULL menu itself to adjust its behavior */ - T((T_CALLED("menu_opts_on(%p,%d)"), menu, opts)); + T((T_CALLED("menu_opts_on(%p,%d)"), (void *)menu, opts)); opts &= ALL_MENU_OPTS; if (opts & ~ALL_MENU_OPTS) @@ -175,10 +176,10 @@ menu_opts_on(MENU * menu, Menu_Options opts) | | Return Values : Menu options +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(Menu_Options) -menu_opts(const MENU * menu) +MENU_EXPORT(Menu_Options) +menu_opts(const MENU *menu) { - T((T_CALLED("menu_opts(%p)"), menu)); + T((T_CALLED("menu_opts(%p)"), (const void *)menu)); returnMenuOpts(ALL_MENU_OPTS & Normalize_Menu(menu)->opt); } diff --git a/lib/libmenu/m_pad.c b/lib/libmenu/m_pad.c index 4ea8d09fdf8..0120781a7f2 100644 --- a/lib/libmenu/m_pad.c +++ b/lib/libmenu/m_pad.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_pad.c,v 1.5 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_pad.c,v 1.6 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,39 +40,39 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_pad.c,v 1.5 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_pad.c,v 1.6 2023/10/17 09:52:10 nicm Exp $") /* Macro to redraw menu if it is posted and changed */ #define Refresh_Menu(menu) \ if ( (menu) && ((menu)->status & _POSTED) )\ {\ _nc_Draw_Menu( menu );\ - _nc_Show_Menu( menu );\ + _nc_Show_Menu( menu ); \ } /*--------------------------------------------------------------------------- -| Facility : libnmenu -| Function : int set_menu_pad(MENU *menu, int pad) -| +| Facility : libnmenu +| Function : int set_menu_pad(MENU* menu, int pad) +| | Description : Set the character to be used to separate the item name -| from its description. This must be a printable +| from its description. This must be a printable | character. | | Return Values : E_OK - success | E_BAD_ARGUMENT - an invalid value has been passed +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -set_menu_pad(MENU * menu, int pad) +MENU_EXPORT(int) +set_menu_pad(MENU *menu, int pad) { - bool do_refresh = (menu != (MENU *) 0); + bool do_refresh = (menu != (MENU *)0); - T((T_CALLED("set_menu_pad(%p,%d)"), menu, pad)); + T((T_CALLED("set_menu_pad(%p,%d)"), (void *)menu, pad)); if (!isprint(UChar(pad))) RETURN(E_BAD_ARGUMENT); Normalize_Menu(menu); - menu->pad = pad; + menu->pad = (unsigned char)pad; if (do_refresh) Refresh_Menu(menu); @@ -80,17 +81,17 @@ set_menu_pad(MENU * menu, int pad) } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int menu_pad(const MENU *menu) -| +| | Description : Return the value of the padding character | | Return Values : The pad character +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -menu_pad(const MENU * menu) +MENU_EXPORT(int) +menu_pad(const MENU *menu) { - T((T_CALLED("menu_pad(%p)"), menu)); + T((T_CALLED("menu_pad(%p)"), (const void *)menu)); returnCode(Normalize_Menu(menu)->pad); } diff --git a/lib/libmenu/m_pattern.c b/lib/libmenu/m_pattern.c index 88ae225339b..86e900ae750 100644 --- a/lib/libmenu/m_pattern.c +++ b/lib/libmenu/m_pattern.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_pattern.c,v 1.5 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_pattern.c,v 1.6 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2006,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,12 +40,12 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_pattern.c,v 1.5 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_pattern.c,v 1.6 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : char *menu_pattern(const MENU *menu) -| +| | Description : Return the value of the pattern buffer. | | Return Values : NULL - if there is no pattern buffer allocated @@ -52,19 +53,19 @@ MODULE_ID("$Id: m_pattern.c,v 1.5 2010/01/12 23:22:08 nicm Exp $") | pattern is stored | PatternString - as expected +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(char *) -menu_pattern(const MENU * menu) +MENU_EXPORT(char *) +menu_pattern(const MENU *menu) { static char empty[] = ""; - T((T_CALLED("menu_pattern(%p)"), menu)); + T((T_CALLED("menu_pattern(%p)"), (const void *)menu)); returnPtr(menu ? (menu->pattern ? menu->pattern : empty) : 0); } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int set_menu_pattern(MENU *menu, const char *p) -| +| | Description : Set the match pattern for a menu and position to the | first item that matches. | @@ -74,13 +75,13 @@ menu_pattern(const MENU * menu) | E_NOT_CONNECTED - no items connected to menu | E_NO_MATCH - no item matches pattern +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -set_menu_pattern(MENU * menu, const char *p) +MENU_EXPORT(int) +set_menu_pattern(MENU *menu, const char *p) { ITEM *matchitem; int matchpos; - T((T_CALLED("set_menu_pattern(%p,%s)"), menu, _nc_visbuf(p))); + T((T_CALLED("set_menu_pattern(%p,%s)"), (void *)menu, _nc_visbuf(p))); if (!menu || !p) RETURN(E_BAD_ARGUMENT); diff --git a/lib/libmenu/m_post.c b/lib/libmenu/m_post.c index 504174189ad..18a669d0aea 100644 --- a/lib/libmenu/m_post.c +++ b/lib/libmenu/m_post.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_post.c,v 1.7 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_post.c,v 1.8 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020-2021,2022 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,7 +40,7 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_post.c,v 1.7 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_post.c,v 1.8 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- | Facility : libnmenu @@ -50,8 +51,8 @@ MODULE_ID("$Id: m_post.c,v 1.7 2010/01/12 23:22:08 nicm Exp $") | | Return Values : - +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(void) -_nc_Post_Item(const MENU * menu, const ITEM * item) +MENU_EXPORT(void) +_nc_Post_Item(const MENU *menu, const ITEM *item) { int i; chtype ch; @@ -59,7 +60,6 @@ _nc_Post_Item(const MENU * menu, const ITEM * item) int count = 0; bool isfore = FALSE, isback = FALSE, isgrey = FALSE; int name_len; - int desc_len; assert(menu->win); @@ -69,7 +69,7 @@ _nc_Post_Item(const MENU * menu, const ITEM * item) - it is a onevalued menu and it is the current item - or it has a selection value */ - wattron(menu->win, menu->back); + wattron(menu->win, (int)menu->back); if (item->value || (item == menu->curitem)) { if (menu->marklen) @@ -81,13 +81,13 @@ _nc_Post_Item(const MENU * menu, const ITEM * item) item. */ if (!(menu->opt & O_ONEVALUE) && item->value && item != menu->curitem) { - wattron(menu->win, menu->fore); + wattron(menu->win, (int)menu->fore); isfore = TRUE; } waddstr(menu->win, menu->mark); if (isfore) { - wattron(menu->win, menu->fore); + wattron(menu->win, (int)menu->fore); isfore = FALSE; } } @@ -95,7 +95,7 @@ _nc_Post_Item(const MENU * menu, const ITEM * item) else /* otherwise we have to wipe out the marker area */ for (ch = ' ', i = menu->marklen; i > 0; i--) waddch(menu->win, ch); - wattroff(menu->win, menu->back); + wattroff(menu->win, (int)menu->back); count += menu->marklen; /* First we have to calculate the attribute depending on selectability @@ -103,19 +103,19 @@ _nc_Post_Item(const MENU * menu, const ITEM * item) */ if (!(item->opt & O_SELECTABLE)) { - wattron(menu->win, menu->grey); + wattron(menu->win, (int)menu->grey); isgrey = TRUE; } else { if (item->value || item == menu->curitem) { - wattron(menu->win, menu->fore); + wattron(menu->win, (int)menu->fore); isfore = TRUE; } else { - wattron(menu->win, menu->back); + wattron(menu->win, (int)menu->back); isback = TRUE; } } @@ -133,6 +133,7 @@ _nc_Post_Item(const MENU * menu, const ITEM * item) { int m = menu->spc_desc / 2; int cy = -1, cx = -1; + int desc_len; for (ch = ' ', i = 0; i < menu->spc_desc; i++) { @@ -160,10 +161,10 @@ _nc_Post_Item(const MENU * menu, const ITEM * item) assert(cx >= 0 && cy >= 0); getyx(menu->win, ncy, ncx); if (isgrey) - wattroff(menu->win, menu->grey); + wattroff(menu->win, (int)menu->grey); else if (isfore) - wattroff(menu->win, menu->fore); - wattron(menu->win, menu->back); + wattroff(menu->win, (int)menu->fore); + wattron(menu->win, (int)menu->back); for (j = 1; j < menu->spc_rows; j++) { if ((item_y + j) < getmaxy(menu->win)) @@ -173,21 +174,21 @@ _nc_Post_Item(const MENU * menu, const ITEM * item) waddch(menu->win, ' '); } if ((cy + j) < getmaxy(menu->win)) - mvwaddch(menu->win, cy + j, cx - 1, menu->pad); + (void)mvwaddch(menu->win, cy + j, cx - 1, menu->pad); } wmove(menu->win, ncy, ncx); if (!isback) - wattroff(menu->win, menu->back); + wattroff(menu->win, (int)menu->back); } } /* Remove attributes */ if (isfore) - wattroff(menu->win, menu->fore); + wattroff(menu->win, (int)menu->fore); if (isback) - wattroff(menu->win, menu->back); + wattroff(menu->win, (int)menu->back); if (isgrey) - wattroff(menu->win, menu->grey); + wattroff(menu->win, (int)menu->grey); } /*--------------------------------------------------------------------------- @@ -198,13 +199,12 @@ _nc_Post_Item(const MENU * menu, const ITEM * item) | | Return Values : - +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(void) -_nc_Draw_Menu(const MENU * menu) +MENU_EXPORT(void) +_nc_Draw_Menu(const MENU *menu) { ITEM *item = menu->items[0]; - ITEM *lasthor, *lastvert; + ITEM *lastvert; ITEM *hitem; - int y = 0; chtype s_bkgd; assert(item && menu->win); @@ -214,50 +214,57 @@ _nc_Draw_Menu(const MENU * menu) werase(menu->win); wbkgdset(menu->win, s_bkgd); - lastvert = (menu->opt & O_NONCYCLIC) ? (ITEM *) 0 : item; + lastvert = (menu->opt & O_NONCYCLIC) ? (ITEM *)0 : item; - do + if (item != NULL) { - wmove(menu->win, y, 0); - - hitem = item; - lasthor = (menu->opt & O_NONCYCLIC) ? (ITEM *) 0 : hitem; + int y = 0; do { - _nc_Post_Item(menu, hitem); + ITEM *lasthor; + + wmove(menu->win, y, 0); - wattron(menu->win, menu->back); - if (((hitem = hitem->right) != lasthor) && hitem) + hitem = item; + lasthor = (menu->opt & O_NONCYCLIC) ? (ITEM *)0 : hitem; + + do { - int i, j, cy, cx; - chtype ch = ' '; + _nc_Post_Item(menu, hitem); - getyx(menu->win, cy, cx); - for (j = 0; j < menu->spc_rows; j++) + wattron(menu->win, (int)menu->back); + if (((hitem = hitem->right) != lasthor) && hitem) { - wmove(menu->win, cy + j, cx); - for (i = 0; i < menu->spc_cols; i++) + int i, j, cy, cx; + chtype ch = ' '; + + getyx(menu->win, cy, cx); + for (j = 0; j < menu->spc_rows; j++) { - waddch(menu->win, ch); + wmove(menu->win, cy + j, cx); + for (i = 0; i < menu->spc_cols; i++) + { + waddch(menu->win, ch); + } } + wmove(menu->win, cy, cx + menu->spc_cols); } - wmove(menu->win, cy, cx + menu->spc_cols); } - } - while (hitem && (hitem != lasthor)); - wattroff(menu->win, menu->back); + while (hitem && (hitem != lasthor)); + wattroff(menu->win, (int)menu->back); - item = item->down; - y += menu->spc_rows; + item = item->down; + y += menu->spc_rows; + } + while (item && (item != lastvert)); } - while (item && (item != lastvert)); } /*--------------------------------------------------------------------------- | Facility : libnmenu -| Function : int post_menu(MENU *) +| Function : int post_menu(MENU* menu) | | Description : Post a menu to the screen. This makes it visible. | @@ -268,10 +275,10 @@ _nc_Draw_Menu(const MENU * menu) | E_BAD_STATE - Menu in userexit routine | E_POSTED - Menu already posted +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -post_menu(MENU * menu) +MENU_EXPORT(int) +post_menu(MENU *menu) { - T((T_CALLED("post_menu(%p)"), menu)); + T((T_CALLED("post_menu(%p)"), (void *)menu)); if (!menu) RETURN(E_BAD_ARGUMENT); @@ -284,7 +291,6 @@ post_menu(MENU * menu) if (menu->items && *(menu->items)) { - int y; int h = 1 + menu->spc_rows * (menu->rows - 1); WINDOW *win = Get_Menu_Window(menu); @@ -292,7 +298,8 @@ post_menu(MENU * menu) if ((menu->win = newpad(h, menu->width))) { - y = (maxy >= h) ? h : maxy; + int y = (maxy >= h) ? h : maxy; + if (y >= menu->height) y = menu->height; if (!(menu->sub = subpad(menu->win, y, menu->width, 0, 0))) @@ -307,7 +314,7 @@ post_menu(MENU * menu) else RETURN(E_NOT_CONNECTED); - menu->status |= _POSTED; + SetStatus(menu, _POSTED); if (!(menu->opt & O_ONEVALUE)) { @@ -331,7 +338,7 @@ post_menu(MENU * menu) /*--------------------------------------------------------------------------- | Facility : libnmenu -| Function : int unpost_menu(MENU *) +| Function : int unpost_menu(MENU*) | | Description : Detach menu from screen | @@ -340,12 +347,12 @@ post_menu(MENU * menu) | E_BAD_STATE - menu in userexit routine | E_NOT_POSTED - menu is not posted +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -unpost_menu(MENU * menu) +MENU_EXPORT(int) +unpost_menu(MENU *menu) { WINDOW *win; - T((T_CALLED("unpost_menu(%p)"), menu)); + T((T_CALLED("unpost_menu(%p)"), (void *)menu)); if (!menu) RETURN(E_BAD_ARGUMENT); @@ -371,7 +378,7 @@ unpost_menu(MENU * menu) delwin(menu->win); menu->win = (WINDOW *)0; - menu->status &= ~_POSTED; + ClrStatus(menu, _POSTED); RETURN(E_OK); } diff --git a/lib/libmenu/m_req_name.c b/lib/libmenu/m_req_name.c index 14eda0f1fa4..697f5c09bd0 100644 --- a/lib/libmenu/m_req_name.c +++ b/lib/libmenu/m_req_name.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_req_name.c,v 1.6 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_req_name.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2008 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2012,2015 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,41 +40,43 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_req_name.c,v 1.6 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_req_name.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") -static const char *request_names[MAX_MENU_COMMAND - MIN_MENU_COMMAND + 1] = +#define DATA(s) { s } + +static const char request_names[MAX_MENU_COMMAND - MIN_MENU_COMMAND + 1][14] = { - "LEFT_ITEM", - "RIGHT_ITEM", - "UP_ITEM", - "DOWN_ITEM", - "SCR_ULINE", - "SCR_DLINE", - "SCR_DPAGE", - "SCR_UPAGE", - "FIRST_ITEM", - "LAST_ITEM", - "NEXT_ITEM", - "PREV_ITEM", - "TOGGLE_ITEM", - "CLEAR_PATTERN", - "BACK_PATTERN", - "NEXT_MATCH", - "PREV_MATCH" + DATA("LEFT_ITEM"), + DATA("RIGHT_ITEM"), + DATA("UP_ITEM"), + DATA("DOWN_ITEM"), + DATA("SCR_ULINE"), + DATA("SCR_DLINE"), + DATA("SCR_DPAGE"), + DATA("SCR_UPAGE"), + DATA("FIRST_ITEM"), + DATA("LAST_ITEM"), + DATA("NEXT_ITEM"), + DATA("PREV_ITEM"), + DATA("TOGGLE_ITEM"), + DATA("CLEAR_PATTERN"), + DATA("BACK_PATTERN"), + DATA("NEXT_MATCH"), + DATA("PREV_MATCH") }; #define A_SIZE (sizeof(request_names)/sizeof(request_names[0])) /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : const char * menu_request_name (int request); -| +| | Description : Get the external name of a menu request. | | Return Values : Pointer to name - on success | NULL - on invalid request code +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(const char *) +MENU_EXPORT(const char *) menu_request_name(int request) { T((T_CALLED("menu_request_name(%d)"), request)); @@ -87,37 +90,41 @@ menu_request_name(int request) } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int menu_request_by_name (const char *str); -| +| | Description : Search for a request with this name. | | Return Values : Request Id - on success | E_NO_MATCH - request not found +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) +MENU_EXPORT(int) menu_request_by_name(const char *str) { /* because the table is so small, it doesn't really hurt to run sequentially through it. */ - unsigned int i = 0; - char buf[16]; + size_t i = 0; T((T_CALLED("menu_request_by_name(%s)"), _nc_visbuf(str))); - if (str) + if (str != 0 && (i = strlen(str)) != 0) { - strncpy(buf, str, sizeof(buf)); - while ((i < sizeof(buf)) && (buf[i] != '\0')) + char buf[16]; + + if (i > sizeof(buf) - 2) + i = sizeof(buf) - 2; + memcpy(buf, str, i); + buf[i] = '\0'; + + for (i = 0; buf[i] != '\0'; ++i) { - buf[i] = toupper(UChar(buf[i])); - i++; + buf[i] = (char)toupper(UChar(buf[i])); } for (i = 0; i < A_SIZE; i++) { - if (strncmp(request_names[i], buf, sizeof(buf)) == 0) + if (strcmp(request_names[i], buf) == 0) returnCode(MIN_MENU_COMMAND + (int)i); } } diff --git a/lib/libmenu/m_scale.c b/lib/libmenu/m_scale.c index 002605cc94b..f3389e9c3c2 100644 --- a/lib/libmenu/m_scale.c +++ b/lib/libmenu/m_scale.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_scale.c,v 1.5 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_scale.c,v 1.6 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2004,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,23 +40,26 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_scale.c,v 1.5 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_scale.c,v 1.6 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int scale_menu(const MENU *menu) -| +| | Description : Returns the minimum window size necessary for the -| subwindow of menu. +| subwindow of menu. | | Return Values : E_OK - success | E_BAD_ARGUMENT - invalid menu pointer | E_NOT_CONNECTED - no items are connected to menu +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -scale_menu(const MENU * menu, int *rows, int *cols) +MENU_EXPORT(int) +scale_menu(const MENU *menu, int *rows, int *cols) { - T((T_CALLED("scale_menu(%p,%p,%p)"), menu, rows, cols)); + T((T_CALLED("scale_menu(%p,%p,%p)"), + (const void *)menu, + (void *)rows, + (void *)cols)); if (!menu) RETURN(E_BAD_ARGUMENT); diff --git a/lib/libmenu/m_spacing.c b/lib/libmenu/m_spacing.c index d1ba795ddbe..78c695fbddb 100644 --- a/lib/libmenu/m_spacing.c +++ b/lib/libmenu/m_spacing.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_spacing.c,v 1.6 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_spacing.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,7 +40,7 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_spacing.c,v 1.6 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_spacing.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") #define MAX_SPC_DESC ((TABSIZE) ? (TABSIZE) : 8) #define MAX_SPC_COLS ((TABSIZE) ? (TABSIZE) : 8) @@ -53,12 +54,13 @@ MODULE_ID("$Id: m_spacing.c,v 1.6 2010/01/12 23:22:08 nicm Exp $") | | Return Values : E_OK - on success +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -set_menu_spacing(MENU * menu, int s_desc, int s_row, int s_col) +MENU_EXPORT(int) +set_menu_spacing(MENU *menu, int s_desc, int s_row, int s_col) { MENU *m; /* split for ATAC workaround */ - T((T_CALLED("set_menu_spacing(%p,%d,%d,%d)"), menu, s_desc, s_row, s_col)); + T((T_CALLED("set_menu_spacing(%p,%d,%d,%d)"), + (void *)menu, s_desc, s_row, s_col)); m = Normalize_Menu(menu); @@ -71,9 +73,9 @@ set_menu_spacing(MENU * menu, int s_desc, int s_row, int s_col) ((s_col < 0) || (s_col > MAX_SPC_COLS))) RETURN(E_BAD_ARGUMENT); - m->spc_desc = s_desc ? s_desc : 1; - m->spc_rows = s_row ? s_row : 1; - m->spc_cols = s_col ? s_col : 1; + m->spc_desc = (short)(s_desc ? s_desc : 1); + m->spc_rows = (short)(s_row ? s_row : 1); + m->spc_cols = (short)(s_col ? s_col : 1); _nc_Calculate_Item_Length_and_Width(m); RETURN(E_OK); @@ -87,12 +89,16 @@ set_menu_spacing(MENU * menu, int s_desc, int s_row, int s_col) | | Return Values : E_OK - on success +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -menu_spacing(const MENU * menu, int *s_desc, int *s_row, int *s_col) +MENU_EXPORT(int) +menu_spacing(const MENU *menu, int *s_desc, int *s_row, int *s_col) { const MENU *m; /* split for ATAC workaround */ - T((T_CALLED("menu_spacing(%p,%p,%p,%p)"), menu, s_desc, s_row, s_col)); + T((T_CALLED("menu_spacing(%p,%p,%p,%p)"), + (const void *)menu, + (void *)s_desc, + (void *)s_row, + (void *)s_col)); m = Normalize_Menu(menu); diff --git a/lib/libmenu/m_sub.c b/lib/libmenu/m_sub.c index 7204ba47e4b..a9f2091c739 100644 --- a/lib/libmenu/m_sub.c +++ b/lib/libmenu/m_sub.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_sub.c,v 1.5 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_sub.c,v 1.6 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,28 +40,42 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_sub.c,v 1.5 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_sub.c,v 1.6 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int set_menu_sub(MENU *menu, WINDOW *win) -| +| | Description : Sets the subwindow of the menu. | | Return Values : E_OK - success | E_POSTED - menu is already posted +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -set_menu_sub(MENU * menu, WINDOW *win) +MENU_EXPORT(int) +set_menu_sub(MENU *menu, WINDOW *win) { - T((T_CALLED("set_menu_sub(%p,%p)"), menu, win)); + T((T_CALLED("set_menu_sub(%p,%p)"), (void *)menu, (void *)win)); if (menu) { if (menu->status & _POSTED) RETURN(E_POSTED); - menu->usersub = win; - _nc_Calculate_Item_Length_and_Width(menu); + else +#if NCURSES_SP_FUNCS + { + /* We ensure that usersub is never null. So even if a null + WINDOW parameter is passed, we store the SCREENS stdscr. + The only MENU that can have a null usersub is the static + _nc_default_Menu. + */ + SCREEN *sp = _nc_screen_of(menu->usersub); + + menu->usersub = win ? win : sp->_stdscr; + _nc_Calculate_Item_Length_and_Width(menu); + } +#else + menu->usersub = win; +#endif } else _nc_Default_Menu.usersub = win; @@ -69,19 +84,19 @@ set_menu_sub(MENU * menu, WINDOW *win) } /*--------------------------------------------------------------------------- -| Facility : libnmenu -| Function : WINDOW *menu_sub(const MENU *menu) -| +| Facility : libnmenu +| Function : WINDOW* menu_sub(const MENU *menu) +| | Description : Returns a pointer to the subwindow of the menu | | Return Values : NULL on error, otherwise a pointer to the window +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(WINDOW *) -menu_sub(const MENU * menu) +MENU_EXPORT(WINDOW *) +menu_sub(const MENU *menu) { const MENU *m = Normalize_Menu(menu); - T((T_CALLED("menu_sub(%p)"), menu)); + T((T_CALLED("menu_sub(%p)"), (const void *)menu)); returnWin(Get_Menu_Window(m)); } diff --git a/lib/libmenu/m_userptr.c b/lib/libmenu/m_userptr.c index a97a5d857a1..7e347a1055a 100644 --- a/lib/libmenu/m_userptr.c +++ b/lib/libmenu/m_userptr.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_userptr.c,v 1.7 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_userptr.c,v 1.8 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2004,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,39 +40,39 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_userptr.c,v 1.7 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_userptr.c,v 1.8 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int set_menu_userptr(MENU *menu, void *userptr) -| +| | Description : Set the pointer that is reserved in any menu to store -| application relevant informations. +| application relevant information. | | Return Values : E_OK - success +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -set_menu_userptr(MENU * menu, void *userptr) +MENU_EXPORT(int) +set_menu_userptr(MENU *menu, void *userptr) { - T((T_CALLED("set_menu_userptr(%p,%p)"), menu, userptr)); + T((T_CALLED("set_menu_userptr(%p,%p)"), (void *)menu, (void *)userptr)); Normalize_Menu(menu)->userptr = userptr; RETURN(E_OK); } /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : void *menu_userptr(const MENU *menu) -| +| | Description : Return the pointer that is reserved in any menu to -| store application relevant informations. +| store application relevant information. | | Return Values : Value of the pointer. If no such pointer has been set, | NULL is returned +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(void *) -menu_userptr(const MENU * menu) +MENU_EXPORT(void *) +menu_userptr(const MENU *menu) { - T((T_CALLED("menu_userptr(%p)"), menu)); + T((T_CALLED("menu_userptr(%p)"), (const void *)menu)); returnVoidPtr(Normalize_Menu(menu)->userptr); } diff --git a/lib/libmenu/m_win.c b/lib/libmenu/m_win.c index 369a922214f..186aed4fe44 100644 --- a/lib/libmenu/m_win.c +++ b/lib/libmenu/m_win.c @@ -1,7 +1,8 @@ -/* $OpenBSD: m_win.c,v 1.7 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: m_win.c,v 1.8 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -39,28 +40,42 @@ #include "menu.priv.h" -MODULE_ID("$Id: m_win.c,v 1.7 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: m_win.c,v 1.8 2023/10/17 09:52:10 nicm Exp $") /*--------------------------------------------------------------------------- -| Facility : libnmenu +| Facility : libnmenu | Function : int set_menu_win(MENU *menu, WINDOW *win) -| +| | Description : Sets the window of the menu. | | Return Values : E_OK - success | E_POSTED - menu is already posted +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(int) -set_menu_win(MENU * menu, WINDOW *win) +MENU_EXPORT(int) +set_menu_win(MENU *menu, WINDOW *win) { - T((T_CALLED("set_menu_win(%p,%p)"), menu, win)); + T((T_CALLED("set_menu_win(%p,%p)"), (void *)menu, (void *)win)); if (menu) { if (menu->status & _POSTED) RETURN(E_POSTED); - menu->userwin = win; - _nc_Calculate_Item_Length_and_Width(menu); + else +#if NCURSES_SP_FUNCS + { + /* We ensure that userwin is never null. So even if a null + WINDOW parameter is passed, we store the SCREENS stdscr. + The only MENU that can have a null userwin is the static + _nc_default_Menu. + */ + SCREEN *sp = _nc_screen_of(menu->userwin); + + menu->userwin = win ? win : sp->_stdscr; + _nc_Calculate_Item_Length_and_Width(menu); + } +#else + menu->userwin = win; +#endif } else _nc_Default_Menu.userwin = win; @@ -69,20 +84,20 @@ set_menu_win(MENU * menu, WINDOW *win) } /*--------------------------------------------------------------------------- -| Facility : libnmenu -| Function : WINDOW *menu_win(const MENU *) -| +| Facility : libnmenu +| Function : WINDOW* menu_win(const MENU*) +| | Description : Returns pointer to the window of the menu | | Return Values : NULL on error, otherwise pointer to window +--------------------------------------------------------------------------*/ -NCURSES_EXPORT(WINDOW *) -menu_win(const MENU * menu) +MENU_EXPORT(WINDOW *) +menu_win(const MENU *menu) { const MENU *m = Normalize_Menu(menu); - T((T_CALLED("menu_win(%p)"), menu)); - returnWin(m->userwin ? m->userwin : stdscr); + T((T_CALLED("menu_win(%p)"), (const void *)menu)); + returnWin(Get_Menu_UserWin(m)); } /* m_win.c ends here */ diff --git a/lib/libmenu/menu.3 b/lib/libmenu/menu.3 index 66a26373d40..3390a3670e3 100644 --- a/lib/libmenu/menu.3 +++ b/lib/libmenu/menu.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: menu.3,v 1.4 2019/02/13 07:18:58 nicm Exp $ +.\" $OpenBSD: menu.3,v 1.5 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2002,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2021,2023 Thomas E. Dickey * +.\" Copyright 1998-2014,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,108 +30,120 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: menu.3,v 1.4 2019/02/13 07:18:58 nicm Exp $ -.TH menu 3 "" +.\" $Id: menu.3,v 1.5 2023/10/17 09:52:10 nicm Exp $ +.TH menu 3 2023-08-19 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .SH NAME -\fBmenu\fR - curses extension for programming menus +\fBmenu\fP \- curses extension for programming menus .SH SYNOPSIS -\fB#include \fR -.br +\fB#include \fP .SH DESCRIPTION -The \fBmenu\fR library provides terminal-independent facilities for composing -menu systems on character-cell terminals. The library includes: item routines, +The \fBmenu\fP library provides terminal-independent facilities for composing +menu systems on character-cell terminals. +The library includes: item routines, which create and modify menu items; and menu routines, which group items into menus, display menus on the screen, and handle interaction with the user. .PP -The \fBmenu\fR library uses the \fBcurses\fR libraries, and a curses -initialization routine such as \fBinitscr\fR must be called before using any of -these functions. To use the \fBmenu\fR library, link with the options -\fB-lmenu -lcurses\fR. +The \fBmenu\fP library uses the \fBcurses\fP libraries, and a curses +initialization routine such as \fBinitscr\fP must be called before using any of +these functions. +To use the \fBmenu\fP library, link with the options +\fB\-lmenu \-lcurses\fP. . .SS Current Default Values for Item Attributes . -The \fBmenu\fR library maintains a default value for item attributes. You can -get or set this default by calling the appropriate \fBget_\fR or \fBset_\fR -routine with a \fBNULL\fR item pointer. Changing this default with a -\fBset_\fR function affects future item creations, but does not change the +The \fBmenu\fP library maintains a default value for item attributes. +You can +get or set this default by calling the appropriate \fBget_\fP or \fBset_\fP +routine with a \fBNULL\fP item pointer. +Changing this default with a +\fBset_\fP function affects future item creations, but does not change the rendering of items already created. . .SS Routine Name Index . -The following table lists each \fBmenu\fR routine and the name of +The following table lists each \fBmenu\fP routine and the name of the manual page on which it is described. -. +.PP .TS l l . -\fBcurses\fR Routine Name Manual Page Name +\fBcurses\fP Routine Name Manual Page Name = -current_item \fBmitem_current\fR(3) -free_item \fBmitem_new\fR(3) -free_menu \fBmenu_new\fR(3) -item_count \fBmenu_items\fR(3) -item_description \fBmitem_name\fR(3) -item_index \fBmitem_current\fR(3) -item_init \fBmenu_hook\fR(3) -item_name \fBmitem_name\fR(3) -item_opts \fBmitem_opts\fR(3) -item_opts_off \fBmitem_opts\fR(3) -item_opts_on \fBmitem_opts\fR(3) -item_term \fBmenu_hook\fR(3) -item_userptr \fBmitem_userptr\fR(3) -item_value \fBmitem_value\fR(3) -item_visible \fBmitem_visible\fR(3) -menu_back \fBmenu_attributes\fR(3) -menu_driver \fBmenu_driver\fR(3) -menu_fore \fBmenu_attributes\fR(3) -menu_format \fBmenu_format\fR(3) -menu_grey \fBmenu_attributes\fR(3) -menu_init \fBmenu_hook\fR(3) -menu_items \fBmenu_items\fR(3) -menu_mark \fBmenu_mark\fR(3) -menu_opts \fBmenu_opts\fR(3) -menu_opts_off \fBmenu_opts\fR(3) -menu_opts_on \fBmenu_opts\fR(3) -menu_pad \fBmenu_attributes\fR(3) -menu_pattern \fBmenu_pattern\fR(3) -menu_request_by_name \fBmenu_requestname\fR(3) -menu_request_name \fBmenu_requestname\fR(3) -menu_spacing \fBmenu_spacing\fR(3) -menu_sub \fBmenu_win\fR(3) -menu_term \fBmenu_hook\fR(3) -menu_userptr \fBmenu_userptr\fR(3) -menu_win \fBmenu_win\fR(3) -new_item \fBmitem_new\fR(3) -new_menu \fBmenu_new\fR(3) -pos_menu_cursor \fBmenu_cursor\fR(3) -post_menu \fBmenu_post\fR(3) -scale_menu \fBmenu_win\fR(3) -set_current_item \fBmitem_current\fR(3) -set_item_init \fBmenu_hook\fR(3) -set_item_opts \fBmitem_opts\fR(3) -set_item_term \fBmenu_hook\fR(3) -set_item_userptr \fBmitem_userptr\fR(3) -set_item_value \fBmitem_value\fR(3) -set_menu_back \fBmenu_attributes\fR(3) -set_menu_fore \fBmenu_attributes\fR(3) -set_menu_format \fBmenu_format\fR(3) -set_menu_grey \fBmenu_attributes\fR(3) -set_menu_init \fBmenu_hook\fR(3) -set_menu_items \fBmenu_items\fR(3) -set_menu_mark \fBmenu_mark\fR(3) -set_menu_opts \fBmitem_opts\fR(3) -set_menu_pad \fBmenu_attributes\fR(3) -set_menu_pattern \fBmenu_pattern\fR(3) -set_menu_spacing \fBmenu_spacing\fR(3) -set_menu_sub \fBmenu_win\fR(3) -set_menu_term \fBmenu_hook\fR(3) -set_menu_userptr \fBmenu_userptr\fR(3) -set_menu_win \fBmenu_win\fR(3) -set_top_row \fBmitem_current\fR(3) -top_row \fBmitem_current\fR(3) -unpost_menu \fBmenu_post\fR(3) +current_item \fBmitem_current\fP(3) +free_item \fBmitem_new\fP(3) +free_menu \fBmenu_new\fP(3) +item_count \fBmenu_items\fP(3) +item_description \fBmitem_name\fP(3) +item_index \fBmitem_current\fP(3) +item_init \fBmenu_hook\fP(3) +item_name \fBmitem_name\fP(3) +item_opts \fBmitem_opts\fP(3) +item_opts_off \fBmitem_opts\fP(3) +item_opts_on \fBmitem_opts\fP(3) +item_term \fBmenu_hook\fP(3) +item_userptr \fBmitem_userptr\fP(3) +item_value \fBmitem_value\fP(3) +item_visible \fBmitem_visible\fP(3) +menu_back \fBmenu_attributes\fP(3) +menu_driver \fBmenu_driver\fP(3) +menu_fore \fBmenu_attributes\fP(3) +menu_format \fBmenu_format\fP(3) +menu_grey \fBmenu_attributes\fP(3) +menu_init \fBmenu_hook\fP(3) +menu_items \fBmenu_items\fP(3) +menu_mark \fBmenu_mark\fP(3) +menu_opts \fBmenu_opts\fP(3) +menu_opts_off \fBmenu_opts\fP(3) +menu_opts_on \fBmenu_opts\fP(3) +menu_pad \fBmenu_attributes\fP(3) +menu_pattern \fBmenu_pattern\fP(3) +menu_request_by_name \fBmenu_requestname\fP(3) +menu_request_name \fBmenu_requestname\fP(3) +menu_spacing \fBmenu_spacing\fP(3) +menu_sub \fBmenu_win\fP(3) +menu_term \fBmenu_hook\fP(3) +menu_userptr \fBmenu_userptr\fP(3) +menu_win \fBmenu_win\fP(3) +new_item \fBmitem_new\fP(3) +new_menu \fBmenu_new\fP(3) +pos_menu_cursor \fBmenu_cursor\fP(3) +post_menu \fBmenu_post\fP(3) +scale_menu \fBmenu_win\fP(3) +set_current_item \fBmitem_current\fP(3) +set_item_init \fBmenu_hook\fP(3) +set_item_opts \fBmitem_opts\fP(3) +set_item_term \fBmenu_hook\fP(3) +set_item_userptr \fBmitem_userptr\fP(3) +set_item_value \fBmitem_value\fP(3) +set_menu_back \fBmenu_attributes\fP(3) +set_menu_fore \fBmenu_attributes\fP(3) +set_menu_format \fBmenu_format\fP(3) +set_menu_grey \fBmenu_attributes\fP(3) +set_menu_init \fBmenu_hook\fP(3) +set_menu_items \fBmenu_items\fP(3) +set_menu_mark \fBmenu_mark\fP(3) +set_menu_opts \fBmitem_opts\fP(3) +set_menu_pad \fBmenu_attributes\fP(3) +set_menu_pattern \fBmenu_pattern\fP(3) +set_menu_spacing \fBmenu_spacing\fP(3) +set_menu_sub \fBmenu_win\fP(3) +set_menu_term \fBmenu_hook\fP(3) +set_menu_userptr \fBmenu_userptr\fP(3) +set_menu_win \fBmenu_win\fP(3) +set_top_row \fBmitem_current\fP(3) +top_row \fBmitem_current\fP(3) +unpost_menu \fBmenu_post\fP(3) .TE .SH RETURN VALUE -Routines that return pointers return \fBNULL\fR on error. Routines that return +Routines that return pointers return \fBNULL\fP on error. +Routines that return an integer return one of the following error codes: .TP 5 .B E_OK @@ -164,32 +177,38 @@ The menu is already posted. The menu driver could not process the request. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .TP 5 .B E_UNKNOWN_COMMAND The menu driver code saw an unknown request code. -.SH SEE ALSO -\fBcurses\fR(3) and related pages whose names begin "menu_" for detailed -descriptions of the entry points. .SH NOTES -The header file \fB\fR automatically includes the header files -\fB\fR and \fB\fR. +The header file \fB\fP automatically includes the header files +\fB\fP and \fB\fP. .PP In your library list, libmenu.a should be before libncurses.a; that is, -you want to say `-lmenu -lncurses', not the other way around (which would -usually give a link-error). +you should say \*(``\-lmenu \-lncurses\*('', not the other way around +(which would give a link-error when using static libraries). .SH PORTABILITY -These routines emulate the System V menu library. They were not supported on +These routines emulate the System V menu library. +They were not supported on Version 7 or BSD versions. +.PP +The menu facility was documented in SVr4.2 in +\fICharacter User Interface Programming (UNIX SVR4.2)\fP. +.PP +It is not part of X/Open Curses. +.PP +Aside from ncurses, there are few implementations: +.bP +systems based on SVr4 source code, e.g., Solaris. +.bP +NetBSD curses. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for ncurses by Eric -S. Raymond. +Juergen Pfeifer. +Manual pages and adaptation for ncurses by Eric S. Raymond. .SH SEE ALSO -This describes \fBncurses\fR -version 5.7. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +\fBcurses\fP(3) and related pages whose names begin \*(``menu_\*('' +for detailed descriptions of the entry points. +.PP +This describes \fBncurses\fP +version 6.4 (patch 20230826). diff --git a/lib/libmenu/menu.h b/lib/libmenu/menu.h index 6a19a547cdc..1aa9f0a8d70 100644 --- a/lib/libmenu/menu.h +++ b/lib/libmenu/menu.h @@ -1,6 +1,7 @@ -/* $OpenBSD: menu.h,v 1.9 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: menu.h,v 1.10 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2007 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,7 +32,7 @@ * Author: Juergen Pfeifer, 1995,1997 * ****************************************************************************/ -/* $Id: menu.h,v 1.9 2015/01/23 22:48:51 krw Exp $ */ +/* $Id: menu.h,v 1.10 2023/10/17 09:52:10 nicm Exp $ */ #ifndef ETI_MENU #define ETI_MENU @@ -44,11 +45,23 @@ #include #ifdef __cplusplus -extern "C" { +extern "C" +{ +#endif + +#if defined(BUILDING_MENU) +# define MENU_IMPEXP NCURSES_EXPORT_GENERAL_EXPORT +#else +# define MENU_IMPEXP NCURSES_EXPORT_GENERAL_IMPORT #endif -typedef int Menu_Options; -typedef int Item_Options; +#define MENU_WRAPPED_VAR(type,name) extern MENU_IMPEXP type NCURSES_PUBLIC_VAR(name)(void) + +#define MENU_EXPORT(type) MENU_IMPEXP type NCURSES_API +#define MENU_EXPORT_VAR(type) MENU_IMPEXP type + + typedef int Menu_Options; + typedef int Item_Options; /* Menu options: */ #define O_ONEVALUE (0x01) @@ -57,81 +70,91 @@ typedef int Item_Options; #define O_IGNORECASE (0x08) #define O_SHOWMATCH (0x10) #define O_NONCYCLIC (0x20) +#define O_MOUSE_MENU (0x40) /* Item options: */ #define O_SELECTABLE (0x01) -typedef struct -{ - const char* str; - unsigned short length; -} TEXT; - -typedef struct tagITEM -{ - TEXT name; /* name of menu item */ - TEXT description; /* description of item, optional in display */ - struct tagMENU *imenu; /* Pointer to parent menu */ - void *userptr; /* Pointer to user defined per item data */ - Item_Options opt; /* Item options */ - short index; /* Item number if connected to a menu */ - short y; /* y and x location of item in menu */ - short x; - bool value; /* Selection value */ - - struct tagITEM *left; /* neighbor items */ - struct tagITEM *right; - struct tagITEM *up; - struct tagITEM *down; - -} ITEM; - -typedef void (*Menu_Hook)(struct tagMENU *); - -typedef struct tagMENU -{ - short height; /* Nr. of chars high */ - short width; /* Nr. of chars wide */ - short rows; /* Nr. of items high */ - short cols; /* Nr. of items wide */ - short frows; /* Nr. of formatted items high */ - short fcols; /* Nr. of formatted items wide */ - short arows; /* Nr. of items high (actual) */ - short namelen; /* Max. name length */ - short desclen; /* Max. description length */ - short marklen; /* Length of mark, if any */ - short itemlen; /* Length of one item */ - short spc_desc; /* Spacing for descriptor */ - short spc_cols; /* Spacing for columns */ - short spc_rows; /* Spacing for rows */ - char *pattern; /* Buffer to store match chars */ - short pindex; /* Index into pattern buffer */ - WINDOW *win; /* Window containing menu */ - WINDOW *sub; /* Subwindow for menu display */ - WINDOW *userwin; /* User's window */ - WINDOW *usersub; /* User's subwindow */ - ITEM **items; /* array of items */ - short nitems; /* Nr. of items in menu */ - ITEM *curitem; /* Current item */ - short toprow; /* Top row of menu */ - chtype fore; /* Selection attribute */ - chtype back; /* Nonselection attribute */ - chtype grey; /* Inactive attribute */ - unsigned char pad; /* Pad character */ - - Menu_Hook menuinit; /* User hooks */ - Menu_Hook menuterm; - Menu_Hook iteminit; - Menu_Hook itemterm; - - void *userptr; /* Pointer to menus user data */ - char *mark; /* Pointer to marker string */ - - Menu_Options opt; /* Menu options */ - unsigned short status; /* Internal state of menu */ - -} MENU; - +#if !NCURSES_OPAQUE_MENU + typedef struct + { + const char *str; + unsigned short length; + } + TEXT; +#endif /* !NCURSES_OPAQUE_MENU */ + + struct tagMENU; + + typedef struct tagITEM +#if !NCURSES_OPAQUE_MENU + { + TEXT name; /* name of menu item */ + TEXT description; /* description of item, optional in display */ + struct tagMENU *imenu; /* Pointer to parent menu */ + void *userptr; /* Pointer to user defined per item data */ + Item_Options opt; /* Item options */ + short index; /* Item number if connected to a menu */ + short y; /* y and x location of item in menu */ + short x; + bool value; /* Selection value */ + + struct tagITEM *left; /* neighbor items */ + struct tagITEM *right; + struct tagITEM *up; + struct tagITEM *down; + + } +#endif /* !NCURSES_OPAQUE_MENU */ + ITEM; + + typedef void (*Menu_Hook) (struct tagMENU *); + + typedef struct tagMENU +#if 1 /* not yet: !NCURSES_OPAQUE_MENU */ + { + short height; /* Nr. of chars high */ + short width; /* Nr. of chars wide */ + short rows; /* Nr. of items high */ + short cols; /* Nr. of items wide */ + short frows; /* Nr. of formatted items high */ + short fcols; /* Nr. of formatted items wide */ + short arows; /* Nr. of items high (actual) */ + short namelen; /* Max. name length */ + short desclen; /* Max. description length */ + short marklen; /* Length of mark, if any */ + short itemlen; /* Length of one item */ + short spc_desc; /* Spacing for descriptor */ + short spc_cols; /* Spacing for columns */ + short spc_rows; /* Spacing for rows */ + char *pattern; /* Buffer to store match chars */ + short pindex; /* Index into pattern buffer */ + WINDOW *win; /* Window containing menu */ + WINDOW *sub; /* Subwindow for menu display */ + WINDOW *userwin; /* User's window */ + WINDOW *usersub; /* User's subwindow */ + ITEM **items; /* array of items */ + short nitems; /* Nr. of items in menu */ + ITEM *curitem; /* Current item */ + short toprow; /* Top row of menu */ + chtype fore; /* Selection attribute */ + chtype back; /* Nonselection attribute */ + chtype grey; /* Inactive attribute */ + unsigned char pad; /* Pad character */ + + Menu_Hook menuinit; /* User hooks */ + Menu_Hook menuterm; + Menu_Hook iteminit; + Menu_Hook itemterm; + + void *userptr; /* Pointer to menus user data */ + char *mark; /* Pointer to marker string */ + + Menu_Options opt; /* Menu options */ + unsigned short status; /* Internal state of menu */ + } +#endif /* !NCURSES_OPAQUE_MENU */ + MENU; /* Define keys */ @@ -170,88 +193,90 @@ typedef struct tagMENU # define MAX_COMMAND (KEY_MAX + 128) #endif - /* --------- prototypes for libmenu functions ----------------------------- */ -extern NCURSES_EXPORT(ITEM **) menu_items (const MENU *); -extern NCURSES_EXPORT(ITEM *) current_item (const MENU *); -extern NCURSES_EXPORT(ITEM *) new_item (const char *,const char *); - -extern NCURSES_EXPORT(MENU *) new_menu (ITEM **); - -extern NCURSES_EXPORT(Item_Options) item_opts (const ITEM *); -extern NCURSES_EXPORT(Menu_Options) menu_opts (const MENU *); - -extern NCURSES_EXPORT(Menu_Hook) item_init (const MENU *); -extern NCURSES_EXPORT(Menu_Hook) item_term (const MENU *); -extern NCURSES_EXPORT(Menu_Hook) menu_init (const MENU *); -extern NCURSES_EXPORT(Menu_Hook) menu_term (const MENU *); - -extern NCURSES_EXPORT(WINDOW *) menu_sub (const MENU *); -extern NCURSES_EXPORT(WINDOW *) menu_win (const MENU *); - -extern NCURSES_EXPORT(const char *) item_description (const ITEM *); -extern NCURSES_EXPORT(const char *) item_name (const ITEM *); -extern NCURSES_EXPORT(const char *) menu_mark (const MENU *); -extern NCURSES_EXPORT(const char *) menu_request_name (int); - -extern NCURSES_EXPORT(char *) menu_pattern (const MENU *); - -extern NCURSES_EXPORT(void *) menu_userptr (const MENU *); -extern NCURSES_EXPORT(void *) item_userptr (const ITEM *); - -extern NCURSES_EXPORT(chtype) menu_back (const MENU *); -extern NCURSES_EXPORT(chtype) menu_fore (const MENU *); -extern NCURSES_EXPORT(chtype) menu_grey (const MENU *); - -extern NCURSES_EXPORT(int) free_item (ITEM *); -extern NCURSES_EXPORT(int) free_menu (MENU *); -extern NCURSES_EXPORT(int) item_count (const MENU *); -extern NCURSES_EXPORT(int) item_index (const ITEM *); -extern NCURSES_EXPORT(int) item_opts_off (ITEM *,Item_Options); -extern NCURSES_EXPORT(int) item_opts_on (ITEM *,Item_Options); -extern NCURSES_EXPORT(int) menu_driver (MENU *,int); -extern NCURSES_EXPORT(int) menu_opts_off (MENU *,Menu_Options); -extern NCURSES_EXPORT(int) menu_opts_on (MENU *,Menu_Options); -extern NCURSES_EXPORT(int) menu_pad (const MENU *); -extern NCURSES_EXPORT(int) pos_menu_cursor (const MENU *); -extern NCURSES_EXPORT(int) post_menu (MENU *); -extern NCURSES_EXPORT(int) scale_menu (const MENU *,int *,int *); -extern NCURSES_EXPORT(int) set_current_item (MENU *menu,ITEM *item); -extern NCURSES_EXPORT(int) set_item_init (MENU *, Menu_Hook); -extern NCURSES_EXPORT(int) set_item_opts (ITEM *,Item_Options); -extern NCURSES_EXPORT(int) set_item_term (MENU *, Menu_Hook); -extern NCURSES_EXPORT(int) set_item_userptr (ITEM *, void *); -extern NCURSES_EXPORT(int) set_item_value (ITEM *,bool); -extern NCURSES_EXPORT(int) set_menu_back (MENU *,chtype); -extern NCURSES_EXPORT(int) set_menu_fore (MENU *,chtype); -extern NCURSES_EXPORT(int) set_menu_format (MENU *,int,int); -extern NCURSES_EXPORT(int) set_menu_grey (MENU *,chtype); -extern NCURSES_EXPORT(int) set_menu_init (MENU *, Menu_Hook); -extern NCURSES_EXPORT(int) set_menu_items (MENU *,ITEM **); -extern NCURSES_EXPORT(int) set_menu_mark (MENU *, const char *); -extern NCURSES_EXPORT(int) set_menu_opts (MENU *,Menu_Options); -extern NCURSES_EXPORT(int) set_menu_pad (MENU *,int); -extern NCURSES_EXPORT(int) set_menu_pattern (MENU *,const char *); -extern NCURSES_EXPORT(int) set_menu_sub (MENU *,WINDOW *); -extern NCURSES_EXPORT(int) set_menu_term (MENU *, Menu_Hook); -extern NCURSES_EXPORT(int) set_menu_userptr (MENU *,void *); -extern NCURSES_EXPORT(int) set_menu_win (MENU *,WINDOW *); -extern NCURSES_EXPORT(int) set_top_row (MENU *,int); -extern NCURSES_EXPORT(int) top_row (const MENU *); -extern NCURSES_EXPORT(int) unpost_menu (MENU *); -extern NCURSES_EXPORT(int) menu_request_by_name (const char *); -extern NCURSES_EXPORT(int) set_menu_spacing (MENU *,int,int,int); -extern NCURSES_EXPORT(int) menu_spacing (const MENU *,int *,int *,int *); - - -extern NCURSES_EXPORT(bool) item_value (const ITEM *); -extern NCURSES_EXPORT(bool) item_visible (const ITEM *); - -extern NCURSES_EXPORT(void) menu_format (const MENU *,int *,int *); + extern MENU_EXPORT(ITEM **) menu_items(const MENU *); + extern MENU_EXPORT(ITEM *) current_item(const MENU *); + extern MENU_EXPORT(ITEM *) new_item(const char *, const char *); + + extern MENU_EXPORT(MENU *) new_menu(ITEM **); + + extern MENU_EXPORT(Item_Options) item_opts(const ITEM *); + extern MENU_EXPORT(Menu_Options) menu_opts(const MENU *); + + extern MENU_EXPORT(Menu_Hook) item_init(const MENU *); + extern MENU_EXPORT(Menu_Hook) item_term(const MENU *); + extern MENU_EXPORT(Menu_Hook) menu_init(const MENU *); + extern MENU_EXPORT(Menu_Hook) menu_term(const MENU *); + + extern MENU_EXPORT(WINDOW *) menu_sub(const MENU *); + extern MENU_EXPORT(WINDOW *) menu_win(const MENU *); + + extern MENU_EXPORT(const char *) item_description(const ITEM *); + extern MENU_EXPORT(const char *) item_name(const ITEM *); + extern MENU_EXPORT(const char *) menu_mark(const MENU *); + extern MENU_EXPORT(const char *) menu_request_name(int); + + extern MENU_EXPORT(char *) menu_pattern(const MENU *); + + extern MENU_EXPORT(void *) menu_userptr(const MENU *); + extern MENU_EXPORT(void *) item_userptr(const ITEM *); + + extern MENU_EXPORT(chtype) menu_back(const MENU *); + extern MENU_EXPORT(chtype) menu_fore(const MENU *); + extern MENU_EXPORT(chtype) menu_grey(const MENU *); + + extern MENU_EXPORT(int) free_item(ITEM *); + extern MENU_EXPORT(int) free_menu(MENU *); + extern MENU_EXPORT(int) item_count(const MENU *); + extern MENU_EXPORT(int) item_index(const ITEM *); + extern MENU_EXPORT(int) item_opts_off(ITEM *, Item_Options); + extern MENU_EXPORT(int) item_opts_on(ITEM *, Item_Options); + extern MENU_EXPORT(int) menu_driver(MENU *, int); + extern MENU_EXPORT(int) menu_opts_off(MENU *, Menu_Options); + extern MENU_EXPORT(int) menu_opts_on(MENU *, Menu_Options); + extern MENU_EXPORT(int) menu_pad(const MENU *); + extern MENU_EXPORT(int) pos_menu_cursor(const MENU *); + extern MENU_EXPORT(int) post_menu(MENU *); + extern MENU_EXPORT(int) scale_menu(const MENU *, int *, int *); + extern MENU_EXPORT(int) set_current_item(MENU *menu, ITEM *item); + extern MENU_EXPORT(int) set_item_init(MENU *, Menu_Hook); + extern MENU_EXPORT(int) set_item_opts(ITEM *, Item_Options); + extern MENU_EXPORT(int) set_item_term(MENU *, Menu_Hook); + extern MENU_EXPORT(int) set_item_userptr(ITEM *, void *); + extern MENU_EXPORT(int) set_item_value(ITEM *, bool); + extern MENU_EXPORT(int) set_menu_back(MENU *, chtype); + extern MENU_EXPORT(int) set_menu_fore(MENU *, chtype); + extern MENU_EXPORT(int) set_menu_format(MENU *, int, int); + extern MENU_EXPORT(int) set_menu_grey(MENU *, chtype); + extern MENU_EXPORT(int) set_menu_init(MENU *, Menu_Hook); + extern MENU_EXPORT(int) set_menu_items(MENU *, ITEM **); + extern MENU_EXPORT(int) set_menu_mark(MENU *, const char *); + extern MENU_EXPORT(int) set_menu_opts(MENU *, Menu_Options); + extern MENU_EXPORT(int) set_menu_pad(MENU *, int); + extern MENU_EXPORT(int) set_menu_pattern(MENU *, const char *); + extern MENU_EXPORT(int) set_menu_sub(MENU *, WINDOW *); + extern MENU_EXPORT(int) set_menu_term(MENU *, Menu_Hook); + extern MENU_EXPORT(int) set_menu_userptr(MENU *, void *); + extern MENU_EXPORT(int) set_menu_win(MENU *, WINDOW *); + extern MENU_EXPORT(int) set_top_row(MENU *, int); + extern MENU_EXPORT(int) top_row(const MENU *); + extern MENU_EXPORT(int) unpost_menu(MENU *); + extern MENU_EXPORT(int) menu_request_by_name(const char *); + extern MENU_EXPORT(int) set_menu_spacing(MENU *, int, int, int); + extern MENU_EXPORT(int) menu_spacing(const MENU *, int *, int *, int *); + + extern MENU_EXPORT(bool) item_value(const ITEM *); + extern MENU_EXPORT(bool) item_visible(const ITEM *); + + extern MENU_EXPORT(void) menu_format(const MENU *, int *, int *); + +#if NCURSES_SP_FUNCS + extern MENU_EXPORT(MENU *) NCURSES_SP_NAME(new_menu) (SCREEN *, ITEM **); +#endif #ifdef __cplusplus - } +} #endif -#endif /* ETI_MENU */ +#endif /* ETI_MENU */ diff --git a/lib/libmenu/menu.priv.h b/lib/libmenu/menu.priv.h index 913e0d1c795..e8d2fca3824 100644 --- a/lib/libmenu/menu.priv.h +++ b/lib/libmenu/menu.priv.h @@ -1,7 +1,8 @@ -/* $OpenBSD: menu.priv.h,v 1.8 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: menu.priv.h,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2004,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,7 +33,7 @@ * Author: Juergen Pfeifer, 1995,1997 * ****************************************************************************/ -/* $Id: menu.priv.h,v 1.8 2010/01/12 23:22:08 nicm Exp $ */ +/* $Id: menu.priv.h,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ /*************************************************************************** * Module menu.priv.h * @@ -41,16 +42,20 @@ #ifndef MENU_PRIV_H_incl #define MENU_PRIV_H_incl 1 +/* *INDENT-OFF* */ #include "curses.priv.h" + +#define NCURSES_OPAQUE_MENU 0 + #include "mf_common.h" #include "menu.h" /* Backspace code */ #define BS (8) -extern NCURSES_EXPORT_VAR(ITEM) _nc_Default_Item; -extern NCURSES_EXPORT_VAR(MENU) _nc_Default_Menu; +extern MENU_EXPORT_VAR(ITEM) _nc_Default_Item; +extern MENU_EXPORT_VAR(MENU) _nc_Default_Menu; /* Normalize item to default if none was given */ #define Normalize_Item( item ) ((item)=(item)?(item):&_nc_Default_Item) @@ -58,8 +63,12 @@ extern NCURSES_EXPORT_VAR(MENU) _nc_Default_Menu; /* Normalize menu to default if none was given */ #define Normalize_Menu( menu ) ((menu)=(menu)?(menu):&_nc_Default_Menu) +#define Get_Menu_Screen( menu ) (menu->userwin ? \ + _nc_screen_of(menu->userwin) : CURRENT_SCREEN) + /* Get the user defined (framing) window of the menu */ -#define Get_Menu_UserWin(menu) ((menu)->userwin ? (menu)->userwin : stdscr) +#define Get_Menu_UserWin(menu) ((menu)->userwin ? \ + (menu)->userwin : CURRENT_SCREEN->_stdscr) /* Normalize menu window */ #define Get_Menu_Window( menu ) \ @@ -75,7 +84,8 @@ extern NCURSES_EXPORT_VAR(MENU) _nc_Default_Menu; O_ROWMAJOR | \ O_IGNORECASE | \ O_SHOWMATCH | \ - O_NONCYCLIC ) + O_NONCYCLIC | \ + O_MOUSE_MENU ) #define ALL_ITEM_OPTS (O_SELECTABLE) @@ -97,10 +107,11 @@ extern NCURSES_EXPORT_VAR(MENU) _nc_Default_Menu; */ #define Adjust_Current_Item(menu,row,item) \ { if ((item)->y < row) \ - row = (item)->y;\ - if ( (item)->y >= (row + (menu)->arows) )\ - row = ( (item)->y < ((menu)->rows - row) ) ? \ - (item)->y : (menu)->rows - (menu)->arows;\ + row = (short) (item)->y; \ + if ( (item)->y >= (row + (menu)->arows) ) \ + row = (short) (( (item)->y < ((menu)->rows - row) ) \ + ? (item)->y \ + : (menu)->rows - (menu)->arows); \ _nc_New_TopRow_and_CurrentItem(menu,row,item); } /* Reset the match pattern buffer */ @@ -111,34 +122,34 @@ extern NCURSES_EXPORT_VAR(MENU) _nc_Default_Menu; #define UChar(c) ((unsigned char)(c)) /* Internal functions. */ -extern NCURSES_EXPORT(void) _nc_Draw_Menu (const MENU *); -extern NCURSES_EXPORT(void) _nc_Show_Menu (const MENU *); -extern NCURSES_EXPORT(void) _nc_Calculate_Item_Length_and_Width (MENU *); -extern NCURSES_EXPORT(int) _nc_Calculate_Text_Width(const TEXT *); -extern NCURSES_EXPORT(void) _nc_Post_Item (const MENU *, const ITEM *); -extern NCURSES_EXPORT(bool) _nc_Connect_Items (MENU *, ITEM **); -extern NCURSES_EXPORT(void) _nc_Disconnect_Items (MENU *); -extern NCURSES_EXPORT(void) _nc_New_TopRow_and_CurrentItem (MENU *,int, ITEM *); -extern NCURSES_EXPORT(void) _nc_Link_Items (MENU *); -extern NCURSES_EXPORT(int) _nc_Match_Next_Character_In_Item_Name (MENU*,int,ITEM**); -extern NCURSES_EXPORT(int) _nc_menu_cursor_pos (const MENU* menu, const ITEM* item, +extern MENU_EXPORT(void) _nc_Draw_Menu (const MENU *); +extern MENU_EXPORT(void) _nc_Show_Menu (const MENU *); +extern MENU_EXPORT(void) _nc_Calculate_Item_Length_and_Width (MENU *); +extern MENU_EXPORT(int) _nc_Calculate_Text_Width(const TEXT *); +extern MENU_EXPORT(void) _nc_Post_Item (const MENU *, const ITEM *); +extern MENU_EXPORT(bool) _nc_Connect_Items (MENU *, ITEM **); +extern MENU_EXPORT(void) _nc_Disconnect_Items (MENU *); +extern MENU_EXPORT(void) _nc_New_TopRow_and_CurrentItem (MENU *,int, ITEM *); +extern MENU_EXPORT(void) _nc_Link_Items (MENU *); +extern MENU_EXPORT(int) _nc_Match_Next_Character_In_Item_Name (MENU*,int,ITEM**); +extern MENU_EXPORT(int) _nc_menu_cursor_pos (const MENU* menu, const ITEM* item, int* pY, int* pX); #ifdef TRACE -#define returnItem(code) TRACE_RETURN(code,item) -#define returnItemPtr(code) TRACE_RETURN(code,item_ptr) -#define returnItemOpts(code) TRACE_RETURN(code,item_opts) -#define returnMenu(code) TRACE_RETURN(code,menu) -#define returnMenuHook(code) TRACE_RETURN(code,menu_hook) -#define returnMenuOpts(code) TRACE_RETURN(code,menu_opts) +#define returnItem(code) TRACE_RETURN1(code,item) +#define returnItemPtr(code) TRACE_RETURN1(code,item_ptr) +#define returnItemOpts(code) TRACE_RETURN1(code,item_opts) +#define returnMenu(code) TRACE_RETURN1(code,menu) +#define returnMenuHook(code) TRACE_RETURN1(code,menu_hook) +#define returnMenuOpts(code) TRACE_RETURN1(code,menu_opts) -extern NCURSES_EXPORT(ITEM *) _nc_retrace_item (ITEM *); -extern NCURSES_EXPORT(ITEM **) _nc_retrace_item_ptr (ITEM **); -extern NCURSES_EXPORT(Item_Options) _nc_retrace_item_opts (Item_Options); -extern NCURSES_EXPORT(MENU *) _nc_retrace_menu (MENU *); -extern NCURSES_EXPORT(Menu_Hook) _nc_retrace_menu_hook (Menu_Hook); -extern NCURSES_EXPORT(Menu_Options) _nc_retrace_menu_opts (Menu_Options); +extern MENU_EXPORT(ITEM *) _nc_retrace_item (ITEM *); +extern MENU_EXPORT(ITEM **) _nc_retrace_item_ptr (ITEM **); +extern MENU_EXPORT(Item_Options) _nc_retrace_item_opts (Item_Options); +extern MENU_EXPORT(MENU *) _nc_retrace_menu (MENU *); +extern MENU_EXPORT(Menu_Hook) _nc_retrace_menu_hook (Menu_Hook); +extern MENU_EXPORT(Menu_Options) _nc_retrace_menu_opts (Menu_Options); #else /* !TRACE */ @@ -150,5 +161,6 @@ extern NCURSES_EXPORT(Menu_Options) _nc_retrace_menu_opts (Menu_Options); #define returnMenuOpts(code) return code #endif /* TRACE/!TRACE */ +/* *INDENT-ON* */ #endif /* MENU_PRIV_H_incl */ diff --git a/lib/libmenu/menu_attributes.3 b/lib/libmenu/menu_attributes.3 index dbaaadb742a..493496e4548 100644 --- a/lib/libmenu/menu_attributes.3 +++ b/lib/libmenu/menu_attributes.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: menu_attributes.3,v 1.3 2015/11/15 22:10:16 jmc Exp $ +.\" $OpenBSD: menu_attributes.3,v 1.4 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,52 +30,64 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: menu_attributes.3,v 1.3 2015/11/15 22:10:16 jmc Exp $ -.TH menu_attributes 3 "" +.\" $Id: menu_attributes.3,v 1.4 2023/10/17 09:52:10 nicm Exp $ +.TH menu_attributes 3 2023-07-01 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .SH NAME -\fBset_menu_fore\fR, \fBmenu_fore\fR, -\fBset_menu_back\fR, \fBmenu_back\fR, -\fBset_menu_grey\fR, \fBmenu_grey\fR, -\fBset_menu_pad\fR, \fBmenu_pad\fR -- color and attribute control for menus +\fBmenu_back\fP, +\fBmenu_fore\fP, +\fBmenu_grey\fP, +\fBmenu_pad\fP, +\fBset_menu_back\fP, +\fBset_menu_fore\fP, +\fBset_menu_grey\fP, +\fBset_menu_pad\fP \- color and attribute control for menus .SH SYNOPSIS -\fB#include \fR +\fB#include \fP +.sp +\fBint set_menu_fore(MENU *\fImenu\fB, chtype \fIattr\fB);\fR .br -int set_menu_fore(MENU *menu, chtype attr); +\fBchtype menu_fore(const MENU *\fImenu\fB);\fR +.sp +\fBint set_menu_back(MENU *\fImenu\fB, chtype \fIattr\fB);\fR .br -chtype menu_fore(const MENU *menu); +\fBchtype menu_back(const MENU *\fImenu\fB);\fR +.sp +\fBint set_menu_grey(MENU *\fImenu\fB, chtype \fIattr\fB);\fR .br -int set_menu_back(MENU *menu, chtype attr); -.br -chtype menu_back(const MENU *menu); -.br -int set_menu_grey(MENU *menu, chtype attr); -.br -chtype menu_grey(const MENU *menu); -.br -int set_menu_pad(MENU *menu, int pad); -.br -int menu_pad(const MENU *menu); +\fBchtype menu_grey(const MENU *\fImenu\fB);\fR +.sp +\fBint set_menu_pad(MENU *\fImenu\fB, int \fIpad\fB);\fR .br +\fBint menu_pad(const MENU *\fImenu\fB);\fR .SH DESCRIPTION -The function \fBset_menu_fore\fR sets the foreground attribute of -\fImenu\fR. This is the highlight used for selected menu items. -\fBmenu_fore\fR returns the foreground attribute. The default -is \fBA_REVERSE\fR. +The function \fBset_menu_fore\fP sets the foreground attribute of +\fImenu\fP. This is the highlight used for selected menu items. +\fBmenu_fore\fP returns the foreground attribute. +The default +is \fBA_REVERSE\fP. .PP -The function \fBset_menu_back\fR sets the background attribute of -\fImenu\fR. This is the highlight used for selectable (but not currently -selected) menu items. The function \fBmenu_back\fR returns the background -attribute. The default is \fBA_NORMAL\fR. +The function \fBset_menu_back\fP sets the background attribute of +\fImenu\fP. This is the highlight used for selectable (but not currently +selected) menu items. +The function \fBmenu_back\fP returns the background +attribute. +The default is \fBA_NORMAL\fP. .PP -The function \fBset_menu_grey\fR sets the grey attribute of \fImenu\fR. This is +The function \fBset_menu_grey\fP sets the grey attribute of \fImenu\fP. This is the highlight used for un-selectable menu items in menus that permit more than -one selection. The function \fBmenu_grey\fR returns the grey attribute. -The default is \fBA_UNDERLINE\fR. +one selection. +The function \fBmenu_grey\fP returns the grey attribute. +The default is \fBA_UNDERLINE\fP. .PP -The function \fBset_menu_pad\fR sets the character used to fill the space -between the name and description parts of a menu item. \fBmenu_pad\fR returns -the given menu's pad character. The default is a blank. +The function \fBset_menu_pad\fP sets the character used to fill the space +between the name and description parts of a menu item. +\fBmenu_pad\fP returns +the given menu's pad character. +The default is a blank. .SH RETURN VALUE These routines return one of the following: .TP 5 @@ -82,25 +95,20 @@ These routines return one of the following: The routine succeeded. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .TP 5 .B E_BAD_ARGUMENT Routine detected an incorrect or out-of-range argument. .SH SEE ALSO -\fBcurses\fR(3) and related pages whose names begin "menu_" for detailed +\fBcurses\fP(3) and related pages whose names begin \*(``menu_\*('' for detailed descriptions of the entry points. .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V menu library. They were not supported on +These routines emulate the System V menu library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/menu_cursor.3 b/lib/libmenu/menu_cursor.3 index c1f88947d7e..f9a394e288e 100644 --- a/lib/libmenu/menu_cursor.3 +++ b/lib/libmenu/menu_cursor.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: menu_cursor.3,v 1.8 2015/11/15 22:10:16 jmc Exp $ +.\" $OpenBSD: menu_cursor.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,18 +30,18 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: menu_cursor.3,v 1.8 2015/11/15 22:10:16 jmc Exp $ -.TH menu_cursor 3 "" +.\" $Id: menu_cursor.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ +.TH menu_cursor 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBpos_menu_cursor\fR - position a menu's cursor +\fBpos_menu_cursor\fP \- position a menu's cursor .SH SYNOPSIS -\fB#include \fR -.br -int pos_menu_cursor(const MENU *menu); -.br +\fB#include \fP +.sp +\fBint pos_menu_cursor(const MENU *\fImenu\fB);\fR .SH DESCRIPTION -The function \fBpos_menu_cursor\fR restores the cursor to the current position -associated with the menu's selected item. This is useful after \fBcurses\fR +The function \fBpos_menu_cursor\fP restores the cursor to the current position +associated with the menu's selected item. +This is useful after \fBcurses\fP routines have been called to do screen-painting in response to a menu select. .SH RETURN VALUE This routine returns one of the following: @@ -49,7 +50,7 @@ This routine returns one of the following: The routine succeeded. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .TP 5 .B E_BAD_ARGUMENT Routine detected an incorrect or out-of-range argument. @@ -57,19 +58,14 @@ Routine detected an incorrect or out-of-range argument. .B E_NOT_POSTED The menu has not been posted. .SH SEE ALSO -\fBcurses\fR(3), \fBmenu\fR(3). +\fBcurses\fP(3), \fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V menu library. They were not supported on +These routines emulate the System V menu library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/menu_driver.3 b/lib/libmenu/menu_driver.3 index 5b9bb140fb1..ccf22cf3e23 100644 --- a/lib/libmenu/menu_driver.3 +++ b/lib/libmenu/menu_driver.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: menu_driver.3,v 1.7 2010/01/12 23:22:08 nicm Exp $ +.\" $OpenBSD: menu_driver.3,v 1.8 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,30 +29,31 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: menu_driver.3,v 1.7 2010/01/12 23:22:08 nicm Exp $ -.TH menu_driver 3 "" +.\" $Id: menu_driver.3,v 1.8 2023/10/17 09:52:10 nicm Exp $ +.TH menu_driver 3 2023-07-01 "ncurses 6.4" "Library calls" +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .SH NAME -\fBmenu_driver\fR - command-processing loop of the menu system +\fBmenu_driver\fP \- command-processing loop of the menu system .SH SYNOPSIS -\fB#include \fR -.br -int menu_driver(MENU *menu, int c); -.br +\fB#include \fP +.sp +\fBint menu_driver(MENU *\fImenu\fB, int \fIc\fB);\fR .SH DESCRIPTION Once a menu has been posted (displayed), you should funnel input events to it -through \fBmenu_driver\fR. This routine has three major input cases: -.TP 3 -- +through \fBmenu_driver\fP. This routine has three major input cases: +.bP The input is a form navigation request. Navigation request codes are constants defined in \fB\fP, -which are distinct from the key- and character codes returned by \fBwgetch\fP. -.TP 3 -- +which are distinct from the key- and character codes +returned by \fBwgetch\fP(3). +.bP The input is a printable character. Printable characters (which must be positive, less than 256) are checked according to the program's locale settings. -.TP 3 -- +.bP The input is the KEY_MOUSE special key associated with an mouse event. .PP The menu driver requests are as follows: @@ -109,75 +111,67 @@ Move to the previous item matching the pattern match. .PP If the second argument is a printable character, the code appends it to the pattern buffer and attempts to move to the next item matching -the new pattern. If there is no such match, \fBmenu_driver\fR returns -\fBE_NO_MATCH\fR and deletes the appended character from the buffer. +the new pattern. +If there is no such match, \fBmenu_driver\fP returns +\fBE_NO_MATCH\fP and deletes the appended character from the buffer. .PP If the second argument is one of the above pre-defined requests, the corresponding action is performed. .SS MOUSE HANDLING -.PP If the second argument is the KEY_MOUSE special key, the associated mouse event is translated into one of the above pre-defined requests. Currently only clicks in the user window (e.g., inside the menu display area or the decoration window) are handled. .PP If you click above the display region of the menu: -.RS -.TP +.bP a REQ_SCR_ULINE is generated for a single click, -.TP +.bP a REQ_SCR_UPAGE is generated for a double-click and -.TP +.bP a REQ_FIRST_ITEM is generated for a triple-click. -.RE .PP If you click below the display region of the menu: -.RS -.TP +.bP a REQ_SCR_DLINE is generated for a single click, -.TP +.bP a REQ_SCR_DPAGE is generated for a double-click and -.TP +.bP a REQ_LAST_ITEM is generated for a triple-click. -.RE .PP If you click at an item inside the display area of the menu: -.RS -.TP 3 -- +.bP the menu cursor is positioned to that item. -.TP 3 -- +.bP If you double-click an item a REQ_TOGGLE_ITEM -is generated and \fBE_UNKNOWN_COMMAND\fR is returned. +is generated and \fBE_UNKNOWN_COMMAND\fP is returned. This return value makes sense, because a double click usually means that an item-specific action should be returned. It is exactly the purpose of this return value to signal that an application specific command should be executed. -.TP 3 -- +.bP If a translation -into a request was done, \fBmenu_driver\fR returns the result of this request. -.RE +into a request was done, \fBmenu_driver\fP returns the result of this request. .PP -If you clicked outside the user window or the mouse event could not be translated -into a menu request an \fBE_REQUEST_DENIED\fR is returned. +If you clicked outside the user window +or the mouse event could not be translated +into a menu request an \fBE_REQUEST_DENIED\fP is returned. .SS APPLICATION-DEFINED COMMANDS -.PP If the second argument is neither printable nor one of the above -pre-defined menu requests or KEY_MOUSE, the drive assumes it is an application-specific -command and returns \fBE_UNKNOWN_COMMAND\fR. Application-defined commands -should be defined relative to \fBMAX_COMMAND\fR, the maximum value of these +pre-defined menu requests or KEY_MOUSE, +the drive assumes it is an application-specific +command and returns \fBE_UNKNOWN_COMMAND\fP. Application-defined commands +should be defined relative to \fBMAX_COMMAND\fP, the maximum value of these pre-defined requests. .SH RETURN VALUE -\fBmenu_driver\fR return one of the following error codes: +\fBmenu_driver\fP return one of the following error codes: .TP 5 .B E_OK The routine succeeded. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .TP 5 .B E_BAD_ARGUMENT Routine detected an incorrect or out-of-range argument. @@ -197,21 +191,17 @@ Character failed to match. .B E_REQUEST_DENIED The menu driver could not process the request. .SH SEE ALSO -\fBcurses\fR(3), -\fBmenu\fR(3), -\fBwgetch\fR(3). +\fBcurses\fP(3), +\fBgetch\fP(3), +\fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header files -\fB\fR. +The header file \fB\fP automatically includes the header files +\fB\fP. .SH PORTABILITY -These routines emulate the System V menu library. They were not supported on -Version 7 or BSD versions. The support for mouse events is ncurses specific. +These routines emulate the System V menu library. +They were not supported on +Version 7 or BSD versions. +The support for mouse events is ncurses specific. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/menu_format.3 b/lib/libmenu/menu_format.3 index 92fb2660cf2..3b078450189 100644 --- a/lib/libmenu/menu_format.3 +++ b/lib/libmenu/menu_format.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: menu_format.3,v 1.8 2015/11/15 22:10:16 jmc Exp $ +.\" $OpenBSD: menu_format.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2001,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2015,2016 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,30 +30,34 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: menu_format.3,v 1.8 2015/11/15 22:10:16 jmc Exp $ -.TH menu_format 3 "" +.\" $Id: menu_format.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ +.TH menu_format 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBset_menu_format\fR, \fBmenu_format\fR - set and get menu sizes +\fBset_menu_format\fP, +\fBmenu_format\fP \- set and get menu sizes .SH SYNOPSIS -\fB#include \fR -.br -int set_menu_format(MENU *menu, int rows, int cols); -.br -void menu_format(const MENU *menu, int *rows, int *cols); +\fB#include \fP +.sp +\fBint set_menu_format(MENU *\fImenu\fB, int \fIrows\fB, int \fIcols\fB);\fR .br +\fBvoid menu_format(const MENU *\fImenu\fB, int *\fIrows\fB, int *\fIcols\fB);\fR .SH DESCRIPTION -The function \fBset_menu_format\fR sets the maximum display size of the given -menu. If this size is too small to display all menu items, the menu will be -made scrollable. If this size is larger than the menus subwindow and the -subwindow is too small to display all menu items, \fBpost_menu()\fR will fail. +The function \fBset_menu_format\fP sets the maximum display size of the given +menu. +If this size is too small to display all menu items, the menu will be +made scrollable. +If this size is larger than the menus subwindow and the +subwindow is too small to display all menu items, \fBpost_menu\fP will fail. .PP -The default format is 16 rows, 1 column. Calling \fBset_menu_format\fR with a -null menu pointer will change this default. A zero row or column argument to -\fBset_menu_format\fR is interpreted as a request not to change the current +The default format is 16 rows, 1 column. +Calling \fBset_menu_format\fP with a +null menu pointer will change this default. +A zero row or column argument to +\fBset_menu_format\fP is interpreted as a request not to change the current value. .PP -The function \fBmenu_format\fR returns the maximum-size constraints for the -given menu into the storage addressed by \fBrows\fR and \fBcols\fR. +The function \fBmenu_format\fP returns the maximum-size constraints for the +given menu into the storage addressed by \fBrows\fP and \fBcols\fP. .SH RETURN VALUE These routines returns one of the following: .TP 5 @@ -60,7 +65,7 @@ These routines returns one of the following: The routine succeeded. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .TP 5 .B E_BAD_ARGUMENT Routine detected an incorrect or out-of-range argument. @@ -71,19 +76,14 @@ The menu is already posted. .B E_NOT_CONNECTED No items are connected to the menu. .SH SEE ALSO -\fBcurses\fR(3), \fBmenu\fR(3). +\fBcurses\fP(3), \fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V menu library. They were not supported on +These routines emulate the System V menu library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/menu_hook.3 b/lib/libmenu/menu_hook.3 index fb4ea94c554..83453edb952 100644 --- a/lib/libmenu/menu_hook.3 +++ b/lib/libmenu/menu_hook.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: menu_hook.3,v 1.8 2015/11/15 22:10:16 jmc Exp $ +.\" $OpenBSD: menu_hook.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2007,2010 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,79 +30,74 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: menu_hook.3,v 1.8 2015/11/15 22:10:16 jmc Exp $ -.TH menu_hook 3 "" +.\" $Id: menu_hook.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ +.TH menu_hook 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBset_item_init\fR, \fBitem_init\fR, -\fBset_item_term\fR, \fBitem_term\fR, -\fBset_menu_init\fR, \fBmenu_init\fR, -\fBset_menu_term\fR, \fBmenu_term\fR -- set hooks for automatic invocation by applications +\fBmenu_hook\fP \- set hooks for automatic invocation by applications .SH SYNOPSIS -\fB#include \fR +\fB#include \fP +.sp +\fBint set_item_init(MENU *\fImenu\fB, Menu_Hook \fIfunc);\fR .br -int set_item_init(MENU *menu, Menu_Hook func); +\fBMenu_Hook item_init(const MENU *\fImenu);\fR +.sp +\fBint set_item_term(MENU *\fImenu\fB, Menu_Hook \fIfunc);\fR .br -Menu_Hook item_init(const MENU *menu); +\fBMenu_Hook item_term(const MENU *\fImenu);\fR +.sp +\fBint set_menu_init(MENU *\fImenu\fB, Menu_Hook \fIfunc);\fR .br -int set_item_term(MENU *menu, Menu_Hook func); -.br -Menu_Hook item_term(const MENU *menu); -.br -int set_menu_init(MENU *menu, Menu_Hook func); -.br -Menu_Hook menu_init(const MENU *menu); -.br -int set_menu_term(MENU *menu, Menu_Hook func); -.br -Menu_Hook menu_term(const MENU *menu); +\fBMenu_Hook menu_init(const MENU *\fImenu);\fR +.sp +\fBint set_menu_term(MENU *\fImenu\fB, Menu_Hook \fIfunc);\fR .br +\fBMenu_Hook menu_term(const MENU *\fImenu);\fR .SH DESCRIPTION These functions make it possible to set hook functions to be called at various -points in the automatic processing of input event codes by \fBmenu_driver\fR. +points in the automatic processing of input event codes by \fBmenu_driver\fP. .PP -The function \fBset_item_init\fR sets a hook to be called at menu-post time and -each time the selected item changes (after the change). \fBitem_init\fR -returns the current item init hook, if any (\fBNULL\fR if there is no such +The function \fBset_item_init\fP sets a hook to be called at menu-post time and +each time the selected item changes (after the change). +\fBitem_init\fP +returns the current item init hook, if any (\fBNULL\fP if there is no such hook). .PP -The function \fBset_item_term\fR sets a hook to be called at menu-unpost time -and each time the selected item changes (before the change). \fBitem_term\fR -returns the current item term hook, if any (\fBNULL\fR if there is no such +The function \fBset_item_term\fP sets a hook to be called at menu-unpost time +and each time the selected item changes (before the change). +\fBitem_term\fP +returns the current item term hook, if any (\fBNULL\fP if there is no such hook). .PP -The function \fBset_menu_init\fR sets a hook to be called at menu-post time and -just after the top row on the menu changes once it is posted. \fBmenu_init\fR -returns the current menu init hook, if any (\fBNULL\fR if there is no such +The function \fBset_menu_init\fP sets a hook to be called at menu-post time and +just after the top row on the menu changes once it is posted. +\fBmenu_init\fP +returns the current menu init hook, if any (\fBNULL\fP if there is no such hook). .PP -The function \fBset_menu_term\fR sets a hook to be called at menu-unpost time +The function \fBset_menu_term\fP sets a hook to be called at menu-unpost time and just before the top row on the menu changes once it is posted. -\fBmenu_term\fR returns the current menu term hook, if any (\fBNULL\fR if there +\fBmenu_term\fP returns the current menu term hook, if any (\fBNULL\fP if there is no such hook). .SH RETURN VALUE -Routines that return pointers return \fBNULL\fR on error. Other routines +Routines that return pointers return \fBNULL\fP on error. +Other routines return one of the following: .TP 5 .B E_OK The routine succeeded. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .SH SEE ALSO -\fBcurses\fR(3), \fBmenu\fR(3). +\fBcurses\fP(3), \fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V menu library. They were not supported on +These routines emulate the System V menu library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: diff --git a/lib/libmenu/menu_items.3 b/lib/libmenu/menu_items.3 index dd7f135d81f..62b4d22f628 100644 --- a/lib/libmenu/menu_items.3 +++ b/lib/libmenu/menu_items.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: menu_items.3,v 1.8 2015/11/15 22:10:16 jmc Exp $ +.\" $OpenBSD: menu_items.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2012,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,35 +30,35 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: menu_items.3,v 1.8 2015/11/15 22:10:16 jmc Exp $ -.TH menu_items 3 "" +.\" $Id: menu_items.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ +.TH menu_items 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBset_menu_items\fR, \fBmenu_items\fR, -\fBitem_count\fR - make and break connections between items and menus +\fBset_menu_items\fP, +\fBmenu_items\fP, +\fBitem_count\fP \- make and break connections between items and menus .SH SYNOPSIS -\fB#include \fR +\fB#include \fP +.sp +\fBint set_menu_items(MENU *\fImenu\fB, ITEM **\fIitems\fB);\fR .br -int set_menu_items(MENU *menu, ITEM **items); -.br -ITEM **menu_items(const MENU *menu); -.br -int item_count(const MENU *menu); +\fBITEM **menu_items(const MENU *\fImenu\fB);\fR .br +\fBint item_count(const MENU *\fImenu\fB);\fR .SH DESCRIPTION -The function \fBset_menu_items\fR changes the item pointer array of the given -\fImenu\fR. The array must be terminated by a \fBNULL\fR. +The function \fBset_menu_items\fP changes the item pointer array of the given +\fImenu\fP. The array must be terminated by a \fBNULL\fP. .PP -The function \fBmenu_items\fR returns the item array of the given menu. +The function \fBmenu_items\fP returns the item array of the given menu. .PP -The function \fBitem_count\fR returns the count of items in \fImenu\fR. -.SH RETURN VALUES -The function \fBmenu_items\fR returns a pointer (which may be \fBNULL\fR). -It does not set errno. +The function \fBitem_count\fP returns the count of items in \fImenu\fP. +.SH RETURN VALUE +The function \fBmenu_items\fP returns a pointer (which may be \fBNULL\fP). +It does not set \fBerrno\fP. .PP -The function \fBitem_count\fR returns \fBERR\fR (the general \fBcurses\fR error +The function \fBitem_count\fP returns \fBERR\fP (the general \fBcurses\fP error return value) if its \fImenu\fP parameter is \fBNULL\fP. .PP -The function \fBset_menu_items\fR returns one of the following codes on error: +The function \fBset_menu_items\fP returns one of the following codes on error: .TP 5 .B E_OK The routine succeeded. @@ -72,25 +73,20 @@ No items are connected to the menu. The menu is already posted. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). . .SH SEE ALSO -\fBcurses\fR(3), \fBmenu\fR(3). +\fBcurses\fP(3), \fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V menu library. They were not supported on +These routines emulate the System V menu library. +They were not supported on Version 7 or BSD versions. .PP -The SVr4 menu library documentation specifies the \fBitem_count\fR error value -as -1 (which is the value of \fBERR\fR). +The SVr4 menu library documentation specifies the \fBitem_count\fP error value +as \-1 (which is the value of \fBERR\fP). .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/menu_mark.3 b/lib/libmenu/menu_mark.3 index ddf3da48aa8..7496a0d1905 100644 --- a/lib/libmenu/menu_mark.3 +++ b/lib/libmenu/menu_mark.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: menu_mark.3,v 1.8 2015/11/15 22:10:16 jmc Exp $ +.\" $OpenBSD: menu_mark.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,37 +30,38 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: menu_mark.3,v 1.8 2015/11/15 22:10:16 jmc Exp $ -.TH menu_mark 3 "" +.\" $Id: menu_mark.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ +.TH menu_mark 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBset_menu_mark\fR, \fBmenu_mark\fR - get and set the menu mark string +\fBset_menu_mark\fP, +\fBmenu_mark\fP \- get and set the menu mark string .SH SYNOPSIS -\fB#include \fR -.br -int set_menu_mark(MENU *menu, const char *mark); -.br -const char *menu_mark(const MENU *menu); +\fB#include \fP +.sp +\fBint set_menu_mark(MENU *\fImenu\fB, const char *\fImark\fB);\fR .br +\fBconst char *menu_mark(const MENU *\fImenu\fB);\fR .SH DESCRIPTION In order to make menu selections visible on older terminals without highlighting or color capability, the menu library marks selected items in a menu with a prefix string. .PP -The function \fBset_menu_mark\fR sets the mark string for the given menu. -Calling \fBset_menu_mark\fR with a null menu item will abolish the mark string. +The function \fBset_menu_mark\fP sets the mark string for the given menu. +Calling \fBset_menu_mark\fP with a null menu item will abolish the mark string. Note that changing the length of the mark string for a menu while the menu is posted is likely to produce unhelpful behavior. .PP -The default string is "-" (a dash). Calling \fBset_menu_mark\fR with -a non-\fBNULL\fR menu argument will change this default. +The default string is "\-" (a dash). +Calling \fBset_menu_mark\fP with +a non-\fBNULL\fP menu argument will change this default. .PP -The function \fBmenu_mark\fR returns the menu's mark string (or \fBNULL\fR if +The function \fBmenu_mark\fP returns the menu's mark string (or \fBNULL\fP if there is none). .SH RETURN VALUE -The function \fBmenu_mark\fR returns a pointer (which may be \fBNULL\fR). -It does not set errno. +The function \fBmenu_mark\fP returns a pointer (which may be \fBNULL\fP). +It does not set \fBerrno\fP. .PP -The function \fBset_menu_mark\fR may return the following error codes: +The function \fBset_menu_mark\fP may return the following error codes: .TP 5 .B E_OK The routine succeeded. @@ -68,21 +70,16 @@ The routine succeeded. Routine detected an incorrect or out-of-range argument. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .SH SEE ALSO -\fBcurses\fR(3), \fBmenu\fR(3). +\fBcurses\fP(3), \fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V menu library. They were not supported on +These routines emulate the System V menu library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/menu_new.3 b/lib/libmenu/menu_new.3 index 8b8a480e1a6..73f5f3aa758 100644 --- a/lib/libmenu/menu_new.3 +++ b/lib/libmenu/menu_new.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: menu_new.3,v 1.8 2015/11/15 22:10:16 jmc Exp $ +.\" $OpenBSD: menu_new.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,26 +30,26 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: menu_new.3,v 1.8 2015/11/15 22:10:16 jmc Exp $ -.TH menu_new 3 "" +.\" $Id: menu_new.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ +.TH menu_new 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBnew_menu\fR, \fBfree_menu\fR - create and destroy menus +\fBnew_menu\fP, +\fBfree_menu\fP \- create and destroy menus .SH SYNOPSIS -\fB#include \fR -.br -MENU *new_menu(ITEM **items); -.br -int free_menu(MENU *menu); +\fB#include \fP +.sp +\fBMENU *new_menu(ITEM **\fIitems\fB);\fR .br +\fBint free_menu(MENU *\fImenu\fB);\fR .SH DESCRIPTION -The function \fBnew_menu\fR creates a new menu connected to a specified item -pointer array (which must be \fBNULL\fR-terminated). +The function \fBnew_menu\fP creates a new menu connected to a specified item +pointer array (which must be \fBNULL\fP-terminated). .PP -The function \fBfree_menu\fR disconnects \fImenu\fR from its item array +The function \fBfree_menu\fP disconnects \fImenu\fP from its item array and frees the storage allocated for the menu. .SH RETURN VALUE -The function \fBnew_menu\fR returns \fBNULL\fR on error. -It sets errno according to the function's failure: +The function \fBnew_menu\fP returns \fBNULL\fP on error. +It sets \fBerrno\fP according to the function's failure: .TP 5 .B E_NOT_CONNECTED No items are connected to the menu. @@ -56,13 +57,13 @@ No items are connected to the menu. .B E_SYSTEM_ERROR System error occurred, e.g., malloc failure. .PP -The function \fBfree_menu\fR returns one of the following: +The function \fBfree_menu\fP returns one of the following: .TP 5 .B E_OK The routine succeeded. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .TP 5 .B E_BAD_ARGUMENT Routine detected an incorrect or out-of-range argument. @@ -70,19 +71,14 @@ Routine detected an incorrect or out-of-range argument. .B E_POSTED The menu has already been posted. .SH SEE ALSO -\fBcurses\fR(3), \fBmenu\fR(3). +\fBcurses\fP(3), \fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V menu library. They were not supported on +These routines emulate the System V menu library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/menu_opts.3 b/lib/libmenu/menu_opts.3 index 56ceae2c469..c46779f25ff 100644 --- a/lib/libmenu/menu_opts.3 +++ b/lib/libmenu/menu_opts.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: menu_opts.3,v 1.9 2015/11/15 22:10:16 jmc Exp $ +.\" $OpenBSD: menu_opts.3,v 1.10 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2015,2016 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,34 +30,34 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: menu_opts.3,v 1.9 2015/11/15 22:10:16 jmc Exp $ -.TH menu_opts 3 "" +.\" $Id: menu_opts.3,v 1.10 2023/10/17 09:52:10 nicm Exp $ +.TH menu_opts 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBset_menu_opts\fR, \fBmenu_opts_on\fR, -\fBmenu_opts_off\fR, \fBmenu_opts\fR -- set and get menu options +\fBset_menu_opts\fP, +\fBmenu_opts_on\fP, +\fBmenu_opts_off\fP, +\fBmenu_opts\fP \- set and get menu options .SH SYNOPSIS -\fB#include \fR +\fB#include \fP +.sp +\fBint set_menu_opts(MENU *\fImenu\fB, Menu_Options \fIopts\fB);\fR .br -int set_menu_opts(MENU *menu, Menu_Options opts); -.br -int menu_opts_on(MENU *menu, Menu_Options opts); -.br -int menu_opts_off(MENU *menu, Menu_Options opts); -.br -Menu_Options menu_opts(const MENU *menu); +\fBMenu_Options menu_opts(const MENU *\fImenu\fB);\fR +.sp +\fBint menu_opts_on(MENU *\fImenu\fB, Menu_Options \fIopts\fB);\fR .br +\fBint menu_opts_off(MENU *\fImenu\fB, Menu_Options \fIopts\fB);\fR .SH DESCRIPTION -The function \fBset_menu_opts\fR sets all the given menu's option bits (menu -option bits may be logically OR'ed together). +The function \fBset_menu_opts\fP sets all the given menu's option bits (menu +option bits may be logically-OR'ed together). .PP -The function \fBmenu_opts_on\fR turns on the given option bits, and leaves +The function \fBmenu_opts_on\fP turns on the given option bits, and leaves others alone. .PP -The function \fBmenu_opts_off\fR turns off the given option bits, and leaves +The function \fBmenu_opts_off\fP turns off the given option bits, and leaves others alone. .PP -The function \fBmenu_opts\fR returns the menu's current option bits. +The function \fBmenu_opts\fP returns the menu's current option bits. .PP The following options are defined (all are on by default): .TP 5 @@ -78,31 +79,32 @@ Move the cursor to within the item name while pattern-matching. O_NONCYCLIC Don't wrap around next-item and previous-item, requests to the other end of the menu. +.TP 5 +O_MOUSE_MENU +If user clicks with the mouse +and it does not fall on the currently active menu, +push \fBKEY_MOUSE\fP and the \fBMEVENT\fP data +back on the queue to allow processing in another part of the calling program. .SH RETURN VALUE -Except for \fBmenu_opts\fR, each routine returns one of the following: +Except for \fBmenu_opts\fP, each routine returns one of the following: .TP 5 .B E_OK The routine succeeded. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .TP 5 .B E_POSTED The menu is already posted. .SH SEE ALSO -\fBcurses\fR(3), \fBmenu\fR(3). +\fBcurses\fP(3), \fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V menu library. They were not supported on +These routines emulate the System V menu library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/menu_pattern.3 b/lib/libmenu/menu_pattern.3 index 555ab2753bb..6c7cda3bef1 100644 --- a/lib/libmenu/menu_pattern.3 +++ b/lib/libmenu/menu_pattern.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: menu_pattern.3,v 1.7 2015/11/15 22:10:16 jmc Exp $ +.\" $OpenBSD: menu_pattern.3,v 1.8 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,35 +29,38 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: menu_pattern.3,v 1.7 2015/11/15 22:10:16 jmc Exp $ -.TH menu_pattern 3 "" +.\" $Id: menu_pattern.3,v 1.8 2023/10/17 09:52:10 nicm Exp $ +.TH menu_pattern 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBset_menu_pattern\fR, \fBmenu_pattern\fR -- get and set a menu's pattern buffer +\fBset_menu_pattern\fP, +\fBmenu_pattern\fP \- set and get a menu's pattern buffer .SH SYNOPSIS -\fB#include \fR -.br -int set_menu_pattern(MENU *menu, const char *pattern); -.br -char *menu_pattern(const MENU *menu); +\fB#include \fP +.sp +\fBint set_menu_pattern(MENU *\fImenu\fB, const char *\fIpattern\fB);\fR .br +\fBchar *menu_pattern(const MENU *\fImenu\fB);\fR .SH DESCRIPTION -Every menu has an associated pattern match buffer. As input events that are +Every menu has an associated pattern match buffer. +As input events that are printable characters come in, they are appended to this match buffer -and tested for a match, as described in \fBmenu_driver\fR(3). +and tested for a match, as described in \fBmenu_driver\fP(3). .PP -The function \fBset_menu_pattern\fR sets the pattern buffer for the given menu -and tries to find the first matching item. If it succeeds, that item becomes -current; if not, the current item does not change. +The function \fBset_menu_pattern\fP sets the pattern buffer for the given menu +and tries to find the first matching item. +If it succeeds, that item becomes +current; if not, the current item does not change. .PP -The function \fBmenu_pattern\fR returns the pattern buffer of the given -\fImenu\fR. +The function \fBmenu_pattern\fP returns the pattern buffer of the given +\fImenu\fP. .SH RETURN VALUE -The function \fBmenu_pattern\fR returns a pointer, which is \fBNULL\fR if the \fImenu\fP parameter is \fBNULL\fP. -Otherwise, it is a pointer to a string which is empty if no pattern has been set. -It does not set errno. +The function \fBmenu_pattern\fP returns a pointer, +which is \fBNULL\fP if the \fImenu\fP parameter is \fBNULL\fP. +Otherwise, it is a pointer to a string which is empty +if no pattern has been set. +It does not set \fBerrno\fP. .PP -The function \fBset_menu_pattern\fR may return the following error codes: +The function \fBset_menu_pattern\fP may return the following error codes: .TP 5 .B E_OK The routine succeeded. @@ -74,21 +78,16 @@ No items are connected to menu. Character failed to match. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .SH SEE ALSO -\fBcurses\fR(3), \fBmenu\fR(3). +\fBcurses\fP(3), \fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V menu library. They were not supported on +These routines emulate the System V menu library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/menu_post.3 b/lib/libmenu/menu_post.3 index 191af1a680d..b697d52fa14 100644 --- a/lib/libmenu/menu_post.3 +++ b/lib/libmenu/menu_post.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: menu_post.3,v 1.8 2015/11/15 22:10:16 jmc Exp $ +.\" $OpenBSD: menu_post.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2016,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,25 +30,27 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: menu_post.3,v 1.8 2015/11/15 22:10:16 jmc Exp $ -.TH menu_post 3 "" +.\" $Id: menu_post.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ +.TH menu_post 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBpost_menu\fR, \fBunpost_menu\fR -- write or erase menus from associated subwindows +\fBpost_menu\fP, +\fBunpost_menu\fP \- write or erase menus from associated subwindows .SH SYNOPSIS -\fB#include \fR -.br -int post_menu(MENU *menu); -.br -int unpost_menu(MENU *menu); +\fB#include \fP +.sp +\fBint post_menu(MENU *\fImenu\fB);\fR .br +\fBint unpost_menu(MENU *\fImenu\fB);\fR .SH DESCRIPTION -The function \fBpost_menu\fR displays a menu to its associated subwindow. To -trigger physical display of the subwindow, use \fBrefresh\fR or some equivalent -\fBcurses\fR routine (the implicit \fBdoupdate\fR triggered by an \fBcurses\fR -input request will do). \fBpost_menu\fR resets the selection status of all items. +The function \fBpost_menu\fP displays a menu to its associated subwindow. +To +trigger physical display of the subwindow, +use \fBrefresh\fP(3) or some equivalent +\fBcurses\fP routine (the implicit \fBdoupdate\fP triggered by an \fBcurses\fP +input request will do). +\fBpost_menu\fP resets the selection status of all items. .PP -The function \fBunpost_menu\fR erases menu from its associated subwindow. +The function \fBunpost_menu\fP erases menu from its associated subwindow. .SH RETURN VALUE These routines return one of the following: .TP 5 @@ -55,7 +58,7 @@ These routines return one of the following: The routine succeeded. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .TP 5 .B E_BAD_ARGUMENT Routine detected an incorrect or out-of-range argument. @@ -67,8 +70,8 @@ The menu has already been posted. Routine was called from an initialization or termination function. .TP 5 .B E_NO_ROOM -Menu is too large for its window. You should consider to use -\fBset_menu_format()\fR to solve the problem. +Menu is too large for its window. +You should consider using \fBset_menu_format\fP to solve the problem. .TP 5 .B E_NOT_POSTED The menu has not been posted. @@ -76,19 +79,14 @@ The menu has not been posted. .B E_NOT_CONNECTED No items are connected to the menu. .SH SEE ALSO -\fBcurses\fR(3), \fBmenu\fR(3). +\fBcurses\fP(3), \fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V menu library. They were not supported on +These routines emulate the System V menu library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/menu_requestname.3 b/lib/libmenu/menu_requestname.3 index 4ca735a568c..f54d6976d10 100644 --- a/lib/libmenu/menu_requestname.3 +++ b/lib/libmenu/menu_requestname.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: menu_requestname.3,v 1.7 2015/11/15 22:10:16 jmc Exp $ +.\" $OpenBSD: menu_requestname.3,v 1.8 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,46 +30,41 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: menu_requestname.3,v 1.7 2015/11/15 22:10:16 jmc Exp $ -.TH menu_requestname 3 "" +.\" $Id: menu_requestname.3,v 1.8 2023/10/17 09:52:10 nicm Exp $ +.TH menu_requestname 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBmenu_request_name\fR, \fBmenu_request_by_name\fR -- handle printable menu request names +\fBmenu_request_by_name\fP, +\fBmenu_request_name\fP \- handle printable menu request names .SH SYNOPSIS -\fB#include \fR -.br -const char *menu_request_name(int request); -.br -int menu_request_by_name(const char *name); +\fB#include \fP +.sp +\fBconst char *menu_request_name(int \fIrequest\fB);\fR .br +\fBint menu_request_by_name(const char *\fIname\fB);\fR .SH DESCRIPTION -The function \fBmenu_request_name\fR returns the printable name of a menu +The function \fBmenu_request_name\fP returns the printable name of a menu request code. .br -The function \fBmenu_request_by_name\fR searches in the name-table for a request +The function \fBmenu_request_by_name\fP searches in the name-table for a request with the given name and returns its request code. Otherwise E_NO_MATCH is returned. .SH RETURN VALUE -\fBmenu_request_name\fR returns \fBNULL\fR on error -and sets errno to \fBE_BAD_ARGUMENT\fR. +\fBmenu_request_name\fP returns \fBNULL\fP on error +and sets \fBerrno\fP to \fBE_BAD_ARGUMENT\fP. .br -\fBmenu_request_by_name\fR returns \fBE_NO_MATCH\fR on error. -It does not set errno. +\fBmenu_request_by_name\fP returns \fBE_NO_MATCH\fP on error. +It does not set \fBerrno\fP. .SH SEE ALSO -\fBcurses\fR(3), \fBmenu\fR(3). +\fBcurses\fP(3), \fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines are specific to ncurses. They were not supported on -Version 7, BSD or System V implementations. It is recommended that +These routines are specific to ncurses. +They were not supported on +Version 7, BSD or System V implementations. +It is recommended that any code depending on them be conditioned using NCURSES_VERSION. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/menu_spacing.3 b/lib/libmenu/menu_spacing.3 index fa0ea0ecd29..233582ce45c 100644 --- a/lib/libmenu/menu_spacing.3 +++ b/lib/libmenu/menu_spacing.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: menu_spacing.3,v 1.7 2015/11/15 22:10:16 jmc Exp $ +.\" $OpenBSD: menu_spacing.3,v 1.8 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2001,2004 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,59 +30,64 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: menu_spacing.3,v 1.7 2015/11/15 22:10:16 jmc Exp $ -.TH menu_spacing 3 "" +.\" $Id: menu_spacing.3,v 1.8 2023/10/17 09:52:10 nicm Exp $ +.TH menu_spacing 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBset_menu_spacing\fR, \fBmenu_spacing\fR -- Control spacing between menu items. +\fBset_menu_spacing\fP, +\fBmenu_spacing\fP \- set and get spacing between menu items. .SH SYNOPSIS -\fB#include \fR -.br -int set_menu_spacing(MENU *menu, - int spc_description, - int spc_rows, - int spc_columns); -.br -int menu_spacing(const MENU *menu, - int* spc_description, - int* spc_rows, - int* spc_columns); +\fB#include \fP +.sp +\fBint set_menu_spacing(MENU *\fImenu\fB,\fR + \fBint \fIspc_description\fB,\fR + \fBint \fIspc_rows\fB,\fR + \fBint \fIspc_columns\fB);\fR .br +\fBint menu_spacing(const MENU *\fImenu\fB,\fR + \fBint* \fIspc_description\fB,\fR + \fBint* \fIspc_rows\fB,\fR + \fBint* \fIspc_columns\fB);\fR .SH DESCRIPTION -The function \fBset_menu_spacing\fR sets the spacing informations for the menu. -\fBspc_description\fR controls the number of spaces between an item name and an item -description. It must not be larger than \fBTABSIZE\fR. The menu system puts in the -middle of this spacing area the pad character. The remaining parts are filled with +The function \fBset_menu_spacing\fP sets the spacing information for the menu. +Its parameter \fBspc_description\fP controls the number of spaces +between an item name and an item description. +It must not be larger than \fBTABSIZE\fP. +The menu system puts in the +middle of this spacing area the pad character. +The remaining parts are filled with spaces. -\fBspc_rows\fR controls the number of rows that are used for an item. It must not be -larger than 3. The menu system inserts the blank lines between item rows, these lines +The \fBspc_rows\fP parameter controls the number of rows +that are used for an item. +It must not be larger than 3. +The menu system inserts the blank lines between item rows, these lines will contain the pad character in the appropriate positions. -\fBspc_columns\fR controls the number of blanks between columns of items. It must not -be larger than TABSIZE. -A value of 0 for all the spacing values resets them to the default, which is 1 for all -of them. +The \fBspc_columns\fP parameter controls +the number of blanks between columns of items. +It must not be larger than \fBTABSIZE\fP. +A value of 0 for all the spacing values resets them to the default, +which is 1 for all of them. .br -The function \fBmenu_spacing\fR passes back the spacing info for the menu. If a +The function \fBmenu_spacing\fP passes back the spacing info for the menu. +If a pointer is NULL, this specific info is simply not returned. .SH RETURN VALUE -Both routines return \fBE_OK\fR on success. \fBset_menu_spacing\fR may return -\fBE_POSTED\fR if the menu is posted, or \fBE_BAD_ARGUMENT\fR if one of the +Both routines return \fBE_OK\fP on success. +\fBset_menu_spacing\fP may return +\fBE_POSTED\fP if the menu is posted, or \fBE_BAD_ARGUMENT\fP if one of the spacing values is out of range. .SH SEE ALSO -\fBcurses\fR(3), \fBmenu\fR(3). +\fBcurses\fP(3), +\fBcurs_variables\fP(3), +\fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines are specific to ncurses. They were not supported on -Version 7, BSD or System V implementations. It is recommended that +These routines are specific to ncurses. +They were not supported on +Version 7, BSD or System V implementations. +It is recommended that any code depending on them be conditioned using NCURSES_VERSION. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/menu_userptr.3 b/lib/libmenu/menu_userptr.3 index 40158d53473..814406f82ad 100644 --- a/lib/libmenu/menu_userptr.3 +++ b/lib/libmenu/menu_userptr.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: menu_userptr.3,v 1.8 2015/11/15 22:10:16 jmc Exp $ +.\" $OpenBSD: menu_userptr.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,44 +30,38 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: menu_userptr.3,v 1.8 2015/11/15 22:10:16 jmc Exp $ -.TH menu_userptr 3 "" +.\" $Id: menu_userptr.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ +.TH menu_userptr 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBset_menu_userptr\fR, \fBmenu_userptr\fR -- associate application data with a menu item +\fBset_menu_userptr\fP, +\fBmenu_userptr\fP \- associate application data with a menu item .SH SYNOPSIS -\fB#include \fR -.br -int set_menu_userptr(MENU *menu, void *userptr); -.br -void *menu_userptr(const MENU *menu); +\fB#include \fP +.sp +\fBint set_menu_userptr(MENU *\fImenu\fB, void *\fIuserptr\fB);\fR .br +\fBvoid *menu_userptr(const MENU *\fImenu\fB);\fR .SH DESCRIPTION Every menu and every menu item has a field that can be used to hold application-specific data (that is, the menu-driver code leaves it alone). These functions get and set the menu user pointer field. .SH RETURN VALUE -\fBmenu_userptr\fR returns a pointer (which may be \fBNULL\fR). -It does not set errno. +\fBmenu_userptr\fP returns a pointer (which may be \fBNULL\fP). +It does not set \fBerrno\fP. .PP \fBset_menu_userptr\fP returns \fBE_OK\fP (success). .SH SEE ALSO -\fBcurses\fR(3), \fBmenu\fR(3). +\fBcurses\fP(3), \fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V menu library. They were not supported on +These routines emulate the System V menu library. +They were not supported on Version 7 or BSD versions. .PP The user pointer is a void pointer. We chose not to leave it as a char pointer for SVr4 compatibility. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/menu_win.3 b/lib/libmenu/menu_win.3 index 55ce2611c88..4b439a227bd 100644 --- a/lib/libmenu/menu_win.3 +++ b/lib/libmenu/menu_win.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: menu_win.3,v 1.8 2015/11/15 22:10:16 jmc Exp $ +.\" $OpenBSD: menu_win.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2006,2010 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,49 +30,48 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: menu_win.3,v 1.8 2015/11/15 22:10:16 jmc Exp $ -.TH menu_win 3 "" +.\" $Id: menu_win.3,v 1.9 2023/10/17 09:52:10 nicm Exp $ +.TH menu_win 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBset_menu_win\fR, \fBmenu_win\fR, -\fBset_menu_sub\fR, \fBmenu_sub\fR, -\fBscale_menu\fR -- make and break menu window and subwindow associations +\fBmenu_win\fP \- make and break menu window and subwindow associations .SH SYNOPSIS -\fB#include \fR +\fB#include \fP +.sp +\fBint set_menu_win(MENU *\fImenu\fB, WINDOW *\fIwin\fB);\fR .br -int set_menu_win(MENU *menu, WINDOW *win); -.br -WINDOW *menu_win(const MENU *menu); -.br -int set_menu_sub(MENU *menu, WINDOW *sub); -.br -WINDOW *menu_sub(const MENU *menu); -.br -int scale_menu(const MENU *menu, int *rows, int *columns); +\fBWINDOW *menu_win(const MENU *\fImenu\fB);\fR +.sp +\fBint set_menu_sub(MENU *\fImenu\fB, WINDOW *\fIsub\fB);\fR .br +\fBWINDOW *menu_sub(const MENU *\fImenu\fB);\fR +.sp +\fBint scale_menu(const MENU *\fImenu, int *\fIrows\fB, int *\fIcolumns);\fR .SH DESCRIPTION -Every menu has an associated pair of \fBcurses\fR windows. The menu window +Every menu has an associated pair of \fBcurses\fP windows. +The menu window displays any title and border associated with the window; the menu subwindow displays the items of the menu that are currently available for selection. .PP -The first four functions get and set those windows. It is not necessary to set -either window; by default, the driver code uses \fBstdscr\fR for both. +The first four functions get and set those windows. +It is not necessary to set +either window; by default, the driver code uses \fBstdscr\fP for both. .PP -In the \fBset_\fR functions, window argument of \fBNULL\fR is treated as though -it were \fBstsdcr\fR. A menu argument of \fBNULL\fR is treated as a request +In the \fBset_\fP functions, window argument of \fBNULL\fP is treated as though +it were \fBstsdcr\fP. A menu argument of \fBNULL\fP is treated as a request to change the system default menu window or subwindow. .PP -The function \fBscale_menu\fR returns the minimum size required for the -subwindow of \fImenu\fR. +The function \fBscale_menu\fP returns the minimum size required for the +subwindow of \fImenu\fP. .SH RETURN VALUE -Routines that return pointers return \fBNULL\fR on error. Routines that return +Routines that return pointers return \fBNULL\fP on error. +Routines that return an integer return one of the following error codes: .TP 5 .B E_OK The routine succeeded. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .TP 5 .B E_BAD_ARGUMENT Routine detected an incorrect or out-of-range argument. @@ -82,19 +82,16 @@ The menu has already been posted. .B E_NOT_CONNECTED No items are connected to the menu. .SH SEE ALSO -\fBcurses\fR(3), \fBmenu\fR(3). +\fBcurses\fP(3), +\fBcurs_variables\fP(3), +\fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V menu library. They were not supported on +These routines emulate the System V menu library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/mf_common.h b/lib/libmenu/mf_common.h index c1a4e32dba4..78153c5e2eb 100644 --- a/lib/libmenu/mf_common.h +++ b/lib/libmenu/mf_common.h @@ -1,7 +1,8 @@ -/* $OpenBSD: mf_common.h,v 1.7 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: mf_common.h,v 1.8 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2003,2004 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2005,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,7 +33,7 @@ * Author: Juergen Pfeifer, 1995,1997 * ****************************************************************************/ -/* $Id: mf_common.h,v 1.7 2010/01/12 23:22:08 nicm Exp $ */ +/* $Id: mf_common.h,v 1.8 2023/10/17 09:52:10 nicm Exp $ */ /* Common internal header for menu and form library */ @@ -65,10 +66,9 @@ extern int errno; #if USE_RCS_IDS #define MODULE_ID(id) static const char Ident[] = id; #else -#define MODULE_ID(id) /*nothing*/ +#define MODULE_ID(id) /*nothing */ #endif - /* Maximum regular 8-bit character code */ #define MAX_REGULAR_CHARACTER (0xff) @@ -82,16 +82,19 @@ extern int errno; #endif /* The few common values in the status fields for menus and forms */ -#define _POSTED (0x01U) /* menu or form is posted */ -#define _IN_DRIVER (0x02U) /* menu or form is processing hook routine */ +#define _POSTED (0x01U) /* menu or form is posted */ +#define _IN_DRIVER (0x02U) /* menu or form is processing hook routine */ + +#define SetStatus(target,mask) (target)->status |= (unsigned short) (mask) +#define ClrStatus(target,mask) (target)->status = (unsigned short) (target->status & (~mask)) /* Call object hook */ #define Call_Hook( object, handler ) \ if ( (object) != 0 && ((object)->handler) != (void *) 0 )\ {\ - (object)->status |= _IN_DRIVER;\ + SetStatus(object, _IN_DRIVER);\ (object)->handler(object);\ - (object)->status &= ~_IN_DRIVER;\ + ClrStatus(object, _IN_DRIVER);\ } #endif /* MF_COMMON_H_incl */ diff --git a/lib/libmenu/mitem_current.3 b/lib/libmenu/mitem_current.3 index c1a7c633b00..91f15e9cde1 100644 --- a/lib/libmenu/mitem_current.3 +++ b/lib/libmenu/mitem_current.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: mitem_current.3,v 1.6 2016/03/26 14:36:37 schwarze Exp $ +.\" $OpenBSD: mitem_current.3,v 1.7 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2006,2010 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,46 +30,46 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: mitem_current.3,v 1.6 2016/03/26 14:36:37 schwarze Exp $ -.TH SET_CURRENT_ITEM 3 "" +.\" $Id: mitem_current.3,v 1.7 2023/10/17 09:52:10 nicm Exp $ +.TH mitem_current 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBset_current_item\fR, \fBcurrent_item\fR, -\fBset_top_row\fR, \fBtop_row\fR, -\fBitem_index\fR - set and get current_menu_item +\fBmitem_current\fP \- set and get current_menu_item .SH SYNOPSIS -\fB#include \fR +\fB#include \fP +.sp +\fBint set_current_item(MENU *\fImenu\fB, ITEM *\fIitem\fB);\fR .br -int set_current_item(MENU *menu, const ITEM *item); -.br -ITEM *current_item(const MENU *menu); -.br -int set_top_row(MENU *menu, int row); -.br -int top_row(const MENU *menu); -.br -int item_index(const ITEM *item); +\fBITEM *current_item(const MENU *\fImenu\fB);\fR +.sp +\fBint set_top_row(MENU *\fImenu\fB, int \fIrow\fB);\fR .br +\fBint top_row(const MENU *\fImenu\fB);\fR +.sp +\fBint item_index(const ITEM *\fIitem\fB);\fR .SH DESCRIPTION -The function \fBset_current_item\fR sets the current item (the item on which -the menu cursor is positioned). \fBcurrent_item\fR returns a pointer to the +The function \fBset_current_item\fP sets the current item (the item on which +the menu cursor is positioned). +\fBcurrent_item\fP returns a pointer to the current item in the given menu. .PP -The function \fBset_top_row\fR sets the top row of the menu to show the given +The function \fBset_top_row\fP sets the top row of the menu to show the given row (the top row is initially 0, and is reset to this value whenever the -\fBO_ROWMAJOR\fR option is toggled). The item leftmost on the given row -becomes current. The function \fBtop_row\fR returns the number of the top menu +\fBO_ROWMAJOR\fP option is toggled). +The item leftmost on the given row +becomes current. +The function \fBtop_row\fP returns the number of the top menu row being displayed. .PP -The function \fBitem_index\fR returns the (zero-origin) index of \fIitem\fR in +The function \fBitem_index\fP returns the (zero-origin) index of \fIitem\fP in the menu's item pointer list. .SH RETURN VALUE -\fBcurrent_item\fR returns a pointer (which may be \fBNULL\fR). -It does not set errno. +\fBcurrent_item\fP returns a pointer (which may be \fBNULL\fP). +It does not set \fBerrno\fP. .PP -\fBtop_row\fR and \fBitem_index\fR return \fBERR\fR (the general \fBcurses\fR +\fBtop_row\fP and \fBitem_index\fP return \fBERR\fP (the general \fBcurses\fP error value) if their \fImenu\fP parameter is \fBNULL\fP. .PP -\fBset_current_item\fR and \fBset_top_row\fR return one of the following: +\fBset_current_item\fP and \fBset_top_row\fP return one of the following: .TP 5 .B E_OK The routine succeeded. @@ -83,24 +84,19 @@ Routine was called from an initialization or termination function. No items are connected to the menu. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .SH SEE ALSO -\fBcurses\fR(3), \fBmenu\fR(3). +\fBcurses\fP(3), \fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V menu library. They were not supported on +These routines emulate the System V menu library. +They were not supported on Version 7 or BSD versions. .PP -The SVr4 menu library documentation specifies the \fBtop_row\fR and -\fBindex_item\fR error value as -1 (which is the value of \fBERR\fR). +The SVr4 menu library documentation specifies the \fBtop_row\fP and +\fBindex_item\fP error value as \-1 (which is the value of \fBERR\fP). .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/mitem_name.3 b/lib/libmenu/mitem_name.3 index a4f1aeece5f..d91774316e3 100644 --- a/lib/libmenu/mitem_name.3 +++ b/lib/libmenu/mitem_name.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: mitem_name.3,v 1.6 2016/03/26 14:36:37 schwarze Exp $ +.\" $OpenBSD: mitem_name.3,v 1.7 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,40 +30,33 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: mitem_name.3,v 1.6 2016/03/26 14:36:37 schwarze Exp $ -.TH ITEM_NAME 3 "" +.\" $Id: mitem_name.3,v 1.7 2023/10/17 09:52:10 nicm Exp $ +.TH mitem_name 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBitem_name\fR, \fBitem_description\f - -get menu item name and description fields +\fBitem_name\fP, +\fBitem_description\fP \- get menu item name and description fields .SH SYNOPSIS -\fB#include \fR -.br -const char *item_name(const ITEM *item); -.br -const char *item_description(const ITEM *item); +\fB#include \fP +.sp +\fBconst char *item_name(const ITEM *\fIitem\fB);\fR .br +\fBconst char *item_description(const ITEM *\fIitem\fB);\fR .SH DESCRIPTION -The function \fBitem_name\fR returns the name part of the given item. +The function \fBitem_name\fP returns the name part of the given item. .br -The function \fBitem_description\fR returns the description part of the given +The function \fBitem_description\fP returns the description part of the given item. .SH RETURN VALUE -These routines return a pointer (which may be \fBNULL\fR). -They do not set errno. +These routines return a pointer (which may be \fBNULL\fP). +They do not set \fBerrno\fP. .SH SEE ALSO -\fBcurses\fR(3), \fBmenu\fR(3). +\fBcurses\fP(3), \fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY These routines emulate the System V menu library. They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/mitem_new.3 b/lib/libmenu/mitem_new.3 index 91575b2c1b6..cb7898e5274 100644 --- a/lib/libmenu/mitem_new.3 +++ b/lib/libmenu/mitem_new.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: mitem_new.3,v 1.7 2016/03/26 14:36:37 schwarze Exp $ +.\" $OpenBSD: mitem_new.3,v 1.8 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2003,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,30 +30,34 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: mitem_new.3,v 1.7 2016/03/26 14:36:37 schwarze Exp $ -.TH NEW_ITEM 3 "" +.\" $Id: mitem_new.3,v 1.8 2023/10/17 09:52:10 nicm Exp $ +.TH mitem_new 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBnew_item\fR, \fBfree_item\fR - create and destroy menu items +\fBnew_item\fP, +\fBfree_item\fP \- create and destroy menu items .SH SYNOPSIS -\fB#include \fR -.br -ITEM *new_item(const char *name, const char *description); -.br -int free_item(ITEM *item); +\fB#include \fP +.sp +\fBITEM *new_item(const char *\fIname\fB, const char *\fIdescription\fB);\fR .br +\fBint free_item(ITEM *\fIitem\fB);\fR .SH DESCRIPTION -The function \fBnew_item\fR allocates a new item and initializes it from the -\fBname\fR and \fBdescription\fR pointers. Please notice that the item stores -only the pointers to the name and description. Those pointers must be valid -during the lifetime of the item. So you should be very careful with names +The function \fBnew_item\fP allocates a new item and initializes it from the +\fBname\fP and \fBdescription\fP pointers. +Please notice that the item stores +only the pointers to the name and description. +Those pointers must be valid +during the lifetime of the item. +So you should be very careful with names or descriptions allocated on the stack of some routines. .br -The function \fBfree_item\fR de-allocates an item. Please notice that it +The function \fBfree_item\fP de-allocates an item. +Please notice that it is the responsibility of the application to release the memory for the name or the description of the item. .SH RETURN VALUE -The function \fBnew_item\fR returns \fBNULL\fR on error. -It sets errno according to the function's failure: +The function \fBnew_item\fP returns \fBNULL\fP on error. +It sets \fBerrno\fP according to the function's failure: .TP 5 .B E_BAD_ARGUMENT Routine detected an incorrect or out-of-range argument. @@ -60,7 +65,7 @@ Routine detected an incorrect or out-of-range argument. .B E_SYSTEM_ERROR System error occurred, e.g., malloc failure. .PP -The function \fBfree_item\fR returns one of the following: +The function \fBfree_item\fP returns one of the following: .TP 5 .B E_OK The routine succeeded. @@ -72,21 +77,16 @@ Routine detected an incorrect or out-of-range argument. Item is connected to a menu. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .SH SEE ALSO -\fBcurses\fR(3), \fBmenu\fR(3). +\fBcurses\fP(3), \fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V menu library. They were not supported on +These routines emulate the System V menu library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/mitem_opts.3 b/lib/libmenu/mitem_opts.3 index 1f2e537c408..9d4ff6b8800 100644 --- a/lib/libmenu/mitem_opts.3 +++ b/lib/libmenu/mitem_opts.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: mitem_opts.3,v 1.7 2016/03/26 14:36:37 schwarze Exp $ +.\" $OpenBSD: mitem_opts.3,v 1.8 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,59 +30,56 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: mitem_opts.3,v 1.7 2016/03/26 14:36:37 schwarze Exp $ -.TH SET_ITEM_OPTS 3 "" +.\" $Id: mitem_opts.3,v 1.8 2023/10/17 09:52:10 nicm Exp $ +.TH mitem_opts 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBset_item_opts\fR, \fBitem_opts_on\fR, \fBitem_opts_off\fR, -\fBitem_opts\fR - set and get menu item options +\fBset_item_opts\fP, +\fBitem_opts_on\fP, +\fBitem_opts_off\fP, +\fBitem_opts\fP \- set and get menu item options .SH SYNOPSIS -\fB#include \fR +\fB#include \fP +.sp +\fBint set_item_opts(ITEM *\fIitem\fB, Item_Options \fIopts\fB);\fR .br -int set_item_opts(ITEM *item, Item_Options opts); -.br -int item_opts_on(ITEM *item, Item_Options opts); -.br -int item_opts_off(ITEM *item, Item_Options opts); -.br -Item_Options item_opts(const ITEM *item); +\fBItem_Options item_opts(const ITEM *\fIitem\fB);\fR +.sp +\fBint item_opts_on(ITEM *\fIitem\fB, Item_Options \fIopts\fB);\fR .br +\fBint item_opts_off(ITEM *\fIitem\fB, Item_Options \fIopts\fB);\fR .SH DESCRIPTION -The function \fBset_item_opts\fR sets all the given item's option bits (menu -option bits may be logically OR'ed together). +The function \fBset_item_opts\fP sets all the given item's option bits (menu +option bits may be logically-OR'ed together). .PP -The function \fBitem_opts_on\fR turns on the given option bits, and leaves +The function \fBitem_opts_on\fP turns on the given option bits, and leaves others alone. .PP -The function \fBitem_opts_off\fR turns off the given option bits, and leaves +The function \fBitem_opts_off\fP turns off the given option bits, and leaves others alone. .PP -The function \fBitem_opts\fR returns the item's current option bits. +The function \fBitem_opts\fP returns the item's current option bits. .PP -There is only one defined option bit mask, \fBO_SELECTABLE\fR. When this is -on, the item may be selected during menu processing. This option defaults +There is only one defined option bit mask, \fBO_SELECTABLE\fP. When this is +on, the item may be selected during menu processing. +This option defaults to on. .SH RETURN VALUE -Except for \fBitem_opts\fR, each routine returns one of the following: +Except for \fBitem_opts\fP, each routine returns one of the following: .TP 5 .B E_OK The routine succeeded. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .SH SEE ALSO -\fBcurses\fR(3), \fBmenu\fR(3). +\fBcurses\fP(3), \fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V menu library. They were not supported on +These routines emulate the System V menu library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/mitem_userptr.3 b/lib/libmenu/mitem_userptr.3 index baa8e692310..6a8a59fdc54 100644 --- a/lib/libmenu/mitem_userptr.3 +++ b/lib/libmenu/mitem_userptr.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: mitem_userptr.3,v 1.6 2016/03/26 14:36:37 schwarze Exp $ +.\" $OpenBSD: mitem_userptr.3,v 1.7 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,45 +30,40 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: mitem_userptr.3,v 1.6 2016/03/26 14:36:37 schwarze Exp $ -.TH SET_ITEM_USERPTR 3 "" +.\" $Id: mitem_userptr.3,v 1.7 2023/10/17 09:52:10 nicm Exp $ +.TH mitem_userptr 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBset_item_userptr\fR, -\fBitem_userptr\fR - associate application data with a menu item +\fBset_item_userptr\fP, +\fBitem_userptr\fP \- associate application data with a menu item .SH SYNOPSIS -\fB#include \fR -.br -int set_item_userptr(ITEM *item, void *userptr); -.br -void *item_userptr(const ITEM *item); +\fB#include \fP +.sp +\fBint set_item_userptr(ITEM *\fIitem\fB, void *\fIuserptr\fB);\fR .br +\fBvoid *item_userptr(const ITEM *\fIitem\fB);\fR .SH DESCRIPTION Every menu item has a field that can be used to hold application-specific data -(that is, the menu-driver code leaves it alone). These functions get and set +(that is, the menu-driver code leaves it alone). +These functions get and set that field. .SH RETURN VALUE -The function \fBitem_userptr\fR returns a pointer (possibly \fBNULL\fR). -It does not set errno. +The function \fBitem_userptr\fP returns a pointer (possibly \fBNULL\fP). +It does not set \fBerrno\fP. .PP The \fBset_item_userptr\fP always returns \fBE_OK\fP (success). . .SH SEE ALSO -\fBcurses\fR(3), \fBmenu\fR(3). +\fBcurses\fP(3), \fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V menu library. They were not supported on +These routines emulate the System V menu library. +They were not supported on Version 7 or BSD versions. .PP The user pointer is a void pointer. We chose not to leave it as a char pointer for SVr4 compatibility. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/mitem_value.3 b/lib/libmenu/mitem_value.3 index 15830a41a62..61896d9d8bb 100644 --- a/lib/libmenu/mitem_value.3 +++ b/lib/libmenu/mitem_value.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: mitem_value.3,v 1.4 2016/03/26 14:36:37 schwarze Exp $ +.\" $OpenBSD: mitem_value.3,v 1.5 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2002,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2015 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,51 +29,46 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: mitem_value.3,v 1.4 2016/03/26 14:36:37 schwarze Exp $ -.TH SET_ITEM_VALUE 3 "" +.\" $Id: mitem_value.3,v 1.5 2023/10/17 09:52:10 nicm Exp $ +.TH mitem_value 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBset_item_value\fR, \fBitem_value\fR - set and get menu item values +\fBset_item_value\fP, +\fBitem_value\fP \- set and get menu item values .SH SYNOPSIS -\fB#include \fR -.br -int set_item_value(ITEM *item, bool value); -.br -bool item_value(const ITEM *item); +\fB#include \fP +.sp +\fBint set_item_value(ITEM *\fIitem\fB, bool \fIvalue\fB);\fR .br +\fBbool item_value(const ITEM *\fIitem\fB);\fR .SH DESCRIPTION -If you turn off the menu option \fBO_ONEVALUE\fR (e.g., with -\fBset_menu_opts\fR or \fBmenu_opts_off\fR; see \fBmenu_opts\fR(3)), the menu +If you turn off the menu option \fBO_ONEVALUE\fP (e.g., with +\fBset_menu_opts\fP or \fBmenu_opts_off\fP; see \fBmenu_opts\fP(3)), the menu becomes multi-valued; that is, more than one item may simultaneously be selected. .PP -In a multi_valued menu, you can used \fBset_item_value\fR to select the -given menu item (second argument \fBTRUE\fR) or deselect it (second argument -\fBFALSE\fR). +In a multi_valued menu, you can used \fBset_item_value\fP to select the +given menu item (second argument \fBTRUE\fP) or deselect it (second argument +\fBFALSE\fP). .SH RETURN VALUE -The function \fBset_item_value\fR returns one of the following: +The function \fBset_item_value\fP returns one of the following: .TP 5 .B E_OK The routine succeeded. .TP 5 .B E_SYSTEM_ERROR -System error occurred (see \fBerrno\fR). +System error occurred (see \fBerrno\fP(3)). .TP 5 .B E_REQUEST_DENIED The menu driver could not process the request. .SH SEE ALSO -\fBcurses\fR(3), \fBmenu\fR(3). +\fBcurses\fP(3), \fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V menu library. They were not supported on +These routines emulate the System V menu library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/mitem_visible.3 b/lib/libmenu/mitem_visible.3 index 071989c66f4..5779d9bdf10 100644 --- a/lib/libmenu/mitem_visible.3 +++ b/lib/libmenu/mitem_visible.3 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: mitem_visible.3,v 1.6 2016/03/26 14:36:37 schwarze Exp $ +.\" $OpenBSD: mitem_visible.3,v 1.7 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998,2010 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,33 +30,27 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: mitem_visible.3,v 1.6 2016/03/26 14:36:37 schwarze Exp $ -.TH ITEM_VISIBLE 3 "" +.\" $Id: mitem_visible.3,v 1.7 2023/10/17 09:52:10 nicm Exp $ +.TH mitem_visible 3 2023-07-01 "ncurses 6.4" "Library calls" .SH NAME -\fBitem_visible\fR - check visibility of a menu item +\fBmitem_visible\fP \- check visibility of a menu item .SH SYNOPSIS -\fB#include \fR -.br -bool item_visible(const ITEM *item); -.br +\fB#include \fP +.sp +\fBbool item_visible(const ITEM *\fIitem\fB);\fR .SH DESCRIPTION A menu item is visible when it is in the portion of a posted menu that is mapped onto the screen (if the menu is scrollable, in particular, this portion will be smaller than the whole menu). .SH SEE ALSO -\fBcurses\fR(3), \fBmenu\fR(3). +\fBcurses\fP(3), \fBmenu\fP(3). .SH NOTES -The header file \fB\fR automatically includes the header file -\fB\fR. +The header file \fB\fP automatically includes the header file +\fB\fP. .SH PORTABILITY -These routines emulate the System V menu library. They were not supported on +These routines emulate the System V menu library. +They were not supported on Version 7 or BSD versions. .SH AUTHORS -Juergen Pfeifer. Manual pages and adaptation for new curses by Eric -S. Raymond. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +Juergen Pfeifer. +Manual pages and adaptation for new curses by Eric S. Raymond. diff --git a/lib/libmenu/shlib_version b/lib/libmenu/shlib_version index 9c1551636c5..5b844bbf422 100644 --- a/lib/libmenu/shlib_version +++ b/lib/libmenu/shlib_version @@ -1,2 +1,2 @@ -major=6 +major=7 minor=0 diff --git a/lib/libpanel/Makefile b/lib/libpanel/Makefile index 2f96f37c9c4..15ab1056754 100644 --- a/lib/libpanel/Makefile +++ b/lib/libpanel/Makefile @@ -1,11 +1,12 @@ -# $OpenBSD: Makefile,v 1.12 2016/07/04 18:01:44 guenther Exp $ +# $OpenBSD: Makefile,v 1.13 2023/10/17 09:52:10 nicm Exp $ LIB= panel -SRCS= p_above.c p_below.c p_bottom.c p_delete.c p_hidden.c p_hide.c p_move.c \ - p_new.c p_replace.c p_show.c p_top.c p_update.c p_user.c p_win.c panel.c +SRCS= p_above.c p_below.c p_bottom.c p_delete.c p_hidden.c p_hide.c \ + p_move.c p_new.c p_replace.c p_show.c p_top.c p_update.c p_user.c \ + p_win.c panel.c HDRS= panel.h +CFLAGS+=-I${.CURDIR}/../libcurses -D_XOPEN_SOURCE_EXTENDED -DNDEBUG MAN= panel.3 -CFLAGS+= -I${.CURDIR}/../libcurses includes: @cd ${.CURDIR}; for i in ${HDRS}; do \ diff --git a/lib/libpanel/p_above.c b/lib/libpanel/p_above.c index b979d464e39..ccef19e5f48 100644 --- a/lib/libpanel/p_above.c +++ b/lib/libpanel/p_above.c @@ -1,7 +1,8 @@ -/* $OpenBSD: p_above.c,v 1.5 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: p_above.c,v 1.6 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,24 +32,56 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1995 * * and: Eric S. Raymond * + * and: Juergen Pfeifer 1997-1999,2008 * ****************************************************************************/ /* p_above.c */ #include "panel.priv.h" -MODULE_ID("$Id: p_above.c,v 1.5 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: p_above.c,v 1.6 2023/10/17 09:52:10 nicm Exp $") -NCURSES_EXPORT(PANEL *) +#if NCURSES_SP_FUNCS +PANEL_EXPORT(PANEL *) +ground_panel(SCREEN * sp) +{ + T((T_CALLED("ground_panel(%p)"), (void *)sp)); + if (sp) + { + struct panelhook *ph = NCURSES_SP_NAME(_nc_panelhook) (sp); + + if (_nc_bottom_panel) /* this is the pseudo panel */ + returnPanel(_nc_bottom_panel->above); + else + returnPanel(0); + } + else + { + if (0 == CURRENT_SCREEN) + returnPanel(0); + else + returnPanel(ground_panel(CURRENT_SCREEN)); + } +} +#endif + +PANEL_EXPORT(PANEL *) panel_above(const PANEL * pan) { - T((T_CALLED("panel_above(%p)"), pan)); - if (!pan) + PANEL *result; + + T((T_CALLED("panel_above(%p)"), (const void *)pan)); + if (pan) + result = pan->above; + else { +#if NCURSES_SP_FUNCS + result = ground_panel(CURRENT_SCREEN); +#else /* if top and bottom are equal, we have no or only the pseudo panel; if not, we return the panel above the pseudo panel */ - returnPanel(EMPTY_STACK()? (PANEL *) 0 : _nc_bottom_panel->above); + result = EMPTY_STACK()? (PANEL *) 0 : _nc_bottom_panel->above; +#endif } - else - returnPanel(pan->above); + returnPanel(result); } diff --git a/lib/libpanel/p_below.c b/lib/libpanel/p_below.c index c684bc9f5fb..ef3541716cb 100644 --- a/lib/libpanel/p_below.c +++ b/lib/libpanel/p_below.c @@ -1,7 +1,8 @@ -/* $OpenBSD: p_below.c,v 1.5 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: p_below.c,v 1.6 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,26 +32,57 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1995 * * and: Eric S. Raymond * + * and: Juergen Pfeifer 1997-1999,2008 * ****************************************************************************/ /* p_below.c */ #include "panel.priv.h" -MODULE_ID("$Id: p_below.c,v 1.5 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: p_below.c,v 1.6 2023/10/17 09:52:10 nicm Exp $") -NCURSES_EXPORT(PANEL *) -panel_below(const PANEL * pan) +#if NCURSES_SP_FUNCS +PANEL_EXPORT(PANEL *) +ceiling_panel(SCREEN * sp) { - T((T_CALLED("panel_below(%p)"), pan)); - if (!pan) + T((T_CALLED("ceiling_panel(%p)"), (void *)sp)); + if (sp) { + struct panelhook *ph = NCURSES_SP_NAME(_nc_panelhook) (sp); + /* if top and bottom are equal, we have no or only the pseudo panel */ returnPanel(EMPTY_STACK()? (PANEL *) 0 : _nc_top_panel); } else { + if (0 == CURRENT_SCREEN) + returnPanel(0); + else + returnPanel(ceiling_panel(CURRENT_SCREEN)); + } +} +#endif + +PANEL_EXPORT(PANEL *) +panel_below(const PANEL * pan) +{ + PANEL *result; + + T((T_CALLED("panel_below(%p)"), (const void *)pan)); + if (pan) + { + GetHook(pan); /* we must not return the pseudo panel */ - returnPanel(Is_Pseudo(pan->below) ? (PANEL *) 0 : pan->below); + result = Is_Pseudo(pan->below) ? (PANEL *) 0 : pan->below; + } + else + { +#if NCURSES_SP_FUNCS + result = ceiling_panel(CURRENT_SCREEN); +#else + /* if top and bottom are equal, we have no or only the pseudo panel */ + result = EMPTY_STACK()? (PANEL *) 0 : _nc_top_panel; +#endif } + returnPanel(result); } diff --git a/lib/libpanel/p_bottom.c b/lib/libpanel/p_bottom.c index 767de9865eb..d4c9c5b51fa 100644 --- a/lib/libpanel/p_bottom.c +++ b/lib/libpanel/p_bottom.c @@ -1,7 +1,8 @@ -/* $OpenBSD: p_bottom.c,v 1.6 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: p_bottom.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2005 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2008,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,27 +32,29 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1995 * * and: Eric S. Raymond * + * and: Juergen Pfeifer 1997-1999,2008 * ****************************************************************************/ /* p_bottom.c - * Place a panel on bottom of the stack; may already be in the stack + * Place a panel on bottom of the stack; may already be in the stack */ #include "panel.priv.h" -MODULE_ID("$Id: p_bottom.c,v 1.6 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: p_bottom.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") -NCURSES_EXPORT(int) +PANEL_EXPORT(int) bottom_panel(PANEL * pan) { int err = OK; - T((T_CALLED("bottom_panel(%p)"), pan)); + T((T_CALLED("bottom_panel(%p)"), (void *)pan)); if (pan) { + GetHook(pan); if (!Is_Bottom(pan)) { - dBug(("--> bottom_panel %s", USER_PTR(pan->user))); + dBug(("--> bottom_panel %s", USER_PTR(pan->user, 1))); HIDE_PANEL(pan, err, OK); assert(_nc_bottom_panel == _nc_stdscr_pseudo_panel); diff --git a/lib/libpanel/p_delete.c b/lib/libpanel/p_delete.c index cc234d70633..1c8b6cb6425 100644 --- a/lib/libpanel/p_delete.c +++ b/lib/libpanel/p_delete.c @@ -1,7 +1,8 @@ -/* $OpenBSD: p_delete.c,v 1.6 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: p_delete.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +32,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1995 * * and: Eric S. Raymond * + * and: Juergen Pfeifer 1999,2008 * ****************************************************************************/ /* p_delete.c @@ -38,18 +40,20 @@ */ #include "panel.priv.h" -MODULE_ID("$Id: p_delete.c,v 1.6 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: p_delete.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") -NCURSES_EXPORT(int) -del_panel(PANEL * pan) +PANEL_EXPORT(int) +del_panel(PANEL *pan) { int err = OK; - T((T_CALLED("del_panel(%p)"), pan)); + T((T_CALLED("del_panel(%p)"), (void *)pan)); if (pan) { - dBug(("--> del_panel %s", USER_PTR(pan->user))); + GetHook(pan); HIDE_PANEL(pan, err, OK); + dBug(("...discard ptr=%s", USER_PTR(pan->user, 1))); + dBug(("...deleted pan=%p", (void *)pan)); free((void *)pan); } else diff --git a/lib/libpanel/p_hidden.c b/lib/libpanel/p_hidden.c index 14db8e9f52f..575be88214a 100644 --- a/lib/libpanel/p_hidden.c +++ b/lib/libpanel/p_hidden.c @@ -1,7 +1,8 @@ -/* $OpenBSD: p_hidden.c,v 1.5 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: p_hidden.c,v 1.6 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +32,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1995 * * and: Eric S. Raymond * + * and: Juergen Pfeifer 1997-1999,2008 * ****************************************************************************/ /* p_hidden.c @@ -38,13 +40,18 @@ */ #include "panel.priv.h" -MODULE_ID("$Id: p_hidden.c,v 1.5 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: p_hidden.c,v 1.6 2023/10/17 09:52:10 nicm Exp $") -NCURSES_EXPORT(int) +PANEL_EXPORT(int) panel_hidden(const PANEL * pan) { - T((T_CALLED("panel_hidden(%p)"), pan)); - if (!pan) - returnCode(ERR); - returnCode(IS_LINKED(pan) ? FALSE : TRUE); + int rc = ERR; + + T((T_CALLED("panel_hidden(%p)"), (const void *)pan)); + if (pan) + { + GetHook(pan); + rc = (IS_LINKED(pan) ? FALSE : TRUE); + } + returnCode(rc); } diff --git a/lib/libpanel/p_hide.c b/lib/libpanel/p_hide.c index c6795095e7c..64a0210f5bd 100644 --- a/lib/libpanel/p_hide.c +++ b/lib/libpanel/p_hide.c @@ -1,7 +1,8 @@ -/* $OpenBSD: p_hide.c,v 1.6 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: p_hide.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -38,23 +39,27 @@ */ #include "panel.priv.h" -MODULE_ID("$Id: p_hide.c,v 1.6 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: p_hide.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") -NCURSES_EXPORT(int) +PANEL_EXPORT(int) hide_panel(register PANEL * pan) { - int err = OK; + int err = ERR; - T((T_CALLED("hide_panel(%p)"), pan)); - if (!pan) - returnCode(ERR); + T((T_CALLED("hide_panel(%p)"), (void *)pan)); - dBug(("--> hide_panel %s", USER_PTR(pan->user))); - dStack("", 1, pan); + if (pan) + { + GetHook(pan); - HIDE_PANEL(pan, err, ERR); + dBug(("--> hide_panel %s", USER_PTR(pan->user, 1))); + dStack("", 1, pan); - dStack("", 9, pan); + HIDE_PANEL(pan, err, ERR); + err = OK; + + dStack("", 9, pan); + } returnCode(err); } diff --git a/lib/libpanel/p_move.c b/lib/libpanel/p_move.c index 353bd310744..bf65bc7b712 100644 --- a/lib/libpanel/p_move.c +++ b/lib/libpanel/p_move.c @@ -1,7 +1,8 @@ -/* $OpenBSD: p_move.c,v 1.6 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: p_move.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2008,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +32,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1995 * * and: Eric S. Raymond * + * and: Juergen Pfeifer 1997-1999,2009 * ****************************************************************************/ /* p_move.c @@ -38,21 +40,24 @@ */ #include "panel.priv.h" -MODULE_ID("$Id: p_move.c,v 1.6 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: p_move.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") -NCURSES_EXPORT(int) +PANEL_EXPORT(int) move_panel(PANEL * pan, int starty, int startx) { - T((T_CALLED("move_panel(%p,%d,%d)"), pan, starty, startx)); + int rc = ERR; - if (!pan) - returnCode(ERR); + T((T_CALLED("move_panel(%p,%d,%d)"), (void *)pan, starty, startx)); - if (IS_LINKED(pan)) + if (pan) { - Touchpan(pan); - PANEL_UPDATE(pan, (PANEL *) 0); + GetHook(pan); + if (IS_LINKED(pan)) + { + Touchpan(pan); + PANEL_UPDATE(pan, (PANEL *) 0); + } + rc = mvwin(pan->win, starty, startx); } - - returnCode(mvwin(pan->win, starty, startx)); + returnCode(rc); } diff --git a/lib/libpanel/p_new.c b/lib/libpanel/p_new.c index f1f5018e6bf..cbba62d437a 100644 --- a/lib/libpanel/p_new.c +++ b/lib/libpanel/p_new.c @@ -1,7 +1,8 @@ -/* $OpenBSD: p_new.c,v 1.5 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: p_new.c,v 1.6 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2008 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -36,15 +37,33 @@ ****************************************************************************/ /* p_new.c - * Creation of a new panel + * Creation of a new panel */ #include "panel.priv.h" -MODULE_ID("$Id: p_new.c,v 1.5 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: p_new.c,v 1.6 2023/10/17 09:52:10 nicm Exp $") #ifdef TRACE static char *stdscr_id; static char *new_id; + +static PANEL * +AllocPanel(const char *name) +{ + PANEL *result = typeMalloc(PANEL, 1); + + _tracef("create :%s %p", name, (void *)result); + return result; +} +#define InitUser(name) \ + if (!name ## _id) \ + name ## _id = strdup(#name); \ + pan->user = name ## _id; \ + _tracef("create :user_ptr %p", pan->user) +#else +#define AllocPanel(name) typeMalloc(PANEL, 1) +#define InitUser(name) \ + pan->user = (void *)0 #endif /*+------------------------------------------------------------------------- @@ -52,63 +71,60 @@ static char *new_id; Establish the pseudo panel for stdscr if necessary. --------------------------------------------------------------------------*/ static PANEL * -root_panel(void) +root_panel(NCURSES_SP_DCL0) { - if (_nc_stdscr_pseudo_panel == (PANEL *) 0) +#if NCURSES_SP_FUNCS + struct panelhook *ph = NCURSES_SP_NAME(_nc_panelhook) (sp); + +#elif NO_LEAKS + struct panelhook *ph = _nc_panelhook(); +#endif + + if (_nc_stdscr_pseudo_panel == (PANEL *)0) { - assert(stdscr && !_nc_bottom_panel && !_nc_top_panel); + assert(SP_PARM && SP_PARM->_stdscr && !_nc_bottom_panel && !_nc_top_panel); #if NO_LEAKS - _nc_panelhook()->destroy = del_panel; + ph->destroy = del_panel; #endif - _nc_stdscr_pseudo_panel = (PANEL *) malloc(sizeof(PANEL)); + _nc_stdscr_pseudo_panel = AllocPanel("root_panel"); if (_nc_stdscr_pseudo_panel != 0) { PANEL *pan = _nc_stdscr_pseudo_panel; - WINDOW *win = stdscr; + WINDOW *win = SP_PARM->_stdscr; pan->win = win; - pan->below = (PANEL *) 0; - pan->above = (PANEL *) 0; -#ifdef TRACE - if (!stdscr_id) - stdscr_id = strdup("stdscr"); - pan->user = stdscr_id; -#else - pan->user = (void *)0; -#endif + pan->below = (PANEL *)0; + pan->above = (PANEL *)0; + InitUser(stdscr); _nc_bottom_panel = _nc_top_panel = pan; } } return _nc_stdscr_pseudo_panel; } -NCURSES_EXPORT(PANEL *) +PANEL_EXPORT(PANEL *) new_panel(WINDOW *win) { - PANEL *pan = (PANEL *) 0; + PANEL *pan = (PANEL *)0; - T((T_CALLED("new_panel(%p)"), win)); + GetWindowHook(win); + + T((T_CALLED("new_panel(%p)"), (void *)win)); if (!win) returnPanel(pan); if (!_nc_stdscr_pseudo_panel) - (void)root_panel(); + (void)root_panel(NCURSES_SP_ARG); assert(_nc_stdscr_pseudo_panel); - if (!(win->_flags & _ISPAD) && (pan = (PANEL *) malloc(sizeof(PANEL)))) + if ((pan = AllocPanel("new_panel")) != NULL) { pan->win = win; - pan->above = (PANEL *) 0; - pan->below = (PANEL *) 0; -#ifdef TRACE - if (!new_id) - new_id = strdup("new"); - pan->user = new_id; -#else - pan->user = (char *)0; -#endif + pan->above = (PANEL *)0; + pan->below = (PANEL *)0; + InitUser(new); (void)show_panel(pan); } returnPanel(pan); diff --git a/lib/libpanel/p_replace.c b/lib/libpanel/p_replace.c index c0bb532cc1a..dd4360f8a87 100644 --- a/lib/libpanel/p_replace.c +++ b/lib/libpanel/p_replace.c @@ -1,7 +1,8 @@ -/* $OpenBSD: p_replace.c,v 1.6 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: p_replace.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -38,23 +39,25 @@ */ #include "panel.priv.h" -MODULE_ID("$Id: p_replace.c,v 1.6 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: p_replace.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") -NCURSES_EXPORT(int) +PANEL_EXPORT(int) replace_panel(PANEL * pan, WINDOW *win) { - T((T_CALLED("replace_panel(%p,%p)"), pan, win)); + int rc = ERR; - if (!pan) - returnCode(ERR); + T((T_CALLED("replace_panel(%p,%p)"), (void *)pan, (void *)win)); - if (IS_LINKED(pan)) + if (pan) { - Touchpan(pan); - PANEL_UPDATE(pan, (PANEL *) 0); + GetHook(pan); + if (IS_LINKED(pan)) + { + Touchpan(pan); + PANEL_UPDATE(pan, (PANEL *) 0); + } + pan->win = win; + rc = OK; } - - pan->win = win; - - returnCode(OK); + returnCode(rc); } diff --git a/lib/libpanel/p_show.c b/lib/libpanel/p_show.c index d841b6cbddf..d836acad9aa 100644 --- a/lib/libpanel/p_show.c +++ b/lib/libpanel/p_show.c @@ -1,7 +1,8 @@ -/* $OpenBSD: p_show.c,v 1.6 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: p_show.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2005 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -34,38 +35,41 @@ ****************************************************************************/ /* p_show.c - * Place a panel on top of the stack; may already be in the stack + * Place a panel on top of the stack; may already be in the stack */ #include "panel.priv.h" -MODULE_ID("$Id: p_show.c,v 1.6 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: p_show.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") -NCURSES_EXPORT(int) +PANEL_EXPORT(int) show_panel(PANEL * pan) { - int err = OK; + int err = ERR; - T((T_CALLED("show_panel(%p)"), pan)); + T((T_CALLED("show_panel(%p)"), (void *)pan)); - if (!pan) - returnCode(ERR); + if (pan) + { + GetHook(pan); - if (Is_Top(pan)) - returnCode(OK); + if (Is_Top(pan)) + returnCode(OK); - dBug(("--> show_panel %s", USER_PTR(pan->user))); + dBug(("--> show_panel %s", USER_PTR(pan->user, 1))); - HIDE_PANEL(pan, err, OK); + HIDE_PANEL(pan, err, OK); - dStack("", 1, pan); - assert(_nc_bottom_panel == _nc_stdscr_pseudo_panel); + dStack("", 1, pan); + assert(_nc_bottom_panel == _nc_stdscr_pseudo_panel); - _nc_top_panel->above = pan; - pan->below = _nc_top_panel; - pan->above = (PANEL *) 0; - _nc_top_panel = pan; + _nc_top_panel->above = pan; + pan->below = _nc_top_panel; + pan->above = (PANEL *) 0; + _nc_top_panel = pan; - dStack("", 9, pan); + err = OK; - returnCode(OK); + dStack("", 9, pan); + } + returnCode(err); } diff --git a/lib/libpanel/p_top.c b/lib/libpanel/p_top.c index f20a91b021b..c18d1b2daae 100644 --- a/lib/libpanel/p_top.c +++ b/lib/libpanel/p_top.c @@ -1,7 +1,8 @@ -/* $OpenBSD: p_top.c,v 1.4 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: p_top.c,v 1.5 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2005,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -38,11 +39,11 @@ */ #include "panel.priv.h" -MODULE_ID("$Id: p_top.c,v 1.4 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: p_top.c,v 1.5 2023/10/17 09:52:10 nicm Exp $") -NCURSES_EXPORT(int) +PANEL_EXPORT(int) top_panel(PANEL * pan) { - T((T_CALLED("top_panel(%p)"), pan)); + T((T_CALLED("top_panel(%p)"), (void *)pan)); returnCode(show_panel(pan)); } diff --git a/lib/libpanel/p_update.c b/lib/libpanel/p_update.c index 63b99459dcf..46325443092 100644 --- a/lib/libpanel/p_update.c +++ b/lib/libpanel/p_update.c @@ -1,7 +1,8 @@ -/* $OpenBSD: p_update.c,v 1.6 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: p_update.c,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2009,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,6 +32,7 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1995 * * and: Eric S. Raymond * + * and: Juergen Pfeifer 1997-1999,2008 * ****************************************************************************/ /* p_update.c @@ -38,28 +40,42 @@ */ #include "panel.priv.h" -MODULE_ID("$Id: p_update.c,v 1.6 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: p_update.c,v 1.7 2023/10/17 09:52:10 nicm Exp $") -NCURSES_EXPORT(void) -update_panels(void) +PANEL_EXPORT(void) +NCURSES_SP_NAME(update_panels) (NCURSES_SP_DCL0) { PANEL *pan; - T((T_CALLED("update_panels()"))); + T((T_CALLED("update_panels(%p)"), (void *)SP_PARM)); dBug(("--> update_panels")); - pan = _nc_bottom_panel; - while (pan && pan->above) - { - PANEL_UPDATE(pan, pan->above); - pan = pan->above; - } - pan = _nc_bottom_panel; - while (pan) + if (SP_PARM) { - Wnoutrefresh(pan); - pan = pan->above; + GetScreenHook(SP_PARM); + + pan = _nc_bottom_panel; + while (pan && pan->above) + { + PANEL_UPDATE(pan, pan->above); + pan = pan->above; + } + + pan = _nc_bottom_panel; + while (pan) + { + Wnoutrefresh(pan); + pan = pan->above; + } } returnVoid; } + +#if NCURSES_SP_FUNCS +PANEL_EXPORT(void) +update_panels(void) +{ + NCURSES_SP_NAME(update_panels) (CURRENT_SCREEN); +} +#endif diff --git a/lib/libpanel/p_user.c b/lib/libpanel/p_user.c index 357a8252d6e..6239d3e8372 100644 --- a/lib/libpanel/p_user.c +++ b/lib/libpanel/p_user.c @@ -1,7 +1,8 @@ -/* $OpenBSD: p_user.c,v 1.4 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: p_user.c,v 1.5 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2005 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2005,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -34,25 +35,25 @@ ****************************************************************************/ /* p_user.c - * Set/Get panels user pointer + * Set/Get panels user pointer */ #include "panel.priv.h" -MODULE_ID("$Id: p_user.c,v 1.4 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: p_user.c,v 1.5 2023/10/17 09:52:10 nicm Exp $") -NCURSES_EXPORT(int) +PANEL_EXPORT(int) set_panel_userptr(PANEL * pan, NCURSES_CONST void *uptr) { - T((T_CALLED("set_panel_userptr(%p,%p)"), pan, uptr)); + T((T_CALLED("set_panel_userptr(%p,%p)"), (void *)pan, (NCURSES_CONST void *)uptr)); if (!pan) returnCode(ERR); pan->user = uptr; returnCode(OK); } -NCURSES_EXPORT(NCURSES_CONST void *) +PANEL_EXPORT(NCURSES_CONST void *) panel_userptr(const PANEL * pan) { - T((T_CALLED("panel_userptr(%p)"), pan)); + T((T_CALLED("panel_userptr(%p)"), (const void *)pan)); returnCVoidPtr(pan ? pan->user : (NCURSES_CONST void *)0); } diff --git a/lib/libpanel/p_win.c b/lib/libpanel/p_win.c index 7559b4311b5..b236fd997e6 100644 --- a/lib/libpanel/p_win.c +++ b/lib/libpanel/p_win.c @@ -1,7 +1,8 @@ -/* $OpenBSD: p_win.c,v 1.4 2010/01/12 23:22:08 nicm Exp $ */ +/* $OpenBSD: p_win.c,v 1.5 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2000,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2005,2010 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -38,11 +39,11 @@ */ #include "panel.priv.h" -MODULE_ID("$Id: p_win.c,v 1.4 2010/01/12 23:22:08 nicm Exp $") +MODULE_ID("$Id: p_win.c,v 1.5 2023/10/17 09:52:10 nicm Exp $") -NCURSES_EXPORT(WINDOW *) +PANEL_EXPORT(WINDOW *) panel_window(const PANEL * pan) { - T((T_CALLED("panel_window(%p)"), pan)); + T((T_CALLED("panel_window(%p)"), (const void *)pan)); returnWin(pan ? pan->win : (WINDOW *)0); } diff --git a/lib/libpanel/panel.3 b/lib/libpanel/panel.3 index 46918c9f0b9..9a97a71d1c2 100644 --- a/lib/libpanel/panel.3 +++ b/lib/libpanel/panel.3 @@ -1,7 +1,8 @@ -.\" $OpenBSD: panel.3,v 1.10 2015/11/12 12:44:27 jmc Exp $ +.\" $OpenBSD: panel.3,v 1.11 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2016,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,168 +29,250 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: panel.3,v 1.10 2015/11/12 12:44:27 jmc Exp $ -.TH panel 3 "" -.ds n 5 -.ds d /usr/share/misc/terminfo +.\" $Id: panel.3,v 1.11 2023/10/17 09:52:10 nicm Exp $ +.TH panel 3 2023-08-19 "ncurses 6.4" "Library calls" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .SH NAME -new_panel, bottom_panel, top_panel, show_panel, update_panels, -hide_panel, panel_window, replace_panel, move_panel, panel_hidden, -panel_above, panel_below, set_panel_userptr, panel_userptr, del_panel -- panel stack extension for curses +panel \- panel stack extension for curses .SH SYNOPSIS -\fB#include \fR +\fB#include \fP .P -\fBcc [flags] sourcefiles -lpanel -lncurses\fR +\fBcc [flags] sourcefiles \-lpanel \-lncurses\fP .P -\fBPANEL *new_panel(WINDOW *win)\fR +\fBPANEL *new_panel(WINDOW *\fIwin\fB);\fR +.sp +\fBint bottom_panel(PANEL *\fIpan\fB);\fR .br -\fBint bottom_panel(PANEL *pan)\fR +\fBint top_panel(PANEL *\fIpan\fB);\fR .br -\fBint top_panel(PANEL *pan)\fR +\fBint show_panel(PANEL *\fIpan\fB);\fR .br -\fBint show_panel(PANEL *pan)\fR +\fBvoid update_panels(void);\fP .br -\fBvoid update_panels();\fR +\fBint hide_panel(PANEL *\fIpan\fB);\fR +.sp +\fBWINDOW *panel_window(const PANEL *\fIpan\fB);\fR .br -\fBint hide_panel(PANEL *pan)\fR +\fBint replace_panel(PANEL *\fIpan\fB, WINDOW *\fIwindow\fB);\fR .br -\fBWINDOW *panel_window(const PANEL *pan)\fR +\fBint move_panel(PANEL *\fIpan\fB, int \fIstarty\fB, int \fIstartx\fB);\fR .br -\fBint replace_panel(PANEL *pan, WINDOW *window)\fR +\fBint panel_hidden(const PANEL *\fIpan\fB);\fR +.sp +\fBPANEL *panel_above(const PANEL *\fIpan\fB);\fR .br -\fBint move_panel(PANEL *pan, int starty, int startx)\fR +\fBPANEL *panel_below(const PANEL *\fIpan\fB);\fR +.sp +\fBint set_panel_userptr(PANEL *\fIpan\fB, const void *\fIptr\fB);\fR .br -\fBint panel_hidden(const PANEL *pan)\fR +\fBconst void *panel_userptr(const PANEL *\fIpan\fB);\fR +.sp +\fBint del_panel(PANEL *\fIpan\fB);\fR +.sp +\fR/* ncurses-extensions */\fP .br -\fBPANEL *panel_above(const PANEL *pan)\fR +\fBPANEL *ground_panel(SCREEN *\fIsp\fB);\fR .br -\fBPANEL *panel_below(const PANEL *pan)\fR -.br -\fBint set_panel_userptr(PANEL *pan, const void *ptr)\fR -.br -\fBconst void *panel_userptr(const PANEL *pan)\fR -.br -\fBint del_panel(PANEL *pan)\fR +\fBPANEL *ceiling_panel(SCREEN *\fIsp\fB);\fR .br .SH DESCRIPTION -Panels are \fBcurses\fR(3) windows with the added feature of -depth. Panel functions allow the use of stacked windows and ensure -the proper portions of each window and the curses \fBstdscr\fR window are +Panels are \fBcurses\fP(3) windows with the added feature of +depth. +Panel functions allow the use of stacked windows and ensure +the proper portions of each window and the curses \fBstdscr\fP window are hidden or displayed when panels are added, moved, modified or removed. -The set of currently visible panels is the stack of panels. The -\fBstdscr\fR window is beneath all panels, and is not considered part +The set of currently visible panels is the stack of panels. +The +\fBstdscr\fP window is beneath all panels, and is not considered part of the stack. .P -A window is associated with every panel. The panel routines enable +A window is associated with every panel. +The panel routines enable you to create, move, hide, and show panels, as well as position a panel at any desired location in the stack. .P -Panel routines are a functional layer added to \fBcurses\fR(3), make only +Panel routines are a functional layer added to \fBcurses\fP(3), make only high-level curses calls, and work anywhere terminfo curses does. .SH FUNCTIONS -.TP -.B new_panel(win) -allocates a \fBPANEL\fR structure, associates it with -\fBwin\fR, places the panel on the top of the stack (causes it -to be displayed above any other panel) and returns a +.\" --------- +.SS bottom_panel +\fBbottom_panel(\fIpan\fB)\fR +puts panel \fIpan\fP at the bottom of all panels. +.\" --------- +.SS ceiling_panel +\fBceiling_panel(\fIsp\fB)\fR +acts like \fBpanel_below(NULL)\fP, for the given \fBSCREEN\fP \fIsp\fP. +.\" --------- +.SS del_panel +\fBdel_panel(\fIpan\fB)\fR +removes the given panel \fIpan\fP from the stack and deallocates the +\fBPANEL\fP structure (but not its associated window). +.\" --------- +.SS ground_panel +\fBground_panel(\fIsp\fB)\fR +acts like \fBpanel_above(NULL)\fP, for the given \fBSCREEN\fP \fIsp\fP. +.\" --------- +.SS hide_panel +\fBhide_panel(\fIpan\fB)\fR +removes the given panel \fIpan\fP from the panel stack +and thus hides it from view. +The \fBPANEL\fP structure is not lost, merely removed from the stack. +.\" --------- +.SS move_panel +\fBmove_panel(\fIpan\fB,\fIstarty\fB,\fIstartx\fB)\fR +moves the given panel \fIpan\fP's window so that its upper-left corner is at +\fIstarty\fP, \fIstartx\fP. +It does not change the position of the panel in the stack. +Be sure to use this function, not \fBmvwin\fP(3), to move a panel window. +.\" --------- +.SS new_panel +\fBnew_panel(\fIwin\fB)\fR allocates a \fBPANEL\fR structure, +associates it with \fIwin\fP, places the panel on the top of the stack +(causes it to be displayed above any other panel) and returns a pointer to the new panel. -.TP -.B update_panels() -refreshes the virtual screen to reflect the relations between the -panels in the stack, but does not call doupdate() to refresh the -physical screen. Use this function and not wrefresh or wnoutrefresh. -update_panels() may be called more than once before a call to -doupdate(), but doupdate() is the function responsible for updating -the physical screen. -.TP -.B del_panel(pan) -removes the given panel from the stack and deallocates the -\fBPANEL\fR structure (but not its associated window). -.TP -.B hide_panel(pan) -removes the given panel from the panel stack and thus hides it from -view. The \fBPANEL\fR structure is not lost, merely removed from the stack. -.TP -.B panel_hidden(pan) -returns TRUE if the panel is in the panel stack, -FALSE if it is not. -If the panel is a null pointer, return ERR. -.TP -.B show_panel(pan) -makes a hidden panel visible by placing it on top of the panels in the -panel stack. See COMPATIBILITY below. -.TP -.B top_panel(pan) -puts the given visible panel on top of all panels in the stack. See -COMPATIBILITY below. -.TP -.B bottom_panel(pan) -puts panel at the bottom of all panels. -.TP -.B move_panel(pan,starty,startx) -moves the given panel window so that its upper-left corner is at -\fBstarty\fR, \fBstartx\fR. It does not change the position of the -panel in the stack. Be sure to use this function, not \fBmvwin()\fR, -to move a panel window. -.TP -.B replace_panel(pan,window) -replaces the current window of panel with \fBwindow\fR (useful, for -example if you want to resize a panel; if you're using \fBncurses\fR, -you can call \fBreplace_panel\fR on the output of \fBwresize\fR(3)). +.\" --------- +.SS panel_above +\fBpanel_above(\fIpan\fB)\fR +returns a pointer to the panel above \fIpan\fP. +If the panel argument is +\fB(PANEL *)0\fP, it returns a pointer to the bottom panel in the stack. +.\" --------- +.SS panel_below +\fBpanel_below(\fIpan\fB)\fR +returns a pointer to the panel just below \fIpan\fP. +If the panel argument +is \fB(PANEL *)0\fP, it returns a pointer to the top panel in the stack. +.\" --------- +.SS panel_hidden +\fBpanel_hidden(\fIpan\fB)\fR +returns \fBFALSE\fP if the panel \fIpan\fP is in the panel stack, +\fBTRUE\fP if it is not. +If the panel is a null pointer, return \fBERR\fP. +.\" --------- +.SS panel_userptr +\fBpanel_userptr(\fIpan\fB)\fR +returns the user pointer for a given panel \fIpan\fP. +.\" --------- +.SS panel_window +\fBpanel_window(\fIpan\fB)\fR +returns a pointer to the window of the given panel \fIpan\fP. +.\" --------- +.SS replace_panel +\fBreplace_panel(\fIpan\fB,\fIwindow\fB)\fR +replaces the current window of panel \fIpan\fP with \fIwindow\fP +This is useful, for example if you want to resize a panel. +In \fBncurses\fP, you can call \fBreplace_panel\fP +to resize a panel using a window resized with \fBwresize\fP(3). It does not change the position of the panel in the stack. -.TP -.B panel_above(pan) -returns a pointer to the panel above pan. If the panel argument is -\fB(PANEL *)0\fR, it returns a pointer to the bottom panel in the stack. -.TP -.B panel_below(pan) -returns a pointer to the panel just below pan. If the panel argument -is \fB(PANEL *)0\fR, it returns a pointer to the top panel in the stack. -.TP -.B set_panel_userptr(pan,ptr) +.\" --------- +.SS set_panel_userptr +\fBset_panel_userptr(\fIpan\fB,\fIptr\fB)\fR sets the panel's user pointer. -.TP -.B panel_userptr(pan) -returns the user pointer for a given panel. -.TP -.B panel_window(pan) -returns a pointer to the window of the given panel. +.\" --------- +.SS show_panel +\fBshow_panel(\fIpan\fB)\fR +makes a hidden panel visible by placing it on top of the panels in the +panel stack. +See \fBCOMPATIBILITY\fP below. +.\" --------- +.SS top_panel +\fBtop_panel(\fIpan\fB)\fR +puts the given visible panel \fIpan\fP on top of all panels in the stack. +See \fBCOMPATIBILITY\fP below. +.\" --------- +.SS update_panels +\fBupdate_panels()\fR +refreshes the \fIvirtual screen\fP to reflect the relations between the +panels in the stack, but does not call \fBdoupdate\fP(3) to refresh the +\fIphysical screen\fP. +Use this function and not \fBwrefresh\fP(3) or \fBwnoutrefresh\fP(3). +.PP +\fBupdate_panels\fP may be called more than once before a call to +\fBdoupdate\fP, but \fBdoupdate\fP is the function responsible for updating +the \fIphysical screen\fP. .SH DIAGNOSTICS -Each routine that returns a pointer returns \fBNULL\fR if an error -occurs. Each routine that returns an int value returns \fBOK\fR if it -executes successfully and \fBERR\fR if not. +Each routine that returns a pointer returns \fBNULL\fP if an error +occurs. +Each routine that returns an int value returns \fBOK\fP if it +executes successfully and \fBERR\fP if not. +.PP +Except as noted, the \fIpan\fP and \fIwindow\fP parameters must be non-null. +If those are null, an error is returned. +.PP +The \fBmove_panel\fP function uses \fBmvwin\fP(3), +and will return an error if \fBmvwin\fP returns an error. .SH COMPATIBILITY Reasonable care has been taken to ensure compatibility -with the native panel facility introduced in SVr3.2 (inspection of +with the native panel facility introduced in System V (inspection of the SVr4 manual pages suggests the programming interface is unchanged). -The \fBPANEL\fR data structures are merely similar. The programmer -is cautioned not to directly use \fBPANEL\fR fields. +The \fBPANEL\fP data structures are merely similar. +The programmer +is cautioned not to directly use \fBPANEL\fP fields. .P -The functions \fBshow_panel()\fR and \fBtop_panel()\fR are identical +The functions \fBshow_panel\fP and \fBtop_panel\fP are identical in this implementation, and work equally well with displayed or hidden -panels. In the native System V implementation, \fBshow_panel()\fR is +panels. +In the native System V implementation, \fBshow_panel\fP is intended for making a hidden panel visible (at the top of the stack) -and \fBtop_panel()\fR is intended for making an already-visible panel -move to the top of the stack. You are cautioned to use the correct +and \fBtop_panel\fP is intended for making an already-visible panel +move to the top of the stack. +You are cautioned to use the correct function to ensure compatibility with native panel libraries. .SH NOTE In your library list, libpanel.a should be before libncurses.a; that is, -you want to say `-lpanel -lncurses', not the other way around (which would -usually give a link-error). +you should say \*(``\-lpanel \-lncurses\*('', not the other way around +(which would give a link-error with static libraries). +.SH PORTABILITY +The panel facility was documented in SVr4.2 in +\fICharacter User Interface Programming (UNIX SVR4.2)\fP. +.PP +It is not part of X/Open Curses. +.PP +A few implementations exist: +.bP +Systems based on SVr4 source code, +e.g., Solaris, provide this library. +.bP +\fBncurses\fP (since version 0.6 in 1993) +and \fBPDCurses\fP (since version 2.2 in 1995) +provide a panel library whose common ancestor +was a public domain implementation by Warren Tucker +published in \fIu386mon\fP 2.20 (1990). +.IP +According to Tucker, the SystemV panel library +was first released in SVr3.2 (1988), +and his implementation helped with a port to SVr3.1 (1987). +.IP +Several developers have improved each of these; +they are no longer the same as Tucker's implementation. +.bP +NetBSD 8 (2018) +has a panel library begun by Valery Ushakov in 2015. +This is based on the AT&T documentation. .SH FILES -.P panel.h interface for the panels library .P libpanel.a the panels library itself .SH SEE ALSO -\fBcurses\fR(3) +\fBcurses\fP(3), +\fBcurs_variables\fP(3), .PP -This describes \fBncurses\fR -version 5.7. +This describes \fBncurses\fP +version 6.4 (patch 20230826). .SH AUTHOR Originally written by Warren Tucker , -primarily to assist in porting u386mon to systems without a native -panels library. Repackaged for ncurses by Zeyd ben-Halim. +primarily to assist in porting \fIu386mon\fP to systems without a native +panels library. +.PP +Repackaged for ncurses by Zeyd ben-Halim. +.PP +Juergen Pfeifer and Thomas E. Dickey revised/improved the library. diff --git a/lib/libpanel/panel.c b/lib/libpanel/panel.c index 4655f30c3ea..28fc61d7578 100644 --- a/lib/libpanel/panel.c +++ b/lib/libpanel/panel.c @@ -1,7 +1,8 @@ -/* $OpenBSD: panel.c,v 1.11 2019/10/08 17:52:37 deraadt Exp $ */ +/* $OpenBSD: panel.c,v 1.12 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2004,2005 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2010,2012 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -31,21 +32,23 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1995 * * and: Eric S. Raymond * + * and: Juergen Pfeifer 1996-1999,2008 * + * and: Thomas E. Dickey * ****************************************************************************/ /* panel.c -- implementation of panels library, some core routines */ #include "panel.priv.h" -MODULE_ID("$Id: panel.c,v 1.11 2019/10/08 17:52:37 deraadt Exp $") +MODULE_ID("$Id: panel.c,v 1.12 2023/10/17 09:52:10 nicm Exp $") /*+------------------------------------------------------------------------- _nc_retrace_panel (pan) --------------------------------------------------------------------------*/ #ifdef TRACE -NCURSES_EXPORT(PANEL *) +PANEL_EXPORT(PANEL *) _nc_retrace_panel(PANEL * pan) { - T((T_RETURN("%p"), pan)); + T((T_RETURN("%p"), (void *)pan)); return pan; } #endif @@ -55,16 +58,16 @@ _nc_retrace_panel(PANEL * pan) --------------------------------------------------------------------------*/ #ifdef TRACE #ifndef TRACE_TXT -NCURSES_EXPORT(const char *) -_nc_my_visbuf(const void *ptr) +PANEL_EXPORT(const char *) +_nc_my_visbuf(const void *ptr, int n) { char temp[32]; if (ptr != 0) - snprintf(temp, sizeof temp, "ptr:%p", ptr); + _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) "%p", ptr); else - strlcpy(temp, "", sizeof temp); - return _nc_visbuf(temp); + _nc_STRCPY(temp, "", sizeof(temp)); + return _nc_visbuf2(n, temp); } #endif #endif @@ -73,13 +76,13 @@ _nc_my_visbuf(const void *ptr) dPanel(text,pan) --------------------------------------------------------------------------*/ #ifdef TRACE -NCURSES_EXPORT(void) +PANEL_EXPORT(void) _nc_dPanel(const char *text, const PANEL * pan) { _tracef("%s id=%s b=%s a=%s y=%d x=%d", - text, USER_PTR(pan->user), - (pan->below) ? USER_PTR(pan->below->user) : "--", - (pan->above) ? USER_PTR(pan->above->user) : "--", + text, USER_PTR(pan->user, 1), + (pan->below) ? USER_PTR(pan->below->user, 2) : "--", + (pan->above) ? USER_PTR(pan->above->user, 3) : "--", PSTARTY(pan), PSTARTX(pan)); } #endif @@ -88,17 +91,19 @@ _nc_dPanel(const char *text, const PANEL * pan) dStack(fmt,num,pan) --------------------------------------------------------------------------*/ #ifdef TRACE -NCURSES_EXPORT(void) +PANEL_EXPORT(void) _nc_dStack(const char *fmt, int num, const PANEL * pan) { char s80[80]; - snprintf(s80, sizeof s80, fmt, num, pan); + GetPanelHook(pan); + + _nc_SPRINTF(s80, _nc_SLIMIT(sizeof(s80)) fmt, num, pan); _tracef("%s b=%s t=%s", s80, - (_nc_bottom_panel) ? USER_PTR(_nc_bottom_panel->user) : "--", - (_nc_top_panel) ? USER_PTR(_nc_top_panel->user) : "--"); + (_nc_bottom_panel) ? USER_PTR(_nc_bottom_panel->user, 1) : "--", + (_nc_top_panel) ? USER_PTR(_nc_top_panel->user, 2) : "--"); if (pan) - _tracef("pan id=%s", USER_PTR(pan->user)); + _tracef("pan id=%s", USER_PTR(pan->user, 1)); pan = _nc_bottom_panel; while (pan) { @@ -112,7 +117,7 @@ _nc_dStack(const char *fmt, int num, const PANEL * pan) Wnoutrefresh(pan) - debugging hook for wnoutrefresh --------------------------------------------------------------------------*/ #ifdef TRACE -NCURSES_EXPORT(void) +PANEL_EXPORT(void) _nc_Wnoutrefresh(const PANEL * pan) { dPanel("wnoutrefresh", pan); @@ -124,7 +129,7 @@ _nc_Wnoutrefresh(const PANEL * pan) Touchpan(pan) --------------------------------------------------------------------------*/ #ifdef TRACE -NCURSES_EXPORT(void) +PANEL_EXPORT(void) _nc_Touchpan(const PANEL * pan) { dPanel("Touchpan", pan); @@ -136,12 +141,12 @@ _nc_Touchpan(const PANEL * pan) Touchline(pan,start,count) --------------------------------------------------------------------------*/ #ifdef TRACE -NCURSES_EXPORT(void) +PANEL_EXPORT(void) _nc_Touchline(const PANEL * pan, int start, int count) { char s80[80]; - snprintf(s80, sizeof s80, "Touchline s=%d c=%d", start, count); + _nc_SPRINTF(s80, _nc_SLIMIT(sizeof(s80)) "Touchline s=%d c=%d", start, count); dPanel(s80, pan); touchline(pan->win, start, count); } diff --git a/lib/libpanel/panel.h b/lib/libpanel/panel.h index 2d7bd4b6807..69ad1605a65 100644 --- a/lib/libpanel/panel.h +++ b/lib/libpanel/panel.h @@ -1,6 +1,7 @@ -/* $OpenBSD: panel.h,v 1.8 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: panel.h,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2001,2006 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2009,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -30,9 +31,10 @@ /**************************************************************************** * Author: Zeyd M. Ben-Halim 1995 * * and: Eric S. Raymond * + * and: Juergen Pfeifer 1996-1999,2008 * ****************************************************************************/ -/* $Id: panel.h,v 1.8 2015/01/23 22:48:51 krw Exp $ */ +/* $Id: panel.h,v 1.9 2023/10/17 09:52:10 nicm Exp $ */ /* panel.h -- interface file for panels library */ @@ -42,32 +44,53 @@ #include typedef struct panel +#if !NCURSES_OPAQUE_PANEL { WINDOW *win; struct panel *below; struct panel *above; NCURSES_CONST void *user; -} PANEL; +} +#endif /* !NCURSES_OPAQUE_PANEL */ +PANEL; #if defined(__cplusplus) extern "C" { #endif -extern NCURSES_EXPORT(WINDOW*) panel_window (const PANEL *); -extern NCURSES_EXPORT(void) update_panels (void); -extern NCURSES_EXPORT(int) hide_panel (PANEL *); -extern NCURSES_EXPORT(int) show_panel (PANEL *); -extern NCURSES_EXPORT(int) del_panel (PANEL *); -extern NCURSES_EXPORT(int) top_panel (PANEL *); -extern NCURSES_EXPORT(int) bottom_panel (PANEL *); -extern NCURSES_EXPORT(PANEL*) new_panel (WINDOW *); -extern NCURSES_EXPORT(PANEL*) panel_above (const PANEL *); -extern NCURSES_EXPORT(PANEL*) panel_below (const PANEL *); -extern NCURSES_EXPORT(int) set_panel_userptr (PANEL *, NCURSES_CONST void *); -extern NCURSES_EXPORT(NCURSES_CONST void*) panel_userptr (const PANEL *); -extern NCURSES_EXPORT(int) move_panel (PANEL *, int, int); -extern NCURSES_EXPORT(int) replace_panel (PANEL *,WINDOW *); -extern NCURSES_EXPORT(int) panel_hidden (const PANEL *); +#if defined(BUILDING_PANEL) +# define PANEL_IMPEXP NCURSES_EXPORT_GENERAL_EXPORT +#else +# define PANEL_IMPEXP NCURSES_EXPORT_GENERAL_IMPORT +#endif + +#define PANEL_WRAPPED_VAR(type,name) extern PANEL_IMPEXP type NCURSES_PUBLIC_VAR(name)(void) + +#define PANEL_EXPORT(type) PANEL_IMPEXP type NCURSES_API +#define PANEL_EXPORT_VAR(type) PANEL_IMPEXP type + +extern PANEL_EXPORT(WINDOW*) panel_window (const PANEL *); +extern PANEL_EXPORT(void) update_panels (void); +extern PANEL_EXPORT(int) hide_panel (PANEL *); +extern PANEL_EXPORT(int) show_panel (PANEL *); +extern PANEL_EXPORT(int) del_panel (PANEL *); +extern PANEL_EXPORT(int) top_panel (PANEL *); +extern PANEL_EXPORT(int) bottom_panel (PANEL *); +extern PANEL_EXPORT(PANEL*) new_panel (WINDOW *); +extern PANEL_EXPORT(PANEL*) panel_above (const PANEL *); +extern PANEL_EXPORT(PANEL*) panel_below (const PANEL *); +extern PANEL_EXPORT(int) set_panel_userptr (PANEL *, NCURSES_CONST void *); +extern PANEL_EXPORT(NCURSES_CONST void*) panel_userptr (const PANEL *); +extern PANEL_EXPORT(int) move_panel (PANEL *, int, int); +extern PANEL_EXPORT(int) replace_panel (PANEL *,WINDOW *); +extern PANEL_EXPORT(int) panel_hidden (const PANEL *); + +#if NCURSES_SP_FUNCS +extern PANEL_EXPORT(PANEL *) ground_panel(SCREEN *); +extern PANEL_EXPORT(PANEL *) ceiling_panel(SCREEN *); + +extern PANEL_EXPORT(void) NCURSES_SP_NAME(update_panels) (SCREEN*); +#endif #if defined(__cplusplus) } diff --git a/lib/libpanel/panel.priv.h b/lib/libpanel/panel.priv.h index 2f33473a5c8..c8247cc0fc4 100644 --- a/lib/libpanel/panel.priv.h +++ b/lib/libpanel/panel.priv.h @@ -1,6 +1,7 @@ -/* $OpenBSD: panel.priv.h,v 1.10 2015/01/23 22:48:51 krw Exp $ */ +/* $OpenBSD: panel.priv.h,v 1.11 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2005,2008 Free Software Foundation, Inc. * + * Copyright 2020 Thomas E. Dickey * + * Copyright 1998-2014,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -27,10 +28,11 @@ * authorization. * ****************************************************************************/ -/* $Id: panel.priv.h,v 1.10 2015/01/23 22:48:51 krw Exp $ */ +/* $Id: panel.priv.h,v 1.11 2023/10/17 09:52:10 nicm Exp $ */ #ifndef NCURSES_PANEL_PRIV_H #define NCURSES_PANEL_PRIV_H 1 +/* *INDENT-OFF* */ #if HAVE_CONFIG_H # include @@ -40,33 +42,30 @@ #include #include -#include "curses.priv.h" -#include "panel.h" -#include +struct screen; /* forward declaration */ -#if USE_RCS_IDS -# define MODULE_ID(id) static const char Ident[] = id; -#else -# define MODULE_ID(id) /*nothing*/ -#endif +#include "curses.priv.h" /* includes nc_panel.h */ + +#define NCURSES_OPAQUE_PANEL 0 +#include "panel.h" #ifdef TRACE - extern NCURSES_EXPORT(const char *) _nc_my_visbuf (const void *); + extern PANEL_EXPORT(const char *) _nc_my_visbuf (const void *, int); # ifdef TRACE_TXT -# define USER_PTR(ptr) _nc_visbuf((const char *)ptr) +# define USER_PTR(ptr,n) _nc_visbuf2(n, (const char *)ptr) # else -# define USER_PTR(ptr) _nc_my_visbuf((const char *)ptr) +# define USER_PTR(ptr,n) _nc_my_visbuf((const char *)ptr, n) # endif -# define returnPanel(code) TRACE_RETURN(code,panel) +# define returnPanel(code) TRACE_RETURN1(code,panel) - extern NCURSES_EXPORT(PANEL *) _nc_retrace_panel (PANEL *); - extern NCURSES_EXPORT(void) _nc_dPanel (const char*, const PANEL*); - extern NCURSES_EXPORT(void) _nc_dStack (const char*, int, const PANEL*); - extern NCURSES_EXPORT(void) _nc_Wnoutrefresh (const PANEL*); - extern NCURSES_EXPORT(void) _nc_Touchpan (const PANEL*); - extern NCURSES_EXPORT(void) _nc_Touchline (const PANEL*, int, int); + extern PANEL_EXPORT(PANEL *) _nc_retrace_panel (PANEL *); + extern PANEL_EXPORT(void) _nc_dPanel (const char*, const PANEL*); + extern PANEL_EXPORT(void) _nc_dStack (const char*, int, const PANEL*); + extern PANEL_EXPORT(void) _nc_Wnoutrefresh (const PANEL*); + extern PANEL_EXPORT(void) _nc_Touchpan (const PANEL*); + extern PANEL_EXPORT(void) _nc_Touchline (const PANEL*, int, int); # define dBug(x) _tracef x # define dPanel(text,pan) _nc_dPanel(text,pan) @@ -84,14 +83,38 @@ # define Touchline(pan,start,count) touchline((pan)->win,start,count) #endif +#if NCURSES_SP_FUNCS +#define GetScreenHook(sp) \ + struct panelhook* ph = NCURSES_SP_NAME(_nc_panelhook)(sp) +#define GetPanelHook(pan) \ + GetScreenHook(pan ? _nc_screen_of((pan)->win) : 0) +#define GetWindowHook(win) \ + SCREEN* sp = _nc_screen_of(win); \ + GetScreenHook(sp) +#define GetHook(pan) SCREEN* sp = _nc_screen_of(pan->win); \ + GetScreenHook(sp) + +#define _nc_stdscr_pseudo_panel ((ph)->stdscr_pseudo_panel) +#define _nc_top_panel ((ph)->top_panel) +#define _nc_bottom_panel ((ph)->bottom_panel) + +#else /* !NCURSES_SP_FUNCS */ + +#define GetScreenHook(sp) /* nothing */ +#define GetPanelHook(pan) /* nothing */ +#define GetWindowHook(win) /* nothing */ +#define GetHook(pan) /* nothing */ + #define _nc_stdscr_pseudo_panel _nc_panelhook()->stdscr_pseudo_panel -#define _nc_top_panel _nc_panelhook()->top_panel -#define _nc_bottom_panel _nc_panelhook()->bottom_panel +#define _nc_top_panel _nc_panelhook()->top_panel +#define _nc_bottom_panel _nc_panelhook()->bottom_panel + +#endif /* NCURSES_SP_FUNCS */ -#define EMPTY_STACK() (_nc_top_panel==_nc_bottom_panel) -#define Is_Bottom(p) (((p)!=(PANEL*)0) && !EMPTY_STACK() && (_nc_bottom_panel->above==(p))) -#define Is_Top(p) (((p)!=(PANEL*)0) && !EMPTY_STACK() && (_nc_top_panel==(p))) -#define Is_Pseudo(p) ((p) && ((p)==_nc_bottom_panel)) +#define EMPTY_STACK() (_nc_top_panel == _nc_bottom_panel) +#define Is_Bottom(p) (((p) != (PANEL*)0) && !EMPTY_STACK() && (_nc_bottom_panel->above == (p))) +#define Is_Top(p) (((p) != (PANEL*)0) && !EMPTY_STACK() && (_nc_top_panel == (p))) +#define Is_Pseudo(p) (((p) != (PANEL*)0) && ((p) == _nc_bottom_panel)) /*+------------------------------------------------------------------------- IS_LINKED(pan) - check to see if panel is in the stack @@ -123,7 +146,7 @@ ix2 = (PENDX(pan1) < PENDX(pan2)) ? PENDX(pan1) : PENDX(pan2);\ iy1 = (PSTARTY(pan1) < PSTARTY(pan2)) ? PSTARTY(pan2) : PSTARTY(pan1);\ iy2 = (PENDY(pan1) < PENDY(pan2)) ? PENDY(pan1) : PENDY(pan2);\ - assert((ix1<=ix2) && (iy1<=iy2));\ + assert((ix1<=ix2) && (iy1<=iy2)) /*+------------------------------------------------------------------------- @@ -135,14 +158,14 @@ ---------------------------------------------------------------------------*/ #define PANEL_UPDATE(pan,panstart)\ { PANEL* pan2 = ((panstart) ? (panstart) : _nc_bottom_panel);\ - while(pan2) {\ + while(pan2 && pan2->win) {\ if ((pan2 != pan) && PANELS_OVERLAPPED(pan,pan2)) {\ - int y,ix1,ix2,iy1,iy2;\ - COMPUTE_INTERSECTION(pan,pan2,ix1,ix2,iy1,iy2);\ + int y, ix1, ix2, iy1, iy2;\ + COMPUTE_INTERSECTION(pan, pan2, ix1, ix2, iy1, iy2);\ for(y = iy1; y <= iy2; y++) {\ if (is_linetouched(pan->win,y - PSTARTY(pan))) {\ struct ldat* line = &(pan2->win->_line[y - PSTARTY(pan2)]);\ - CHANGED_RANGE(line,ix1-PSTARTX(pan2),ix2-PSTARTX(pan2));\ + CHANGED_RANGE(line, ix1 - PSTARTX(pan2), ix2 - PSTARTX(pan2));\ }\ }\ }\ @@ -181,4 +204,10 @@ err = err_if_unlinked;\ } +#if NCURSES_SP_FUNCS +/* These may become later renamed and part of panel.h and the public API */ +extern PANEL_EXPORT(void) NCURSES_SP_NAME(_nc_update_panels)(SCREEN*); +#endif +/* *INDENT-ON* */ + #endif /* NCURSES_PANEL_PRIV_H */ diff --git a/lib/libpanel/shlib_version b/lib/libpanel/shlib_version index 9c1551636c5..5b844bbf422 100644 --- a/lib/libpanel/shlib_version +++ b/lib/libpanel/shlib_version @@ -1,2 +1,2 @@ -major=6 +major=7 minor=0 diff --git a/usr.bin/infocmp/Makefile b/usr.bin/infocmp/Makefile index 315cbbad0ce..13a61f7bb73 100644 --- a/usr.bin/infocmp/Makefile +++ b/usr.bin/infocmp/Makefile @@ -1,18 +1,18 @@ -# $OpenBSD: Makefile,v 1.6 2022/07/11 03:11:49 daniel Exp $ +# $OpenBSD: Makefile,v 1.7 2023/10/17 09:52:10 nicm Exp $ PROG= infocmp -SRCS= infocmp.c dump_entry.c +SRCS= dump_entry.c infocmp.c +CURSES= ${.CURDIR}/../../lib/libcurses DPADD= ${LIBCURSES} LDADD= -lcurses -CURSES= ${.CURDIR}/../../lib/libcurses TIC= ${.CURDIR}/../tic CFLAGS+= -I${CURSES} -I${TIC} -I${.CURDIR} -I. -CLEANFILES+= termsort.c .PATH: ${TIC} +CLEANFILES+= termsort.h -dump_entry.o: termsort.c +dump_entry.o: termsort.h -termsort.c: ${TIC}/MKtermsort.sh +termsort.h: ${TIC}/MKtermsort.sh sh ${TIC}/MKtermsort.sh awk ${CURSES}/Caps > ${.TARGET} .include diff --git a/usr.bin/infocmp/infocmp.1 b/usr.bin/infocmp/infocmp.1 index 90142531ca0..3a2fde5cc74 100644 --- a/usr.bin/infocmp/infocmp.1 +++ b/usr.bin/infocmp/infocmp.1 @@ -1,8 +1,9 @@ '\" t -.\" $OpenBSD: infocmp.1,v 1.1 2022/07/11 03:11:49 daniel Exp $ +.\" $OpenBSD: infocmp.1,v 1.2 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2004,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2017,2018 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -29,24 +30,49 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: infocmp.1,v 1.1 2022/07/11 03:11:49 daniel Exp $ -.TH infocmp 1 "" +.\" $Id: infocmp.1,v 1.2 2023/10/17 09:52:10 nicm Exp $ +.TH infocmp 1 2023-08-19 "ncurses 6.4" "User commands" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .ds n 5 +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.de NS +.ie n .sp +.el .sp .5 +.ie n .in +4 +.el .in +2 +.nf +.ft CR \" Courier +.. +.de NE +.fi +.ft R +.ie n .in -4 +.el .in -2 +.. .ds d /usr/share/terminfo .SH NAME -\fBinfocmp\fR - compare or print out \fIterminfo\fR descriptions +\fBinfocmp\fP \- compare or print out \fIterminfo\fP descriptions .SH SYNOPSIS -\fBinfocmp\fR [\fB-\ +\fBinfocmp\fP [\fB\-\ 1\ C\ +D\ E\ F\ G\ I\ +K\ L\ T\ U\ V\ +W\ c\ d\ e\ @@ -60,213 +86,298 @@ r\ t\ u\ x\ -\fR] -.br - [\fB-v\fR \fIn\fR] [\fB-s d\fR| \fBi\fR| \fBl\fR| \fBc\fR] [\fB-R \fR\fBsubset\fR] -.br - [\fB-w\fR\ \fIwidth\fR] [\fB-A\fR\ \fIdirectory\fR] [\fB-B\fR\ \fIdirectory\fR] -.br - [\fItermname\fR...] +\fP] + [\fB\-v\fR \fIn\fR] [\fB\-s d\fR| \fBi\fR| \fBl\fR| \fBc\fR] [\fB\-Q\fR \fIn\fR] [\fB\-R \fBsubset\fR] + [\fB\-w\fP\ \fIwidth\fP] [\fB\-A\fP\ \fIdirectory\fP] [\fB\-B\fP\ \fIdirectory\fP] + [\fItermname\fP...] .SH DESCRIPTION -\fBinfocmp\fR can be used to compare a binary \fBterminfo\fR entry with other -terminfo entries, rewrite a \fBterminfo\fR description to take advantage of the -\fBuse=\fR terminfo field, or print out a \fBterminfo\fR description from the -binary file (\fBterm\fR) in a variety of formats. In all cases, the boolean +\fBinfocmp\fP can be used to compare a binary \fBterminfo\fP entry with other +terminfo entries, rewrite a \fBterminfo\fP description to take advantage of the +\fBuse=\fP terminfo field, or print out a \fBterminfo\fP description from the +binary file (\fBterm\fP) in a variety of formats. +In all cases, the boolean fields will be printed first, followed by the numeric fields, followed by the string fields. .SS Default Options -If no options are specified and zero or one \fItermnames\fR are specified, the -\fB-I\fR option will be assumed. If more than one \fItermname\fR is specified, -the \fB-d\fR option will be assumed. -.SS Comparison Options [-d] [-c] [-n] -\fBinfocmp\fR compares the \fBterminfo\fR description of the first terminal -\fItermname\fR with each of the descriptions given by the entries for the other -terminal's \fItermnames\fR. If a capability is defined for only one of the -terminals, the value returned will depend on the type of the capability: -\fBF\fR for boolean variables, \fB-1\fR for integer variables, and \fBNULL\fR -for string variables. +If no options are specified and zero or one \fItermnames\fP are specified, the +\fB\-I\fP option will be assumed. +If more than one \fItermname\fP is specified, +the \fB\-d\fP option will be assumed. +.SS Comparison Options [\-d] [\-c] [\-n] +\fBinfocmp\fP compares the \fBterminfo\fP description of the first terminal +\fItermname\fP with each of the descriptions given by the entries for the other +terminal's \fItermnames\fP. +If a capability is defined for only one of the +terminals, the value returned depends on the type of the capability: +.bP +\fBF\fP for missing boolean variables +.bP +\fBNULL\fP for missing integer or string variables .PP -The \fB-d\fR option produces a list of each capability that is different -between two entries. This option is useful to show the difference between two -entries, created by different people, for the same or similar terminals. +Use the \fB\-q\fP option to show the distinction between +\fIabsent\fP and \fIcancelled\fP capabilities. .PP -The \fB-c\fR option produces a list of each capability that is common between -two entries. Capabilities that are not set are ignored. This option can be -used as a quick check to see if the \fB-u\fR option is worth using. +These options produce a list which you can use to compare two +or more terminal descriptions: +.TP 5 +\fB\-d\fP +produces a list of each capability that is \fIdifferent\fP +between two entries. +Each item in the list shows \*(``:\*('' after the capability name, +followed by the capability values, separated by a comma. +.TP +\fB\-c\fP +produces a list of each capability that is \fIcommon\fP between +two or more entries. +Missing capabilities are ignored. +Each item in the list shows \*(``=\*('' after the capability name, +followed by the capability value. +.IP +The \fB\-u\fP option provides a related output, +showing the first terminal description rewritten to use the second +as a building block via the \*(``use=\*('' clause. +.TP +\fB\-n\fP +produces a list of each capability that is in \fInone\fP of the given entries. +Each item in the list shows \*(``!\*('' before the capability name. +.IP +Normally only the conventional capabilities are shown. +Use the \fB\-x\fP option to add the BSD-compatibility +capabilities (names prefixed with \*(``OT\*(''). +.IP +If no \fItermnames\fP are given, +\fBinfocmp\fP uses the environment variable \fBTERM\fP +for each of the \fItermnames\fP. +.SS Source Listing Options [\-I] [\-L] [\-C] [\-r] +The \fB\-I\fP, \fB\-L\fP, and \fB\-C\fP options will produce +a source listing for each terminal named. .PP -The \fB-n\fR option produces a list of each capability that is in neither -entry. If no \fItermnames\fR are given, the environment variable \fBTERM\fR -will be used for both of the \fItermnames\fR. This can be used as a quick -check to see if anything was left out of a description. -.SS Source Listing Options [-I] [-L] [-C] [-r] -The \fB-I\fR, \fB-L\fR, and \fB-C\fR options will produce a source listing for -each terminal named. -. .TS center tab(/) ; l l . -\fB-I\fR/use the \fBterminfo\fR names -\fB-L\fR/use the long C variable name listed in <\fBterm.h\fR> -\fB-C\fR/use the \fBtermcap\fR names -\fB-r\fR/when using \fB-C\fR, put out all capabilities in \fBtermcap\fR form +\fB\-I\fP/use the \fBterminfo\fP names +\fB\-L\fP/use the long C variable name listed in <\fBterm.h\fP> +\fB\-C\fP/use the \fBtermcap\fP names +\fB\-r\fP/when using \fB\-C\fP, put out all capabilities in \fBtermcap\fP form +\fB\-K\fP/modifies the \fB\-C\fP option, improving BSD-compatibility. .TE .PP -If no \fItermnames\fR are given, the environment variable \fBTERM\fR will be +If no \fItermnames\fP are given, the environment variable \fBTERM\fP will be used for the terminal name. .PP -The source produced by the \fB-C\fR option may be used directly as a -\fBtermcap\fR entry, but not all parameterized strings can be changed to -the \fBtermcap\fR format. \fBinfocmp\fR will attempt to convert most of the +The source produced by the \fB\-C\fP option may be used directly as a +\fBtermcap\fP entry, but not all parameterized strings can be changed to +the \fBtermcap\fP format. +\fBinfocmp\fP will attempt to convert most of the parameterized information, and anything not converted will be plainly marked in -the output and commented out. These should be edited by hand. +the output and commented out. +These should be edited by hand. +.PP +For best results when converting to \fBtermcap\fP format, +you should use both \fB\-C\fP and \fB\-r\fP. +Normally a termcap description is limited to 1023 bytes. +\fBinfocmp\fP trims away less essential parts to make it fit. +If you are converting to one of the (rare) termcap implementations +which accept an unlimited size of termcap, +you may want to add the \fB\-T\fP option. +More often however, you must help the termcap implementation, +and trim excess whitespace (use the \fB\-0\fP option for that). .PP All padding information for strings will be collected together and placed -at the beginning of the string where \fBtermcap\fR expects it. Mandatory -padding (padding information with a trailing '/') will become optional. +at the beginning of the string where \fBtermcap\fP expects it. +Mandatory +padding (padding information with a trailing \*(``/\*('') will become optional. .PP -All \fBtermcap\fR variables no longer supported by \fBterminfo\fR, but which -are derivable from other \fBterminfo\fR variables, will be output. Not all -\fBterminfo\fR capabilities will be translated; only those variables which were -part of \fBtermcap\fR will normally be output. Specifying the \fB-r\fR option +All \fBtermcap\fP variables no longer supported by \fBterminfo\fP, but which +are derivable from other \fBterminfo\fP variables, will be output. +Not all +\fBterminfo\fP capabilities will be translated; only those variables which were +part of \fBtermcap\fP will normally be output. +Specifying the \fB\-r\fP option will take off this restriction, allowing all capabilities to be output in -\fItermcap\fR form. +\fItermcap\fP form. +Normally you would use both the \fB\-C\fP and \fB\-r\fP options. +The actual format used incorporates some improvements for escaped characters +from terminfo format. +For a stricter BSD-compatible translation, use the \fB\-K\fP option +rather than \fB\-C\fP. .PP Note that because padding is collected to the beginning of the capability, not -all capabilities are output. Mandatory padding is not supported. Because -\fBtermcap\fR strings are not as flexible, it is not always possible to convert -a \fBterminfo\fR string capability into an equivalent \fBtermcap\fR format. A -subsequent conversion of the \fBtermcap\fR file back into \fBterminfo\fR format -will not necessarily reproduce the original \fBterminfo\fR -source. +all capabilities are output. +Mandatory padding is not supported. +Because +\fBtermcap\fP strings are not as flexible, it is not always possible to convert +a \fBterminfo\fP string capability into an equivalent \fBtermcap\fP format. +A subsequent conversion of the \fBtermcap\fP file +back into \fBterminfo\fP format +will not necessarily reproduce the original \fBterminfo\fP source. .PP -Some common \fBterminfo\fR parameter sequences, their \fBtermcap\fR +Some common \fBterminfo\fP parameter sequences, their \fBtermcap\fP equivalents, and some terminal types which commonly have such sequences, are: -. +.PP .TS center tab(/) ; l c l l l l. -\fBterminfo/termcap\fR/Representative Terminals +\fBterminfo/termcap\fP/Representative Terminals = -\fB%p1%c/%.\fR/adm -\fB%p1%d/%d\fR/hp, ANSI standard, vt100 -\fB%p1%'x'%+%c/%+x\fR/concept -\fB%i/%i\fRq/ANSI standard, vt100 -\fB%p1%?%'x'%>%t%p1%'y'%+%;/%>xy\fR/concept -\fB%p2\fR is printed before \fB%p1/%r\fR/hp +\fB%p1%c/%.\fP/adm +\fB%p1%d/%d\fP/hp, ANSI standard, vt100 +\fB%p1%'x'%+%c/%+x\fP/concept +\fB%i/%i\fPq/ANSI standard, vt100 +\fB%p1%?%'x'%>%t%p1%'y'%+%;/%>xy\fP/concept +\fB%p2\fP is printed before \fB%p1/%r\fP/hp .TE -.SS Use= Option [-u] -The \fB-u\fR option produces a \fBterminfo\fR source description of the first -terminal \fItermname\fR which is relative to the sum of the descriptions given -by the entries for the other terminals \fItermnames\fR. It does this by -analyzing the differences between the first \fItermname\fR and the other -\fItermnames\fR and producing a description with \fBuse=\fR fields for the -other terminals. In this manner, it is possible to retrofit generic terminfo -entries into a terminal's description. Or, if two similar terminals exist, but +.SS Use= Option [\-u] +The \fB\-u\fP option produces a \fBterminfo\fP source description of the first +terminal \fItermname\fP which is relative to the sum of the descriptions given +by the entries for the other terminals \fItermnames\fP. +It does this by +analyzing the differences between the first \fItermname\fP and the other +\fItermnames\fP and producing a description with \fBuse=\fP fields for the +other terminals. +In this manner, it is possible to retrofit generic terminfo +entries into a terminal's description. +Or, if two similar terminals exist, but were coded at different times or by different people so that each description -is a full description, using \fBinfocmp\fR will show what can be done to change +is a full description, using \fBinfocmp\fP +will show what can be done to change one description to be relative to the other. .PP -A capability will get printed with an at-sign (@) if it no longer exists in the -first \fItermname\fR, but one of the other \fItermname\fR entries contains a -value for it. A capability's value gets printed if the value in the first -\fItermname\fR is not found in any of the other \fItermname\fR entries, or if -the first of the other \fItermname\fR entries that has this capability gives a -different value for the capability than that in the first \fItermname\fR. +A capability will be printed with an at-sign (@) if it no longer exists in the +first \fItermname\fP, but one of the other \fItermname\fP entries contains a +value for it. +A capability's value will be printed if the value in the first +\fItermname\fP is not found in any of the other \fItermname\fP entries, or if +the first of the other \fItermname\fP entries that has this capability gives a +different value for the capability than that in the first \fItermname\fP. .PP -The order of the other \fItermname\fR entries is significant. Since the -terminfo compiler \fBtic\fR does a left-to-right scan of the capabilities, -specifying two \fBuse=\fR entries that contain differing entries for the same +The order of the other \fItermname\fP entries is significant. +Since the +terminfo compiler \fBtic\fP does a left-to-right scan of the capabilities, +specifying two \fBuse=\fP entries that contain differing entries for the same capabilities will produce different results depending on the order that the -entries are given in. \fBinfocmp\fR will flag any such inconsistencies between -the other \fItermname\fR entries as they are found. +entries are given in. +\fBinfocmp\fP will flag any such inconsistencies between +the other \fItermname\fP entries as they are found. .PP -Alternatively, specifying a capability \fIafter\fR a \fBuse=\fR entry that +Alternatively, specifying a capability \fIafter\fP a \fBuse=\fP entry that contains that capability will cause the second specification to be ignored. -Using \fBinfocmp\fR to recreate a description can be a useful check to make +Using \fBinfocmp\fP to recreate a description can be a useful check to make sure that everything was specified correctly in the original source description. .PP Another error that does not cause incorrect compiled files, but will slow down -the compilation time, is specifying extra \fBuse=\fR fields that are -superfluous. \fBinfocmp\fR will flag any other \fItermname use=\fR fields that +the compilation time, is specifying extra \fBuse=\fP fields that are +superfluous. +\fBinfocmp\fP will flag any other \fItermname use=\fP fields that were not needed. -.SS Changing Databases [-A \fIdirectory\fR] [-B \fIdirectory\fR] -The location of the compiled \fBterminfo\fR database is taken from the -environment variable \fBTERMINFO\fR . If the variable is not defined, or the -terminal is not found in that location, the system \fBterminfo\fR database, -in \fB/usr/share/terminfo\fR, will be used. The options \fB-A\fR -and \fB-B\fR may be used to override this location. The \fB-A\fR option will -set \fBTERMINFO\fR for the first \fItermname\fR and the \fB-B\fR option will -set \fBTERMINFO\fR for the other \fItermnames\fR. With this, it is possible to +.SS Changing Databases [\-A \fIdirectory\fR] [\-B \fIdirectory\fR] +Like other \fBncurses\fP utilities, +\fBinfocmp\fP looks for the terminal descriptions in several places. +You can use the \fBTERMINFO\fP and \fBTERMINFO_DIRS\fP environment variables +to override the compiled-in default list of places to search +(see \fBcurses\fP(3) for details). +.PP +You can also use the options \fB\-A\fP +and \fB\-B\fP to override the list of places to search +when comparing terminal descriptions: +.bP +The \fB\-A\fP option sets the location for the first \fItermname\fP +.bP +The \fB\-B\fP option sets the location for the other \fItermnames\fP. +.PP +Using these options, it is possible to compare descriptions for a terminal with the same name located in two different -databases. This is useful for comparing descriptions for the same terminal +databases. +For instance, +you can use this feature for comparing descriptions for the same terminal created by different people. .SS Other Options .TP 5 -\fB-1\fR -causes the fields to be printed out one to a line. Otherwise, +\fB\-0\fP +causes the fields to be printed on one line, without wrapping. +.TP 5 +\fB\-1\fP +causes the fields to be printed out one to a line. +Otherwise, the fields will be printed several to a line to a maximum width of 60 characters. .TP -\fB-a\fR -tells \fBinfocmp\fP to retain commented-out capabilities rather than discarding -them. Capabilities are commented by prefixing them with a period. +\fB\-a\fP +tells \fBinfocmp\fP to retain commented-out capabilities +rather than discarding them. +Capabilities are commented by prefixing them with a period. +.TP +\fB\-D\fP +tells \fBinfocmp\fP to print the database locations that it knows about, +and exit. .TP 5 -\fB-E\fR +\fB\-E\fP Dump the capabilities of the given terminal as tables, needed in the C initializer for a -TERMTYPE structure (the terminal capability structure in the \fB\fR). +TERMTYPE structure (the terminal capability structure in the \fB\fP). This option is useful for preparing versions of the curses library hardwired for a given terminal type. The tables are all declared static, and are named according to the type and the name of the corresponding terminal entry. .sp -Before ncurses 5.0, the split between the \fB-e\fP and \fB-E\fP +Before ncurses 5.0, the split between the \fB\-e\fP and \fB\-E\fP options was not needed; but support for extended names required making the arrays of terminal capabilities separate from the TERMTYPE structure. .TP 5 -\fB-e\fR +\fB\-e\fP Dump the capabilities of the given terminal as a C initializer for a -TERMTYPE structure (the terminal capability structure in the \fB\fR). +TERMTYPE structure (the terminal capability structure in the \fB\fP). This option is useful for preparing versions of the curses library hardwired for a given terminal type. .TP 5 -\fB-F\fR -compare terminfo files. This assumes that two following arguments are -filenames. The files are searched for pairwise matches between +\fB\-F\fP +compare terminfo files. +This assumes that two following arguments are filenames. +The files are searched for pairwise matches between entries, with two entries considered to match if any of their names do. The report printed to standard output lists entries with no matches in -the other file, and entries with more than one match. For entries -with exactly one match it includes a difference report. Normally, +the other file, and entries with more than one match. +For entries +with exactly one match it includes a difference report. +Normally, to reduce the volume of the report, use references are not resolved before looking for differences, but resolution can be forced -by also specifying \fB-r\fR. +by also specifying \fB\-r\fP. .TP 5 -\fB-f\fR +\fB\-f\fP Display complex terminfo strings which contain if/then/else/endif expressions indented for readability. .TP 5 -\fB-G\fR +\fB\-G\fP Display constant literals in decimal form rather than their character equivalents. .TP 5 -\fB-g\fR +\fB\-g\fP Display constant character literals in quoted form rather than their decimal equivalents. .TP 5 -\fB-i\fR -Analyze the initialization (\fBis1\fR, \fBis2\fR, \fBis3\fR), and reset -(\fBrs1\fR, \fBrs2\fR, \fBrs3\fR), strings in the entry. For each string, the +\fB\-i\fP +Analyze the initialization (\fBis1\fP, \fBis2\fP, \fBis3\fP), and reset +(\fBrs1\fP, \fBrs2\fP, \fBrs3\fP), strings in the entry, +as well as those used for starting/stopping cursor-positioning mode +(\fBsmcup\fP, \fBrmcup\fP) as well as starting/stopping keymap mode +(\fBsmkx\fP, \fBrmkx\fP). +.IP +For each string, the code tries to analyze it into actions in terms of the other capabilities in the -entry, certain X3.64/ISO 6429/ECMA-48 capabilities, and certain DEC VT-series +entry, certain X3.64/ISO 6429/ECMA\-48 capabilities, and certain DEC VT-series private modes (the set of recognized special sequences has been selected for -completeness over the existing terminfo database). Each report line consists +completeness over the existing terminfo database). +Each report line consists of the capability name, followed by a colon and space, followed by a printable expansion of the capability string with sections matching recognized actions -translated into {}-bracketed descriptions. Here is a list of the DEC/ANSI +translated into {}-bracketed descriptions. +.IP +Here is a list of the DEC/ANSI special sequences recognized: -i. +.PP .TS center tab(/) ; l l @@ -293,144 +404,253 @@ DECPAM/application keypad mode DECPNM/normal keypad mode DECANSI/enter ANSI mode = -ECMA[+-]AM/keyboard action mode -ECMA[+-]IRM/insert replace mode -ECMA[+-]SRM/send receive mode -ECMA[+-]LNM/linefeed mode +ECMA[+\-]AM/keyboard action mode +ECMA[+\-]IRM/insert replace mode +ECMA[+\-]SRM/send receive mode +ECMA[+\-]LNM/linefeed mode = -DEC[+-]CKM/application cursor keys -DEC[+-]ANM/set VT52 mode -DEC[+-]COLM/132-column mode -DEC[+-]SCLM/smooth scroll -DEC[+-]SCNM/reverse video mode -DEC[+-]OM/origin mode -DEC[+-]AWM/wraparound mode -DEC[+-]ARM/auto-repeat mode +DEC[+\-]CKM/application cursor keys +DEC[+\-]ANM/set VT52 mode +DEC[+\-]COLM/132-column mode +DEC[+\-]SCLM/smooth scroll +DEC[+\-]SCNM/reverse video mode +DEC[+\-]OM/origin mode +DEC[+\-]AWM/wraparound mode +DEC[+\-]ARM/auto-repeat mode .TE .sp It also recognizes a SGR action corresponding to ANSI/ISO 6429/ECMA Set Graphics Rendition, with the values NORMAL, BOLD, UNDERLINE, BLINK, and -REVERSE. All but NORMAL may be prefixed with `+' (turn on) or `-' (turn off). -.PP +REVERSE. +All but NORMAL may be prefixed with +.RS +.bP +\*(``+\*('' (turn on) or +.bP +\*(``\-\*('' (turn off). +.RE +.IP An SGR0 designates an empty highlight sequence (equivalent to {SGR:NORMAL}). .TP 5 -\fB-l\fR +\fB\-l\fP Set output format to terminfo. .TP 5 -\fB-p\fR +\fB\-p\fP Ignore padding specifications when comparing strings. .TP 5 -\fB-q\fR +\fB\-Q\fP \fIn\fP +Rather than show source in terminfo (text) format, +print the compiled (binary) format in hexadecimal or base64 form, +depending on the option's value: +.RS 8 +.TP 3 +1 +hexadecimal +.TP 3 +2 +base64 +.TP 3 +3 +hexadecimal and base64 +.RE +.IP +For example, this prints the compiled terminfo value as a string +which could be assigned to the \fBTERMINFO\fP environment variable: +.NS +infocmp -0 -q -Q2 +.NE +.TP 5 +\fB\-q\fP +This makes the output a little shorter: +.RS +.bP Make the comparison listing shorter by omitting subheadings, and using -"-" for absent capabilities, "@" for canceled rather than "NULL". +\*(``\-\*('' for absent capabilities, \*(``@\*('' +for canceled rather than \*(``NULL\*(''. +.bP +However, show differences between absent and cancelled capabilities. +.bP +Omit the \*(``Reconstructed from\*('' comment for source listings. +.RE .TP 5 -\fB-R\fR\fIsubset\fR -Restrict output to a given subset. This option is for use with archaic -versions of terminfo like those on SVr1, Ultrix, or HP/UX that do not support +\fB\-R\fIsubset\fR +Restrict output to a given subset. +This option is for use with archaic +versions of terminfo like those on SVr1, Ultrix, or HP-UX that do not support the full set of SVR4/XSI Curses terminfo; and variants such as AIX -that have their own extensions incompatible with SVr4/XSI. Available terminfo -subsets are "SVr1", "Ultrix", "HP", and "AIX"; see \fBterminfo\fR(\*n) for -details. You can also choose the subset "BSD" which selects only capabilities +that have their own extensions incompatible with SVr4/XSI. +.RS +.bP +Available terminfo +subsets are \*(``SVr1\*('', \*(``Ultrix\*('', \*(``HP\*('', and \*(``AIX\*(''; +see \fBterminfo\fP(\*n) for details. +.bP +You can also choose the subset \*(``BSD\*('' which selects only capabilities with termcap equivalents recognized by 4.4BSD. +.bP +If you select any other value for \fB\-R\fP, +it is the same as no subset, i.e., all capabilities are used. +.RE +.IP +A few options override the subset selected with \fB\-R\fP, +if they are processed later in the command parameters: +.RS +.TP 5 +\fB\-C\fP +sets the \*(``BSD\*('' subset as a side-effect. +.TP 5 +\fB\-I\fP +sets the subset to all capabilities. +.TP 5 +\fB\-r\fP +sets the subset to all capabilities. +.RE .TP -\fB-s \fR\fI[d|i|l|c]\fR -The \fB-s\fR option sorts the fields within each type according to the argument +\fB\-s \fI[d|i|l|c]\fR +The \fB\-s\fP option sorts the fields within each type according to the argument below: .br .RS 5 .TP 5 -\fBd\fR -leave fields in the order that they are stored in the \fIterminfo\fR database. +\fBd\fP +leave fields in the order that they are stored in the \fIterminfo\fP database. .TP 5 -\fBi\fR -sort by \fIterminfo\fR name. +\fBi\fP +sort by \fIterminfo\fP name. .TP 5 -\fBl\fR +\fBl\fP sort by the long C variable name. .TP 5 -\fBc\fR -sort by the \fItermcap\fR name. +\fBc\fP +sort by the \fItermcap\fP name. .RE .IP -If the \fB-s\fR option is not given, the fields printed out will be -sorted alphabetically by the \fBterminfo\fR name within each type, -except in the case of the \fB-C\fR or the \fB-L\fR options, which cause the -sorting to be done by the \fBtermcap\fR name or the long C variable +If the \fB\-s\fP option is not given, the fields printed out will be +sorted alphabetically by the \fBterminfo\fP name within each type, +except in the case of the \fB\-C\fP or the \fB\-L\fP options, which cause the +sorting to be done by the \fBtermcap\fP name or the long C variable name, respectively. .TP 5 -\fB-T\fR +\fB\-T\fP eliminates size-restrictions on the generated text. This is mainly useful for testing and analysis, since the compiled descriptions are limited (e.g., 1023 for termcap, 4096 for terminfo). .TP -\fB-t\fR +\fB\-t\fP tells \fBtic\fP to discard commented-out capabilities. Normally when translating from terminfo to termcap, untranslatable capabilities are commented-out. .TP 5 -\fB-U\fR -tells \fBinfocmp\fP to not post-process the data after parsing the source file. +\fB\-U\fP +tells \fBinfocmp\fP to not post-process the data +after parsing the source file. This feature helps when comparing the actual contents of two source files, since it excludes the inferences that \fBinfocmp\fP makes to fill in missing data. .TP 5 -\fB-V\fR +\fB\-V\fP reports the version of ncurses which was used in this program, and exits. .TP 5 -\fB-v\fR \fIn\fR +\fB\-v\fP \fIn\fP prints out tracing information on standard error as the program runs. -Higher values of n induce greater verbosity. +.IP +The optional parameter \fIn\fP is a number from 1 to 10, inclusive, +indicating the desired level of detail of information. +If ncurses is built without tracing support, the optional parameter is ignored. +.TP +\fB\-W\fP +By itself, the \fB\-w\fP option will not force long strings to be wrapped. +Use the \fB\-W\fP option to do this. .TP 5 -\fB-w\fR \fIwidth\fR -changes the output to \fIwidth\fR characters. +\fB\-w\fP \fIwidth\fP +changes the output to \fIwidth\fP characters. .TP -\fB-x\fR -print information for user-defined capabilities. +\fB\-x\fP +print information for user-defined capabilities (see \fBuser_caps(\*n)\fP. These are extensions to the terminfo repertoire which can be loaded -using the \fB-x\fR option of \fBtic\fP. +using the \fB\-x\fP option of \fBtic\fP. .SH FILES .TP 20 \*d Compiled terminal description database. +.SH HISTORY +Although System V Release 2 provided a terminfo library, +it had no documented tool for decompiling the terminal descriptions. +Tony Hansen (AT&T) wrote the first \fBinfocmp\fP in early 1984, +for System V Release 3. +.PP +Eric Raymond used the AT&T documentation in 1995 to provide an equivalent +\fBinfocmp\fP for ncurses. +In addition, he added a few new features such as: +.bP +the \fB\-e\fP option, to support \fIfallback\fP +(compiled-in) terminal descriptions +.bP +the \fB\-i\fP option, to help with analysis +.PP +Later, Thomas Dickey added the \fB\-x\fP (user-defined capabilities) +option, and the \fB\-E\fP option to support fallback entries with +user-defined capabilities. +.PP +For a complete list, see the \fIEXTENSIONS\fP section. +.PP +In 2010, Roy Marples provided an \fBinfocmp\fP program for NetBSD. +It is less capable than the SVr4 or ncurses versions +(e.g., it lacks the sorting options documented in X/Open), +but does include the \fB\-x\fP option adapted from ncurses. +.SH PORTABILITY +X/Open Curses, Issue 7 (2009) provides a description of \fBinfocmp\fP. +It does not mention the options used for converting to termcap format. .SH EXTENSIONS The -\fB-E\fR, -\fB-F\fR, -\fB-G\fR, -\fB-R\fR, -\fB-T\fR, -\fB-V\fR, -\fB-a\fR, -\fB-e\fR, -\fB-f\fR, -\fB-g\fR, -\fB-i\fR, -\fB-l\fR, -\fB-p\fR, -\fB-q\fR and -\fB-t\fR +\fB\-0\fP, +\fB\-1\fP, +\fB\-E\fP, +\fB\-F\fP, +\fB\-G\fP, +\fB\-Q\fP, +\fB\-R\fP, +\fB\-T\fP, +\fB\-V\fP, +\fB\-a\fP, +\fB\-e\fP, +\fB\-f\fP, +\fB\-g\fP, +\fB\-i\fP, +\fB\-l\fP, +\fB\-p\fP, +\fB\-q\fP and +\fB\-t\fP options are not supported in SVr4 curses. .PP -The \fB-r\fR option's notion of `termcap' capabilities is System V Release 4's. -Actual BSD curses versions will have a more restricted set. To see only the -4.4BSD set, use \fB-r\fR \fB-RBSD\fR. +SVr4 infocmp does not distinguish between absent and cancelled capabilities. +Also, it shows missing integer capabilities as \fB\-1\fP +(the internal value used to represent missing integers). +This implementation shows those as \*(``NULL\*('', +for consistency with missing strings. +.PP +The \fB\-r\fP option's notion of \*(``termcap\*('' capabilities +is System V Release 4's. +Actual BSD curses versions will have a more restricted set. +To see only the +4.4BSD set, use \fB\-r\fP \fB\-RBSD\fP. +.SH BUGS +The \fB\-F\fP option of \fBinfocmp\fP(1) should be a \fBtoe\fP(1) mode. .SH SEE ALSO -\fBcaptoinfo\fR(1), -\fBinfotocap\fR(1), -\fBtic\fR(1), -\fBcurses\fR(3), -\fBterminfo\fR(\*n). +\fBcaptoinfo\fP(1), +\fBinfotocap\fP(1), +\fBtic\fP(1), +\fBtoe\fP(1), +\fBcurses\fP(3), +\fBterminfo\fP(\*n). +\fBuser_caps\fP(\*n). +.sp +https://invisible-island.net/ncurses/tctest.html .PP -This describes \fBncurses\fR -version 5.7. +This describes \fBncurses\fP +version 6.4 (patch 20230826). .SH AUTHOR Eric S. Raymond and .br Thomas E. Dickey -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: diff --git a/usr.bin/infocmp/infocmp.c b/usr.bin/infocmp/infocmp.c index 9caaa8f0858..e23b729b99b 100644 --- a/usr.bin/infocmp/infocmp.c +++ b/usr.bin/infocmp/infocmp.c @@ -1,7 +1,8 @@ -/* $OpenBSD: infocmp.c,v 1.23 2016/08/03 16:32:08 krw Exp $ */ +/* $OpenBSD: infocmp.c,v 1.24 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020-2022,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -44,10 +45,7 @@ #include -MODULE_ID("$Id: infocmp.c,v 1.23 2016/08/03 16:32:08 krw Exp $") - -#define L_CURL "{" -#define R_CURL "}" +MODULE_ID("$Id: infocmp.c,v 1.24 2023/10/17 09:52:10 nicm Exp $") #define MAX_STRING 1024 /* maximum formatted string */ @@ -72,8 +70,9 @@ static const char *bool_sep = ":"; static const char *s_absent = "NULL"; static const char *s_cancel = "NULL"; static const char *tversion; /* terminfo version selected */ -static int itrace; /* trace flag for debugging */ +static unsigned itrace; /* trace flag for debugging */ static int mwidth = 60; +static int mheight = 65535; static int numbers = 0; /* format "%'char'" to/from "%{number}" */ static int outform = F_TERMINFO; /* output format */ static int sortmode; /* sort_mode */ @@ -88,31 +87,85 @@ static int compare; static bool ignorepads; /* ignore pad prefixes when diffing */ #if NO_LEAKS + +typedef struct { + ENTRY *head; + ENTRY *tail; +} ENTERED; + +static ENTERED *entered; + #undef ExitProgram -static void ExitProgram(int code) GCC_NORETURN; +static GCC_NORETURN void ExitProgram(int code); /* prototype is to get gcc to accept the noreturn attribute */ static void ExitProgram(int code) { - while (termcount-- > 0) - _nc_free_termtype(&entries[termcount].tterm); + int n; + + for (n = 0; n < termcount; ++n) { + ENTRY *new_head = _nc_head; + ENTRY *new_tail = _nc_tail; + _nc_head = entered[n].head; + _nc_tail = entered[n].tail; + _nc_free_entries(entered[n].head); + _nc_head = new_head; + _nc_tail = new_tail; + } _nc_leaks_dump_entry(); free(entries); + free(entered); _nc_free_tic(code); } #endif -static char * -canonical_name(char *ptr, char *buf, size_t bufl) +static void +failed(const char *s) +{ + perror(s); + ExitProgram(EXIT_FAILURE); +} + +static void +canonical_name(char *source, char *target) /* extract the terminal type's primary name */ { - char *bp; + int limit = NAMESIZE; + + while (--limit > 0) { + char ch = *source++; + if (ch == '|') + break; + *target++ = ch; + } + *target = '\0'; +} + +static bool +no_boolean(int value) +{ + bool result = (value == ABSENT_BOOLEAN); + if (!strcmp(s_absent, s_cancel)) + result = !VALID_BOOLEAN(value); + return result; +} - (void) strlcpy(buf, ptr, bufl); - if ((bp = strchr(buf, '|')) != 0) - *bp = '\0'; +static bool +no_numeric(int value) +{ + bool result = (value == ABSENT_NUMERIC); + if (!strcmp(s_absent, s_cancel)) + result = !VALID_NUMERIC(value); + return result; +} - return (buf); +static bool +no_string(const char *const value) +{ + bool result = (value == ABSENT_STRING); + if (!strcmp(s_absent, s_cancel)) + result = !VALID_STRING(value); + return result; } /*************************************************************************** @@ -247,7 +300,7 @@ useeq(ENTRY * e1, ENTRY * e2) } static bool -entryeq(TERMTYPE *t1, TERMTYPE *t2) +entryeq(TERMTYPE2 *t1, TERMTYPE2 *t2) /* are two entries equivalent? */ { unsigned i; @@ -273,16 +326,17 @@ static void print_uses(ENTRY * ep, FILE *fp) /* print an entry's use references */ { - unsigned i; - - if (!ep->nuses) + if (!ep->nuses) { fputs("NULL", fp); - else + } else { + unsigned i; + for (i = 0; i < ep->nuses; i++) { fputs(ep->uses[i].name, fp); if (i < ep->nuses - 1) fputs(" ", fp); } + } } static const char * @@ -304,53 +358,116 @@ dump_boolean(int val) } static void -dump_numeric(int val, char *buf, size_t bufl) -/* display the value of a boolean capability */ +dump_numeric(int val, char *buf) +/* display the value of a numeric capability */ { switch (val) { case ABSENT_NUMERIC: - strlcpy(buf, s_absent, bufl); + _nc_STRCPY(buf, s_absent, MAX_STRING); break; case CANCELLED_NUMERIC: - strlcpy(buf, s_cancel, bufl); + _nc_STRCPY(buf, s_cancel, MAX_STRING); break; default: - snprintf(buf, bufl, "%d", val); + _nc_SPRINTF(buf, _nc_SLIMIT(MAX_STRING) "%d", val); break; } } static void -dump_string(char *val, char *buf, size_t bufl) +dump_string(char *val, char *buf) /* display the value of a string capability */ { if (val == ABSENT_STRING) - strlcpy(buf, s_absent, bufl); + _nc_STRCPY(buf, s_absent, MAX_STRING); else if (val == CANCELLED_STRING) - strlcpy(buf, s_cancel, bufl); + _nc_STRCPY(buf, s_cancel, MAX_STRING); else { - snprintf(buf, bufl, "'%.*s'", MAX_STRING - 3, TIC_EXPAND(val)); + _nc_SPRINTF(buf, _nc_SLIMIT(MAX_STRING) + "'%.*s'", MAX_STRING - 3, TIC_EXPAND(val)); + } +} + +/* + * Show "comparing..." message for the given terminal names. + */ +static void +show_comparing(char **names) +{ + if (itrace) { + switch (compare) { + case C_DIFFERENCE: + (void) fprintf(stderr, "%s: dumping differences\n", _nc_progname); + break; + + case C_COMMON: + (void) fprintf(stderr, "%s: dumping common capabilities\n", _nc_progname); + break; + + case C_NAND: + (void) fprintf(stderr, "%s: dumping differences\n", _nc_progname); + break; + } + } + if (*names) { + printf("comparing %s", *names++); + if (*names) { + printf(" to %s", *names++); + while (*names) { + printf(", %s", *names++); + } + } + printf(".\n"); } } +/* + * ncurses stores two types of non-standard capabilities: + * a) capabilities listed past the "STOP-HERE" comment in the Caps file. + * These are used in the terminfo source file to provide data for termcaps, + * e.g., when there is no equivalent capability in terminfo, as well as for + * widely-used non-standard capabilities. + * b) user-definable capabilities, via "tic -x". + * + * However, if "-x" is omitted from the tic command, both types of + * non-standard capability are not loaded into the terminfo database. This + * macro is used for limit-checks against the symbols that tic uses to omit + * the two types of non-standard entry. + */ +#if NCURSES_XNAMES +#define check_user_definable(n,limit) if (!_nc_user_definable && (n) > (limit)) break +#else +#define check_user_definable(n,limit) if ((n) > (limit)) break +#endif + +/* + * Use these macros to simplify loops on C_COMMON and C_NAND: + */ +#define for_each_entry() while (entries[extra].tterm.term_names) +#define next_entry (&(entries[extra++].tterm)) + static void compare_predicate(PredType type, PredIdx idx, const char *name) /* predicate function to use for entry difference reports */ { ENTRY *e1 = &entries[0]; ENTRY *e2 = &entries[1]; - char buf1[MAX_STRING], buf2[MAX_STRING]; + char buf1[MAX_STRING]; + char buf2[MAX_STRING]; int b1, b2; int n1, n2; char *s1, *s2; + bool found; + int extra = 1; switch (type) { case CMP_BOOLEAN: + check_user_definable(idx, BOOLWRITE); b1 = e1->tterm.Booleans[idx]; - b2 = e2->tterm.Booleans[idx]; switch (compare) { case C_DIFFERENCE: - if (!(b1 == ABSENT_BOOLEAN && b2 == ABSENT_BOOLEAN) && b1 != b2) + b2 = next_entry->Booleans[idx]; + if (!(no_boolean(b1) && no_boolean(b2)) && (b1 != b2)) (void) printf("\t%s: %s%s%s.\n", name, dump_boolean(b1), @@ -359,61 +476,131 @@ compare_predicate(PredType type, PredIdx idx, const char *name) break; case C_COMMON: - if (b1 == b2 && b1 != ABSENT_BOOLEAN) - (void) printf("\t%s= %s.\n", name, dump_boolean(b1)); + if (b1 != ABSENT_BOOLEAN) { + found = TRUE; + for_each_entry() { + b2 = next_entry->Booleans[idx]; + if (b1 != b2) { + found = FALSE; + break; + } + } + if (found) { + (void) printf("\t%s= %s.\n", name, dump_boolean(b1)); + } + } break; case C_NAND: - if (b1 == ABSENT_BOOLEAN && b2 == ABSENT_BOOLEAN) - (void) printf("\t!%s.\n", name); + if (b1 == ABSENT_BOOLEAN) { + found = TRUE; + for_each_entry() { + b2 = next_entry->Booleans[idx]; + if (b1 != b2) { + found = FALSE; + break; + } + } + if (found) { + (void) printf("\t!%s.\n", name); + } + } break; } break; case CMP_NUMBER: + check_user_definable(idx, NUMWRITE); n1 = e1->tterm.Numbers[idx]; - n2 = e2->tterm.Numbers[idx]; - dump_numeric(n1, buf1, sizeof buf1); - dump_numeric(n2, buf2, sizeof buf2); switch (compare) { case C_DIFFERENCE: - if (!((n1 == ABSENT_NUMERIC && n2 == ABSENT_NUMERIC)) && n1 != n2) + n2 = next_entry->Numbers[idx]; + if (!(no_numeric(n1) && no_numeric(n2)) && n1 != n2) { + dump_numeric(n1, buf1); + dump_numeric(n2, buf2); (void) printf("\t%s: %s, %s.\n", name, buf1, buf2); + } break; case C_COMMON: - if (n1 != ABSENT_NUMERIC && n2 != ABSENT_NUMERIC && n1 == n2) - (void) printf("\t%s= %s.\n", name, buf1); + if (n1 != ABSENT_NUMERIC) { + found = TRUE; + for_each_entry() { + n2 = next_entry->Numbers[idx]; + if (n1 != n2) { + found = FALSE; + break; + } + } + if (found) { + dump_numeric(n1, buf1); + (void) printf("\t%s= %s.\n", name, buf1); + } + } break; case C_NAND: - if (n1 == ABSENT_NUMERIC && n2 == ABSENT_NUMERIC) - (void) printf("\t!%s.\n", name); + if (n1 == ABSENT_NUMERIC) { + found = TRUE; + for_each_entry() { + n2 = next_entry->Numbers[idx]; + if (n1 != n2) { + found = FALSE; + break; + } + } + if (found) { + (void) printf("\t!%s.\n", name); + } + } break; } break; case CMP_STRING: + check_user_definable(idx, STRWRITE); s1 = e1->tterm.Strings[idx]; - s2 = e2->tterm.Strings[idx]; switch (compare) { case C_DIFFERENCE: - if (capcmp(idx, s1, s2)) { - dump_string(s1, buf1, sizeof buf1); - dump_string(s2, buf2, sizeof buf2); + s2 = next_entry->Strings[idx]; + if (!(no_string(s1) && no_string(s2)) && capcmp(idx, s1, s2)) { + dump_string(s1, buf1); + dump_string(s2, buf2); if (strcmp(buf1, buf2)) (void) printf("\t%s: %s, %s.\n", name, buf1, buf2); } break; case C_COMMON: - if (s1 && s2 && !capcmp(idx, s1, s2)) - (void) printf("\t%s= '%s'.\n", name, TIC_EXPAND(s1)); + if (s1 != ABSENT_STRING) { + found = TRUE; + for_each_entry() { + s2 = next_entry->Strings[idx]; + if (capcmp(idx, s1, s2) != 0) { + found = FALSE; + break; + } + } + if (found) { + (void) printf("\t%s= '%s'.\n", name, TIC_EXPAND(s1)); + } + } break; case C_NAND: - if (!s1 && !s2) - (void) printf("\t!%s.\n", name); + if (s1 == ABSENT_STRING) { + found = TRUE; + for_each_entry() { + s2 = next_entry->Strings[idx]; + if (s2 != s1) { + found = FALSE; + break; + } + } + if (found) { + (void) printf("\t!%s.\n", name); + } + } break; } break; @@ -432,16 +619,37 @@ compare_predicate(PredType type, PredIdx idx, const char *name) break; case C_COMMON: - if (e1->nuses && e2->nuses && useeq(e1, e2)) { - (void) fputs("\tuse: ", stdout); - print_uses(e1, stdout); - fputs(".\n", stdout); + if (e1->nuses) { + found = TRUE; + for_each_entry() { + e2 = &entries[extra++]; + if (e2->nuses != e1->nuses || !useeq(e1, e2)) { + found = FALSE; + break; + } + } + if (found) { + (void) fputs("\tuse: ", stdout); + print_uses(e1, stdout); + fputs(".\n", stdout); + } } break; case C_NAND: - if (!e1->nuses && !e2->nuses) - (void) printf("\t!use.\n"); + if (!e1->nuses) { + found = TRUE; + for_each_entry() { + e2 = &entries[extra++]; + if (e2->nuses != e1->nuses) { + found = FALSE; + break; + } + } + if (found) { + (void) printf("\t!use.\n"); + } + } break; } } @@ -453,99 +661,104 @@ compare_predicate(PredType type, PredIdx idx, const char *name) * ***************************************************************************/ +#define DATA(from, to) { { from }, { to } } +#define DATAX() DATA("", "") + typedef struct { - const char *from; - const char *to; + const char from[4]; + const char to[12]; } assoc; static const assoc std_caps[] = { /* these are specified by X.364 and iBCS2 */ - {"\033c", "RIS"}, /* full reset */ - {"\0337", "SC"}, /* save cursor */ - {"\0338", "RC"}, /* restore cursor */ - {"\033[r", "RSR"}, /* not an X.364 mnemonic */ - {"\033[m", "SGR0"}, /* not an X.364 mnemonic */ - {"\033[2J", "ED2"}, /* clear page */ + DATA("\033c", "RIS"), /* full reset */ + DATA("\0337", "SC"), /* save cursor */ + DATA("\0338", "RC"), /* restore cursor */ + DATA("\033[r", "RSR"), /* not an X.364 mnemonic */ + DATA("\033[m", "SGR0"), /* not an X.364 mnemonic */ + DATA("\033[2J", "ED2"), /* clear page */ /* this group is specified by ISO 2022 */ - {"\033(0", "ISO DEC G0"}, /* enable DEC graphics for G0 */ - {"\033(A", "ISO UK G0"}, /* enable UK chars for G0 */ - {"\033(B", "ISO US G0"}, /* enable US chars for G0 */ - {"\033)0", "ISO DEC G1"}, /* enable DEC graphics for G1 */ - {"\033)A", "ISO UK G1"}, /* enable UK chars for G1 */ - {"\033)B", "ISO US G1"}, /* enable US chars for G1 */ + DATA("\033(0", "ISO DEC G0"), /* enable DEC graphics for G0 */ + DATA("\033(A", "ISO UK G0"), /* enable UK chars for G0 */ + DATA("\033(B", "ISO US G0"), /* enable US chars for G0 */ + DATA("\033)0", "ISO DEC G1"), /* enable DEC graphics for G1 */ + DATA("\033)A", "ISO UK G1"), /* enable UK chars for G1 */ + DATA("\033)B", "ISO US G1"), /* enable US chars for G1 */ /* these are DEC private controls widely supported by emulators */ - {"\033=", "DECPAM"}, /* application keypad mode */ - {"\033>", "DECPNM"}, /* normal keypad mode */ - {"\033<", "DECANSI"}, /* enter ANSI mode */ - {"\033[!p", "DECSTR"}, /* soft reset */ - {"\033 F", "S7C1T"}, /* 7-bit controls */ + DATA("\033=", "DECPAM"), /* application keypad mode */ + DATA("\033>", "DECPNM"), /* normal keypad mode */ + DATA("\033<", "DECANSI"), /* enter ANSI mode */ + DATA("\033[!p", "DECSTR"), /* soft reset */ + DATA("\033 F", "S7C1T"), /* 7-bit controls */ - {(char *) 0, (char *) 0} + DATAX() }; static const assoc std_modes[] = /* ECMA \E[ ... [hl] modes recognized by many emulators */ { - {"2", "AM"}, /* keyboard action mode */ - {"4", "IRM"}, /* insert/replace mode */ - {"12", "SRM"}, /* send/receive mode */ - {"20", "LNM"}, /* linefeed mode */ - {(char *) 0, (char *) 0} + DATA("2", "AM"), /* keyboard action mode */ + DATA("4", "IRM"), /* insert/replace mode */ + DATA("12", "SRM"), /* send/receive mode */ + DATA("20", "LNM"), /* linefeed mode */ + DATAX() }; static const assoc private_modes[] = /* DEC \E[ ... [hl] modes recognized by many emulators */ { - {"1", "CKM"}, /* application cursor keys */ - {"2", "ANM"}, /* set VT52 mode */ - {"3", "COLM"}, /* 132-column mode */ - {"4", "SCLM"}, /* smooth scroll */ - {"5", "SCNM"}, /* reverse video mode */ - {"6", "OM"}, /* origin mode */ - {"7", "AWM"}, /* wraparound mode */ - {"8", "ARM"}, /* auto-repeat mode */ - {(char *) 0, (char *) 0} + DATA("1", "CKM"), /* application cursor keys */ + DATA("2", "ANM"), /* set VT52 mode */ + DATA("3", "COLM"), /* 132-column mode */ + DATA("4", "SCLM"), /* smooth scroll */ + DATA("5", "SCNM"), /* reverse video mode */ + DATA("6", "OM"), /* origin mode */ + DATA("7", "AWM"), /* wraparound mode */ + DATA("8", "ARM"), /* auto-repeat mode */ + DATAX() }; static const assoc ecma_highlights[] = /* recognize ECMA attribute sequences */ { - {"0", "NORMAL"}, /* normal */ - {"1", "+BOLD"}, /* bold on */ - {"2", "+DIM"}, /* dim on */ - {"3", "+ITALIC"}, /* italic on */ - {"4", "+UNDERLINE"}, /* underline on */ - {"5", "+BLINK"}, /* blink on */ - {"6", "+FASTBLINK"}, /* fastblink on */ - {"7", "+REVERSE"}, /* reverse on */ - {"8", "+INVISIBLE"}, /* invisible on */ - {"9", "+DELETED"}, /* deleted on */ - {"10", "MAIN-FONT"}, /* select primary font */ - {"11", "ALT-FONT-1"}, /* select alternate font 1 */ - {"12", "ALT-FONT-2"}, /* select alternate font 2 */ - {"13", "ALT-FONT-3"}, /* select alternate font 3 */ - {"14", "ALT-FONT-4"}, /* select alternate font 4 */ - {"15", "ALT-FONT-5"}, /* select alternate font 5 */ - {"16", "ALT-FONT-6"}, /* select alternate font 6 */ - {"17", "ALT-FONT-7"}, /* select alternate font 7 */ - {"18", "ALT-FONT-1"}, /* select alternate font 1 */ - {"19", "ALT-FONT-1"}, /* select alternate font 1 */ - {"20", "FRAKTUR"}, /* Fraktur font */ - {"21", "DOUBLEUNDER"}, /* double underline */ - {"22", "-DIM"}, /* dim off */ - {"23", "-ITALIC"}, /* italic off */ - {"24", "-UNDERLINE"}, /* underline off */ - {"25", "-BLINK"}, /* blink off */ - {"26", "-FASTBLINK"}, /* fastblink off */ - {"27", "-REVERSE"}, /* reverse off */ - {"28", "-INVISIBLE"}, /* invisible off */ - {"29", "-DELETED"}, /* deleted off */ - {(char *) 0, (char *) 0} + DATA("0", "NORMAL"), /* normal */ + DATA("1", "+BOLD"), /* bold on */ + DATA("2", "+DIM"), /* dim on */ + DATA("3", "+ITALIC"), /* italic on */ + DATA("4", "+UNDERLINE"), /* underline on */ + DATA("5", "+BLINK"), /* blink on */ + DATA("6", "+FASTBLINK"), /* fastblink on */ + DATA("7", "+REVERSE"), /* reverse on */ + DATA("8", "+INVISIBLE"), /* invisible on */ + DATA("9", "+DELETED"), /* deleted on */ + DATA("10", "MAIN-FONT"), /* select primary font */ + DATA("11", "ALT-FONT-1"), /* select alternate font 1 */ + DATA("12", "ALT-FONT-2"), /* select alternate font 2 */ + DATA("13", "ALT-FONT-3"), /* select alternate font 3 */ + DATA("14", "ALT-FONT-4"), /* select alternate font 4 */ + DATA("15", "ALT-FONT-5"), /* select alternate font 5 */ + DATA("16", "ALT-FONT-6"), /* select alternate font 6 */ + DATA("17", "ALT-FONT-7"), /* select alternate font 7 */ + DATA("18", "ALT-FONT-1"), /* select alternate font 1 */ + DATA("19", "ALT-FONT-1"), /* select alternate font 1 */ + DATA("20", "FRAKTUR"), /* Fraktur font */ + DATA("21", "DOUBLEUNDER"), /* double underline */ + DATA("22", "-DIM"), /* dim off */ + DATA("23", "-ITALIC"), /* italic off */ + DATA("24", "-UNDERLINE"), /* underline off */ + DATA("25", "-BLINK"), /* blink off */ + DATA("26", "-FASTBLINK"), /* fastblink off */ + DATA("27", "-REVERSE"), /* reverse off */ + DATA("28", "-INVISIBLE"), /* invisible off */ + DATA("29", "-DELETED"), /* deleted off */ + DATAX() }; +#undef DATA + static int skip_csi(const char *cap) { @@ -558,7 +771,7 @@ skip_csi(const char *cap) } static bool -same_param(const char *table, const char *param, unsigned length) +same_param(const char *table, const char *param, size_t length) { bool result = FALSE; if (strncmp(table, param, length) == 0) { @@ -568,7 +781,7 @@ same_param(const char *table, const char *param, unsigned length) } static char * -lookup_params(const assoc * table, char *dst, char *src, size_t dstlen) +lookup_params(const assoc * table, char *dst, char *src) { char *result = 0; const char *ep = strtok(src, ";"); @@ -579,24 +792,23 @@ lookup_params(const assoc * table, char *dst, char *src, size_t dstlen) do { bool found = FALSE; - for (ap = table; ap->from; ap++) { + for (ap = table; ap->from[0]; ap++) { size_t tlen = strlen(ap->from); if (same_param(ap->from, ep, tlen)) { - (void) strlcat(dst, ap->to, dstlen); + _nc_STRCAT(dst, ap->to, MAX_TERMINFO_LENGTH); found = TRUE; break; } } if (!found) - (void) strlcat(dst, ep, dstlen); - (void) strlcat(dst, ";", dstlen); + _nc_STRCAT(dst, ep, MAX_TERMINFO_LENGTH); + _nc_STRCAT(dst, ";", MAX_TERMINFO_LENGTH); } while ((ep = strtok((char *) 0, ";"))); - if (dst[0] != '\0' && dst[strlen(dst) - 1] == ';') - dst[strlen(dst) - 1] = '\0'; + dst[strlen(dst) - 1] = '\0'; result = dst; } @@ -604,14 +816,14 @@ lookup_params(const assoc * table, char *dst, char *src, size_t dstlen) } static void -analyze_string(const char *name, const char *cap, TERMTYPE *tp) +analyze_string(const char *name, const char *cap, TERMTYPE2 *tp) { char buf2[MAX_TERMINFO_LENGTH]; const char *sp; const assoc *ap; int tp_lines = tp->Numbers[2]; - if (cap == ABSENT_STRING || cap == CANCELLED_STRING) + if (!VALID_STRING(cap)) return; (void) printf("%s: ", name); @@ -627,20 +839,23 @@ analyze_string(const char *name, const char *cap, TERMTYPE *tp) for (i = 0; i < STRCOUNT; i++) { char *cp = tp->Strings[i]; - /* don't use soft-key capabilities */ + /* don't use function-key capabilities */ + if (strnames[i] == NULL) + continue; if (strnames[i][0] == 'k' && strnames[i][1] == 'f') continue; - if (cp != ABSENT_STRING && cp != CANCELLED_STRING && cp[0] && cp - != cap) { + if (VALID_STRING(cp) && + cp[0] != '\0' && + cp != cap) { len = strlen(cp); - (void) strncpy(buf2, sp, len); + _nc_STRNCPY(buf2, sp, len); buf2[len] = '\0'; if (_nc_capcmp(cp, buf2)) continue; -#define ISRS(s) (!strncmp((s), "is", 2) || !strncmp((s), "rs", 2)) +#define ISRS(s) (!strncmp((s), "is", (size_t) 2) || !strncmp((s), "rs", (size_t) 2)) /* * Theoretically we just passed the test for translation * (equality once the padding is stripped). However, there @@ -661,7 +876,7 @@ analyze_string(const char *name, const char *cap, TERMTYPE *tp) /* now check the standard capabilities */ if (!expansion) { csi = skip_csi(sp); - for (ap = std_caps; ap->from; ap++) { + for (ap = std_caps; ap->from[0]; ap++) { size_t adj = (size_t) (csi ? 2 : 0); len = strlen(ap->from); @@ -680,60 +895,64 @@ analyze_string(const char *name, const char *cap, TERMTYPE *tp) /* now check for standard-mode sequences */ if (!expansion && (csi = skip_csi(sp)) != 0 - && (len = strspn(sp + csi, "0123456789;")) + && (len = (strspn) (sp + csi, "0123456789;")) && (len < sizeof(buf3)) && (next = (size_t) csi + len) && ((sp[next] == 'h') || (sp[next] == 'l'))) { - (void) strlcpy(buf2, (sp[next] == 'h') ? "ECMA+" : "ECMA-", - sizeof buf2); - (void) strncpy(buf3, sp + csi, len); + _nc_STRCPY(buf2, + ((sp[next] == 'h') + ? "ECMA+" + : "ECMA-"), + sizeof(buf2)); + _nc_STRNCPY(buf3, sp + csi, len); buf3[len] = '\0'; - len += (size_t) csi + 1; - expansion = lookup_params(std_modes, buf2, buf3, sizeof buf2); + expansion = lookup_params(std_modes, buf2, buf3); } /* now check for private-mode sequences */ if (!expansion && (csi = skip_csi(sp)) != 0 && sp[csi] == '?' - && (len = strspn(sp + csi + 1, "0123456789;")) + && (len = (strspn) (sp + csi + 1, "0123456789;")) && (len < sizeof(buf3)) && (next = (size_t) csi + 1 + len) && ((sp[next] == 'h') || (sp[next] == 'l'))) { - (void) strlcpy(buf2, (sp[next] == 'h') ? "DEC+" : "DEC-", - sizeof buf2); - (void) strncpy(buf3, sp + csi + 1, len); + _nc_STRCPY(buf2, + ((sp[next] == 'h') + ? "DEC+" + : "DEC-"), + sizeof(buf2)); + _nc_STRNCPY(buf3, sp + csi + 1, len); buf3[len] = '\0'; - len += (size_t) csi + 2; - expansion = lookup_params(private_modes, buf2, buf3, sizeof buf2); + expansion = lookup_params(private_modes, buf2, buf3); } /* now check for ECMA highlight sequences */ if (!expansion && (csi = skip_csi(sp)) != 0 - && (len = strspn(sp + csi, "0123456789;")) != 0 + && (len = (strspn) (sp + csi, "0123456789;")) != 0 && (len < sizeof(buf3)) && (next = (size_t) csi + len) && sp[next] == 'm') { - (void) strlcpy(buf2, "SGR:", sizeof buf2); - (void) strncpy(buf3, sp + csi, len); + _nc_STRCPY(buf2, "SGR:", sizeof(buf2)); + _nc_STRNCPY(buf3, sp + csi, len); buf3[len] = '\0'; len += (size_t) csi + 1; - expansion = lookup_params(ecma_highlights, buf2, buf3, sizeof buf2); + expansion = lookup_params(ecma_highlights, buf2, buf3); } if (!expansion && (csi = skip_csi(sp)) != 0 && sp[csi] == 'm') { len = (size_t) csi + 1; - (void) strlcpy(buf2, "SGR:", sizeof buf2); - strlcat(buf2, ecma_highlights[0].to, sizeof buf2); + _nc_STRCPY(buf2, "SGR:", sizeof(buf2)); + _nc_STRCAT(buf2, ecma_highlights[0].to, sizeof(buf2)); expansion = buf2; } @@ -744,7 +963,7 @@ analyze_string(const char *name, const char *cap, TERMTYPE *tp) expansion = "RSR"; len = 1; } else { - (void) snprintf(buf2, sizeof buf2, "1;%dr", tp_lines); + _nc_SPRINTF(buf2, _nc_SLIMIT(sizeof(buf2)) "1;%dr", tp_lines); len = strlen(buf2); if (strncmp(buf2, sp + csi, len) == 0) expansion = "RSR"; @@ -755,12 +974,12 @@ analyze_string(const char *name, const char *cap, TERMTYPE *tp) /* now check for home-down */ if (!expansion && (csi = skip_csi(sp)) != 0) { - (void) snprintf(buf2, sizeof buf2, "%d;1H", tp_lines); + _nc_SPRINTF(buf2, _nc_SLIMIT(sizeof(buf2)) "%d;1H", tp_lines); len = strlen(buf2); if (strncmp(buf2, sp + csi, len) == 0) { expansion = "LL"; } else { - (void) snprintf(buf2, sizeof buf2, "%dH", tp_lines); + _nc_SPRINTF(buf2, _nc_SLIMIT(sizeof(buf2)) "%dH", tp_lines); len = strlen(buf2); if (strncmp(buf2, sp + csi, len) == 0) { expansion = "LL"; @@ -800,12 +1019,17 @@ file_comparison(int argc, char *argv[]) int i, n; memset(heads, 0, sizeof(heads)); - dump_init((char *) 0, F_LITERAL, S_TERMINFO, 0, itrace, FALSE); + dump_init((char *) 0, F_LITERAL, S_TERMINFO, + FALSE, 0, 65535, itrace, FALSE, FALSE, FALSE); for (n = 0; n < argc && n < MAXCOMPARE; n++) { if (freopen(argv[n], "r", stdin) == 0) _nc_err_abort("Can't open %s", argv[n]); +#if NO_LEAKS + entered[n].head = _nc_head; + entered[n].tail = _nc_tail; +#endif _nc_head = _nc_tail = 0; /* parse entries out of the source file */ @@ -899,8 +1123,6 @@ file_comparison(int argc, char *argv[]) (void) printf("The following entries are equivalent:\n"); for (qp = heads[0]; qp; qp = qp->next) { - rp = qp->crosslinks[0]; - if (qp->ncrosslinks == 1) { rp = qp->crosslinks[0]; @@ -912,8 +1134,8 @@ file_comparison(int argc, char *argv[]) if (entryeq(&qp->tterm, &rp->tterm) && useeq(qp, rp)) { char name1[NAMESIZE], name2[NAMESIZE]; - (void) canonical_name(qp->tterm.term_names, name1, sizeof name1); - (void) canonical_name(rp->tterm.term_names, name2, sizeof name2); + canonical_name(qp->tterm.term_names, name1); + canonical_name(rp->tterm.term_names, name2); (void) printf("%s = %s\n", name1, name2); } @@ -932,38 +1154,31 @@ file_comparison(int argc, char *argv[]) #endif if (!(entryeq(&qp->tterm, &rp->tterm) && useeq(qp, rp))) { char name1[NAMESIZE], name2[NAMESIZE]; + char *names[3]; + + names[0] = name1; + names[1] = name2; + names[2] = 0; entries[0] = *qp; entries[1] = *rp; - (void) canonical_name(qp->tterm.term_names, name1, sizeof name1); - (void) canonical_name(rp->tterm.term_names, name2, sizeof name2); + canonical_name(qp->tterm.term_names, name1); + canonical_name(rp->tterm.term_names, name2); switch (compare) { case C_DIFFERENCE: - if (itrace) - (void) fprintf(stderr, - "%s: dumping differences\n", - _nc_progname); - (void) printf("comparing %s to %s.\n", name1, name2); + show_comparing(names); compare_entry(compare_predicate, &entries->tterm, quiet); break; case C_COMMON: - if (itrace) - (void) fprintf(stderr, - "%s: dumping common capabilities\n", - _nc_progname); - (void) printf("comparing %s to %s.\n", name1, name2); + show_comparing(names); compare_entry(compare_predicate, &entries->tterm, quiet); break; case C_NAND: - if (itrace) - (void) fprintf(stderr, - "%s: dumping differences\n", - _nc_progname); - (void) printf("comparing %s to %s.\n", name1, name2); + show_comparing(names); compare_entry(compare_predicate, &entries->tterm, quiet); break; @@ -976,34 +1191,46 @@ file_comparison(int argc, char *argv[]) static void usage(void) { - static const char *tbl[] = +#define DATA(s) s "\n" + static const char head[] = { - "Usage: infocmp [options] [-A directory] [-B directory] [termname...]" - ,"" - ,"Options:" + DATA("Usage: infocmp [options] [-A directory] [-B directory] [termname...]") + DATA("") + DATA("Options:") + }; +#undef DATA + /* length is given here so the compiler can make everything readonly */ +#define DATA(s) s + static const char options[][46] = + { + " -0 print single-row" ," -1 print single-column" ," -C use termcap-names" + ," -D print database locations" + ," -E format output as C tables" ," -F compare terminfo-files" + ," -G format %{number} to %'char'" ," -I use terminfo-names" + ," -K use termcap-names and BSD syntax" ," -L use long names" ," -R subset (see manpage)" ," -T eliminate size limits (test)" - ," -U eliminate post-processing of entries" + ," -U do not post-process entries" ," -V print version" + ," -W wrap long strings per -w[n]" #if NCURSES_XNAMES ," -a with -F, list commented-out caps" #endif ," -c list common capabilities" ," -d list different capabilities" ," -e format output for C initializer" - ," -E format output as C tables" ," -f with -1, format complex strings" - ," -G format %{number} to %'char'" ," -g format %'char' to %{number}" ," -i analyze initialization/reset" ," -l output terminfo names" ," -n list capabilities in neither" ," -p ignore padding specifiers" + ," -Q number dump compiled description" ," -q brief listing, removes headers" ," -r with -C, output in termcap form" ," -r with -F, resolve use-references" @@ -1015,20 +1242,21 @@ usage(void) ," -v number (verbose)" ," -w number (width)" #if NCURSES_XNAMES - ," -x treat unknown capabilities as user-defined" + ," -x unknown capabilities are user-defined" #endif }; - const size_t first = 3; - const size_t last = SIZEOF(tbl); - const size_t left = (last - first + 1) / 2 + first; +#undef DATA + const size_t last = SIZEOF(options); + const size_t left = (last + 1) / 2; size_t n; + fputs(head, stderr); for (n = 0; n < left; n++) { - size_t m = (n < first) ? last : n + left - first; + size_t m = n + left; if (m < last) - fprintf(stderr, "%-40.40s%s\n", tbl[n], tbl[m]); + fprintf(stderr, "%-40.40s%s\n", options[n], options[m]); else - fprintf(stderr, "%s\n", tbl[n]); + fprintf(stderr, "%s\n", options[n]); } ExitProgram(EXIT_FAILURE); } @@ -1037,21 +1265,25 @@ static char * any_initializer(const char *fmt, const char *type) { static char *initializer; - static size_t len; + static size_t need; char *s; if (initializer == 0) { - len = strlen(entries->tterm.term_names) + strlen(type) + strlen(fmt); - initializer = (char *) malloc(len); + need = (strlen(entries->tterm.term_names) + + strlen(type) + + strlen(fmt)); + initializer = (char *) malloc(need + 1); + if (initializer == 0) + failed("any_initializer"); } - (void) strlcpy(initializer, entries->tterm.term_names, len); + _nc_STRCPY(initializer, entries->tterm.term_names, need); for (s = initializer; *s != 0 && *s != '|'; s++) { if (!isalnum(UChar(*s))) *s = '_'; } *s = 0; - (void) snprintf(s, len - (s - initializer), fmt, type); + _nc_SPRINTF(s, _nc_SLIMIT(need) fmt, type); return initializer; } @@ -1069,7 +1301,7 @@ string_variable(const char *type) /* dump C initializers for the terminal type */ static void -dump_initializers(TERMTYPE *term) +dump_initializers(TERMTYPE2 *term) { unsigned n; const char *str = 0; @@ -1078,13 +1310,14 @@ dump_initializers(TERMTYPE *term) name_initializer("alias"), entries->tterm.term_names); for_each_string(n, term) { - char buf[MAX_STRING], *sp, *tp; - if (VALID_STRING(term->Strings[n])) { + char buf[MAX_STRING], *sp, *tp; + tp = buf; +#define TP_LIMIT ((MAX_STRING - 5) - (size_t)(tp - buf)) *tp++ = '"'; for (sp = term->Strings[n]; - *sp != 0 && (tp - buf) < MAX_STRING - 6; + *sp != 0 && TP_LIMIT > 2; sp++) { if (isascii(UChar(*sp)) && isprint(UChar(*sp)) @@ -1092,15 +1325,15 @@ dump_initializers(TERMTYPE *term) && *sp != '"') *tp++ = *sp; else { - (void) snprintf(tp, buf + sizeof buf - tp, "\\%03o", - UChar(*sp)); - tp += strlen(tp); + _nc_SPRINTF(tp, _nc_SLIMIT(TP_LIMIT) "\\%03o", UChar(*sp)); + tp += 4; } } *tp++ = '"'; *tp = '\0'; (void) printf("static char %-20s[] = %s;\n", - string_variable(ExtStrname(term, n, strnames)), buf); + string_variable(ExtStrname(term, (int) n, strnames)), + buf); } } printf("\n"); @@ -1126,7 +1359,7 @@ dump_initializers(TERMTYPE *term) break; } (void) printf("\t/* %3u: %-8s */\t%s,\n", - n, ExtBoolname(term, n, boolnames), str); + n, ExtBoolname(term, (int) n, boolnames), str); } (void) printf("%s;\n", R_CURL); @@ -1142,12 +1375,12 @@ dump_initializers(TERMTYPE *term) str = "CANCELLED_NUMERIC"; break; default: - snprintf(buf, sizeof buf, "%d", term->Numbers[n]); + _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf)) "%d", term->Numbers[n]); str = buf; break; } (void) printf("\t/* %3u: %-8s */\t%s,\n", n, - ExtNumname(term, n, numnames), str); + ExtNumname(term, (int) n, numnames), str); } (void) printf("%s;\n", R_CURL); @@ -1160,10 +1393,10 @@ dump_initializers(TERMTYPE *term) else if (term->Strings[n] == CANCELLED_STRING) str = "CANCELLED_STRING"; else { - str = string_variable(ExtStrname(term, n, strnames)); + str = string_variable(ExtStrname(term, (int) n, strnames)); } (void) printf("\t/* %3u: %-8s */\t%s,\n", n, - ExtStrname(term, n, strnames), str); + ExtStrname(term, (int) n, strnames), str); } (void) printf("%s;\n", R_CURL); @@ -1175,15 +1408,15 @@ dump_initializers(TERMTYPE *term) name_initializer("string_ext"), L_CURL); for (n = BOOLCOUNT; n < NUM_BOOLEANS(term); ++n) { (void) printf("\t/* %3u: bool */\t\"%s\",\n", - n, ExtBoolname(term, n, boolnames)); + n, ExtBoolname(term, (int) n, boolnames)); } for (n = NUMCOUNT; n < NUM_NUMBERS(term); ++n) { (void) printf("\t/* %3u: num */\t\"%s\",\n", - n, ExtNumname(term, n, numnames)); + n, ExtNumname(term, (int) n, numnames)); } for (n = STRCOUNT; n < NUM_STRINGS(term); ++n) { (void) printf("\t/* %3u: str */\t\"%s\",\n", - n, ExtStrname(term, n, strnames)); + n, ExtStrname(term, (int) n, strnames)); } (void) printf("%s;\n", R_CURL); } @@ -1192,7 +1425,7 @@ dump_initializers(TERMTYPE *term) /* dump C initializers for the terminal type */ static void -dump_termtype(TERMTYPE *term) +dump_termtype(TERMTYPE2 *term) { (void) printf("\t%s\n\t\t%s,\n", L_CURL, name_initializer("alias")); (void) printf("\t\t(char *)0,\t/* pointer to string table */\n"); @@ -1257,12 +1490,40 @@ terminal_env(void) return terminal; } +/* + * Show the databases that infocmp knows about. The location to which it writes is + */ +static void +show_databases(void) +{ + DBDIRS state; + int offset; + const char *path2; + + _nc_first_db(&state, &offset); + while ((path2 = _nc_next_db(&state, &offset)) != 0) { + printf("%s\n", path2); + } + _nc_last_db(); +} + /*************************************************************************** * * Main sequence * ***************************************************************************/ +#if NO_LEAKS +#define MAIN_LEAKS() \ + _nc_free_termtype2(&entries[0].tterm); \ + _nc_free_termtype2(&entries[1].tterm); \ + free(myargv); \ + free(tfile); \ + free(tname) +#else +#define MAIN_LEAKS() /* nothing */ +#endif + int main(int argc, char *argv[]) { @@ -1270,21 +1531,23 @@ main(int argc, char *argv[]) /* Also avoid overflowing smaller stacks on systems like AmigaOS */ path *tfile = 0; char **tname = 0; - int maxterms; + size_t maxterms; char **myargv; char *firstdir, *restdir; - int c, i, len; + int c; bool formatted = FALSE; bool filecompare = FALSE; int initdump = 0; bool init_analyze = FALSE; bool suppress_untranslatable = FALSE; + int quickdump = 0; + bool wrap_strings = FALSE; if (pledge("stdio rpath", NULL) == -1) { - perror("pledge"); - exit(1); + perror("pledge"); + exit(1); } /* where is the terminfo database location going to default to? */ @@ -1293,18 +1556,27 @@ main(int argc, char *argv[]) #if NCURSES_XNAMES use_extended_names(FALSE); #endif + _nc_strict_bsd = 0; _nc_progname = _nc_rootname(argv[0]); /* make sure we have enough space to add two terminal entries */ myargv = typeCalloc(char *, (size_t) (argc + 3)); + if (myargv == 0) + failed("myargv"); + memcpy(myargv, argv, (sizeof(char *) * (size_t) argc)); argv = myargv; while ((c = getopt(argc, argv, - "1A:aB:CcdEeFfGgIiLlnpqR:rs:TtUuVv:w:x")) != -1) { + "01A:aB:CcDdEeFfGgIiKLlnpQ:qR:rs:TtUuVv:Ww:x")) != -1) { switch (c) { + case '0': + mwidth = 65535; + mheight = 1; + break; + case '1': mwidth = 0; break; @@ -1323,6 +1595,9 @@ main(int argc, char *argv[]) restdir = optarg; break; + case 'K': + _nc_strict_bsd = 1; + /* FALLTHRU */ case 'C': outform = F_TERMCAP; tversion = "BSD"; @@ -1330,6 +1605,11 @@ main(int argc, char *argv[]) sortmode = S_TERMCAP; break; + case 'D': + show_databases(); + ExitProgram(EXIT_SUCCESS); + break; + case 'c': compare = C_COMMON; break; @@ -1391,6 +1671,10 @@ main(int argc, char *argv[]) ignorepads = TRUE; break; + case 'Q': + quickdump = optarg_to_number(); + break; + case 'q': quiet = TRUE; s_absent = "-"; @@ -1447,8 +1731,12 @@ main(int argc, char *argv[]) ExitProgram(EXIT_SUCCESS); case 'v': - itrace = optarg_to_number(); - set_trace_level(itrace); + itrace = (unsigned) optarg_to_number(); + use_verbosity(itrace); + break; + + case 'W': + wrap_strings = TRUE; break; case 'w': @@ -1466,10 +1754,17 @@ main(int argc, char *argv[]) } } - maxterms = (argc + 2 - optind); - tfile = typeMalloc(path, maxterms); - tname = typeCalloc(char *, maxterms); - entries = typeCalloc(ENTRY, maxterms); + maxterms = (size_t) (argc + 2 - optind); + if ((tfile = typeMalloc(path, maxterms)) == 0) + failed("tfile"); + if ((tname = typeCalloc(char *, maxterms)) == 0) + failed("tname"); + if ((entries = typeCalloc(ENTRY, maxterms)) == 0) + failed("entries"); +#if NO_LEAKS + if ((entered = typeCalloc(ENTERED, maxterms)) == 0) + failed("entered"); +#endif if (tfile == 0 || tname == 0 @@ -1482,9 +1777,6 @@ main(int argc, char *argv[]) if (sortmode == S_DEFAULT) sortmode = S_TERMINFO; - /* set up for display */ - dump_init(tversion, outform, sortmode, mwidth, itrace, formatted); - /* make sure we have at least one terminal name to work with */ if (optind >= argc) argv[argc++] = terminal_env(); @@ -1493,9 +1785,25 @@ main(int argc, char *argv[]) if (compare != C_DEFAULT && optind >= argc - 1) argv[argc++] = terminal_env(); + /* exactly one terminal name with no options means display it */ /* exactly two terminal names with no options means do -d */ - if (argc - optind == 2 && compare == C_DEFAULT) - compare = C_DIFFERENCE; + if (compare == C_DEFAULT) { + switch (argc - optind) { + default: + fprintf(stderr, "%s: too many names to compare\n", _nc_progname); + ExitProgram(EXIT_FAILURE); + case 1: + break; + case 2: + compare = C_DIFFERENCE; + break; + } + } + + /* set up for display */ + dump_init(tversion, outform, sortmode, + wrap_strings, mwidth, mheight, itrace, + formatted, FALSE, quickdump); if (!filecompare) { /* grab the entries */ @@ -1507,15 +1815,17 @@ main(int argc, char *argv[]) tname[termcount] = argv[optind]; if (directory) { -#if USE_DATABASE +#if NCURSES_USE_DATABASE #if MIXEDCASE_FILENAMES #define LEAF_FMT "%c" #else #define LEAF_FMT "%02x" #endif - (void) snprintf(tfile[termcount], sizeof (path), - "%s/" LEAF_FMT "/%s", directory, - UChar(*argv[optind]), argv[optind]); + _nc_SPRINTF(tfile[termcount], + _nc_SLIMIT(sizeof(path)) + "%s/" LEAF_FMT "/%s", + directory, + UChar(*argv[optind]), argv[optind]); if (itrace) (void) fprintf(stderr, "%s: reading entry %s from file %s\n", @@ -1523,10 +1833,11 @@ main(int argc, char *argv[]) argv[optind], tfile[termcount]); status = _nc_read_file_entry(tfile[termcount], - &entries[termcount].tterm); + &entries[termcount].tterm); #else (void) fprintf(stderr, "%s: terminfo files not supported\n", _nc_progname); + MAIN_LEAKS(); ExitProgram(EXIT_FAILURE); #endif } else { @@ -1536,10 +1847,9 @@ main(int argc, char *argv[]) _nc_progname, tname[termcount]); - status = _nc_read_entry(tname[termcount], - tfile[termcount], - &entries[termcount].tterm); - directory = TERMINFO; /* for error message */ + status = _nc_read_entry2(tname[termcount], + tfile[termcount], + &entries[termcount].tterm); } if (status <= 0) { @@ -1547,6 +1857,7 @@ main(int argc, char *argv[]) "%s: couldn't open terminfo file %s.\n", _nc_progname, tfile[termcount]); + MAIN_LEAKS(); ExitProgram(EXIT_FAILURE); } repair_acsc(&entries[termcount].tterm); @@ -1578,8 +1889,12 @@ main(int argc, char *argv[]) analyze_string("rs3", reset_3string, &entries[0].tterm); analyze_string("smcup", enter_ca_mode, &entries[0].tterm); analyze_string("rmcup", exit_ca_mode, &entries[0].tterm); + analyze_string("smkx", keypad_xmit, &entries[0].tterm); + analyze_string("rmkx", keypad_local, &entries[0].tterm); #undef CUR } else { + int i; + int len; /* * Here's where the real work gets done @@ -1591,8 +1906,10 @@ main(int argc, char *argv[]) "%s: about to dump %s\n", _nc_progname, tname[0]); - (void) printf("#\tReconstructed via infocmp from file: %s\n", - tfile[0]); + if (!quiet) + (void) + printf("#\tReconstructed via infocmp from file: %s\n", + tfile[0]); dump_entry(&entries[0].tterm, suppress_untranslatable, limited, @@ -1604,27 +1921,17 @@ main(int argc, char *argv[]) break; case C_DIFFERENCE: - if (itrace) - (void) fprintf(stderr, "%s: dumping differences\n", _nc_progname); - (void) printf("comparing %s to %s.\n", tname[0], tname[1]); + show_comparing(tname); compare_entry(compare_predicate, &entries->tterm, quiet); break; case C_COMMON: - if (itrace) - (void) fprintf(stderr, - "%s: dumping common capabilities\n", - _nc_progname); - (void) printf("comparing %s to %s.\n", tname[0], tname[1]); + show_comparing(tname); compare_entry(compare_predicate, &entries->tterm, quiet); break; case C_NAND: - if (itrace) - (void) fprintf(stderr, - "%s: dumping differences\n", - _nc_progname); - (void) printf("comparing %s to %s.\n", tname[0], tname[1]); + show_comparing(tname); compare_entry(compare_predicate, &entries->tterm, quiet); break; @@ -1645,21 +1952,18 @@ main(int argc, char *argv[]) break; } } - } else if (compare == C_USEALL) + } else if (compare == C_USEALL) { (void) fprintf(stderr, "Sorry, -u doesn't work with -F\n"); - else if (compare == C_DEFAULT) + } else if (compare == C_DEFAULT) { (void) fprintf(stderr, "Use `tic -[CI] ' for this.\n"); - else if (argc - optind != 2) + } else if (argc - optind != 2) { (void) fprintf(stderr, "File comparison needs exactly two file arguments.\n"); - else + } else { file_comparison(argc - optind, argv + optind); + } -#if NO_LEAKS - free(myargv); - free(tfile); - free(tname); -#endif + MAIN_LEAKS(); ExitProgram(EXIT_SUCCESS); } diff --git a/usr.bin/tic/MKtermsort.sh b/usr.bin/tic/MKtermsort.sh index 43e1174cdb2..e13c365c837 100644 --- a/usr.bin/tic/MKtermsort.sh +++ b/usr.bin/tic/MKtermsort.sh @@ -1,11 +1,12 @@ +# $OpenBSD: MKtermsort.sh,v 1.6 2023/10/17 09:52:10 nicm Exp $ #!/bin/sh -# $OpenBSD: MKtermsort.sh,v 1.5 2010/01/12 23:22:14 nicm Exp $ -# $Id: MKtermsort.sh,v 1.5 2010/01/12 23:22:14 nicm Exp $ +# $Id: MKtermsort.sh,v 1.6 2023/10/17 09:52:10 nicm Exp $ # # MKtermsort.sh -- generate indirection vectors for the various sort methods # ############################################################################## -# Copyright (c) 1998-2003,2008 Free Software Foundation, Inc. # +# Copyright 2020-2021,2022 Thomas E. Dickey # +# Copyright 1998-2015,2017 Free Software Foundation, Inc. # # # # Permission is hereby granted, free of charge, to any person obtaining a # # copy of this software and associated documentation files (the "Software"), # @@ -47,15 +48,26 @@ AWK=${1-awk} DATA=${2-../include/Caps} data=data$$ -trap 'rm -f $data' 1 2 5 15 -sed -e 's/[ ][ ]*/ /g' < $DATA >$data +trap 'rm -f $data; exit 1' 1 2 3 15 +sed -e 's/[ ][ ]*/ /g' < "$DATA" >$data DATA=$data -echo "/*"; -echo " * termsort.c --- sort order arrays for use by infocmp."; -echo " *"; -echo " * Note: this file is generated using MKtermsort.sh, do not edit by hand."; -echo " */"; +cat < + +#ifndef DUMP_ENTRY_H +typedef unsigned PredType; +typedef unsigned PredIdx; +#endif + +EOF echo "static const PredIdx bool_terminfo_sort[] = {"; $AWK <$DATA ' @@ -140,26 +152,36 @@ echo ""; echo "static const bool bool_from_termcap[] = {"; $AWK <$DATA ' -$3 == "bool" && substr($7, 1, 1) == "-" {print "\tFALSE,\t/* ", $2, " */";} -$3 == "bool" && substr($7, 1, 1) == "Y" {print "\tTRUE,\t/* ", $2, " */";} +BEGIN { count = 0; valid = 0; } +$3 == "bool" && substr($7, 1, 1) == "-" {print "\tFALSE,\t/* ", $2, " */"; count++; } +$3 == "bool" && substr($7, 1, 1) == "Y" {print "\tTRUE,\t/* ", $2, " */"; valid = count++; } +END { printf "#define OK_bool_from_termcap %d\n", valid; } ' echo "};"; echo ""; echo "static const bool num_from_termcap[] = {"; $AWK <$DATA ' -$3 == "num" && substr($7, 1, 1) == "-" {print "\tFALSE,\t/* ", $2, " */";} -$3 == "num" && substr($7, 1, 1) == "Y" {print "\tTRUE,\t/* ", $2, " */";} +BEGIN { count = 0; valid = 0; } +$3 == "num" && substr($7, 1, 1) == "-" {print "\tFALSE,\t/* ", $2, " */"; count++; } +$3 == "num" && substr($7, 1, 1) == "Y" {print "\tTRUE,\t/* ", $2, " */"; valid = count++; } +END { printf "#define OK_num_from_termcap %d\n", valid; } ' echo "};"; echo ""; echo "static const bool str_from_termcap[] = {"; $AWK <$DATA ' -$3 == "str" && substr($7, 1, 1) == "-" {print "\tFALSE,\t/* ", $2, " */";} -$3 == "str" && substr($7, 1, 1) == "Y" {print "\tTRUE,\t/* ", $2, " */";} +BEGIN { count = 0; valid = 0; } +$3 == "str" && substr($7, 1, 1) == "-" {print "\tFALSE,\t/* ", $2, " */"; count++; } +$3 == "str" && substr($7, 1, 1) == "Y" {print "\tTRUE,\t/* ", $2, " */"; valid = count++; } +END { printf "#define OK_str_from_termcap %d\n", valid; } ' -echo "};"; -echo ""; + +cat < ${.TARGET} .include diff --git a/usr.bin/tic/capconvert b/usr.bin/tic/capconvert new file mode 100644 index 00000000000..94560c92178 --- /dev/null +++ b/usr.bin/tic/capconvert @@ -0,0 +1,260 @@ +#!/bin/sh +############################################################################## +# Copyright 2019-2021,2022 Thomas E. Dickey # +# Copyright 1998-2011,2017 Free Software Foundation, Inc. # +# # +# Permission is hereby granted, free of charge, to any person obtaining a # +# copy of this software and associated documentation files (the "Software"), # +# to deal in the Software without restriction, including without limitation # +# the rights to use, copy, modify, merge, publish, distribute, distribute # +# with modifications, sublicense, and/or sell copies of the Software, and to # +# permit persons to whom the Software is furnished to do so, subject to the # +# following conditions: # +# # +# The above copyright notice and this permission notice shall be included in # +# all copies or substantial portions of the Software. # +# # +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # +# THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # +# DEALINGS IN THE SOFTWARE. # +# # +# Except as contained in this notice, the name(s) of the above copyright # +# holders shall not be used in advertising or otherwise to promote the sale, # +# use or other dealings in this Software without prior written # +# authorization. # +############################################################################## +# $Id: capconvert,v 1.1 2023/10/17 09:52:10 nicm Exp $ +# +# capconvert -- automated conversion from termcap to terminfo +# + +echo "This script tries to automatically set you up so that your applications" +echo "that now use termcap can use terminfo and the ncurses library." +echo "" + +# Note, except for telling if we're running under xterm we don't use TERM at +# all. This is because BSD users not infrequently have multiple termtypes +# selected by conditionals in tset -- unless they're xterm users, in which +# case they're on a workstation and probably don't. + +# Check to make sure TERMINFO is not already defined +if test -n "$TERMINFO" +then + echo "TERMINFO is already defined in your environment. This means" + echo "you already have a local terminfo tree, so you do not need any" + echo "conversion." + if test ! -d "$TERMINFO" ; then + echo "Caution: TERMINFO does not point to a directory!" + fi + exit; +fi + +# Check to see if terminfo is present in one of the standard locations. +terminfo=no +for p in $TERMINFO \ + /usr/lib/terminfo \ + /usr/share/lib/terminfo \ + /usr/share/terminfo \ + /usr/local/lib/terminfo \ + /usr/local/share/terminfo +do + if test -d "$p" ; then + terminfo=yes + break + fi +done + +if test $terminfo = yes +then + echo "Your system already has a system-wide terminfo tree." + echo "" + if test -z "$TERMCAP" + then + echo "You have no TERMCAP variable set, so we are done." + # Assumes the terminfo master covers all canned terminal types + exit; + fi + case $TERM in + xterm | xterm-*) + echo "You are running xterm, which usually sets TERMCAP itself." + echo "We can ignore this, because terminfo knows about xterm." + echo "So you will just use the system-wide terminfo tree." + exit + ;; + *) + echo "We will have to make a local one for you anyway, to capture the effect" + echo "of your TERMCAP variable." + ;; + esac +else + echo "No system-wide terminfo tree. We will make you a local one." +fi +echo ""; + +# Check if test -x works (it is not portable, but useful) +OPT="-x" +TMP=test$$; touch $TMP && chmod 755 $TMP +if test $OPT $TMP ; then + chmod 644 $TMP + test $OPT $TMP && OPT="-f" +else + OPT="-f" +fi +rm -f $TMP + +# First step -- go find tic +TIC= +IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}:" +for x in $PATH . +do + if test "$OPT" "$x"/tic + then + TIC=$x/tic + break + fi +done +IFS="$save_ifs" + +if test -n "$TIC" +then + echo "I see tic at $TIC." + case $TIC in # (vi + ./tic) + if test $OPT ../misc/shlib ; then + TIC="../misc/shlib $TIC" + fi + ;; + esac +else + echo "You do not have tic installed anywhere I can see, please fix that." + exit; +fi +echo ""; + +# We have tic. Either there's no system terminfo tree or there is one but +# the user has a TERMCAP variable that may modify a stock description. +# + +# Make the user a terminfo directory +if test -d "$HOME"/.terminfo +then + echo "It appears you already have a private terminfo directory" + echo "at $HOME/.terminfo; this seems odd, because TERMINFO" + echo "is not defined. I am not going to second-guess this -- if you" + echo "really want me to try auto-configuring for you, remove or" + echo "rename $HOME/terminfo and run me again." + exit; +else + echo "I am creating your private terminfo directory at $HOME/.terminfo" + mkdir "$HOME"/.terminfo + # Ensure that that's where tic's compilation results. + # This isn't strictly necessary with a 1.9.7 or later tic. + TERMINFO="$HOME/.terminfo"; export TERMINFO +fi +echo ""; + +# Find a terminfo source to work from +if test -f ../misc/terminfo.src +then + echo "I see the terminfo master source is handy; I will use that." + master=../misc/terminfo.src +else + # Ooops...looks like we're running from somewhere other than the + # progs directory of an ncurses source tree. + master=`find "$HOME" -name "*terminfo.src" -print` + mcount=`find "$HOME" -name "*terminfo.src" | wc -l` + case $mcount in + 0) + echo "I can not find a terminfo source file anywhere under your home directory." + echo "There should be a file called terminfo.src somewhere in your" + echo "ncurses distribution; please put it in your home directotry" + echo "and run me again (it does not have to live there permanently)." + exit; + ;; + 1) + echo "I see a file called $master." + echo "I am going to assume this is the terminfo source included with" + echo "the ncurses distribution. If this assumption is wrong, please" + echo "interrupt me now! OK to continue?" + read answer; + ;; + 2) + echo "I see more than one possible terminfo source. Here they are:" + echo "$master" | sed "/^/s// /"; + while : + do + echo "Please tell me which one to use:" + read master; + if test -f "$master" + then + break + else + echo "That file does not exist. Try again?"; + fi + done + ;; + esac +fi +echo ""; + +# Now that we have a master, compile it into the local tree +echo "OK, now I will make your private terminfo tree. This may take a bit..." +# +# Kluge alert: we compile terminfo.src in two pieces because a lot of machines +# with < 16MB RAM choke on tic's core-hog habits. +trap 'rm -f tsplit$$.*; exit 1' 1 2 3 15 +trap 'rm -f tsplit$$.*' 0 +sed -n "$master" \ + -e '1,/SPLIT HERE/w 'tsplit$$.01 \ + -e '/SPLIT HERE/,$w 'tsplit$$.02 \ + 2>/dev/null +for x in tsplit$$.*; do eval $TIC "$x"; done +rm tsplit$$.* +trap EXIT INT QUIT TERM HUP +# +echo "You now have a private tree under $HOME/.terminfo;" +echo "the ncurses library will automatically read from it," +echo "and ncurses tic will automatically compile entries to it." + +# We're done unless user has a .termcap file or equivalent named by TERMCAP +if test -z "$TERMCAP" +then + echo "You have no TERMCAP set, so we are done." +fi + +# OK, here comes the nasty case...user has a TERMCAP. Instead of +# trying to follow all the convolutions of the relationship between +# TERM and TERMCAP (partly because it is too painful, and partly because +# we don't actually know what TERM will be nor even if it always has +# the same value for this user) we do the following three steps... + +if test -f "$HOME"/.termcap +then + echo "I see you have a \$HOME/.termcap file. I will compile that." + eval $TIC "$HOME"/.termcap + echo "Done." + echo "Note that editing $HOME/.termcap will no longer change the data curses sees." +elif test -f "$TERMCAP" +then + echo "Your TERMCAP names the file $TERMCAP. I will compile that." + eval $TIC "$TERMCAP" + echo "Done." + echo "Note that editing $TERMCAP will no longer change the data curses sees." +else + echo "Your TERMCAP value appears to be an entry in termcap format." + echo "I will compile it." + echo "$TERMCAP" >myterm$$ + eval $TIC myterm$$ + rm myterm$$ + echo "Done." + echo "Note that editing TERMCAP will no longer change the data curses sees." +fi +echo "To do that, decompile the terminal description you want with infocmp(1)," +echo "edit to taste, and recompile using tic(1)." + +# capconvert ends here + diff --git a/usr.bin/tic/captoinfo.1 b/usr.bin/tic/captoinfo.1 index ee563e6852f..5c363dd2ae1 100644 --- a/usr.bin/tic/captoinfo.1 +++ b/usr.bin/tic/captoinfo.1 @@ -1,6 +1,8 @@ -.\" $OpenBSD: captoinfo.1,v 1.1 2022/07/11 03:11:49 daniel Exp $ +'\" t +.\" $OpenBSD: captoinfo.1,v 1.2 2023/10/17 09:52:10 nicm Exp $ .\"*************************************************************************** -.\" Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2010,2016 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -27,47 +29,52 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: captoinfo.1,v 1.1 2022/07/11 03:11:49 daniel Exp $ -.TH captoinfo 1 "" +.\" $Id: captoinfo.1,v 1.2 2023/10/17 09:52:10 nicm Exp $ +.TH captoinfo 1 2023-08-19 "ncurses 6.4" "User commands" .ds n 5 -.ds d /usr/share/misc/terminfo +.ds d /usr/share/terminfo .SH NAME -\fBcaptoinfo\fR - convert a \fItermcap\fR description into a \fIterminfo\fR description +\fBcaptoinfo\fP \- convert a \fItermcap\fP description into a \fIterminfo\fP description .SH SYNOPSIS -\fBcaptoinfo\fR [\fB-v\fR\fIn\fR \fIwidth\fR] [\fB-V\fR] [\fB-1\fR] [\fB-w\fR \fIwidth\fR] \fIfile\fR . . . +\fBcaptoinfo\fR [\fB\-v\fIn\fR \fIwidth\fR] [\fB\-V\fR] [\fB\-1\fR] [\fB\-w\fR \fIwidth\fR] \fIfile\fR ... .SH DESCRIPTION -\fBcaptoinfo\fR looks in \fIfile\fR for \fBtermcap\fR descriptions. For each -one found, an equivalent \fBterminfo\fR description is written to standard -output. Termcap \fBtc\fR capabilities are translated directly to terminfo -\fBuse\fR capabilities. +\fBcaptoinfo\fP looks in each given text +\fIfile\fP for \fBtermcap\fP descriptions. +For each +one found, an equivalent \fBterminfo\fP description is written to standard +output. +Termcap \fBtc\fP capabilities are translated directly to terminfo +\fBuse\fP capabilities. .PP -If no \fIfile\fR is given, then the environment variable \fBTERMCAP\fR is used -for the filename or entry. If \fBTERMCAP\fR is a full pathname to a file, only -the terminal whose name is specified in the environment variable \fBTERM\fR is -extracted from that file. If the environment variable \fBTERMCAP\fR is not -set, then the file \fB\*d\fR is read. +If no \fIfile\fP is given, then the environment variable \fBTERMCAP\fP is used +for the filename or entry. +If \fBTERMCAP\fP is a full pathname to a file, only +the terminal whose name is specified in the environment variable \fBTERM\fP is +extracted from that file. +If the environment variable \fBTERMCAP\fP is not +set, then the file \fB\*d\fP is read. .TP 5 -\fB-v\fR +\fB\-v\fP print out tracing information on standard error as the program runs. .TP 5 -\fB-V\fR +\fB\-V\fP print out the version of the program in use on standard error and exit. .TP 5 -\fB-1\fR -cause the fields to print out one to a line. Otherwise, the fields +\fB\-1\fP +cause the fields to print out one to a line. +Otherwise, the fields will be printed several to a line to a maximum width of 60 characters. .TP 5 -\fB-w\fR -change the output to \fIwidth\fR characters. +\fB\-w\fP +change the output to \fIwidth\fP characters. .SH FILES .TP 20 \*d Compiled terminal description database. .SH TRANSLATIONS FROM NONSTANDARD CAPABILITIES -.PP Some obsolete nonstandard capabilities will automatically be translated -into standard (SVr4/XSI Curses) terminfo capabilities by \fBcaptoinfo\fR. +into standard (SVr4/XSI Curses) terminfo capabilities by \fBcaptoinfo\fP. Whenever one of these automatic translations is done, the program will issue an notification to stderr, inviting the user to check that it has not mistakenly translated a completely unknown and random @@ -112,7 +119,8 @@ HS mh Iris enter_dim_mode .PP XENIX termcap also used to have a set of extension capabilities for forms drawing, designed to take advantage of the IBM PC -high-half graphics. They were as follows: +high-half graphics. +They were as follows: .PP .TS H c c @@ -145,12 +153,15 @@ GG acs magic cookie count .TE .PP If the single-line capabilities occur in an entry, they will automatically -be composed into an \fIacsc\fR string. The double-line capabilities and -\fBGG\fR are discarded with a warning message. +be composed into an \fBacsc\fP string. +The double-line capabilities and +\fBGG\fP are discarded with a warning message. .PP IBM's AIX has a terminfo facility descended from SVr1 terminfo but incompatible -with the SVr4 format. The following AIX extensions are automatically +with the SVr4 format. +The following AIX extensions are automatically translated: +.PP .TS c c l l. @@ -164,30 +175,34 @@ font2 s2ds font3 s3ds .TE .PP -Additionally, the AIX \fIbox1\fR capability will be automatically translated to -an \fIacsc\fR string. +Additionally, the AIX \fIbox1\fP capability will be automatically translated to +an \fBacsc\fP string. .PP Hewlett-Packard's terminfo library supports two nonstandard terminfo -capabilities \fImeml\fR (memory lock) and \fImemu\fR (memory unlock). +capabilities \fBmeml\fP (memory lock) and \fBmemu\fP (memory unlock). These will be discarded with a warning message. .SH NOTES -This utility is actually a link to \fBtic\fR(1), running in \fI-I\fR mode. -You can use other \fBtic\fR options such as \fB-f\fR and \fB-x\fR. +This utility is actually a link to \fBtic\fP(1), running in \fI\-I\fP mode. +You can use other \fBtic\fP options such as \fB\-f\fP and \fB\-x\fP. +.PP +The verbose option is not identical to SVr4's. +Under SVr4, instead of following +the \fB\-v\fP with a trace level n, you repeat it n times. +.SH PORTABILITY +X/Open Curses, Issue 7 (2009) describes \fBtic\fP briefly, +but omits this program. +SVr4 systems provide \fBcaptoinfo\fP as a separate application from \fBtic\fP. .PP -The trace option is not identical to SVr4's. Under SVr4, instead of following -the \fB-v\fR with a trace level n, you repeat it n times. +NetBSD does not provide this application. .SH SEE ALSO -\fBinfocmp\fR(1), -\fBcurses\fR(3), -\fBterminfo\fR(\*n) +\fBinfocmp\fP(1), +\fBcurses\fP(3), +\fBterminfo\fP(\*n) .PP -This describes \fBncurses\fR -version 5.7. +This describes \fBncurses\fP +version 6.4 (patch 20230826). .SH AUTHOR Eric S. Raymond -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +and +.br +Thomas E. Dickey diff --git a/usr.bin/tic/clear_cmd.c b/usr.bin/tic/clear_cmd.c new file mode 100644 index 00000000000..f035563f59e --- /dev/null +++ b/usr.bin/tic/clear_cmd.c @@ -0,0 +1,60 @@ +/**************************************************************************** + * Copyright 2018,2020 Thomas E. Dickey * + * Copyright 2016,2017 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey * + ****************************************************************************/ + +/* + * clear.c -- clears the terminal's screen + */ + +#define USE_LIBTINFO +#include + +MODULE_ID("$Id: clear_cmd.c,v 1.1 2023/10/17 09:52:10 nicm Exp $") + +static int +putch(int c) +{ + return putchar(c); +} + +int +clear_cmd(bool legacy) +{ + int retval = tputs(clear_screen, lines > 0 ? lines : 1, putch); + if (!legacy) { + /* Clear the scrollback buffer if possible. */ + char *E3 = tigetstr("E3"); + if (E3) + (void) tputs(E3, lines > 0 ? lines : 1, putch); + } + return retval; +} diff --git a/usr.bin/tic/clear_cmd.h b/usr.bin/tic/clear_cmd.h new file mode 100644 index 00000000000..61acb3921fa --- /dev/null +++ b/usr.bin/tic/clear_cmd.h @@ -0,0 +1,45 @@ +/**************************************************************************** + * Copyright 2020 Thomas E. Dickey * + * Copyright 2016,2017 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey * + ****************************************************************************/ + +/* + * $Id: clear_cmd.h,v 1.1 2023/10/17 09:52:10 nicm Exp $ + * + * Utility functions for clearing terminal. + */ +#ifndef CLEAR_CMD_H +#define CLEAR_CMD_H 1 + +#include +extern int clear_cmd(bool); + +#endif /* CLEAR_CMD_H */ diff --git a/usr.bin/tic/dump_entry.c b/usr.bin/tic/dump_entry.c index 9bb5dfbd7b8..474fd3f830d 100644 --- a/usr.bin/tic/dump_entry.c +++ b/usr.bin/tic/dump_entry.c @@ -1,7 +1,8 @@ -/* $OpenBSD: dump_entry.c,v 1.20 2017/05/11 19:13:17 millert Exp $ */ +/* $OpenBSD: dump_entry.c,v 1.21 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -37,17 +38,18 @@ #define __INTERNAL_CAPS_VISIBLE #include -#include "dump_entry.h" -#include "termsort.c" /* this C file is generated */ +#include +#include /* this C file is generated */ #include /* so is this */ -MODULE_ID("$Id: dump_entry.c,v 1.20 2017/05/11 19:13:17 millert Exp $") +MODULE_ID("$Id: dump_entry.c,v 1.21 2023/10/17 09:52:10 nicm Exp $") -#define INDENT 8 #define DISCARD(string) string = ABSENT_STRING #define PRINTF (void) printf +#define WRAPPED 32 #define OkIndex(index,array) ((int)(index) >= 0 && (int)(index) < (int) SIZEOF(array)) +#define TcOutput() (outform == F_TERMCAP || outform == F_TCONVERR) typedef struct { char *text; @@ -59,9 +61,14 @@ static int tversion; /* terminfo version */ static int outform; /* output format to use */ static int sortmode; /* sort mode to use */ static int width = 60; /* max line width for listings */ +static int height = 65535; /* max number of lines for listings */ static int column; /* current column, limited by 'width' */ static int oldcol; /* last value of column before wrap */ static bool pretty; /* true if we format if-then-else strings */ +static bool wrapped; /* true if we wrap too-long strings */ +static bool did_wrap; /* true if last wrap_concat did wrapping */ +static bool checking; /* true if we are checking for tic */ +static int quickdump; /* true if we are dumping compiled data */ static char *save_sgr; @@ -74,12 +81,13 @@ static NCURSES_CONST char *const *bool_names; static NCURSES_CONST char *const *num_names; static NCURSES_CONST char *const *str_names; -static const char *separator, *trailer; +static const char *separator = "", *trailer = ""; +static int indent = 8; /* cover various ports and variants of terminfo */ #define V_ALLCAPS 0 /* all capabilities (SVr4, XSI, ncurses) */ #define V_SVR1 1 /* SVR1, Ultrix */ -#define V_HPUX 2 /* HP/UX */ +#define V_HPUX 2 /* HP-UX */ #define V_AIX 3 /* AIX */ #define V_BSD 4 /* BSD */ @@ -89,7 +97,7 @@ static const char *separator, *trailer; #define OBSOLETE(n) (n[0] == 'O' && n[1] == 'T') #endif -#define isObsolete(f,n) ((f == F_TERMINFO || f == F_VARIABLE) && OBSOLETE(n)) +#define isObsolete(f,n) ((f == F_TERMINFO || f == F_VARIABLE) && (sortmode != S_VARIABLE) && OBSOLETE(n)) #if NCURSES_XNAMES #define BoolIndirect(j) ((j >= BOOLCOUNT) ? (j) : ((sortmode == S_NOSORT) ? j : bool_indirect[j])) @@ -101,6 +109,13 @@ static const char *separator, *trailer; #define StrIndirect(j) ((sortmode == S_NOSORT) ? (j) : str_indirect[j]) #endif +static GCC_NORETURN void +failed(const char *s) +{ + perror(s); + ExitProgram(EXIT_FAILURE); +} + static void strncpy_DYN(DYNBUF * dst, const char *src, size_t need) { @@ -108,8 +123,10 @@ strncpy_DYN(DYNBUF * dst, const char *src, size_t need) if (want > dst->size) { dst->size += (want + 1024); /* be generous */ dst->text = typeRealloc(char, dst->size, dst->text); + if (dst->text == 0) + failed("strncpy_DYN"); } - (void) strncpy(dst->text + dst->used, src, need); + _nc_STRNCPY(dst->text + dst->used, src, need + 1); dst->used += need; dst->text[dst->used] = 0; } @@ -145,17 +162,17 @@ _nc_leaks_dump_entry(void) #endif #define NameTrans(check,result) \ - if (OkIndex(np->nte_index, check) \ + if ((np->nte_index <= OK_ ## check) \ && check[np->nte_index]) \ return (result[np->nte_index]) NCURSES_CONST char * nametrans(const char *name) -/* translate a capability name from termcap to terminfo */ +/* translate a capability name to termcap from terminfo */ { const struct name_table_entry *np; - if ((np = _nc_find_entry(name, _nc_get_hash_table(0))) != 0) + if ((np = _nc_find_entry(name, _nc_get_hash_table(0))) != 0) { switch (np->nte_type) { case BOOLEAN: NameTrans(bool_from_termcap, boolcodes); @@ -169,17 +186,32 @@ nametrans(const char *name) NameTrans(str_from_termcap, strcodes); break; } + } return (0); } void -dump_init(const char *version, int mode, int sort, int twidth, int traceval, - bool formatted) +dump_init(const char *version, + int mode, + int sort, + bool wrap_strings, + int twidth, + int theight, + unsigned traceval, + bool formatted, + bool check, + int quick) /* set up for entry display */ { width = twidth; + height = theight; pretty = formatted; + wrapped = wrap_strings; + checking = check; + quickdump = (quick & 3); + + did_wrap = (width <= 0); /* versions */ if (version == 0) @@ -203,7 +235,7 @@ dump_init(const char *version, int mode, int sort, int twidth, int traceval, bool_names = boolnames; num_names = numnames; str_names = strnames; - separator = twidth ? ", " : ","; + separator = (twidth > 0 && theight > 1) ? ", " : ","; trailer = "\n\t"; break; @@ -211,7 +243,7 @@ dump_init(const char *version, int mode, int sort, int twidth, int traceval, bool_names = boolfnames; num_names = numfnames; str_names = strfnames; - separator = twidth ? ", " : ","; + separator = (twidth > 0 && theight > 1) ? ", " : ","; trailer = "\n\t"; break; @@ -224,6 +256,7 @@ dump_init(const char *version, int mode, int sort, int twidth, int traceval, trailer = "\\\n\t:"; break; } + indent = 8; /* implement sort modes */ switch (sortmode = sort) { @@ -267,7 +300,7 @@ dump_init(const char *version, int mode, int sort, int twidth, int traceval, _nc_progname, width, tversion, outform); } -static TERMTYPE *cur_type; +static TERMTYPE2 *cur_type; static int dump_predicate(PredType type, PredIdx idx) @@ -290,10 +323,14 @@ dump_predicate(PredType type, PredIdx idx) return (FALSE); /* pacify compiler */ } -static void set_obsolete_termcaps(TERMTYPE *tp); +static void set_obsolete_termcaps(TERMTYPE2 *tp); /* is this the index of a function key string? */ -#define FNKEY(i) (((i)>= 65 && (i)<= 75) || ((i)>= 216 && (i)<= 268)) +#define FNKEY(i) \ + (((i) >= STR_IDX(key_f0) && \ + (i) <= STR_IDX(key_f9)) || \ + ((i) >= STR_IDX(key_f11) && \ + (i) <= STR_IDX(key_f63))) /* * If we configure with a different Caps file, the offsets into the arrays @@ -389,22 +426,257 @@ force_wrap(void) oldcol = column; trim_trailing(); strcpy_DYN(&outbuf, trailer); - column = INDENT; + column = indent; +} + +static int +op_length(const char *src, int offset) +{ + int result = 0; + + if (offset > 0 && src[offset - 1] == '\\') { + result = 0; + } else { + int ch; + + result++; /* for '%' mark */ + ch = src[offset + result]; + if (TcOutput()) { + if (ch == '>') { + result += 3; + } else if (ch == '+') { + result += 2; + } else { + result++; + } + } else if (ch == '\'') { + result += 3; + } else if (ch == L_CURL[0]) { + int n = result; + while ((ch = src[offset + n]) != '\0') { + if (ch == R_CURL[0]) { + result = ++n; + break; + } + n++; + } + } else if (strchr("pPg", ch) != 0) { + result += 2; + } else { + result++; /* ordinary operator */ + } + } + return result; } +/* + * When wrapping too-long strings, avoid splitting a backslash sequence, or + * a terminfo '%' operator. That will leave things a little ragged, but avoids + * a stray backslash at the end of the line, as well as making the result a + * little more readable. + */ +static int +find_split(const char *src, int step, int size) +{ + int result = size; + + if (size > 0) { + /* check if that would split a backslash-sequence */ + int mark = size; + int n; + + for (n = size - 1; n > 0; --n) { + int ch = UChar(src[step + n]); + if (ch == '\\') { + if (n > 0 && src[step + n - 1] == ch) + --n; + mark = n; + break; + } else if (!isalnum(ch)) { + break; + } + } + if (mark < size) { + result = mark; + } else { + /* check if that would split a backslash-sequence */ + for (n = size - 1; n > 0; --n) { + int ch = UChar(src[step + n]); + if (ch == '%') { + int need = op_length(src, step + n); + if ((n + need) > size) { + mark = n; + } + break; + } + } + if (mark < size) { + result = mark; + } + } + } + return result; +} + +/* + * If we are going to wrap lines, we cannot leave literal spaces because that + * would be ambiguous if we split on that space. + */ +static char * +fill_spaces(const char *src) +{ + const char *fill = "\\s"; + size_t need = strlen(src); + size_t size = strlen(fill); + char *result = 0; + int pass; + size_t s, d; + for (pass = 0; pass < 2; ++pass) { + for (s = d = 0; src[s] != '\0'; ++s) { + if (src[s] == ' ') { + if (pass) { + _nc_STRCPY(&result[d], fill, need + 1 - d); + d += size; + } else { + need += size; + } + } else { + if (pass) { + result[d++] = src[s]; + } else { + ++d; + } + } + } + if (pass) { + result[d] = '\0'; + } else { + result = calloc(need + 1, sizeof(char)); + if (result == 0) + failed("fill_spaces"); + } + } + return result; +} + +typedef enum { + wOFF = 0 + ,w1ST = 1 + ,w2ND = 2 + ,wEND = 4 + ,wERR = 8 +} WRAPMODE; + +#define wrap_1ST(mode) ((mode)&w1ST) +#define wrap_END(mode) ((mode)&wEND) +#define wrap_ERR(mode) ((mode)&wERR) + static void -wrap_concat(const char *src) +wrap_concat(const char *src, int need, unsigned mode) { - unsigned need = strlen(src); - unsigned want = strlen(separator) + need; + int gaps = (int) strlen(separator); + int want = gaps + need; + + did_wrap = (width <= 0); + if (wrap_1ST(mode) + && column > indent + && column + want > width) { + force_wrap(); + } + if ((wrap_END(mode) && !wrap_ERR(mode)) && + wrapped && + (width >= 0) && + (column + want) > width) { + int step = 0; + int used = width > WRAPPED ? width : WRAPPED; + int base = 0; + char *p, align[9]; + const char *my_t = trailer; + char *fill = fill_spaces(src); + int last = (int) strlen(fill); + + need = last; + + if (TcOutput()) + trailer = "\\\n\t "; + + if (!TcOutput() && (p = strchr(fill, '=')) != 0) { + base = (int) (p + 1 - fill); + if (base > 8) + base = 8; + _nc_SPRINTF(align, _nc_SLIMIT(align) "%*s", base, " "); + } else if (column > 8) { + base = column - 8; + if (base > 8) + base = 8; + _nc_SPRINTF(align, _nc_SLIMIT(align) "%*s", base, " "); + } else { + align[base] = '\0'; + } + /* "pretty" overrides wrapping if it already split the line */ + if (!pretty || strchr(fill, '\n') == 0) { + int tag = 0; - if (column > INDENT - && column + (int) want > width) { + if (TcOutput() && outbuf.used && !wrap_1ST(mode)) { + tag = 3; + } + + while ((column + (need + gaps)) > used) { + int size = used - tag; + if (step) { + strcpy_DYN(&outbuf, align); + size -= base; + } + if (size > (last - step)) { + size = (last - step); + } + size = find_split(fill, step, size); + strncpy_DYN(&outbuf, fill + step, (size_t) size); + step += size; + need -= size; + if (need > 0) { + force_wrap(); + did_wrap = TRUE; + tag = 0; + } + } + } + if (need > 0) { + if (step) + strcpy_DYN(&outbuf, align); + strcpy_DYN(&outbuf, fill + step); + } + if (wrap_END(mode)) + strcpy_DYN(&outbuf, separator); + trailer = my_t; force_wrap(); + + free(fill); + } else { + strcpy_DYN(&outbuf, src); + if (wrap_END(mode)) + strcpy_DYN(&outbuf, separator); + column += (int) strlen(src); } - strcpy_DYN(&outbuf, src); - strcpy_DYN(&outbuf, separator); - column += (int) need; +} + +static void +wrap_concat1(const char *src) +{ + int need = (int) strlen(src); + wrap_concat(src, need, w1ST | wEND); +} + +static void +wrap_concat3(const char *name, const char *eqls, const char *value) +{ + int nlen = (int) strlen(name); + int elen = (int) strlen(eqls); + int vlen = (int) strlen(value); + + wrap_concat(name, nlen + elen + vlen, w1ST); + wrap_concat(eqls, elen + vlen, w2ND); + wrap_concat(value, vlen, wEND); } #define IGNORE_SEP_TRAIL(first,last,sep_trail) \ @@ -447,11 +719,38 @@ indent_DYN(DYNBUF * buffer, int level) int n; for (n = 0; n < level; n++) - strncpy_DYN(buffer, "\t", 1); + strncpy_DYN(buffer, "\t", (size_t) 1); } +/* + * Check if the current line which was begun consists only of a tab and the + * given leading text. + */ static bool -has_params(const char *src) +leading_DYN(DYNBUF * buffer, const char *leading) +{ + bool result = FALSE; + size_t need = strlen(leading); + if (buffer->used > need) { + need = buffer->used - need; + if (!strcmp(buffer->text + need, leading)) { + result = TRUE; + while (--need != 0) { + if (buffer->text[need] == '\n') { + break; + } + if (buffer->text[need] != '\t') { + result = FALSE; + break; + } + } + } + } + return result; +} + +bool +has_params(const char *src, bool formatting) { bool result = FALSE; int len = (int) strlen(src); @@ -460,31 +759,39 @@ has_params(const char *src) bool params = FALSE; for (n = 0; n < len - 1; ++n) { - if (!strncmp(src + n, "%p", 2)) { + if (!strncmp(src + n, "%p", (size_t) 2)) { params = TRUE; - } else if (!strncmp(src + n, "%;", 2)) { + } else if (!strncmp(src + n, "%;", (size_t) 2)) { ifthen = TRUE; result = params; break; } } if (!ifthen) { - result = ((len > 50) && params); + if (formatting) { + result = ((len > 50) && params); + } else { + result = params; + } } return result; } static char * -fmt_complex(char *src, int level) +fmt_complex(TERMTYPE2 *tterm, const char *capability, char *src, int level) { bool percent = FALSE; - bool params = has_params(src); + bool params = has_params(src, TRUE); while (*src != '\0') { switch (*src) { + case '^': + percent = FALSE; + strncpy_DYN(&tmpbuf, src++, (size_t) 1); + break; case '\\': percent = FALSE; - strncpy_DYN(&tmpbuf, src++, 1); + strncpy_DYN(&tmpbuf, src++, (size_t) 1); break; case '%': percent = TRUE; @@ -498,26 +805,29 @@ fmt_complex(char *src, int level) /* treat a "%e" as else-if, on the same level */ if (*src == 'e') { indent_DYN(&tmpbuf, level); - strncpy_DYN(&tmpbuf, "%", 1); - strncpy_DYN(&tmpbuf, src, 1); + strncpy_DYN(&tmpbuf, "%", (size_t) 1); + strncpy_DYN(&tmpbuf, src, (size_t) 1); src++; - params = has_params(src); + params = has_params(src, TRUE); if (!params && *src != '\0' && *src != '%') { - strncpy_DYN(&tmpbuf, "\n", 1); + strncpy_DYN(&tmpbuf, "\n", (size_t) 1); indent_DYN(&tmpbuf, level + 1); } } else { indent_DYN(&tmpbuf, level + 1); - strncpy_DYN(&tmpbuf, "%", 1); - strncpy_DYN(&tmpbuf, src, 1); + strncpy_DYN(&tmpbuf, "%", (size_t) 1); + strncpy_DYN(&tmpbuf, src, (size_t) 1); if (*src++ == '?') { - src = fmt_complex(src, level + 1); + src = fmt_complex(tterm, capability, src, level + 1); if (*src != '\0' && *src != '%') { - strncpy_DYN(&tmpbuf, "\n", 1); + strncpy_DYN(&tmpbuf, "\n", (size_t) 1); indent_DYN(&tmpbuf, level + 1); } } else if (level == 1) { - _nc_warning("%%%c without %%?", *src); + if (checking) + _nc_warning("%s: %%%c without %%? in %s", + _nc_first_name(tterm->term_names), + *src, capability); } } continue; @@ -529,49 +839,83 @@ fmt_complex(char *src, int level) if (level > 1) { tmpbuf.text[tmpbuf.used - 1] = '\n'; indent_DYN(&tmpbuf, level); - strncpy_DYN(&tmpbuf, "%", 1); - strncpy_DYN(&tmpbuf, src++, 1); + strncpy_DYN(&tmpbuf, "%", (size_t) 1); + strncpy_DYN(&tmpbuf, src++, (size_t) 1); + if (src[0] == '%' + && src[1] != '\0' + && (strchr("?e;", src[1])) == 0) { + tmpbuf.text[tmpbuf.used++] = '\n'; + indent_DYN(&tmpbuf, level); + } return src; } - _nc_warning("%%; without %%?"); + if (checking) + _nc_warning("%s: %%; without %%? in %s", + _nc_first_name(tterm->term_names), + capability); } break; case 'p': - if (percent && params) { + if (percent && params && !leading_DYN(&tmpbuf, "%")) { tmpbuf.text[tmpbuf.used - 1] = '\n'; indent_DYN(&tmpbuf, level + 1); - strncpy_DYN(&tmpbuf, "%", 1); + strncpy_DYN(&tmpbuf, "%", (size_t) 1); } - params = FALSE; percent = FALSE; break; case ' ': - strncpy_DYN(&tmpbuf, "\\s", 2); + strncpy_DYN(&tmpbuf, "\\s", (size_t) 2); ++src; continue; default: percent = FALSE; break; } - strncpy_DYN(&tmpbuf, src++, 1); + strncpy_DYN(&tmpbuf, src++, (size_t) 1); } return src; } +/* + * Make "large" numbers a little easier to read by showing them in hexadecimal + * if they are "close" to a power of two. + */ +static const char * +number_format(int value) +{ + const char *result = "%d"; + + if ((outform != F_TERMCAP) && (value > 255)) { + unsigned long lv = (unsigned long) value; + int bits = sizeof(unsigned long) * 8; + int nn; + + for (nn = 8; nn < bits; ++nn) { + unsigned long mm; + + mm = 1UL << nn; + if ((mm - 16) <= lv && (mm + 16) > lv) { + result = "%#x"; + break; + } + } + } + return result; +} + #define SAME_CAP(n,cap) (&tterm->Strings[n] == &cap) #define EXTRA_CAP 20 int -fmt_entry(TERMTYPE *tterm, +fmt_entry(TERMTYPE2 *tterm, PredFunc pred, - bool content_only, - bool suppress_untranslatable, - bool infodump, + int content_only, + int suppress_untranslatable, + int infodump, int numbers) { PredIdx i, j; char buffer[MAX_TERMINFO_LENGTH + EXTRA_CAP]; - char *capability; NCURSES_CONST char *name; int predval, len; PredIdx num_bools = 0; @@ -579,9 +923,8 @@ fmt_entry(TERMTYPE *tterm, PredIdx num_strings = 0; bool outcount = 0; -#define WRAP_CONCAT \ - wrap_concat(buffer); \ - outcount = TRUE +#define WRAP_CONCAT1(s) wrap_concat1(s); outcount = TRUE +#define WRAP_CONCAT WRAP_CONCAT1(buffer) len = 12; /* terminfo file-header */ @@ -592,17 +935,31 @@ fmt_entry(TERMTYPE *tterm, strcpy_DYN(&outbuf, 0); if (content_only) { - column = INDENT; /* FIXME: workaround to prevent empty lines */ + column = indent; /* workaround to prevent empty lines */ } else { strcpy_DYN(&outbuf, tterm->term_names); + + /* + * Colon is legal in terminfo descriptions, but not in termcap. + */ + if (!infodump) { + char *p = outbuf.text; + while (*p) { + if (*p == ':') { + *p = '='; + } + ++p; + } + } strcpy_DYN(&outbuf, separator); column = (int) outbuf.used; - force_wrap(); + if (height > 1) + force_wrap(); } for_each_boolean(j, tterm) { i = BoolIndirect(j); - name = ExtBoolname(tterm, i, bool_names); + name = ExtBoolname(tterm, (int) i, bool_names); assert(strlen(name) < sizeof(buffer) - EXTRA_CAP); if (!version_filter(BOOLEAN, i)) @@ -612,21 +969,21 @@ fmt_entry(TERMTYPE *tterm, predval = pred(BOOLEAN, i); if (predval != FAIL) { - (void) strlcpy(buffer, name, sizeof buffer); + _nc_STRCPY(buffer, name, sizeof(buffer)); if (predval <= 0) - (void) strlcat(buffer, "@", sizeof buffer); + _nc_STRCAT(buffer, "@", sizeof(buffer)); else if (i + 1 > num_bools) num_bools = i + 1; WRAP_CONCAT; } } - if (column != INDENT) + if (column != indent && height > 1) force_wrap(); for_each_number(j, tterm) { i = NumIndirect(j); - name = ExtNumname(tterm, i, num_names); + name = ExtNumname(tterm, (int) i, num_names); assert(strlen(name) < sizeof(buffer) - EXTRA_CAP); if (!version_filter(NUMBER, i)) @@ -637,9 +994,16 @@ fmt_entry(TERMTYPE *tterm, predval = pred(NUMBER, i); if (predval != FAIL) { if (tterm->Numbers[i] < 0) { - snprintf(buffer, sizeof buffer, "%s@", name); + _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) + "%s@", name); } else { - snprintf(buffer, sizeof buffer, "%s#%d", name, tterm->Numbers[i]); + size_t nn; + _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) + "%s#", name); + nn = strlen(buffer); + _nc_SPRINTF(buffer + nn, _nc_SLIMIT(sizeof(buffer) - nn) + number_format(tterm->Numbers[i]), + tterm->Numbers[i]); if (i + 1 > num_values) num_values = i + 1; } @@ -647,7 +1011,7 @@ fmt_entry(TERMTYPE *tterm, } } - if (column != INDENT) + if (column != indent && height > 1) force_wrap(); len += (int) (num_bools @@ -659,20 +1023,21 @@ fmt_entry(TERMTYPE *tterm, #undef CUR #define CUR tterm-> if (outform == F_TERMCAP) { - if (termcap_reset != ABSENT_STRING) { - if (init_3string != ABSENT_STRING + if (VALID_STRING(termcap_reset)) { + if (VALID_STRING(init_3string) && !strcmp(init_3string, termcap_reset)) DISCARD(init_3string); - if (reset_2string != ABSENT_STRING + if (VALID_STRING(reset_2string) && !strcmp(reset_2string, termcap_reset)) DISCARD(reset_2string); } } for_each_string(j, tterm) { + char *capability; i = StrIndirect(j); - name = ExtStrname(tterm, i, str_names); + name = ExtStrname(tterm, (int) i, str_names); assert(strlen(name) < sizeof(buffer) - EXTRA_CAP); capability = tterm->Strings[i]; @@ -700,14 +1065,14 @@ fmt_entry(TERMTYPE *tterm, if (PRESENT(insert_character) || PRESENT(parm_ich)) { if (SAME_CAP(i, enter_insert_mode) && enter_insert_mode == ABSENT_STRING) { - (void) strlcpy(buffer, "im=", sizeof(buffer)); + _nc_STRCPY(buffer, "im=", sizeof(buffer)); WRAP_CONCAT; continue; } if (SAME_CAP(i, exit_insert_mode) && exit_insert_mode == ABSENT_STRING) { - (void) strlcpy(buffer, "ei=", sizeof(buffer)); + _nc_STRCPY(buffer, "ei=", sizeof(buffer)); WRAP_CONCAT; continue; } @@ -724,8 +1089,12 @@ fmt_entry(TERMTYPE *tterm, set_attributes = save_sgr; trimmed_sgr0 = _nc_trim_sgr0(tterm); - if (strcmp(capability, trimmed_sgr0)) + if (strcmp(capability, trimmed_sgr0)) { capability = trimmed_sgr0; + } else { + if (trimmed_sgr0 != exit_attribute_mode) + free(trimmed_sgr0); + } set_attributes = my_sgr; } @@ -736,45 +1105,67 @@ fmt_entry(TERMTYPE *tterm, buffer[0] = '\0'; if (predval != FAIL) { - if (capability != ABSENT_STRING + if (VALID_STRING(capability) && i + 1 > num_strings) num_strings = i + 1; if (!VALID_STRING(capability)) { - snprintf(buffer, sizeof(buffer), "%s@", name); + _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) + "%s@", name); WRAP_CONCAT; - } else if (outform == F_TERMCAP || outform == F_TCONVERR) { + } else if (TcOutput()) { + char *srccap = _nc_tic_expand(capability, TRUE, numbers); int params = ((i < (int) SIZEOF(parametrized)) ? parametrized[i] - : 0); - char *srccap = _nc_tic_expand(capability, TRUE, numbers); + : ((*srccap == 'k') + ? 0 + : has_params(srccap, FALSE))); char *cv = _nc_infotocap(name, srccap, params); if (cv == 0) { if (outform == F_TCONVERR) { - snprintf(buffer, sizeof(buffer), - "%s=!!! %s WILL NOT CONVERT !!!", name, srccap); + _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) + "%s=!!! %s WILL NOT CONVERT !!!", + name, srccap); + WRAP_CONCAT; } else if (suppress_untranslatable) { continue; } else { - char *d, *s = srccap; - snprintf(buffer, sizeof(buffer), "..%s=", name); - d = buffer + strlen(buffer); - while ((*d = *s++) != 0) { /* XXX overflow */ + char *s = srccap, *d = buffer; + int need = 3 + (int) strlen(name); + while ((*d = *s++) != 0) { + if ((d - buffer + 2) >= (int) sizeof(buffer)) { + fprintf(stderr, + "%s: value for %s is too long\n", + _nc_progname, + name); + *d = '\0'; + break; + } if (*d == ':') { *d++ = '\\'; *d = ':'; } else if (*d == '\\') { - *++d = *s++; + if ((*++d = *s++) == '\0') + break; } d++; + *d = '\0'; } + need += (int) (d - buffer); + wrap_concat("..", need, w1ST | wERR); + need -= 2; + wrap_concat(name, need, wOFF | wERR); + need -= (int) strlen(name); + wrap_concat("=", need, w2ND | wERR); + need -= 1; + wrap_concat(buffer, need, wEND | wERR); + outcount = TRUE; } } else { - snprintf(buffer, sizeof buffer, "%s=%s", name, cv); + wrap_concat3(name, "=", cv); } len += (int) strlen(capability) + 1; - WRAP_CONCAT; } else { char *src = _nc_tic_expand(capability, outform == F_TERMINFO, numbers); @@ -785,17 +1176,17 @@ fmt_entry(TERMTYPE *tterm, if (pretty && (outform == F_TERMINFO || outform == F_VARIABLE)) { - fmt_complex(src, 1); + fmt_complex(tterm, name, src, 1); } else { strcpy_DYN(&tmpbuf, src); } len += (int) strlen(capability) + 1; - wrap_concat(tmpbuf.text); - outcount = TRUE; + WRAP_CONCAT1(tmpbuf.text); } } /* e.g., trimmed_sgr0 */ - if (capability != tterm->Strings[i]) + if (VALID_STRING(capability) && + capability != tterm->Strings[i]) free(capability); } len += (int) (num_strings * 2); @@ -807,11 +1198,13 @@ fmt_entry(TERMTYPE *tterm, */ if (tversion == V_HPUX) { if (VALID_STRING(memory_lock)) { - (void) snprintf(buffer, sizeof(buffer), "meml=%s", memory_lock); + _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) + "meml=%s", memory_lock); WRAP_CONCAT; } if (VALID_STRING(memory_unlock)) { - (void) snprintf(buffer, sizeof(buffer), "memu=%s", memory_unlock); + _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) + "memu=%s", memory_unlock); WRAP_CONCAT; } } else if (tversion == V_AIX) { @@ -823,7 +1216,7 @@ fmt_entry(TERMTYPE *tterm, tp = boxchars; for (cp = acstrans; *cp; cp++) { - sp = strchr(acs_chars, *cp); + sp = (strchr) (acs_chars, *cp); if (sp) *tp++ = sp[1]; else { @@ -834,9 +1227,41 @@ fmt_entry(TERMTYPE *tterm, tp[0] = '\0'; if (box_ok) { - (void) strlcpy(buffer, "box1=", sizeof(buffer)); - (void) strlcat(buffer, _nc_tic_expand(boxchars, - outform == F_TERMINFO, numbers), sizeof(buffer)); + char *tmp = _nc_tic_expand(boxchars, + (outform == F_TERMINFO), + numbers); + _nc_STRCPY(buffer, "box1=", sizeof(buffer)); + while (*tmp != '\0') { + size_t have = strlen(buffer); + size_t next = strlen(tmp); + size_t want = have + next + 1; + size_t last = next; + char save = '\0'; + + /* + * If the expanded string is too long for the buffer, + * chop it off and save the location where we chopped it. + */ + if (want >= sizeof(buffer)) { + save = tmp[last]; + tmp[last] = '\0'; + } + _nc_STRCAT(buffer, tmp, sizeof(buffer)); + + /* + * If we chopped the buffer, replace the missing piece and + * shift everything to append the remainder. + */ + if (save != '\0') { + next = 0; + tmp[last] = save; + while ((tmp[next] = tmp[last + next]) != '\0') { + ++next; + } + } else { + break; + } + } WRAP_CONCAT; } } @@ -848,10 +1273,12 @@ fmt_entry(TERMTYPE *tterm, */ if (outcount) { bool trimmed = FALSE; - j = outbuf.used; - if (j >= 2 - && outbuf.text[j - 1] == '\t' - && outbuf.text[j - 2] == '\n') { + j = (PredIdx) outbuf.used; + if (wrapped && did_wrap) { + /* EMPTY */ ; + } else if (j >= 2 + && outbuf.text[j - 1] == '\t' + && outbuf.text[j - 2] == '\n') { outbuf.used -= 2; trimmed = TRUE; } else if (j >= 4 @@ -886,7 +1313,7 @@ fmt_entry(TERMTYPE *tterm, } static bool -kill_string(TERMTYPE *tterm, char *cap) +kill_string(TERMTYPE2 *tterm, const char *const cap) { unsigned n; for (n = 0; n < NUM_STRINGS(tterm); ++n) { @@ -899,7 +1326,7 @@ kill_string(TERMTYPE *tterm, char *cap) } static char * -find_string(TERMTYPE *tterm, char *name) +find_string(TERMTYPE2 *tterm, char *name) { PredIdx n; for (n = 0; n < NUM_STRINGS(tterm); ++n) { @@ -920,16 +1347,18 @@ find_string(TERMTYPE *tterm, char *name) * make it smaller. */ static int -kill_labels(TERMTYPE *tterm, int target) +kill_labels(TERMTYPE2 *tterm, int target) { int n; int result = 0; - char *cap; - char name[10]; + char name[20]; for (n = 0; n <= 10; ++n) { - snprintf(name, sizeof(name), "lf%d", n); - if ((cap = find_string(tterm, name)) != ABSENT_STRING + char *cap; + + _nc_SPRINTF(name, _nc_SLIMIT(sizeof(name)) "lf%d", n); + cap = find_string(tterm, name); + if (VALID_STRING(cap) && kill_string(tterm, cap)) { target -= (int) (strlen(cap) + 5); ++result; @@ -945,16 +1374,18 @@ kill_labels(TERMTYPE *tterm, int target) * make it smaller. */ static int -kill_fkeys(TERMTYPE *tterm, int target) +kill_fkeys(TERMTYPE2 *tterm, int target) { int n; int result = 0; - char *cap; - char name[10]; + char name[20]; for (n = 60; n >= 0; --n) { - snprintf(name, sizeof(name), "kf%d", n); - if ((cap = find_string(tterm, name)) != ABSENT_STRING + char *cap; + + _nc_SPRINTF(name, _nc_SLIMIT(sizeof(name)) "kf%d", n); + cap = find_string(tterm, name); + if (VALID_STRING(cap) && kill_string(tterm, cap)) { target -= (int) (strlen(cap) + 5); ++result; @@ -976,9 +1407,9 @@ one_one_mapping(const char *mapping) { bool result = TRUE; - if (mapping != ABSENT_STRING) { + if (VALID_STRING(mapping)) { int n = 0; - while (mapping[n] != '\0') { + while (mapping[n] != '\0' && mapping[n + 1] != '\0') { if (isLine(mapping[n]) && mapping[n] != mapping[n + 1]) { result = FALSE; @@ -999,7 +1430,7 @@ one_one_mapping(const char *mapping) #define SHOW_WHY PRINTF static bool -purged_acs(TERMTYPE *tterm) +purged_acs(TERMTYPE2 *tterm) { bool result = FALSE; @@ -1014,22 +1445,103 @@ purged_acs(TERMTYPE *tterm) return result; } +static void +encode_b64(char *target, char *source, unsigned state, int *saved) +{ + /* RFC-4648 */ + static const char data[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789" "-_"; + int ch = UChar(source[state]); + + switch (state % 3) { + case 0: + *target++ = data[(ch >> 2) & 077]; + *saved = (ch << 4); + break; + case 1: + *target++ = data[((ch >> 4) | *saved) & 077]; + *saved = (ch << 2); + break; + case 2: + *target++ = data[((ch >> 6) | *saved) & 077]; + *target++ = data[ch & 077]; + *saved = 0; + break; + } + *target = '\0'; +} + /* * Dump a single entry. */ void -dump_entry(TERMTYPE *tterm, - bool suppress_untranslatable, - bool limited, +dump_entry(TERMTYPE2 *tterm, + int suppress_untranslatable, + int limited, int numbers, PredFunc pred) { - TERMTYPE save_tterm; - int len, critlen; + TERMTYPE2 save_tterm; + int critlen; const char *legend; bool infodump; - if (outform == F_TERMCAP || outform == F_TCONVERR) { + if (quickdump) { + char bigbuf[65536]; + unsigned offset = 0; + + separator = ""; + trailer = "\n"; + indent = 0; + + if (_nc_write_object(tterm, bigbuf, &offset, sizeof(bigbuf)) == OK) { + char numbuf[80]; + unsigned n; + + if (quickdump & 1) { + if (outbuf.used) + wrap_concat1("\n"); + wrap_concat1("hex:"); + for (n = 0; n < offset; ++n) { + _nc_SPRINTF(numbuf, _nc_SLIMIT(sizeof(numbuf)) + "%02X", UChar(bigbuf[n])); + wrap_concat1(numbuf); + } + } + if (quickdump & 2) { + static char padding[] = + {0, 0}; + int value = 0; + + if (outbuf.used) + wrap_concat1("\n"); + wrap_concat1("b64:"); + for (n = 0; n < offset; ++n) { + encode_b64(numbuf, bigbuf, n, &value); + wrap_concat1(numbuf); + } + switch (n % 3) { + case 0: + break; + case 1: + encode_b64(numbuf, padding, 1, &value); + wrap_concat1(numbuf); + wrap_concat1("=="); + break; + case 2: + encode_b64(numbuf, padding, 1, &value); + wrap_concat1(numbuf); + wrap_concat1("="); + break; + } + } + } + return; + } + + if (TcOutput()) { critlen = MAX_TERMCAP_LENGTH; legend = "older termcap"; infodump = FALSE; @@ -1042,7 +1554,8 @@ dump_entry(TERMTYPE *tterm, save_sgr = set_attributes; - if (((len = FMT_ENTRY()) > critlen) + if ((FMT_ENTRY() > critlen) + && TcOutput() && limited) { save_tterm = *tterm; @@ -1051,9 +1564,9 @@ dump_entry(TERMTYPE *tterm, critlen); suppress_untranslatable = TRUE; } - if ((len = FMT_ENTRY()) > critlen) { + if (FMT_ENTRY() > critlen) { /* - * We pick on sgr because it's a nice long string capability that + * We pick on sgr because it is a nice long string capability that * is really just an optimization hack. Another good candidate is * acsc since it is both long and unused by BSD termcap. */ @@ -1066,7 +1579,7 @@ dump_entry(TERMTYPE *tterm, */ unsigned n; for (n = STRCOUNT; n < NUM_STRINGS(tterm); n++) { - const char *name = ExtStrname(tterm, n, strnames); + const char *name = ExtStrname(tterm, (int) n, strnames); if (VALID_STRING(tterm->Strings[n])) { set_attributes = ABSENT_STRING; @@ -1077,7 +1590,7 @@ dump_entry(TERMTYPE *tterm, critlen); } changed = TRUE; - if ((len = FMT_ENTRY()) <= critlen) + if (FMT_ENTRY() <= critlen) break; } } @@ -1088,7 +1601,7 @@ dump_entry(TERMTYPE *tterm, critlen); changed = TRUE; } - if (!changed || ((len = FMT_ENTRY()) > critlen)) { + if (!changed || (FMT_ENTRY() > critlen)) { if (purged_acs(tterm)) { acs_chars = ABSENT_STRING; SHOW_WHY("# (acsc removed to fit entry within %d bytes)\n", @@ -1096,8 +1609,9 @@ dump_entry(TERMTYPE *tterm, changed = TRUE; } } - if (!changed || ((len = FMT_ENTRY()) > critlen)) { + if (!changed || (FMT_ENTRY() > critlen)) { int oldversion = tversion; + int len; tversion = V_BSD; SHOW_WHY("# (terminfo-only capabilities suppressed to fit entry within %d bytes)\n", @@ -1118,7 +1632,8 @@ dump_entry(TERMTYPE *tterm, } if (len > critlen) { (void) fprintf(stderr, - "warning: %s entry is %d bytes long\n", + "%s: %s entry is %d bytes long\n", + _nc_progname, _nc_first_name(tterm->term_names), len); SHOW_WHY("# WARNING: this entry, %d bytes long, may core-dump %s libraries!\n", @@ -1132,37 +1647,72 @@ dump_entry(TERMTYPE *tterm, } else if (!version_filter(STRING, STR_IDX(acs_chars))) { save_tterm = *tterm; if (purged_acs(tterm)) { - len = FMT_ENTRY(); + (void) FMT_ENTRY(); } *tterm = save_tterm; } } void -dump_uses(const char *name, bool infodump) +dump_uses(const char *value, bool infodump) /* dump "use=" clauses in the appropriate format */ { - char buffer[MAX_TERMINFO_LENGTH]; + char buffer[MAX_TERMINFO_LENGTH + EXTRA_CAP]; + int limit = (VALID_STRING(value) ? (int) strlen(value) : 0); + const char *cap = infodump ? "use" : "tc"; - if (outform == F_TERMCAP || outform == F_TCONVERR) + if (TcOutput()) trim_trailing(); - (void) snprintf(buffer, sizeof(buffer), "%s%s", infodump ? "use=" : "tc=", - name); - wrap_concat(buffer); + if (limit == 0) { + _nc_warning("empty \"%s\" field", cap); + value = ""; + } else if (limit > MAX_ALIAS) { + _nc_warning("\"%s\" field too long (%d), limit to %d", + cap, limit, MAX_ALIAS); + limit = MAX_ALIAS; + } + _nc_SPRINTF(buffer, _nc_SLIMIT(sizeof(buffer)) + "%s=%.*s", cap, limit, value); + wrap_concat1(buffer); } int show_entry(void) { - trim_trailing(); - (void) fputs(outbuf.text, stdout); - putchar('\n'); + /* + * Trim any remaining whitespace. + */ + if (outbuf.used != 0) { + bool infodump = !TcOutput(); + char delim = (char) (infodump ? ',' : ':'); + int j; + + for (j = (int) outbuf.used - 1; j > 0; --j) { + char ch = outbuf.text[j]; + if (ch == '\n') { + ; + } else if (isspace(UChar(ch))) { + outbuf.used = (size_t) j; + } else if (!infodump && ch == '\\') { + outbuf.used = (size_t) j; + } else if (ch == delim && (outbuf.text[j - 1] != '\\')) { + outbuf.used = (size_t) (j + 1); + } else { + break; + } + } + outbuf.text[outbuf.used] = '\0'; + } + if (outbuf.text != 0) { + (void) fputs(outbuf.text, stdout); + putchar('\n'); + } return (int) outbuf.used; } void -compare_entry(void (*hook) (PredType t, PredIdx i, const char *name), - TERMTYPE *tp GCC_UNUSED, +compare_entry(PredHook hook, + TERMTYPE2 *tp GCC_UNUSED, bool quiet) /* compare two entries */ { @@ -1173,7 +1723,7 @@ compare_entry(void (*hook) (PredType t, PredIdx i, const char *name), fputs(" comparing booleans.\n", stdout); for_each_boolean(j, tp) { i = BoolIndirect(j); - name = ExtBoolname(tp, i, bool_names); + name = ExtBoolname(tp, (int) i, bool_names); if (isObsolete(outform, name)) continue; @@ -1185,7 +1735,7 @@ compare_entry(void (*hook) (PredType t, PredIdx i, const char *name), fputs(" comparing numbers.\n", stdout); for_each_number(j, tp) { i = NumIndirect(j); - name = ExtNumname(tp, i, num_names); + name = ExtNumname(tp, (int) i, num_names); if (isObsolete(outform, name)) continue; @@ -1197,7 +1747,7 @@ compare_entry(void (*hook) (PredType t, PredIdx i, const char *name), fputs(" comparing strings.\n", stdout); for_each_string(j, tp) { i = StrIndirect(j); - name = ExtStrname(tp, i, str_names); + name = ExtStrname(tp, (int) i, str_names); if (isObsolete(outform, name)) continue; @@ -1221,7 +1771,7 @@ compare_entry(void (*hook) (PredType t, PredIdx i, const char *name), #define CUR tp-> static void -set_obsolete_termcaps(TERMTYPE *tp) +set_obsolete_termcaps(TERMTYPE2 *tp) { #include "capdefaults.c" } @@ -1231,12 +1781,11 @@ set_obsolete_termcaps(TERMTYPE *tp) * unique. */ void -repair_acsc(TERMTYPE *tp) +repair_acsc(TERMTYPE2 *tp) { if (VALID_STRING(acs_chars)) { - size_t n, m; + size_t n; char mapped[256]; - char extra = 0; unsigned source; unsigned target; bool fix_needed = FALSE; @@ -1251,7 +1800,11 @@ repair_acsc(TERMTYPE *tp) if (acs_chars[n + 1]) n++; } + if (fix_needed) { + size_t m; + char extra = 0; + memset(mapped, 0, sizeof(mapped)); for (n = 0; acs_chars[n] != 0; n++) { source = UChar(acs_chars[n]); diff --git a/usr.bin/tic/dump_entry.h b/usr.bin/tic/dump_entry.h index a1838120868..8670a92b77e 100644 --- a/usr.bin/tic/dump_entry.h +++ b/usr.bin/tic/dump_entry.h @@ -1,7 +1,8 @@ -/* $OpenBSD: dump_entry.h,v 1.6 2010/01/12 23:22:14 nicm Exp $ */ +/* $OpenBSD: dump_entry.h,v 1.7 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. * + * Copyright 2018-2020,2021 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -34,9 +35,8 @@ * and: Thomas E. Dickey 1996-on * ****************************************************************************/ - /* - * $Id: dump_entry.h,v 1.6 2010/01/12 23:22:14 nicm Exp $ + * $Id: dump_entry.h,v 1.7 2023/10/17 09:52:10 nicm Exp $ * * Dump control definitions and variables */ @@ -44,6 +44,11 @@ #ifndef DUMP_ENTRY_H #define DUMP_ENTRY_H 1 +#define NCURSES_OPAQUE 0 +#define NCURSES_INTERNALS 1 +#include +#include + /* capability output formats */ #define F_TERMINFO 0 /* use terminfo names */ #define F_VARIABLE 1 /* use C variable names */ @@ -64,18 +69,27 @@ #define CMP_STRING 2 /* comparison on strings */ #define CMP_USE 3 /* comparison on use capabilities */ +#ifndef _TERMSORT_H typedef unsigned PredType; typedef unsigned PredIdx; -typedef int (*PredFunc)(PredType, PredIdx); +#endif + +typedef int (*PredFunc) (PredType, PredIdx); +typedef void (*PredHook) (PredType, PredIdx, const char *); extern NCURSES_CONST char *nametrans(const char *); -extern int fmt_entry(TERMTYPE *, PredFunc, bool, bool, bool, int); +extern bool has_params(const char *, bool); +extern int fmt_entry(TERMTYPE2 *, PredFunc, int, int, int, int); extern int show_entry(void); -extern void compare_entry(void (*)(PredType, PredIdx, const char *), TERMTYPE *, bool); -extern void dump_entry(TERMTYPE *, bool, bool, int, PredFunc); -extern void dump_init(const char *, int, int, int, int, bool); +extern void compare_entry(PredHook, TERMTYPE2 *, bool); +extern void dump_entry(TERMTYPE2 *, int, int, int, PredFunc); +extern void dump_init(const char *, int, int, bool, int, int, unsigned, bool, + bool, int); extern void dump_uses(const char *, bool); -extern void repair_acsc(TERMTYPE * tp); +extern void repair_acsc(TERMTYPE2 *tp); + +#define L_CURL "{" +#define R_CURL "}" #define FAIL -1 diff --git a/usr.bin/tic/infotocap.1 b/usr.bin/tic/infotocap.1 index 16e6d5b2abe..466ff52ebf5 100644 --- a/usr.bin/tic/infotocap.1 +++ b/usr.bin/tic/infotocap.1 @@ -1,6 +1,8 @@ -.\" $OpenBSD: infotocap.1,v 1.5 2010/01/12 23:22:14 nicm Exp $ +'\" t +.\" $OpenBSD: infotocap.1,v 1.6 2023/10/17 09:52:10 nicm Exp $ .\"*************************************************************************** -.\" Copyright (c) 1999-2004,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2021,2022 Thomas E. Dickey * +.\" Copyright 1999-2010,2016 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -27,51 +29,54 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: infotocap.1,v 1.5 2010/01/12 23:22:14 nicm Exp $ -.TH infotocap 1 "" +.\" $Id: infotocap.1,v 1.6 2023/10/17 09:52:10 nicm Exp $ +.TH infotocap 1 2022-02-12 "ncurses 6.4" "User commands" .ds n 5 -.ds d /usr/share/misc/terminfo +.ds d /usr/share/terminfo .SH NAME -\fBinfotocap\fR - convert a \fIterminfo\fR description into a \fItermcap\fR description +\fBinfotocap\fP \- convert a \fIterminfo\fP description into a \fItermcap\fP description .SH SYNOPSIS -\fBinfotocap\fR [\fB-v\fR\fIn\fR \fIwidth\fR] [\fB-V\fR] [\fB-1\fR] [\fB-w\fR \fIwidth\fR] \fIfile\fR . . . +\fBinfotocap\fR [\fB\-v\fIn\fR \fIwidth\fR] [\fB\-V\fR] [\fB\-1\fR] [\fB\-w\fR \fIwidth\fR] \fIfile\fR ... .SH DESCRIPTION -\fBinfotocap\fR looks in \fIfile\fR for \fBterminfo\fR descriptions. For each -one found, an equivalent \fBtermcap\fR description is written to standard -output. Terminfo \fBuse\fR capabilities are translated directly to termcap -\fBtc\fR capabilities. +\fBinfotocap\fP looks in each given text +\fIfile\fP for \fBterminfo\fP descriptions. +For each terminfo description found, +an equivalent \fBtermcap\fP description is written to standard output. +Terminfo \fBuse\fP capabilities are translated directly to termcap +\fBtc\fP capabilities. .TP 5 -\fB-v\fR +\fB\-v\fP print out tracing information on standard error as the program runs. .TP 5 -\fB-V\fR +\fB\-V\fP print out the version of the program in use on standard error and exit. .TP 5 -\fB-1\fR -cause the fields to print out one to a line. Otherwise, the fields -will be printed several to a line to a maximum width of 60 -characters. +\fB\-1\fP +cause the fields to print out one to a line. +Otherwise, the fields +will be printed several to a line to a maximum width of 60 characters. .TP 5 -\fB-w\fR -change the output to \fIwidth\fR characters. +\fB\-w\fP +change the output to \fIwidth\fP characters. .SH FILES .TP 20 \*d Compiled terminal description database. .SH NOTES -This utility is actually a link to \fItic\fR, running in \fI-C\fR mode. -You can use other \fItic\fR options such as \fB-f\fR and \fB-x\fR. +This utility is actually a link to \fBtic\fP, running in \fI\-C\fP mode. +You can use other \fBtic\fP options such as \fB\-f\fP and \fB\-x\fP. +.SH PORTABILITY +None of X/Open Curses, Issue 7 (2009), SVr4 or NetBSD document this application. .SH SEE ALSO -\fBcurses\fR(3), -\fBtic\fR(1), -\fBinfocmp\fR(1), -\fBterminfo\fR(\*n) +\fBinfocmp\fP(1), +\fBtic\fP(1), +\fBcurses\fP(3), +\fBterminfo\fP(\*n) .PP -This describes \fBncurses\fR -version 5.7. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +This describes \fBncurses\fP +version 6.4 (patch 20230826). +.SH AUTHOR +Eric S. Raymond +and +.br +Thomas E. Dickey diff --git a/usr.bin/tic/progs.priv.h b/usr.bin/tic/progs.priv.h index 1499fabddf2..1a7c4d7ade6 100644 --- a/usr.bin/tic/progs.priv.h +++ b/usr.bin/tic/progs.priv.h @@ -1,7 +1,8 @@ -/* $OpenBSD: progs.priv.h,v 1.10 2015/01/16 06:40:13 deraadt Exp $ */ +/* $OpenBSD: progs.priv.h,v 1.11 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2019-2021,2022 Thomas E. Dickey * + * Copyright 1998-2015,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -32,19 +33,22 @@ * Author: Thomas E. Dickey 1997-on * ****************************************************************************/ /* - * $Id: progs.priv.h,v 1.10 2015/01/16 06:40:13 deraadt Exp $ + * $Id: progs.priv.h,v 1.11 2023/10/17 09:52:10 nicm Exp $ * * progs.priv.h * * Header file for curses utility programs */ +#ifndef PROGS_PRIV_H +#define PROGS_PRIV_H 1 + #include #if USE_RCS_IDS #define MODULE_ID(id) static const char Ident[] = id; #else -#define MODULE_ID(id) /*nothing*/ +#define MODULE_ID(id) /*nothing */ #endif #include @@ -56,14 +60,10 @@ #include #endif -#if HAVE_SYS_BSDTYPES_H -#include /* needed for ISC */ -#endif - #if HAVE_LIMITS_H # include #elif HAVE_SYS_PARAM_H -# include /* only if no limits.h */ +# include #endif #if HAVE_DIRENT_H @@ -92,6 +92,14 @@ # endif #endif +#if HAVE_INTTYPES_H +# include +#else +# if HAVE_STDINT_H +# include +# endif +#endif + #include #include @@ -101,7 +109,7 @@ extern int errno; #if HAVE_GETOPT_H #include -#else +#elif !defined(HAVE_GETOPT_HEADER) /* 'getopt()' may be prototyped in , but declaring its * variables doesn't hurt. */ @@ -109,22 +117,55 @@ extern char *optarg; extern int optind; #endif /* HAVE_GETOPT_H */ +#undef _NC_WINDOWS +#if (defined(_WIN32) || defined(_WIN64)) +#define _NC_WINDOWS 1 +#endif + +#define NCURSES_INTERNALS 1 +#define NCURSES_OPAQUE 0 + #include + +#if !(defined(NCURSES_WGETCH_EVENTS) && defined(NEED_KEY_EVENT)) +#undef KEY_EVENT /* reduce compiler-warnings with Visual C++ */ +#endif + #include +#include #include #include +#include #include +#include + #if HAVE_NC_FREEALL #undef ExitProgram #ifdef USE_LIBTINFO -#define ExitProgram(code) _nc_free_tinfo(code) +#define ExitProgram(code) exit_terminfo(code) #else #define ExitProgram(code) _nc_free_tic(code) #endif #endif +/* error-returns for tput */ +#define ErrUsage 2 +#define ErrTermType 3 +#define ErrCapName 4 +#define ErrSystem(n) (4 + (n)) + +#if defined(__GNUC__) && defined(_FORTIFY_SOURCE) +#define IGNORE_RC(func) errno = (int) func +#else +#define IGNORE_RC(func) (void) func +#endif /* gcc workarounds */ + /* usually in */ +#ifndef STDIN_FILENO +#define STDIN_FILENO 0 +#endif + #ifndef STDOUT_FILENO #define STDOUT_FILENO 1 #endif @@ -173,7 +214,7 @@ extern int optind; # elif defined(MAXPATHLEN) # define PATH_MAX MAXPATHLEN # else -# define PATH_MAX 255 /* the Posix minimum pathsize */ +# define PATH_MAX 255 /* the Posix minimum pathsize */ # endif #endif @@ -185,10 +226,40 @@ extern int optind; # if ('z'-'a' == 25) && ('z' < 127) && ('Z'-'A' == 25) && ('Z' < 127) && ('9' < 127) # define isascii(c) (UChar(c) <= 127) # else -# define isascii(c) 1 /* not really ascii anyway */ +# define isascii(c) 1 /* not really ascii anyway */ # endif #endif #define UChar(c) ((unsigned char)(c)) #define SIZEOF(v) (sizeof(v)/sizeof(v[0])) + +#define VtoTrace(opt) (unsigned) ((opt > 0) ? opt : (opt == 0)) + +/* + * If configured for tracing, the debug- and trace-output are merged together + * in the trace file for "upper" levels of the verbose option. + */ +#ifdef TRACE +#define use_verbosity(level) do { \ + set_trace_level(level); \ + if (_nc_tracing > DEBUG_LEVEL(2)) \ + _nc_tracing |= TRACE_MAXIMUM; \ + else if (_nc_tracing == DEBUG_LEVEL(2)) \ + _nc_tracing |= TRACE_ORDINARY; \ + if (level >= 2) \ + curses_trace(_nc_tracing); \ + } while (0) +#else +#define use_verbosity(level) do { set_trace_level(level); } while (0) +#endif + +#define NCURSES_EXT_NUMBERS (NCURSES_EXT_COLORS && HAVE_INIT_EXTENDED_COLOR) + +#if NCURSES_EXT_NUMBERS +#else +#define _nc_free_termtype2(t) _nc_free_termtype(t) +#define _nc_read_entry2(n,f,t) _nc_read_entry(n,f,t) +#endif + +#endif /* PROGS_PRIV_H */ diff --git a/usr.bin/tic/reset_cmd.c b/usr.bin/tic/reset_cmd.c new file mode 100644 index 00000000000..d9c27635014 --- /dev/null +++ b/usr.bin/tic/reset_cmd.c @@ -0,0 +1,663 @@ +/**************************************************************************** + * Copyright 2019-2021,2023 Thomas E. Dickey * + * Copyright 2016,2017 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey * + ****************************************************************************/ + +#include +#include + +#include +#include +#include + +#if HAVE_SIZECHANGE +# if !defined(sun) || !TERMIOS +# if HAVE_SYS_IOCTL_H +# include +# endif +# endif +#endif + +#if NEED_PTEM_H +/* they neglected to define struct winsize in termios.h -- it is only + in termio.h */ +#include +#include +#endif + +MODULE_ID("$Id: reset_cmd.c,v 1.1 2023/10/17 09:52:10 nicm Exp $") + +/* + * SCO defines TIOCGSIZE and the corresponding struct. Other systems (SunOS, + * Solaris, IRIX) define TIOCGWINSZ and struct winsize. + */ +#ifdef TIOCGSIZE +# define IOCTL_GET_WINSIZE TIOCGSIZE +# define IOCTL_SET_WINSIZE TIOCSSIZE +# define STRUCT_WINSIZE struct ttysize +# define WINSIZE_ROWS(n) n.ts_lines +# define WINSIZE_COLS(n) n.ts_cols +#else +# ifdef TIOCGWINSZ +# define IOCTL_GET_WINSIZE TIOCGWINSZ +# define IOCTL_SET_WINSIZE TIOCSWINSZ +# define STRUCT_WINSIZE struct winsize +# define WINSIZE_ROWS(n) n.ws_row +# define WINSIZE_COLS(n) n.ws_col +# endif +#endif + +static FILE *my_file; + +static bool use_reset = FALSE; /* invoked as reset */ +static bool use_init = FALSE; /* invoked as init */ + +static GCC_NORETURN void +failed(const char *msg) +{ + int code = errno; + + (void) fprintf(stderr, "%s: %s: %s\n", _nc_progname, msg, strerror(code)); + restore_tty_settings(); + (void) fprintf(my_file, "\n"); + fflush(my_file); + ExitProgram(ErrSystem(code)); + /* NOTREACHED */ +} + +static bool +cat_file(char *file) +{ + FILE *fp; + size_t nr; + char buf[BUFSIZ]; + bool sent = FALSE; + + if (file != 0) { + if ((fp = safe_fopen(file, "r")) == 0) + failed(file); + + while ((nr = fread(buf, sizeof(char), sizeof(buf), fp)) != 0) { + if (fwrite(buf, sizeof(char), nr, my_file) != nr) { + failed(file); + } + sent = TRUE; + } + fclose(fp); + } + return sent; +} + +static int +out_char(int c) +{ + return putc(c, my_file); +} + +/************************************************************************** + * Mode-setting logic + **************************************************************************/ + +/* some BSD systems have these built in, some systems are missing + * one or more definitions. The safest solution is to override unless the + * commonly-altered ones are defined. + */ +#if !(defined(CERASE) && defined(CINTR) && defined(CKILL) && defined(CQUIT)) +#undef CEOF +#undef CERASE +#undef CINTR +#undef CKILL +#undef CLNEXT +#undef CRPRNT +#undef CQUIT +#undef CSTART +#undef CSTOP +#undef CSUSP +#endif + +/* control-character defaults */ +#ifndef CEOF +#define CEOF CTRL('D') +#endif +#ifndef CERASE +#define CERASE CTRL('H') +#endif +#ifndef CINTR +#define CINTR 127 /* ^? */ +#endif +#ifndef CKILL +#define CKILL CTRL('U') +#endif +#ifndef CLNEXT +#define CLNEXT CTRL('v') +#endif +#ifndef CRPRNT +#define CRPRNT CTRL('r') +#endif +#ifndef CQUIT +#define CQUIT CTRL('\\') +#endif +#ifndef CSTART +#define CSTART CTRL('Q') +#endif +#ifndef CSTOP +#define CSTOP CTRL('S') +#endif +#ifndef CSUSP +#define CSUSP CTRL('Z') +#endif + +#if defined(_POSIX_VDISABLE) +#define DISABLED(val) (((_POSIX_VDISABLE != -1) \ + && ((val) == _POSIX_VDISABLE)) \ + || ((val) <= 0)) +#else +#define DISABLED(val) ((int)(val) <= 0) +#endif + +#define CHK(val, dft) (unsigned char) (DISABLED(val) ? dft : val) + +#define reset_char(item, value) \ + tty_settings->c_cc[item] = CHK(tty_settings->c_cc[item], value) + +/* + * Reset the terminal mode bits to a sensible state. Very useful after + * a child program dies in raw mode. + */ +void +reset_tty_settings(int fd, TTY * tty_settings, int noset) +{ + GET_TTY(fd, tty_settings); + +#ifdef TERMIOS +#if defined(VDISCARD) && defined(CDISCARD) + reset_char(VDISCARD, CDISCARD); +#endif + reset_char(VEOF, CEOF); + reset_char(VERASE, CERASE); +#if defined(VERASE2) && defined(CERASE2) + reset_char(VERASE2, CERASE2); +#endif +#if defined(VFLUSH) && defined(CFLUSH) + reset_char(VFLUSH, CFLUSH); +#endif + reset_char(VINTR, CINTR); + reset_char(VKILL, CKILL); +#if defined(VLNEXT) && defined(CLNEXT) + reset_char(VLNEXT, CLNEXT); +#endif + reset_char(VQUIT, CQUIT); +#if defined(VREPRINT) && defined(CRPRNT) + reset_char(VREPRINT, CRPRNT); +#endif +#if defined(VSTART) && defined(CSTART) + reset_char(VSTART, CSTART); +#endif +#if defined(VSTOP) && defined(CSTOP) + reset_char(VSTOP, CSTOP); +#endif +#if defined(VSUSP) && defined(CSUSP) + reset_char(VSUSP, CSUSP); +#endif +#if defined(VWERASE) && defined(CWERASE) + reset_char(VWERASE, CWERASE); +#endif + + tty_settings->c_iflag &= ~((unsigned) (IGNBRK + | PARMRK + | INPCK + | ISTRIP + | INLCR + | IGNCR +#ifdef IUCLC + | IUCLC +#endif +#ifdef IXANY + | IXANY +#endif + | IXOFF)); + + tty_settings->c_iflag |= (BRKINT + | IGNPAR + | ICRNL + | IXON +#ifdef IMAXBEL + | IMAXBEL +#endif + ); + + tty_settings->c_oflag &= ~((unsigned) (0 +#ifdef OLCUC + | OLCUC +#endif +#ifdef OCRNL + | OCRNL +#endif +#ifdef ONOCR + | ONOCR +#endif +#ifdef ONLRET + | ONLRET +#endif +#ifdef OFILL + | OFILL +#endif +#ifdef OFDEL + | OFDEL +#endif +#ifdef NLDLY + | NLDLY +#endif +#ifdef CRDLY + | CRDLY +#endif +#ifdef TABDLY + | TABDLY +#endif +#ifdef BSDLY + | BSDLY +#endif +#ifdef VTDLY + | VTDLY +#endif +#ifdef FFDLY + | FFDLY +#endif + )); + + tty_settings->c_oflag |= (OPOST +#ifdef ONLCR + | ONLCR +#endif + ); + + tty_settings->c_cflag &= ~((unsigned) (CSIZE + | CSTOPB + | PARENB + | PARODD + | CLOCAL)); + tty_settings->c_cflag |= (CS8 | CREAD); + tty_settings->c_lflag &= ~((unsigned) (ECHONL + | NOFLSH +#ifdef TOSTOP + | TOSTOP +#endif +#ifdef ECHOPTR + | ECHOPRT +#endif +#ifdef XCASE + | XCASE +#endif + )); + + tty_settings->c_lflag |= (ISIG + | ICANON + | ECHO + | ECHOE + | ECHOK +#ifdef ECHOCTL + | ECHOCTL +#endif +#ifdef ECHOKE + | ECHOKE +#endif + ); +#endif + + if (!noset) { + SET_TTY(fd, tty_settings); + } +} + +/* + * Returns a "good" value for the erase character. This is loosely based on + * the BSD4.4 logic. + */ +static int +default_erase(void) +{ + int result; + + if (over_strike + && VALID_STRING(key_backspace) + && strlen(key_backspace) == 1) { + result = key_backspace[0]; + } else { + result = CERASE; + } + + return result; +} + +/* + * Update the values of the erase, interrupt, and kill characters in the TTY + * parameter. + * + * SVr4 tset (e.g., Solaris 2.5) only modifies the intr, quit or erase + * characters if they're unset, or if we specify them as options. This differs + * from BSD 4.4 tset, which always sets erase. + */ +void +set_control_chars(TTY * tty_settings, int my_erase, int my_intr, int my_kill) +{ +#if defined(EXP_WIN32_DRIVER) + /* noop */ + (void) tty_settings; + (void) my_erase; + (void) my_intr; + (void) my_kill; +#else + if (DISABLED(tty_settings->c_cc[VERASE]) || my_erase >= 0) { + tty_settings->c_cc[VERASE] = UChar((my_erase >= 0) + ? my_erase + : default_erase()); + } + + if (DISABLED(tty_settings->c_cc[VINTR]) || my_intr >= 0) { + tty_settings->c_cc[VINTR] = UChar((my_intr >= 0) + ? my_intr + : CINTR); + } + + if (DISABLED(tty_settings->c_cc[VKILL]) || my_kill >= 0) { + tty_settings->c_cc[VKILL] = UChar((my_kill >= 0) + ? my_kill + : CKILL); + } +#endif +} + +/* + * Set up various conversions in the TTY parameter, including parity, tabs, + * returns, echo, and case, according to the termcap entry. + */ +void +set_conversions(TTY * tty_settings) +{ +#if defined(EXP_WIN32_DRIVER) + /* FIXME */ +#else +#ifdef ONLCR + tty_settings->c_oflag |= ONLCR; +#endif + tty_settings->c_iflag |= ICRNL; + tty_settings->c_lflag |= ECHO; +#ifdef OXTABS + tty_settings->c_oflag |= OXTABS; +#endif /* OXTABS */ + + /* test used to be tgetflag("NL") */ + if (VALID_STRING(newline) && newline[0] == '\n' && !newline[1]) { + /* Newline, not linefeed. */ +#ifdef ONLCR + tty_settings->c_oflag &= ~((unsigned) ONLCR); +#endif + tty_settings->c_iflag &= ~((unsigned) ICRNL); + } +#ifdef OXTABS + /* test used to be tgetflag("pt") */ + if (VALID_STRING(set_tab) && VALID_STRING(clear_all_tabs)) + tty_settings->c_oflag &= ~OXTABS; +#endif /* OXTABS */ + tty_settings->c_lflag |= (ECHOE | ECHOK); +#endif +} + +static bool +sent_string(const char *s) +{ + bool sent = FALSE; + if (VALID_STRING(s)) { + tputs(s, 0, out_char); + sent = TRUE; + } + return sent; +} + +static bool +to_left_margin(void) +{ + if (VALID_STRING(carriage_return)) { + sent_string(carriage_return); + } else { + out_char('\r'); + } + return TRUE; +} + +/* + * Set the hardware tabs on the terminal, using the 'ct' (clear all tabs), + * 'st' (set one tab) and 'ch' (horizontal cursor addressing) capabilities. + * This is done before 'if' and 'is', so they can recover in case of error. + * + * Return TRUE if we set any tab stops, FALSE if not. + */ +static bool +reset_tabstops(int wide) +{ + if ((init_tabs != 8) + && VALID_NUMERIC(init_tabs) + && VALID_STRING(set_tab) + && VALID_STRING(clear_all_tabs)) { + int c; + + to_left_margin(); + tputs(clear_all_tabs, 0, out_char); + if (init_tabs > 1) { + if (init_tabs > wide) + init_tabs = (short) wide; + for (c = init_tabs; c < wide; c += init_tabs) { + fprintf(my_file, "%*s", init_tabs, " "); + tputs(set_tab, 0, out_char); + } + to_left_margin(); + } + return (TRUE); + } + return (FALSE); +} + +/* Output startup string. */ +bool +send_init_strings(int fd GCC_UNUSED, TTY * old_settings) +{ + int i; + bool need_flush = FALSE; + + (void) old_settings; +#ifdef TAB3 + if (old_settings != 0 && + old_settings->c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) { + old_settings->c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET); + SET_TTY(fd, old_settings); + } +#endif + if (use_reset || use_init) { + if (VALID_STRING(init_prog)) { + IGNORE_RC(system(init_prog)); + } + + need_flush |= sent_string((use_reset && (reset_1string != 0)) + ? reset_1string + : init_1string); + + need_flush |= sent_string((use_reset && (reset_2string != 0)) + ? reset_2string + : init_2string); + + if (VALID_STRING(clear_margins)) { + need_flush |= sent_string(clear_margins); + } else +#if defined(set_lr_margin) + if (VALID_STRING(set_lr_margin)) { + need_flush |= sent_string(TIPARM_2(set_lr_margin, 0, columns - 1)); + } else +#endif +#if defined(set_left_margin_parm) && defined(set_right_margin_parm) + if (VALID_STRING(set_left_margin_parm) + && VALID_STRING(set_right_margin_parm)) { + need_flush |= sent_string(TIPARM_1(set_left_margin_parm, 0)); + need_flush |= sent_string(TIPARM_1(set_right_margin_parm, + columns - 1)); + } else +#endif + if (VALID_STRING(set_left_margin) + && VALID_STRING(set_right_margin)) { + need_flush |= to_left_margin(); + need_flush |= sent_string(set_left_margin); + if (VALID_STRING(parm_right_cursor)) { + need_flush |= sent_string(TIPARM_1(parm_right_cursor, + columns - 1)); + } else { + for (i = 0; i < columns - 1; i++) { + out_char(' '); + need_flush = TRUE; + } + } + need_flush |= sent_string(set_right_margin); + need_flush |= to_left_margin(); + } + + need_flush |= reset_tabstops(columns); + + need_flush |= cat_file((use_reset && reset_file) ? reset_file : init_file); + + need_flush |= sent_string((use_reset && (reset_3string != 0)) + ? reset_3string + : init_3string); + } + + return need_flush; +} + +/* + * Tell the user if a control key has been changed from the default value. + */ +static void +show_tty_change(TTY * old_settings, + TTY * new_settings, + const char *name, + int which, + unsigned def) +{ + unsigned older = 0, newer = 0; + char *p; + +#if defined(EXP_WIN32_DRIVER) + /* noop */ + (void) old_settings; + (void) new_settings; + (void) name; + (void) which; + (void) def; +#else + newer = new_settings->c_cc[which]; + older = old_settings->c_cc[which]; + + if (older == newer && older == def) + return; +#endif + (void) fprintf(stderr, "%s %s ", name, older == newer ? "is" : "set to"); + + if (DISABLED(newer)) { + (void) fprintf(stderr, "undef.\n"); + /* + * Check 'delete' before 'backspace', since the key_backspace value + * is ambiguous. + */ + } else if (newer == 0177) { + (void) fprintf(stderr, "delete.\n"); + } else if ((p = key_backspace) != 0 + && newer == (unsigned char) p[0] + && p[1] == '\0') { + (void) fprintf(stderr, "backspace.\n"); + } else if (newer < 040) { + newer ^= 0100; + (void) fprintf(stderr, "control-%c (^%c).\n", UChar(newer), UChar(newer)); + } else + (void) fprintf(stderr, "%c.\n", UChar(newer)); +} + +/************************************************************************** + * Miscellaneous. + **************************************************************************/ + +void +reset_start(FILE *fp, bool is_reset, bool is_init) +{ + my_file = fp; + use_reset = is_reset; + use_init = is_init; +} + +void +reset_flush(void) +{ + if (my_file != 0) + fflush(my_file); +} + +void +print_tty_chars(TTY * old_settings, TTY * new_settings) +{ +#if defined(EXP_WIN32_DRIVER) + /* noop */ +#else + show_tty_change(old_settings, new_settings, "Erase", VERASE, CERASE); + show_tty_change(old_settings, new_settings, "Kill", VKILL, CKILL); + show_tty_change(old_settings, new_settings, "Interrupt", VINTR, CINTR); +#endif +} + +#if HAVE_SIZECHANGE +/* + * Set window size if not set already, but update our copy of the values if the + * size was set. + */ +void +set_window_size(int fd, short *high, short *wide) +{ + STRUCT_WINSIZE win; + (void) ioctl(fd, IOCTL_GET_WINSIZE, &win); + if (WINSIZE_ROWS(win) == 0 && + WINSIZE_COLS(win) == 0) { + if (*high > 0 && *wide > 0) { + WINSIZE_ROWS(win) = (unsigned short) *high; + WINSIZE_COLS(win) = (unsigned short) *wide; + (void) ioctl(fd, IOCTL_SET_WINSIZE, &win); + } + } else if (WINSIZE_ROWS(win) > 0 && + WINSIZE_COLS(win) > 0) { + *high = (short) WINSIZE_ROWS(win); + *wide = (short) WINSIZE_COLS(win); + } +} +#endif diff --git a/usr.bin/tic/reset_cmd.h b/usr.bin/tic/reset_cmd.h new file mode 100644 index 00000000000..7cac78f0bb1 --- /dev/null +++ b/usr.bin/tic/reset_cmd.h @@ -0,0 +1,66 @@ +/**************************************************************************** + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 2016 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E Dickey * + ****************************************************************************/ + +/* + * $Id: reset_cmd.h,v 1.1 2023/10/17 09:52:10 nicm Exp $ + * + * Utility functions for resetting terminal. + */ +#ifndef RESET_CMD_H +#define RESET_CMD_H 1 +/* *INDENT-OFF* */ + +#define USE_LIBTINFO +#define __INTERNAL_CAPS_VISIBLE /* we need to see has_hardware_tabs */ +#include + +#undef CTRL +#define CTRL(x) ((x) & 0x1f) + +extern bool send_init_strings(int /* fd */, TTY * /* old_settings */); +extern void print_tty_chars(TTY * /* old_settings */, TTY * /* new_settings */); +extern void reset_flush(void); +extern void reset_start(FILE * /* fp */, bool /* is_reset */, bool /* is_init */ ); +extern void reset_tty_settings(int /* fd */, TTY * /* tty_settings */, int /* noset */); +extern void set_control_chars(TTY * /* tty_settings */, int /* erase */, int /* intr */, int /* kill */); +extern void set_conversions(TTY * /* tty_settings */); + +#if HAVE_SIZECHANGE +extern void set_window_size(int /* fd */, short * /* high */, short * /* wide */); +#endif + +extern const char *_nc_progname; + +/* *INDENT-ON* */ + +#endif /* RESET_CMD_H */ diff --git a/usr.bin/tic/tic.1 b/usr.bin/tic/tic.1 index 43e3af8ee00..2ede20004c3 100644 --- a/usr.bin/tic/tic.1 +++ b/usr.bin/tic/tic.1 @@ -1,7 +1,8 @@ -.\" $OpenBSD: tic.1,v 1.16 2013/03/24 00:09:30 nicm Exp $ +.\" $OpenBSD: tic.1,v 1.17 2023/10/17 09:52:10 nicm Exp $ .\" .\"*************************************************************************** -.\" Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. * +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2016,2017 Free Software Foundation, Inc. * .\" * .\" Permission is hereby granted, free of charge, to any person obtaining a * .\" copy of this software and associated documentation files (the * @@ -28,86 +29,184 @@ .\" authorization. * .\"*************************************************************************** .\" -.\" $Id: tic.1,v 1.16 2013/03/24 00:09:30 nicm Exp $ -.TH tic 1 "" +.\" $Id: tic.1,v 1.17 2023/10/17 09:52:10 nicm Exp $ +.TH tic 1 2023-08-19 "ncurses 6.4" "User commands" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' .ds n 5 .ds d /usr/share/terminfo +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. .SH NAME -\fBtic\fR - the \fIterminfo\fR entry-description compiler +\fBtic\fP \- the \fIterminfo\fP entry-description compiler .SH SYNOPSIS -\fBtic\fR -[\fB-\ +\fBtic\fP +[\fB\-\ +0\ 1\ C\ +D\ G\ I\ +K\ L\ N\ T\ U\ V\ +W\ a\ c\ f\ g\ +q\ r\ s\ t\ x\ -\fR] -[\fB-e\fR \fInames\fR] -[\fB-o\fR \fIdir\fR] -[\fB-R\fR \fIsubset\fR] -[\fB-v\fR[\fIn\fR]] -[\fB-w\fR[\fIn\fR]] -\fIfile\fR -.br +\fP] +[\fB\-e\fP \fInames\fP] +[\fB\-o\fP \fIdir\fP] +[\fB\-Q\fP[\fIn\fP]] +[\fB\-R\fP \fIsubset\fP] +[\fB\-v\fP[\fIn\fP]] +[\fB\-w\fP[\fIn\fP]] +\fIfile\fP .SH DESCRIPTION -The command \fBtic\fR translates a \fBterminfo\fR file from source -format into compiled format. The compiled format is necessary for use with -the library routines in \fBncurses\fR(3X). +The \fBtic\fP command translates a \fBterminfo\fP file from source +format into compiled format. +The compiled format is necessary for use with +the library routines in \fBncurses\fP(3). .PP -The results are normally placed in the system terminfo -directory \fB\*d\fR. There are two ways to change this behavior. +As described in \fBterm\fP(\*n), the database may be either a directory +tree (one file per terminal entry) or a hashed database (one record per entry). +The \fBtic\fP command writes only one type of entry, +depending on how it was built: +.bP +For directory trees, the top-level directory, e.g., /usr/share/terminfo, +specifies the location of the database. +.bP +For hashed databases, a filename is needed. +If the given file is not found by that name, +but can be found by adding the suffix ".db", +then that is used. +.IP +The default name for the hashed database is the same as the +default directory name (only adding a ".db" suffix). .PP -First, you may override the system default by setting the variable -\fBTERMINFO\fR in your shell environment to a valid (existing) directory name. +In either case (directory or hashed database), +\fBtic\fP will create the container if it does not exist. +For a directory, this would be the \*(``terminfo\*('' leaf, +versus a "terminfo.db" file. .PP -Secondly, if \fBtic\fR cannot get access to \fI\*d\fR or your TERMINFO -directory, it looks for the directory \fI$HOME/.terminfo\fR; if that directory -exists, the entry is placed there. +The results are normally placed in the system terminfo database \fB\*d\fP. +The compiled terminal description can be placed +in a different terminfo database. +There are two ways to achieve this: +.bP +First, you may override the system default either by +using the \fB\-o\fP option, +or by setting the variable \fBTERMINFO\fP +in your shell environment to a valid database location. +.bP +Secondly, if \fBtic\fP cannot write in \fI\*d\fP +or the location specified using your TERMINFO variable, +it looks for the directory \fI$HOME/.terminfo\fP +(or hashed database \fI$HOME/.terminfo.db)\fP; +if that location exists, the entry is placed there. .PP -Libraries that read terminfo entries are expected to check for a TERMINFO -directory first, look at \fI$HOME/.terminfo\fR if TERMINFO is not set, and -finally look in \fI\*d\fR. +Libraries that read terminfo entries are expected to check in succession +.bP +a location specified with the TERMINFO environment variable, +.bP +\fI$HOME/.terminfo\fP, +.bP +directories listed in the TERMINFO_DIRS environment variable, +.bP +a compiled-in list of directories (?), and +.bP +the system terminfo database (\fI\*d\fP). +.SS ALIASES +This is the same program as infotocap and captoinfo; +usually those are linked to, or copied from this program: +.bP +When invoked as infotocap, tic sets the \fB\-I\fP option. +.bP +When invoked as captoinfo, tic sets the \fB\-C\fP option. +.SS OPTIONS +.TP +\fB\-0\fP +restricts the output to a single line .TP -\fB-1\fR +\fB\-1\fP restricts the output to a single column .TP -\fB-a\fR +\fB\-a\fP tells \fBtic\fP to retain commented-out capabilities rather than discarding -them. Capabilities are commented by prefixing them with a period. -This sets the \fB-x\fR option, because it treats the commented-out +them. +Capabilities are commented by prefixing them with a period. +This sets the \fB\-x\fP option, because it treats the commented-out entries as user-defined names. If the source is termcap, accept the 2-character names required by version 6. Otherwise these are ignored. .TP -\fB-C\fR -Force source translation to termcap format. Note: this differs from the \fB-C\fR -option of \fBinfocmp\fR(1M) in that it does not merely translate capability -names, but also translates terminfo strings to termcap format. Capabilities +\fB\-C\fP +Force source translation to termcap format. +Note: this differs from the \fB\-C\fP +option of \fBinfocmp\fP(1) in that it does not merely translate capability +names, but also translates terminfo strings to termcap format. +Capabilities that are not translatable are left in the entry under their terminfo names but commented out with two preceding dots. +The actual format used incorporates some improvements for escaped characters +from terminfo format. +For a stricter BSD-compatible translation, add the \fB\-K\fP option. +.IP +If this is combined with \fB\-c\fP, \fBtic\fP makes additional checks +to report cases where the terminfo values do not have an exact equivalent +in termcap form. +For example: +.RS +.bP +\fBsgr\fP usually will not convert, because termcap lacks the ability to +work with more than two parameters, and because termcap lacks many of +the arithmetic/logical operators used in terminfo. +.bP +capabilities with more than one delay or with delays before the end of +the string will not convert completely. +.RE .TP -\fB-c\fR -tells \fBtic\fP to only check \fIfile\fR for errors, including syntax problems and -bad use links. If you specify \fB-C\fR (\fB-I\fR) with this option, the code +\fB\-c\fP +tells \fBtic\fP to only check \fIfile\fP for errors, +including syntax problems and bad use-links. +If you specify \fB\-C\fP (\fB\-I\fP) with this option, the code will print warnings about entries which, after use resolution, are more than -1023 (4096) bytes long. Due to a fixed buffer length in older termcap -libraries (and a documented limit in terminfo), these entries may cause core -dumps. +1023 (4096) bytes long. +Due to a fixed buffer length in older termcap libraries, +as well as buggy checking for the buffer length +(and a documented limit in terminfo), +these entries may cause core +dumps with other implementations. +.IP +\fBtic\fP checks string capabilities to ensure that those with parameters +will be valid expressions. +It does this check only for the predefined string capabilities; +those which are defined with the \fB\-x\fP option are ignored. +.TP +\fB\-D\fP +tells \fBtic\fP to print the database locations that it knows about, and exit. +The first location shown is the one to which it would write compiled +terminal descriptions. +If \fBtic\fP is not able to find a writable database location +according to the rules summarized above, +it will print a diagnostic and exit with an error rather than +printing a list of database locations. .TP -\fB-e \fR\fInames\fR +\fB\-e \fInames\fR Limit writes and translations to the following comma-separated list of terminals. If any name or alias of a terminal matches one of the names in @@ -115,119 +214,153 @@ the list, the entry will be written or translated as normal. Otherwise no output will be generated for it. The option value is interpreted as a file containing the list if it contains a '/'. -(Note: depending on how tic was compiled, this option may require \fB-I\fR or \fB-C\fR.) +(Note: depending on how tic was compiled, +this option may require \fB\-I\fP or \fB\-C\fP.) .TP -\fB-f\fR +\fB\-f\fP Display complex terminfo strings which contain if/then/else/endif expressions indented for readability. .TP -\fB-G\fR +\fB\-G\fP Display constant literals in decimal form rather than their character equivalents. .TP -\fB-g\fR +\fB\-g\fP Display constant character literals in quoted form rather than their decimal equivalents. .TP -\fB-I\fR +\fB\-I\fP Force source translation to terminfo format. .TP -\fB-L\fR +\fB\-K\fP +Suppress some longstanding ncurses extensions to termcap format, +e.g., "\\s" for space. +.TP +\fB\-L\fP Force source translation to terminfo format -using the long C variable names listed in <\fBterm.h\fR> +using the long C variable names listed in <\fBterm.h\fP> .TP -\fB-N\fR +\fB\-N\fP Disable smart defaults. Normally, when translating from termcap to terminfo, the compiler makes a number of assumptions about the defaults of string capabilities -\fBreset1_string\fR, \fBcarriage_return\fR, \fBcursor_left\fR, -\fBcursor_down\fR, \fBscroll_forward\fR, \fBtab\fR, \fBnewline\fR, -\fBkey_backspace\fR, \fBkey_left\fR, and \fBkey_down\fR, then attempts -to use obsolete termcap capabilities to deduce correct values. It also -normally suppresses output of obsolete termcap capabilities such as \fBbs\fR. +\fBreset1_string\fP, \fBcarriage_return\fP, \fBcursor_left\fP, +\fBcursor_down\fP, \fBscroll_forward\fP, \fBtab\fP, \fBnewline\fP, +\fBkey_backspace\fP, \fBkey_left\fP, and \fBkey_down\fP, then attempts +to use obsolete termcap capabilities to deduce correct values. +It also +normally suppresses output of obsolete termcap capabilities such as \fBbs\fP. This option forces a more literal translation that also preserves the obsolete capabilities. .TP -\fB-o\fR\fIdir\fR -Write compiled entries to given directory. Overrides the TERMINFO environment -variable. +\fB\-o\fIdir\fR +Write compiled entries to given database location. +Overrides the TERMINFO environment variable. +.TP +\fB\-Q\fIn\fR +Rather than show source in terminfo (text) format, +print the compiled (binary) format in hexadecimal or base64 form, +depending on the option's value: +.RS 8 +.TP 3 +1 +hexadecimal +.TP 3 +2 +base64 +.TP 3 +3 +hexadecimal and base64 +.RE +.TP +\fB\-q\fP +Suppress comments and blank lines when showing translated source. .TP -\fB-R\fR\fIsubset\fR -Restrict output to a given subset. This option is for use with archaic +\fB\-R\fIsubset\fR +Restrict output to a given subset. +This option is for use with archaic versions of terminfo like those on SVr1, Ultrix, or HP-UX that do not support the full set of SVR4/XSI Curses terminfo; and outright broken ports like AIX 3.x -that have their own extensions incompatible with SVr4/XSI. Available subsets -are "SVr1", "Ultrix", "HP", "BSD" and "AIX"; see \fBterminfo\fR(\*n) for details. +that have their own extensions incompatible with SVr4/XSI. +.IP +Available subsets are +.RS +\*(``SVr1\*('', +\*(``Ultrix\*('', +\*(``HP\*('', +\*(``BSD\*('', and +\*(``AIX\*('' +.RE +.IP +See \fBterminfo\fP(\*n) for details. .TP -\fB-r\fR +\fB\-r\fP Force entry resolution (so there are no remaining tc capabilities) even -when doing translation to termcap format. This may be needed if you are +when doing translation to termcap format. +This may be needed if you are preparing a termcap file for a termcap library (such as GNU termcap through version 1.3 or BSD termcap through 4.3BSD) that does not handle multiple tc capabilities per entry. .TP -\fB-s\fR -Summarize the compile by showing the directory into which entries +\fB\-s\fP +Summarize the compile by showing the database location into which entries are written, and the number of entries which are compiled. .TP -\fB-T\fR +\fB\-T\fP eliminates size-restrictions on the generated text. This is mainly useful for testing and analysis, since the compiled descriptions are limited (e.g., 1023 for termcap, 4096 for terminfo). .TP -\fB-t\fR +\fB\-t\fP tells \fBtic\fP to discard commented-out capabilities. Normally when translating from terminfo to termcap, untranslatable capabilities are commented-out. .TP 5 -\fB-U\fR +\fB\-U\fP tells \fBtic\fP to not post-process the data after parsing the source file. Normally, it infers data which is commonly missing in older terminfo data, or in termcaps. .TP -\fB-V\fR +\fB\-V\fP reports the version of ncurses which was used in this program, and exits. .TP -\fB-v\fR\fIn\fR +\fB\-v\fIn\fR specifies that (verbose) output be written to standard error trace -information showing \fBtic\fR's progress. -The optional parameter \fIn\fR is a number from 1 to 10, inclusive, +information showing \fBtic\fP's progress. +.IP +The optional parameter \fIn\fP is a number from 1 to 9, inclusive, indicating the desired level of detail of information. -If \fIn\fR is omitted, the default level is 1. -If \fIn\fR is specified and greater than 1, the level of -detail is increased. -.TP -\fB-w\fR\fIn\fR -specifies the width of the output. -The parameter is optional. -If it is omitted, it defaults to 60. -.TP -\fB-x\fR -Treat unknown capabilities as user-defined. -That is, if you supply a capability name which \fBtic\fP does not recognize, -it will infer its type (boolean, number or string) from the syntax and -make an extended table entry for that. -User-defined capability strings -whose name begins with ``k'' are treated as function keys. -.TP -\fIfile\fR -contains one or more \fBterminfo\fR terminal descriptions in source -format [see \fBterminfo\fR(\*n)]. Each description in the file -describes the capabilities of a particular terminal. +.RS +.bP +If ncurses is built without tracing support, the optional parameter is ignored. +.bP +If \fIn\fP is omitted, the default level is 1. +.bP +If \fIn\fP is specified and greater than 1, the level of +detail is increased, and the output is written (with tracing information) +to the \*(``trace\*('' file. +.RE +.RS .PP The debug flag levels are as follows: -.TP +.TP 4 1 Names of files created and linked .TP 2 -Information related to the ``use'' facility +Information related to the \*(``use\*('' facility .TP 3 Statistics from the hashing algorithm .TP +4 +Details of extended capabilities +.TP 5 -String-table memory allocations +(unused) +.TP +6 +(unused) .TP 7 Entries into the string-table @@ -237,96 +370,237 @@ List of tokens encountered by scanner .TP 9 All values computed in construction of the hash table -.LP -If the debug level \fIn\fR is not given, it is taken to be one. -.PP -All but one of the capabilities recognized by \fBtic\fR are documented -in \fBterminfo\fR(\*n). The exception is the \fBuse\fR capability. +.RE +.TP +\fB\-W\fP +By itself, the \fB\-w\fP option will not force long strings to be wrapped. +Use the \fB\-W\fP option to do this. +.IP +If you specify both \fB\-f\fP and \fB\-W\fP options, +the latter is ignored when \fB\-f\fP has already split the line. +.TP +\fB\-w\fIn\fR +specifies the width of the output. +The parameter is optional. +If it is omitted, it defaults to 60. +.TP +\fB\-x\fP +Treat unknown capabilities as user-defined (see \fBuser_caps(\*n)\fP). +That is, if you supply a capability name which \fBtic\fP does not recognize, +it will infer its type (boolean, number or string) from the syntax and +make an extended table entry for that. +User-defined capability strings +whose name begins with \*(``k\*('' are treated as function keys. +.SS PARAMETERS +.TP +\fIfile\fP +contains one or more \fBterminfo\fP terminal descriptions in source +format [see \fBterminfo\fP(\*n)]. +Each description in the file +describes the capabilities of a particular terminal. +.IP +If \fIfile\fP is \*(``-\*('', then the data is read from the standard input. +The \fIfile\fP parameter may also be the path of a character-device. +.SS PROCESSING +All but one of the capabilities recognized by \fBtic\fP are documented +in \fBterminfo\fP(\*n). +The exception is the \fBuse\fP capability. .PP -When a \fBuse\fR=\fIentry\fR-\fIname\fR field is discovered in a -terminal entry currently being compiled, \fBtic\fR reads in the binary -from \fB\*d\fR to complete the entry. (Entries created from -\fIfile\fR will be used first. If the environment variable -\fBTERMINFO\fR is set, that directory is searched instead of -\fB\*d\fR.) \fBtic\fR duplicates the capabilities in -\fIentry\fR-\fIname\fR for the current entry, with the exception of +When a \fBuse\fP=\fIentry\fP\-\fIname\fP field is discovered in a +terminal entry currently being compiled, \fBtic\fP reads in the binary +from \fB\*d\fP to complete the entry. +(Entries created from +\fIfile\fP will be used first. +\fBtic\fP duplicates the capabilities in +\fIentry\fP\-\fIname\fP for the current entry, with the exception of those capabilities that explicitly are defined in the current entry. .PP -When an entry, e.g., \fBentry_name_1\fR, contains a -\fBuse=\fR\fIentry\fR_\fIname\fR_\fI2\fR field, any canceled -capabilities in \fIentry\fR_\fIname\fR_\fI2\fR must also appear in -\fBentry_name_1\fR before \fBuse=\fR for these capabilities to be -canceled in \fBentry_name_1\fR. +When an entry, e.g., \fBentry_name_1\fP, contains a +\fBuse=\fIentry\fR_\fIname\fR_\fI2\fR field, any canceled +capabilities in \fIentry\fR_\fIname\fR_\fI2\fP must also appear in +\fBentry_name_1\fP before \fBuse=\fP for these capabilities to be +canceled in \fBentry_name_1\fP. .PP -If the environment variable \fBTERMINFO\fR is set, the compiled -results are placed there instead of \fB\*d\fR. -.PP -Total compiled entries cannot exceed 4096 bytes. The name field cannot -exceed 512 bytes. Terminal names exceeding the maximum alias length +Total compiled entries cannot exceed 4096 bytes. +The name field cannot +exceed 512 bytes. +Terminal names exceeding the maximum alias length (32 characters on systems with long filenames, 14 characters otherwise) -will be truncated to the maximum alias length and a warning message will be printed. -.SH COMPATIBILITY -There is some evidence that historic \fBtic\fR implementations treated +will be truncated to the maximum alias length +and a warning message will be printed. +.SH HISTORY +System V Release 2 provided a \fBtic\fP utility. +It accepted a single option: \fB\-v\fP (optionally followed by a number). +According to Ross Ridge's comment in \fImytinfo\fP, +this version of \fBtic\fP was +unable to represent cancelled capabilities. +.PP +System V Release 3 provided a different \fBtic\fP utility, +written by Pavel Curtis, +(originally named \*(``compile\*('' in \fIpcurses\fP). +This added an option \fB\-c\fP to check the file for +errors, with the caveat that errors in \*(``use=\*('' links +would not be reported. +System V Release 3 documented a few warning messages which +did not appear in \fIpcurses\fP. +While the program itself was changed little as development +continued with System V Release 4, +the table of capabilities grew from 180 (\fIpcurses\fP) to 464 (Solaris). +.PP +In early development of ncurses (1993), +Zeyd Ben-Halim used the table from \fImytinfo\fP to +extend the \fIpcurses\fP table to 469 capabilities +(456 matched SVr4, 8 were only in SVr4, 13 were not in SVr4). +Of those 13, 11 were ultimately discarded +(perhaps to match the draft of X/Open Curses). +The exceptions were +\fBmemory_lock_above\fP and +\fBmemory_unlock\fP (see \fBuser_caps\fP(5)). +.PP +Eric Raymond incorporated parts of \fImytinfo\fP into ncurses +to implement the termcap-to-terminfo source conversion, +and extended that to begin development of +the corresponding terminfo-to-termcap source conversion, +Thomas Dickey completed that development over the course of several years. +.PP +In 1999, Thomas Dickey added the \fB\-x\fP option +to support user-defined capabilities. +.PP +In 2010, Roy Marples provided a \fBtic\fP program +and terminfo library for NetBSD. +That implementation adapts several features from ncurses, +including \fBtic\fP's \fB\-x\fP option. +.PP +The \fB\-c\fP option tells \fBtic\fP to check for problems in the +terminfo source file. +Continued development provides additional checks: +.bP +\fIpcurses\fP had 8 warnings +.bP +ncurses in 1996 had 16 warnings +.bP +Solaris (SVr4) curses has 28 warnings +.bP +NetBSD tic in 2019 has 19 warnings. +.bP +ncurses in 2019 has 96 warnings +.PP +The checking done in ncurses' \fBtic\fP helps with the conversion to +termcap, as well as pointing out errors and inconsistencies. +It is also used to ensure consistency with the user-defined capabilities. +There are 527 distinct capabilities in ncurses' terminal database; +128 of those are user-defined. +.SH PORTABILITY +X/Open Curses, Issue 7 (2009) provides a brief description of \fBtic\fP. +It lists one option: \fB\-c\fP. +The omission of \fB\-v\fP is unexpected. +The change history states that the description is derived from True64 UNIX. +According to its manual pages, that system also supported the \fB\-v\fP option. +.PP +Shortly after Issue 7 was released, Tru64 was discontinued. +As of 2019, the surviving implementations of \fBtic\fP +are SVr4 (AIX, HP-UX and Solaris), +ncurses +and NetBSD curses. +The SVr4 \fBtic\fP programs all support the \fB\-v\fP option. +The NetBSD \fBtic\fP program follows X/Open's documentation, +omitting the \fB\-v\fP option. +.PP +The X/Open rationale states that some implementations of \fBtic\fP +read terminal descriptions from the standard input if the \fIfile\fP +parameter is omitted. +None of these implementations do that. +Further, it comments that some may choose to read from \*(''./terminfo.src\*('' +but that is obsolescent behavior from SVr2, +and is not (for example) a documented feature of SVr3. +.SS COMPATIBILITY +There is some evidence that historic \fBtic\fP implementations treated description fields with no whitespace in them as additional aliases or -short names. This \fBtic\fR does not do that, but it does warn when +short names. +This \fBtic\fP does not do that, but it does warn when description fields may be treated that way and check them for dangerous characters. -.SH EXTENSIONS -Unlike the stock SVr4 \fBtic\fR command, this implementation can actually -compile termcap sources. In fact, entries in terminfo and termcap syntax can -be mixed in a single source file. See \fBterminfo\fR(\*n) for the list of +.SS EXTENSIONS +Unlike the SVr4 \fBtic\fP command, this implementation can actually +compile termcap sources. +In fact, entries in terminfo and termcap syntax can +be mixed in a single source file. +See \fBterminfo\fP(\*n) for the list of termcap names taken to be equivalent to terminfo names. .PP -The SVr4 manual pages are not clear on the resolution rules for \fBuse\fR +The SVr4 manual pages are not clear on the resolution rules for \fBuse\fP capabilities. -This implementation of \fBtic\fR will find \fBuse\fR targets anywhere -in the source file, or anywhere in the file tree rooted at \fBTERMINFO\fR (if -\fBTERMINFO\fR is defined), or in the user's \fI$HOME/.terminfo\fR directory -(if it exists), or (finally) anywhere in the system's file tree of +This implementation of \fBtic\fP will find \fBuse\fP targets anywhere +in the source file, or anywhere in the file tree rooted at \fBTERMINFO\fP (if +\fBTERMINFO\fP is defined), +or in the user's \fI$HOME/.terminfo\fP database +(if it exists), +or (finally) anywhere in the system's file tree of compiled entries. .PP -The error messages from this \fBtic\fR have the same format as GNU C +The error messages from this \fBtic\fP have the same format as GNU C error messages, and can be parsed by GNU Emacs's compile facility. .PP -The -\fB-C\fR, -\fB-G\fR, -\fB-I\fR, -\fB-N\fR, -\fB-R\fR, -\fB-T\fR, -\fB-V\fR, -\fB-a\fR, -\fB-e\fR, -\fB-f\fR, -\fB-g\fR, -\fB-o\fR, -\fB-r\fR, -\fB-s\fR, -\fB-t\fR and -\fB-x\fR -options -are not supported under SVr4. -The SVr4 \fB-c\fR mode does not report bad use links. +Aside from \fB\-c\fP and \fB\-v\fP, options are not portable: +.bP +Most of tic's options +are not supported by SVr4 \fBtic\fP: +.sp +.RS +\fB\-0\fP +\fB\-1\fP +\fB\-C\fP +\fB\-G\fP +\fB\-I\fP +\fB\-N\fP +\fB\-R\fP +\fB\-T\fP +\fB\-V\fP +\fB\-a\fP +\fB\-e\fP +\fB\-f\fP +\fB\-g\fP +\fB\-o\fP +\fB\-r\fP +\fB\-s\fP +\fB\-t\fP +\fB\-x\fP +.RE +.bP +The NetBSD \fBtic\fP supports a few of the ncurses options +.sp +.RS +\fB\-a\fP +\fB\-o\fP +\fB\-x\fP +.RE +.IP +and adds \fB\-S\fP +(a feature which does the same thing +as infocmp's \fB\-e\fP and \fB\-E\fP options). +.PP +The SVr4 \fB\-c\fP mode does not report bad \*(``use=\*('' links. .PP System V does not compile entries to or read entries from your -\fI$HOME/.terminfo\fR directory unless TERMINFO is explicitly set to it. +\fI$HOME/.terminfo\fP database unless TERMINFO is explicitly set to it. .SH FILES .TP 5 -\fB\*d/?/*\fR +\fB\*d/?/*\fP Compiled terminal description database. .SH SEE ALSO -\fBinfocmp\fR(1), -\fBcaptoinfo\fR(1), -\fBinfotocap\fR(1), -\fBcurses\fR(3), -\fBterminfo\fR(\*n). +\fBcaptoinfo\fP(1), +\fBinfocmp\fP(1), +\fBinfotocap\fP(1), +\fBtoe\fP(1), +\fBcurses\fP(3), +\fBterm\fP(\*n). +\fBterminfo\fP(\*n). +\fBuser_caps\fP(\*n). .PP -This describes \fBncurses\fR -version 5.7. -.\"# -.\"# The following sets edit modes for GNU EMACS -.\"# Local Variables: -.\"# mode:nroff -.\"# fill-column:79 -.\"# End: +This describes \fBncurses\fP +version 6.4 (patch 20230826). +.SH AUTHOR +Eric S. Raymond +and +.br +Thomas E. Dickey diff --git a/usr.bin/tic/tic.c b/usr.bin/tic/tic.c index 4e4c606600c..3f3f682b954 100644 --- a/usr.bin/tic/tic.c +++ b/usr.bin/tic/tic.c @@ -1,7 +1,8 @@ -/* $OpenBSD: tic.c,v 1.34 2019/06/28 13:35:04 deraadt Exp $ */ +/* $OpenBSD: tic.c,v 1.35 2023/10/17 09:52:10 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2017,2018 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -37,6 +38,7 @@ /* * tic.c --- Main program for terminfo compiler * by Eric S. Raymond + * and Thomas E Dickey * */ @@ -44,9 +46,14 @@ #include #include +#include +#include +#include #include -MODULE_ID("$Id: tic.c,v 1.34 2019/06/28 13:35:04 deraadt Exp $") +MODULE_ID("$Id: tic.c,v 1.35 2023/10/17 09:52:10 nicm Exp $") + +#define STDIN_NAME "" const char *_nc_progname = "tic"; @@ -55,10 +62,16 @@ static FILE *tmp_fp; static bool capdump = FALSE; /* running as infotocap? */ static bool infodump = FALSE; /* running as captoinfo? */ static bool showsummary = FALSE; +static unsigned debug_level; +static char **namelst = 0; static const char *to_remove; -static void (*save_check_termtype) (TERMTYPE *, bool); -static void check_termtype(TERMTYPE *tt, bool); +#if NCURSES_XNAMES +static bool using_extensions = FALSE; +#endif + +static void (*save_check_termtype) (TERMTYPE2 *, bool); +static void check_termtype(TERMTYPE2 *tt, bool); static const char usage_string[] = "\ [-e names] \ @@ -71,11 +84,13 @@ static const char usage_string[] = "\ 1\ a\ C\ +D\ c\ f\ G\ g\ I\ +K\ L\ N\ r\ @@ -101,19 +116,24 @@ free_namelist(char **src) #endif static void -cleanup(char **namelst GCC_UNUSED) +cleanup(void) { #if NO_LEAKS free_namelist(namelst); + _nc_leaks_dump_entry(); #endif if (tmp_fp != 0) fclose(tmp_fp); if (to_remove != 0) { + int rc; + #if HAVE_REMOVE - remove(to_remove); + rc = remove(to_remove); #else - unlink(to_remove); + rc = unlink(to_remove); #endif + if (rc != 0) + perror(to_remove); } } @@ -121,61 +141,64 @@ static void failed(const char *msg) { perror(msg); - cleanup((char **) 0); ExitProgram(EXIT_FAILURE); } static void usage(void) { - static const char *const tbl[] = +#define DATA(s) s "\n" + static const char options_string[] = { - "Options:", - " -1 format translation output one capability per line", + DATA("Options:") + DATA(" -0 format translation output all capabilities on one line") + DATA(" -1 format translation output one capability per line") #if NCURSES_XNAMES - " -a retain commented-out capabilities (sets -x also)", + DATA(" -a retain commented-out capabilities (sets -x also)") #endif - " -C translate entries to termcap source form", - " -c check only, validate input without compiling or translating", - " -e translate/compile only entries named by comma-separated list", - " -f format complex strings for readability", - " -G format %{number} to %'char'", - " -g format %'char' to %{number}", - " -I translate entries to terminfo source form", - " -L translate entries to full terminfo source form", - " -N disable smart defaults for source translation", - " -o set output directory for compiled entry writes", - " -R restrict translation to given terminfo/termcap version", - " -r force resolution of all use entries in source translation", - " -s print summary statistics", - " -T remove size-restrictions on compiled description", + DATA(" -C translate entries to termcap source form") + DATA(" -D print list of tic's database locations (first must be writable)") + DATA(" -c check only, validate input without compiling or translating") + DATA(" -e translate/compile only entries named by comma-separated list") + DATA(" -f format complex strings for readability") + DATA(" -G format %{number} to %'char'") + DATA(" -g format %'char' to %{number}") + DATA(" -I translate entries to terminfo source form") + DATA(" -K translate entries to termcap source form with BSD syntax") + DATA(" -L translate entries to full terminfo source form") + DATA(" -N disable smart defaults for source translation") + DATA(" -o set output directory for compiled entry writes") + DATA(" -Q[n] dump compiled description") + DATA(" -q brief listing, removes headers") + DATA(" -R restrict translation to given terminfo/termcap version") + DATA(" -r force resolution of all use entries in source translation") + DATA(" -s print summary statistics") + DATA(" -T remove size-restrictions on compiled description") #if NCURSES_XNAMES - " -t suppress commented-out capabilities", + DATA(" -t suppress commented-out capabilities") #endif - " -U suppress post-processing of entries", - " -V print version", - " -v[n] set verbosity level", - " -w[n] set format width for translation output", + DATA(" -U suppress post-processing of entries") + DATA(" -V print version") + DATA(" -W wrap long strings according to -w[n] option") + DATA(" -v[n] set verbosity level") + DATA(" -w[n] set format width for translation output") #if NCURSES_XNAMES - " -x treat unknown capabilities as user-defined", + DATA(" -x treat unknown capabilities as user-defined") #endif - "", - "Parameters:", - " file to translate or compile" + DATA("") + DATA("Parameters:") + DATA(" file to translate or compile") }; - size_t j; +#undef DATA fprintf(stderr, "Usage: %s %s\n", _nc_progname, usage_string); - for (j = 0; j < SIZEOF(tbl); j++) { - fputs(tbl[j], stderr); - putc('\n', stderr); - } + fputs(options_string, stderr); ExitProgram(EXIT_FAILURE); } #define L_BRACE '{' #define R_BRACE '}' -#define S_QUOTE '\''; +#define S_QUOTE '\'' static void write_it(ENTRY * ep) @@ -198,7 +221,8 @@ write_it(ENTRY * ep) while ((ch = *t++) != 0) { *d++ = (char) ch; if (ch == '\\') { - *d++ = *t++; + if ((*d++ = *t++) == '\0') + break; } else if ((ch == '%') && (*t == L_BRACE)) { char *v = 0; @@ -217,15 +241,13 @@ write_it(ENTRY * ep) } } *d = 0; - if (strlen(result) < strlen(s)) { - /* new string is same length as what is there, or shorter */ - strlcpy(s, result, strlen(s)); - } + if (strlen(result) < strlen(s)) + _nc_STRCPY(s, result, strlen(s) + 1); } } _nc_set_type(_nc_first_name(ep->tterm.term_names)); - _nc_curr_line = ep->startline; + _nc_curr_line = (int) ep->startline; _nc_write_entry(&ep->tterm); } @@ -284,14 +306,18 @@ put_translate(int c) /* emit a comment char, translating terminfo names to termcap names */ { static bool in_name = FALSE; - static size_t have, used; - static char *namebuf, *suffix; + static size_t used; if (in_name) { + static size_t have; + static char *namebuf, *suffix; + if (used + 1 >= have) { have += 132; - namebuf = typeRealloc(char, have, namebuf); - suffix = typeRealloc(char, have, suffix); + if ((namebuf = typeRealloc(char, have, namebuf)) == NULL) + failed("put_translate namebuf"); + if ((suffix = typeRealloc(char, have, suffix)) == NULL) + failed("put_translate suffix"); } if (c == '\n' || c == '@') { namebuf[used++] = '\0'; @@ -312,7 +338,7 @@ put_translate(int c) if ((up = strchr(namebuf, '#')) != 0 || (up = strchr(namebuf, '=')) != 0 || ((up = strchr(namebuf, '@')) != 0 && up[1] == '>')) { - (void) strlcpy(suffix, up, have); + _nc_STRCPY(suffix, up, have); *up = '\0'; } @@ -343,36 +369,120 @@ put_translate(int c) static char * stripped(char *src) { + char *dst = 0; + while (isspace(UChar(*src))) src++; - if (*src != '\0') { - char *dst; - size_t len; - if ((dst = strdup(src)) == NULL) + if (*src != '\0') { + if ((dst = strdup(src)) == NULL) { failed("strdup"); - len = strlen(dst); - while (--len != 0 && isspace(UChar(dst[len]))) - dst[len] = '\0'; - return dst; + } else { + size_t len = strlen(dst); + while (--len != 0 && isspace(UChar(dst[len]))) + dst[len] = '\0'; + } + } + return dst; +} + +static FILE * +open_tempfile(char *filename) +{ + FILE *result = 0; + + _nc_STRCPY(filename, "/tmp/XXXXXX", PATH_MAX); +#if HAVE_MKSTEMP + { + int oldmask = (int) umask(077); + int fd = mkstemp(filename); + if (fd >= 0) + result = fdopen(fd, "w"); + umask((mode_t) oldmask); + } +#else + if (tmpnam(filename) != 0) + result = safe_fopen(filename, "w"); +#endif + return result; +} + +static FILE * +copy_input(FILE *source, const char *filename, char *alt_file) +{ + char my_altfile[PATH_MAX]; + FILE *result = 0; + FILE *target; + int ch; + + if (alt_file == NULL) + alt_file = my_altfile; + + if (source == NULL) { + failed("copy_input (source)"); + } else if ((target = open_tempfile(alt_file)) == NULL) { + failed("copy_input (target)"); + } else { + clearerr(source); + for (;;) { + ch = fgetc(source); + if (feof(source)) { + break; + } else if (ferror(source)) { + failed(filename); + } else if (ch == 0) { + /* don't loop in case someone wants to convert /dev/zero */ + fprintf(stderr, "%s: %s is not a text-file\n", _nc_progname, filename); + ExitProgram(EXIT_FAILURE); + } + fputc(ch, target); + } + fclose(source); + /* + * rewind() does not force the target file's data to disk (not does + * fflush()...). So open a second stream on the data and then close + * the one that we were writing on before starting to read from the + * second stream. + */ + result = safe_fopen(alt_file, "r+"); + fclose(target); + to_remove = strdup(alt_file); } - return 0; + return result; } static FILE * -open_input(const char *filename) +open_input(const char *filename, char *alt_file) { - FILE *fp = fopen(filename, "r"); + FILE *fp; struct stat sb; + int mode; - if (fp == 0) { - fprintf(stderr, "%s: Can't open %s\n", _nc_progname, filename); + if (!strcmp(filename, "-")) { + fp = copy_input(stdin, STDIN_NAME, alt_file); + } else if (stat(filename, &sb) == -1) { + fprintf(stderr, "%s: %s %s\n", _nc_progname, filename, strerror(errno)); ExitProgram(EXIT_FAILURE); - } - if (fstat(fileno(fp), &sb) == -1 - || (sb.st_mode & S_IFMT) != S_IFREG) { + } else if ((mode = (sb.st_mode & S_IFMT)) == S_IFDIR + || (mode != S_IFREG && mode != S_IFCHR && mode != S_IFIFO)) { fprintf(stderr, "%s: %s is not a file\n", _nc_progname, filename); ExitProgram(EXIT_FAILURE); + } else { + fp = safe_fopen(filename, "r"); + + if (fp == NULL) { + fprintf(stderr, "%s: Can't open %s\n", _nc_progname, filename); + ExitProgram(EXIT_FAILURE); + } + if (mode != S_IFREG) { + if (alt_file != 0) { + FILE *fp2 = copy_input(fp, filename, alt_file); + fp = fp2; + } else { + fprintf(stderr, "%s: %s is not a file\n", _nc_progname, filename); + ExitProgram(EXIT_FAILURE); + } + } } return fp; } @@ -387,14 +497,14 @@ make_namelist(char *src) unsigned pass, n, nn; char buffer[BUFSIZ]; - if (src == 0) { + if (src == NULL) { /* EMPTY */ ; } else if (strchr(src, '/') != 0) { /* a filename */ - FILE *fp = open_input(src); + FILE *fp = open_input(src, (char *) 0); for (pass = 1; pass <= 2; pass++) { nn = 0; - while (fgets(buffer, sizeof(buffer), fp) != NULL) { + while (fgets(buffer, sizeof(buffer), fp) != 0) { if ((s = stripped(buffer)) != 0) { if (dst != 0) dst[nn] = s; @@ -404,7 +514,8 @@ make_namelist(char *src) } } if (pass == 1) { - dst = typeCalloc(char *, nn + 1); + if ((dst = typeCalloc(char *, nn + 1)) == NULL) + failed("make_namelist"); rewind(fp); } } @@ -426,8 +537,10 @@ make_namelist(char *src) if (mark == '\0') break; } - if (pass == 1) - dst = typeCalloc(char *, nn + 1); + if (pass == 1) { + if ((dst = typeCalloc(char *, nn + 1)) == NULL) + failed("make_namelist"); + } } } if (showsummary && (dst != 0)) { @@ -443,9 +556,10 @@ matches(char **needle, const char *haystack) /* does entry in needle list match |-separated field in haystack? */ { bool code = FALSE; - size_t n; if (needle != 0) { + size_t n; + for (n = 0; needle[n] != 0; n++) { if (_nc_name_match(haystack, needle[n], "|")) { code = TRUE; @@ -457,26 +571,120 @@ matches(char **needle, const char *haystack) return (code); } -static FILE * -open_tempfile(char *name) +static char * +valid_db_path(const char *nominal) { - FILE *result = 0; -#if HAVE_MKSTEMP - int fd = mkstemp(name); - if (fd >= 0) - result = fdopen(fd, "w"); + struct stat sb; +#if USE_HASHED_DB + char suffix[] = DBM_SUFFIX; + size_t need = strlen(nominal) + sizeof(suffix); + char *result = malloc(need); + + if (result == NULL) + failed("valid_db_path"); + _nc_STRCPY(result, nominal, need); + if (strcmp(result + need - sizeof(suffix), suffix)) { + _nc_STRCAT(result, suffix, need); + } +#else + char *result = strdup(nominal); +#endif + + DEBUG(1, ("** stat(%s)", result)); + if (stat(result, &sb) >= 0) { +#if USE_HASHED_DB + if (!S_ISREG(sb.st_mode) + || access(result, R_OK | W_OK) != 0) { + DEBUG(1, ("...not a writable file")); + free(result); + result = 0; + } #else - if (tmpnam(name) != 0) - result = fopen(name, "w"); + if (!S_ISDIR(sb.st_mode) + || access(result, R_OK | W_OK | X_OK) != 0) { + DEBUG(1, ("...not a writable directory")); + free(result); + result = 0; + } #endif + } else { + /* check if parent is directory and is writable */ + unsigned leaf = _nc_pathlast(result); + + DEBUG(1, ("...not found")); + if (leaf) { + char save = result[leaf]; + result[leaf] = 0; + if (stat(result, &sb) >= 0 + && S_ISDIR(sb.st_mode) + && access(result, R_OK | W_OK | X_OK) == 0) { + result[leaf] = save; + } else { + DEBUG(1, ("...parent directory %s is not writable", result)); + free(result); + result = 0; + } + } else { + DEBUG(1, ("... no parent directory")); + free(result); + result = 0; + } + } return result; } +/* + * Show the databases to which tic could write. The location to which it + * writes is always the first one. If none are writable, print an error + * message. + */ +static void +show_databases(const char *outdir) +{ + bool specific = (outdir != 0) || getenv("TERMINFO") != 0; + char *result; + const char *tried = 0; + + if (outdir == NULL) { + outdir = _nc_tic_dir(NULL); + } + if ((result = valid_db_path(outdir)) != 0) { + printf("%s\n", result); + free(result); + } else { + tried = outdir; + } + + if ((outdir = _nc_home_terminfo())) { + if ((result = valid_db_path(outdir)) != 0) { + printf("%s\n", result); + free(result); + } else if (!specific) { + tried = outdir; + } + } + + /* + * If we can write in neither location, give an error message. + */ + if (tried) { + fflush(stdout); + fprintf(stderr, "%s: %s (no permission)\n", _nc_progname, tried); + ExitProgram(EXIT_FAILURE); + } +} + +static void +add_digit(int *target, int source) +{ + *target = (*target * 10) + (source - '0'); +} + int main(int argc, char *argv[]) { char my_tmpname[PATH_MAX]; - int v_opt = -1, debug_level; + int v_opt = -1; int smart_defaults = TRUE; char *termcap; ENTRY *qp; @@ -487,6 +695,7 @@ main(int argc, char *argv[]) int sortmode = S_TERMINFO; /* sort_mode */ int width = 60; + int height = 65535; bool formatted = FALSE; /* reformat complex strings? */ bool literal = FALSE; /* suppress post-processing? */ int numbers = 0; /* format "%'char'" to/from "%{number}" */ @@ -494,31 +703,36 @@ main(int argc, char *argv[]) bool limited = TRUE; char *tversion = (char *) NULL; const char *source_file = "terminfo"; - char **namelst = 0; char *outdir = (char *) NULL; bool check_only = FALSE; bool suppress_untranslatable = FALSE; + int quickdump = 0; + bool quiet = FALSE; + bool wrap_strings = FALSE; if (pledge("stdio rpath wpath cpath", NULL) == -1) { - perror("pledge"); - exit(1); + perror("pledge"); + exit(1); } log_fp = stderr; _nc_progname = _nc_rootname(argv[0]); + atexit(cleanup); - if ((infodump = (strcmp(_nc_progname, PROG_CAPTOINFO) == 0)) != FALSE) { + if ((infodump = same_program(_nc_progname, PROG_CAPTOINFO)) != FALSE) { outform = F_TERMINFO; sortmode = S_TERMINFO; } - if ((capdump = (strcmp(_nc_progname, PROG_INFOTOCAP) == 0)) != FALSE) { + if ((capdump = same_program(_nc_progname, PROG_INFOTOCAP)) != FALSE) { outform = F_TERMCAP; sortmode = S_TERMCAP; } #if NCURSES_XNAMES - use_extended_names(FALSE); + /* set this directly to avoid interaction with -v and -D options */ + _nc_user_definable = FALSE; #endif + _nc_strict_bsd = 0; /* * Processing arguments is a little complicated, since someone made a @@ -526,29 +740,53 @@ main(int argc, char *argv[]) * be optional. */ while ((this_opt = getopt(argc, argv, - "0123456789CILNR:TUVace:fGgo:rstvwx")) != -1) { + "0123456789CDIKLNQR:TUVWace:fGgo:qrstvwx")) != -1) { if (isdigit(this_opt)) { switch (last_opt) { + case 'Q': + add_digit(&quickdump, this_opt); + break; case 'v': - v_opt = (v_opt * 10) + (this_opt - '0'); + add_digit(&v_opt, this_opt); break; case 'w': - width = (width * 10) + (this_opt - '0'); + add_digit(&width, this_opt); break; default: - if (this_opt != '1') + switch (this_opt) { + case '0': + last_opt = this_opt; + width = 65535; + height = 1; + break; + case '1': + last_opt = this_opt; + width = 0; + break; + default: usage(); - last_opt = this_opt; - width = 0; + } } continue; } switch (this_opt) { + case 'K': + _nc_strict_bsd = 1; + /* the initial version of -K in 20110730 fell-thru here, but the + * same flag is useful when reading sources -TD + */ + break; case 'C': capdump = TRUE; outform = F_TERMCAP; sortmode = S_TERMCAP; break; + case 'D': + debug_level = VtoTrace(v_opt); + use_verbosity(debug_level); + show_databases(outdir); + ExitProgram(EXIT_SUCCESS); + break; case 'I': infodump = TRUE; outform = F_TERMINFO; @@ -563,6 +801,9 @@ main(int argc, char *argv[]) smart_defaults = FALSE; literal = TRUE; break; + case 'Q': + quickdump = 0; + break; case 'R': tversion = optarg; break; @@ -574,8 +815,10 @@ main(int argc, char *argv[]) break; case 'V': puts(curses_version()); - cleanup(namelst); ExitProgram(EXIT_SUCCESS); + case 'W': + wrap_strings = TRUE; + break; case 'c': check_only = TRUE; break; @@ -594,6 +837,9 @@ main(int argc, char *argv[]) case 'o': outdir = optarg; break; + case 'q': + quiet = TRUE; + break; case 'r': forceresolve = TRUE; break; @@ -615,7 +861,7 @@ main(int argc, char *argv[]) _nc_disable_period = TRUE; /* FALLTHRU */ case 'x': - use_extended_names(TRUE); + using_extensions = TRUE; break; #endif default: @@ -624,8 +870,23 @@ main(int argc, char *argv[]) last_opt = this_opt; } - debug_level = (v_opt > 0) ? v_opt : (v_opt == 0); - set_trace_level(debug_level); + /* + * If the -v option is set, it may override the $NCURSES_TRACE environment + * variable, e.g., for -v3 and up. + */ + debug_level = VtoTrace(v_opt); + use_verbosity(debug_level); + + /* + * Do this after setting debug_level, since the function calls START_TRACE, + * which uses the $NCURSES_TRACE environment variable if _nc_tracing bits + * for tracing are zero. + */ +#if NCURSES_XNAMES + if (using_extensions) { + use_extended_names(TRUE); + } +#endif if (_nc_tracing) { save_check_termtype = _nc_check_termtype2; @@ -638,14 +899,14 @@ main(int argc, char *argv[]) * One problem with immedhook is it means we can't do -e. Problem * is that we can't guarantee that for each terminal listed, all the * terminals it depends on will have been kept in core for reference - * resolution -- in fact it's certain the primitive types at the end + * resolution -- in fact it is certain the primitive types at the end * of reference chains *won't* be in core unless they were explicitly * in the select list themselves. */ if (namelst && (!infodump && !capdump)) { (void) fprintf(stderr, - "Sorry, -e can't be used without -I or -C\n"); - cleanup(namelst); + "%s: Sorry, -e can't be used without -I or -C\n", + _nc_progname); ExitProgram(EXIT_FAILURE); } #endif /* HAVE_BIG_CORE */ @@ -666,18 +927,19 @@ main(int argc, char *argv[]) source_file = "/etc/termcap"; if ((termcap = getenv("TERMCAP")) != 0 && (namelst = make_namelist(getenv("TERM"))) != 0) { - strlcpy(my_tmpname, "/tmp/XXXXXXXXXX", sizeof my_tmpname); if (access(termcap, F_OK) == 0) { /* file exists */ source_file = termcap; - } else if ((tmp_fp = open_tempfile(my_tmpname)) != 0) { - source_file = my_tmpname; - fprintf(tmp_fp, "%s\n", termcap); - fclose(tmp_fp); - tmp_fp = open_input(source_file); - to_remove = source_file; } else { - failed("tmpnam"); + if ((tmp_fp = open_tempfile(my_tmpname)) != 0) { + source_file = my_tmpname; + fprintf(tmp_fp, "%s\n", termcap); + fclose(tmp_fp); + tmp_fp = open_input(source_file, (char *) 0); + to_remove = source_file; + } else { + failed("tmpnam"); + } } } } else { @@ -687,24 +949,33 @@ main(int argc, char *argv[]) _nc_progname, _nc_progname, usage_string); - cleanup(namelst); ExitProgram(EXIT_FAILURE); } } - if (tmp_fp == 0) - tmp_fp = open_input(source_file); + if (tmp_fp == NULL) { + char my_altfile[PATH_MAX]; + tmp_fp = open_input(source_file, my_altfile); + if (!strcmp(source_file, "-")) { + source_file = STDIN_NAME; + } + } - if (infodump) + if (infodump || check_only) { dump_init(tversion, - smart_defaults - ? outform - : F_LITERAL, - sortmode, width, debug_level, formatted); - else if (capdump) + (smart_defaults + ? outform + : F_LITERAL), + sortmode, + wrap_strings, width, height, + debug_level, formatted || check_only, check_only, quickdump); + } else if (capdump) { dump_init(tversion, outform, - sortmode, width, debug_level, FALSE); + sortmode, + wrap_strings, width, height, + debug_level, FALSE, FALSE, FALSE); + } /* parse entries out of the source file */ _nc_set_source(source_file); @@ -721,20 +992,20 @@ main(int argc, char *argv[]) /* do use resolution */ if (check_only || (!infodump && !capdump) || forceresolve) { if (!_nc_resolve_uses2(TRUE, literal) && !check_only) { - cleanup(namelst); ExitProgram(EXIT_FAILURE); } } /* length check */ - if (check_only && (capdump || infodump)) { + if (check_only && limited && (capdump || infodump)) { for_entry_list(qp) { if (matches(namelst, qp->tterm.term_names)) { int len = fmt_entry(&qp->tterm, NULL, FALSE, TRUE, infodump, numbers); if (len > (infodump ? MAX_TERMINFO_LENGTH : MAX_TERMCAP_LENGTH)) (void) fprintf(stderr, - "warning: resolved %s entry is %d bytes long\n", + "%s: resolved %s entry is %d bytes long\n", + _nc_progname, _nc_first_name(qp->tterm.term_names), len); } @@ -742,7 +1013,21 @@ main(int argc, char *argv[]) } /* write or dump all entries */ - if (!check_only) { + if (check_only) { + /* this is in case infotocap() generates warnings */ + _nc_curr_col = _nc_curr_line = -1; + + for_entry_list(qp) { + if (matches(namelst, qp->tterm.term_names)) { + /* this is in case infotocap() generates warnings */ + _nc_set_type(_nc_first_name(qp->tterm.term_names)); + _nc_curr_line = (int) qp->startline; + repair_acsc(&qp->tterm); + dump_entry(&qp->tterm, suppress_untranslatable, + limited, numbers, NULL); + } + } + } else { if (!infodump && !capdump) { _nc_set_writedir(outdir); for_entry_list(qp) { @@ -755,30 +1040,37 @@ main(int argc, char *argv[]) for_entry_list(qp) { if (matches(namelst, qp->tterm.term_names)) { - int j = qp->cend - qp->cstart; + long j = qp->cend - qp->cstart; int len = 0; /* this is in case infotocap() generates warnings */ _nc_set_type(_nc_first_name(qp->tterm.term_names)); - (void) fseek(tmp_fp, qp->cstart, SEEK_SET); - while (j-- > 0) { - if (infodump) - (void) putchar(fgetc(tmp_fp)); - else - put_translate(fgetc(tmp_fp)); + if (!quiet) { + (void) fseek(tmp_fp, qp->cstart, SEEK_SET); + while (j-- > 0) { + int ch = fgetc(tmp_fp); + if (ch == EOF || ferror(tmp_fp)) { + break; + } else if (infodump) { + (void) putchar(ch); + } else { + put_translate(ch); + } + } } + repair_acsc(&qp->tterm); dump_entry(&qp->tterm, suppress_untranslatable, limited, numbers, NULL); - for (j = 0; j < (int) qp->nuses; j++) + for (j = 0; j < (long) qp->nuses; j++) dump_uses(qp->uses[j].name, !capdump); len = show_entry(); if (debug_level != 0 && !limited) printf("# length=%d\n", len); } } - if (!namelst && _nc_tail) { + if (!namelst && _nc_tail && !quiet) { int c, oldc = '\0'; bool in_comment = FALSE; bool trailing_comment = FALSE; @@ -811,11 +1103,10 @@ main(int argc, char *argv[]) if (total != 0) fprintf(log_fp, "%d entries written to %s\n", total, - _nc_tic_dir((char *) 0)); + _nc_tic_dir(NULL)); else fprintf(log_fp, "No entries written\n"); } - cleanup(namelst); ExitProgram(EXIT_SUCCESS); } @@ -831,8 +1122,52 @@ main(int argc, char *argv[]) * Check if the alternate character-set capabilities are consistent. */ static void -check_acs(TERMTYPE *tp) +check_acs(TERMTYPE2 *tp) { + int vt100_smacs = 0; + int vt100_rmacs = 0; + int vt100_enacs = 0; + + /* + * ena_acs is not always necessary, but if it is present, the enter/exit + * capabilities should be. + */ + ANDMISSING(ena_acs, enter_alt_charset_mode); + ANDMISSING(ena_acs, exit_alt_charset_mode); + PAIRED(exit_alt_charset_mode, exit_alt_charset_mode); + + /* + * vt100-like is frequently used, but perhaps ena_acs is missing, etc. + */ + if (VALID_STRING(enter_alt_charset_mode)) { + vt100_smacs = (!strcmp("\033(0", enter_alt_charset_mode) + ? 2 + : (!strcmp("\016", enter_alt_charset_mode) + ? 1 + : 0)); + } + if (VALID_STRING(exit_alt_charset_mode)) { + vt100_rmacs = (!strcmp("\033(B", exit_alt_charset_mode) + ? 2 + : (!strcmp("\017", exit_alt_charset_mode) + ? 1 + : 0)); + } + if (VALID_STRING(ena_acs)) { + vt100_enacs = (!strcmp("\033(B\033)0", ena_acs) + ? 2 + : 0); + } + if (vt100_rmacs && vt100_smacs && (vt100_rmacs != vt100_smacs)) { + _nc_warning("rmacs/smacs are inconsistent"); + } + if ((vt100_rmacs == 2) && (vt100_smacs == 2) && vt100_enacs) { + _nc_warning("rmacs/smacs make enacs redundant"); + } + if ((vt100_rmacs == 1) && (vt100_smacs == 1) && !vt100_enacs) { + _nc_warning("VT100-style rmacs/smacs require enacs"); + } + if (VALID_STRING(acs_chars)) { const char *boxes = "lmkjtuvwqxn"; char mapped[256]; @@ -841,6 +1176,7 @@ check_acs(TERMTYPE *tp) char *q; memset(mapped, 0, sizeof(mapped)); + memset(missing, 0, sizeof(missing)); for (p = acs_chars; *p != '\0'; p += 2) { if (p[1] == '\0') { _nc_warning("acsc has odd number of characters"); @@ -867,14 +1203,45 @@ check_acs(TERMTYPE *tp) } } +static char * +safe_strdup(const char *value) +{ + if (value == NULL) + value = ""; + return strdup(value); +} + +static bool +same_color(NCURSES_CONST char *oldcap, NCURSES_CONST char *newcap, int limit) +{ + bool result = FALSE; + if (limit > 16) + limit = 16; + if (limit >= 8) { + int n; + int same; + for (n = same = 0; n < limit; ++n) { + char *oldvalue = safe_strdup(TIPARM_1(oldcap, n)); + char *newvalue = safe_strdup(TIPARM_1(newcap, n)); + same += !strcmp(oldvalue, newvalue); + free(oldvalue); + free(newvalue); + } + result = (same == limit); + } + return result; +} + /* * Check if the color capabilities are consistent */ static void -check_colors(TERMTYPE *tp) +check_colors(TERMTYPE2 *tp) { + char *value; + if ((max_colors > 0) != (max_pairs > 0) - || ((max_colors > max_pairs) && (initialize_pair == 0))) + || ((max_colors > max_pairs) && !VALID_STRING(initialize_pair))) _nc_warning("inconsistent values for max_colors (%d) and max_pairs (%d)", max_colors, max_pairs); @@ -883,25 +1250,66 @@ check_colors(TERMTYPE *tp) PAIRED(set_color_pair, initialize_pair); if (VALID_STRING(set_foreground) - && VALID_STRING(set_a_foreground) - && !_nc_capcmp(set_foreground, set_a_foreground)) - _nc_warning("expected setf/setaf to be different"); + && VALID_STRING(set_a_foreground)) { + if (!_nc_capcmp(set_foreground, set_a_foreground)) { + _nc_warning("expected setf/setaf to be different"); + } else if (same_color(set_foreground, set_a_foreground, max_colors)) { + _nc_warning("setf/setaf are equivalent"); + } + } if (VALID_STRING(set_background) - && VALID_STRING(set_a_background) - && !_nc_capcmp(set_background, set_a_background)) - _nc_warning("expected setb/setab to be different"); + && VALID_STRING(set_a_background)) { + if (!_nc_capcmp(set_background, set_a_background)) { + _nc_warning("expected setb/setab to be different"); + } else if (same_color(set_background, set_a_background, max_colors)) { + _nc_warning("setb/setab are equivalent"); + } + } /* see: has_colors() */ if (VALID_NUMERIC(max_colors) && VALID_NUMERIC(max_pairs) - && (((set_foreground != NULL) - && (set_background != NULL)) - || ((set_a_foreground != NULL) - && (set_a_background != NULL)) + && ((VALID_STRING(set_foreground) + && VALID_STRING(set_background)) + || (VALID_STRING(set_a_foreground) + && VALID_STRING(set_a_background)) || set_color_pair)) { if (!VALID_STRING(orig_pair) && !VALID_STRING(orig_colors)) _nc_warning("expected either op/oc string for resetting colors"); } + if (can_change) { + if (!VALID_STRING(initialize_pair) && + !VALID_STRING(initialize_color)) { + _nc_warning("expected initc or initp because ccc is given"); + } + } else { + if (VALID_STRING(initialize_pair) || + VALID_STRING(initialize_color)) { + _nc_warning("expected ccc because initc is given"); + } + } + value = tigetstr("RGB"); + if (VALID_STRING(value)) { + int r, g, b; + char bad; + int code = sscanf(value, "%d/%d/%d%c", &r, &g, &b, &bad); + if (code != 3 || r <= 0 || g <= 0 || b <= 0) { + _nc_warning("unexpected value for RGB capability: %s", value); + } + } +} + +static int +csi_length(const char *value) +{ + int result = 0; + + if (value[0] == '\033' && value[1] == '[') { + result = 2; + } else if (UChar(value[0]) == 0x9a) { + result = 1; + } + return result; } static char @@ -919,29 +1327,224 @@ keypad_final(const char *string) return result; } -static int +static long keypad_index(const char *string) { - char *test; - const char *list = "PQRSwxymtuvlqrsPpn"; /* app-keypad except "Enter" */ int ch; - int result = -1; + long result = -1; if ((ch = keypad_final(string)) != '\0') { - test = strchr(list, ch); + const char *list = "PQRSwxymtuvlqrsPpn"; /* app-keypad except "Enter" */ + char *test = (strchr) (list, ch); if (test != 0) - result = (test - list); + result = (long) (test - list); } return result; } +/* + * list[] is down, up, left, right + * "left" may be ^H rather than \E[D + * "down" may be ^J rather than \E[B + * But up/right are generally consistently escape sequences for ANSI terminals. + */ +static void +check_ansi_cursor(char *list[4]) +{ + int j, k; + bool skip[4]; + bool repeated = FALSE; + + for (j = 0; j < 4; ++j) { + skip[j] = FALSE; + for (k = 0; k < j; ++k) { + if (!strcmp(list[j], list[k])) { + char *value = _nc_tic_expand(list[k], TRUE, 0); + _nc_warning("repeated cursor control %s", value); + repeated = TRUE; + } + } + } + if (!repeated) { + char *up = list[1]; + size_t prefix = (size_t) csi_length(up); + size_t suffix; + + if (prefix) { + suffix = prefix; + while (up[suffix] && isdigit(UChar(up[suffix]))) + ++suffix; + } + if (prefix && up[suffix] == 'A') { + skip[1] = TRUE; + if (!strcmp(list[0], "\n")) + skip[0] = TRUE; + if (!strcmp(list[2], "\b")) + skip[2] = TRUE; + + for (j = 0; j < 4; ++j) { + int want; + + if (skip[j] || strlen(list[j]) == 1) + continue; + if (memcmp(list[j], up, prefix)) { + char *value = _nc_tic_expand(list[j], TRUE, 0); + _nc_warning("inconsistent prefix for %s", value); + continue; + } + if (strlen(list[j]) < suffix) { + char *value = _nc_tic_expand(list[j], TRUE, 0); + _nc_warning("inconsistent length for %s, expected %d", + value, (int) suffix + 1); + continue; + } + want = "BADC"[j]; + if (list[j][suffix] != want) { + char *value = _nc_tic_expand(list[j], TRUE, 0); + _nc_warning("inconsistent suffix for %s, expected %c, have %c", + value, want, list[j][suffix]); + } + } + } + } +} + +#define EXPECTED(name) if (!PRESENT(name)) _nc_warning("expected " #name) +#define UNEXPECTED(name) if (PRESENT(name)) _nc_warning("unexpected " #name ", for %s", why) + +static void +check_noaddress(TERMTYPE2 *tp, const char *why) +{ + UNEXPECTED(column_address); + UNEXPECTED(cursor_address); + UNEXPECTED(cursor_home); + UNEXPECTED(cursor_mem_address); + UNEXPECTED(cursor_to_ll); + UNEXPECTED(row_address); + UNEXPECTED(row_address); +} + +static void +check_cursor(TERMTYPE2 *tp) +{ + int count; + char *list[4]; + + if (hard_copy) { + check_noaddress(tp, "hard_copy"); + } else if (generic_type) { + check_noaddress(tp, "generic_type"); + } else if (strchr(tp->term_names, '+') == NULL) { + int y = 0; + int x = 0; + if (PRESENT(column_address)) + ++y; + if (PRESENT(cursor_address)) + y = x = 10; + if (PRESENT(cursor_home)) + ++y, ++x; + if (PRESENT(cursor_mem_address)) + y = x = 10; + if (PRESENT(cursor_to_ll)) + ++y, ++x; + if (PRESENT(row_address)) + ++x; + if (PRESENT(cursor_down)) + ++y; + if (PRESENT(cursor_up)) + ++y; + if (PRESENT(cursor_left)) + ++x; + if (PRESENT(cursor_right)) + ++x; + if (x < 2 && y < 2) { + _nc_warning("terminal lacks cursor addressing"); + } else { + if (x < 2) + _nc_warning("terminal lacks cursor column-addressing"); + if (y < 2) + _nc_warning("terminal lacks cursor row-addressing"); + } + } + + /* it is rare to have an insert-line feature without a matching delete */ + ANDMISSING(parm_insert_line, insert_line); + ANDMISSING(parm_delete_line, delete_line); + ANDMISSING(parm_insert_line, parm_delete_line); + + /* if we have a parameterized form, then the non-parameterized is easy */ + ANDMISSING(parm_down_cursor, cursor_down); + ANDMISSING(parm_up_cursor, cursor_up); + ANDMISSING(parm_left_cursor, cursor_left); + ANDMISSING(parm_right_cursor, cursor_right); + + /* Given any of a set of cursor movement, the whole set should be present. + * Technically this is not true (we could use cursor_address to fill in + * unsupported controls), but it is likely. + */ + count = 0; + if (PRESENT(parm_down_cursor)) { + list[count++] = parm_down_cursor; + } + if (PRESENT(parm_up_cursor)) { + list[count++] = parm_up_cursor; + } + if (PRESENT(parm_left_cursor)) { + list[count++] = parm_left_cursor; + } + if (PRESENT(parm_right_cursor)) { + list[count++] = parm_right_cursor; + } + if (count == 4) { + check_ansi_cursor(list); + } else if (count != 0) { + EXPECTED(parm_down_cursor); + EXPECTED(parm_up_cursor); + EXPECTED(parm_left_cursor); + EXPECTED(parm_right_cursor); + } + + count = 0; + if (PRESENT(cursor_down)) { + list[count++] = cursor_down; + } + if (PRESENT(cursor_up)) { + list[count++] = cursor_up; + } + if (PRESENT(cursor_left)) { + list[count++] = cursor_left; + } + if (PRESENT(cursor_right)) { + list[count++] = cursor_right; + } + if (count == 4) { + check_ansi_cursor(list); + } else if (count != 0) { + count = 0; + if (PRESENT(cursor_down) && strcmp(cursor_down, "\n")) + ++count; + if (PRESENT(cursor_left) && strcmp(cursor_left, "\b")) + ++count; + if (PRESENT(cursor_up) && strlen(cursor_up) > 1) + ++count; + if (PRESENT(cursor_right) && strlen(cursor_right) > 1) + ++count; + if (count) { + EXPECTED(cursor_down); + EXPECTED(cursor_up); + EXPECTED(cursor_left); + EXPECTED(cursor_right); + } + } +} + #define MAX_KP 5 /* * Do a quick sanity-check for vt100-style keypads to see if the 5-key keypad * is mapped inconsistently. */ static void -check_keypad(TERMTYPE *tp) +check_keypad(TERMTYPE2 *tp) { char show[80]; @@ -951,11 +1554,9 @@ check_keypad(TERMTYPE *tp) VALID_STRING(key_c1) && VALID_STRING(key_c3)) { char final[MAX_KP + 1]; - int list[MAX_KP]; + long list[MAX_KP]; int increase = 0; - int j, k, kk; - int last; - int test; + int j; final[0] = keypad_final(key_a1); final[1] = keypad_final(key_a3); @@ -988,10 +1589,17 @@ check_keypad(TERMTYPE *tp) ++increase; } } + if (increase != (MAX_KP - 1)) { + long last; + show[0] = '\0'; for (j = 0, last = -1; j < MAX_KP; ++j) { + int k; + int kk; + long test; + for (k = 0, kk = -1, test = 100; k < 5; ++k) { if (list[k] > last && list[k] < test) { @@ -1003,19 +1611,19 @@ check_keypad(TERMTYPE *tp) assert(strlen(show) < (MAX_KP * 4)); switch (kk) { case 0: - strlcat(show, " ka1", sizeof(show)); + _nc_STRCAT(show, " ka1", sizeof(show)); break; case 1: - strlcat(show, " ka3", sizeof(show)); + _nc_STRCAT(show, " ka3", sizeof(show)); break; case 2: - strlcat(show, " kb2", sizeof(show)); + _nc_STRCAT(show, " kb2", sizeof(show)); break; case 3: - strlcat(show, " kc1", sizeof(show)); + _nc_STRCAT(show, " kc1", sizeof(show)); break; case 4: - strlcat(show, " kc3", sizeof(show)); + _nc_STRCAT(show, " kc3", sizeof(show)); break; } } @@ -1030,132 +1638,386 @@ check_keypad(TERMTYPE *tp) VALID_STRING(key_c3)) { show[0] = '\0'; if (keypad_index(key_a1) >= 0) - strlcat(show, " ka1", sizeof(show)); + _nc_STRCAT(show, " ka1", sizeof(show)); if (keypad_index(key_a3) >= 0) - strlcat(show, " ka3", sizeof(show)); + _nc_STRCAT(show, " ka3", sizeof(show)); if (keypad_index(key_b2) >= 0) - strlcat(show, " kb2", sizeof(show)); + _nc_STRCAT(show, " kb2", sizeof(show)); if (keypad_index(key_c1) >= 0) - strlcat(show, " kc1", sizeof(show)); + _nc_STRCAT(show, " kc1", sizeof(show)); if (keypad_index(key_c3) >= 0) - strlcat(show, " kc3", sizeof(show)); + _nc_STRCAT(show, " kc3", sizeof(show)); if (*show != '\0') _nc_warning("vt100 keypad map incomplete:%s", show); } -} - -/* - * Returns the expected number of parameters for the given capability. - */ -static int -expected_params(const char *name) -{ - /* *INDENT-OFF* */ - static const struct { - const char *name; - int count; - } table[] = { - { "S0", 1 }, /* 'screen' extension */ - { "birep", 2 }, - { "chr", 1 }, - { "colornm", 1 }, - { "cpi", 1 }, - { "csnm", 1 }, - { "csr", 2 }, - { "cub", 1 }, - { "cud", 1 }, - { "cuf", 1 }, - { "cup", 2 }, - { "cuu", 1 }, - { "cvr", 1 }, - { "cwin", 5 }, - { "dch", 1 }, - { "defc", 3 }, - { "dial", 1 }, - { "dispc", 1 }, - { "dl", 1 }, - { "ech", 1 }, - { "getm", 1 }, - { "hpa", 1 }, - { "ich", 1 }, - { "il", 1 }, - { "indn", 1 }, - { "initc", 4 }, - { "initp", 7 }, - { "lpi", 1 }, - { "mc5p", 1 }, - { "mrcup", 2 }, - { "mvpa", 1 }, - { "pfkey", 2 }, - { "pfloc", 2 }, - { "pfx", 2 }, - { "pfxl", 3 }, - { "pln", 2 }, - { "qdial", 1 }, - { "rcsd", 1 }, - { "rep", 2 }, - { "rin", 1 }, - { "sclk", 3 }, - { "scp", 1 }, - { "scs", 1 }, - { "scsd", 2 }, - { "setab", 1 }, - { "setaf", 1 }, - { "setb", 1 }, - { "setcolor", 1 }, - { "setf", 1 }, - { "sgr", 9 }, - { "sgr1", 6 }, - { "slength", 1 }, - { "slines", 1 }, - { "smgbp", 1 }, /* 2 if smgtp is not given */ - { "smglp", 1 }, - { "smglr", 2 }, - { "smgrp", 1 }, - { "smgtb", 2 }, - { "smgtp", 1 }, - { "tsl", 1 }, - { "u6", -1 }, - { "vpa", 1 }, - { "wind", 4 }, - { "wingo", 1 }, - }; - /* *INDENT-ON* */ - - unsigned n; - int result = 0; /* function-keys, etc., use none */ - - for (n = 0; n < SIZEOF(table); n++) { - if (!strcmp(name, table[n].name)) { - result = table[n].count; - break; - } - } - return result; + /* + * These warnings are useful for consistency checks - it is possible that + * there are real terminals with mismatches in these + */ + ANDMISSING(key_ic, key_dc); } -/* - * Make a quick sanity check for the parameters which are used in the given - * strings. If there are no "%p" tokens, then there should be no other "%" - * markers. - */ static void -check_params(TERMTYPE *tp, const char *name, char *value) +check_printer(TERMTYPE2 *tp) { - int expected = expected_params(name); - int actual = 0; - int n; - bool params[10]; - char *s = value; - -#ifdef set_top_margin_parm - if (!strcmp(name, "smgbp") - && set_top_margin_parm == 0) + (void) tp; +#if defined(enter_doublewide_mode) && defined(exit_doublewide_mode) + PAIRED(enter_doublewide_mode, exit_doublewide_mode); +#endif +#if defined(enter_italics_mode) && defined(exit_italics_mode) + PAIRED(enter_italics_mode, exit_italics_mode); +#endif +#if defined(enter_leftward_mode) && defined(exit_leftward_mode) + PAIRED(enter_leftward_mode, exit_leftward_mode); +#endif +#if defined(enter_micro_mode) && defined(exit_micro_mode) + PAIRED(enter_micro_mode, exit_micro_mode); +#endif +#if defined(enter_shadow_mode) && defined(exit_shadow_mode) + PAIRED(enter_shadow_mode, exit_shadow_mode); +#endif +#if defined(enter_subscript_mode) && defined(exit_subscript_mode) + PAIRED(enter_subscript_mode, exit_subscript_mode); +#endif +#if defined(enter_superscript_mode) && defined(exit_superscript_mode) + PAIRED(enter_superscript_mode, exit_superscript_mode); +#endif +#if defined(enter_upward_mode) && defined(exit_upward_mode) + PAIRED(enter_upward_mode, exit_upward_mode); +#endif + +#if defined(start_char_set_def) && defined(stop_char_set_def) + ANDMISSING(start_char_set_def, stop_char_set_def); +#endif + + /* + * If we have a parameterized form, then the non-parameterized is easy. + * note: parameterized/non-parameterized margin settings are unrelated. + */ +#if defined(parm_down_micro) && defined(micro_down) + ANDMISSING(parm_down_micro, micro_down); +#endif +#if defined(parm_left_micro) && defined(micro_left) + ANDMISSING(parm_left_micro, micro_left); +#endif +#if defined(parm_right_micro) && defined(micro_right) + ANDMISSING(parm_right_micro, micro_right); +#endif +#if defined(parm_up_micro) && defined(micro_up) + ANDMISSING(parm_up_micro, micro_up); +#endif +} + +#if NCURSES_XNAMES +static bool +uses_SGR_39_49(const char *value) +{ + return (strstr(value, "39;49") != 0 + || strstr(value, "49;39") != 0); +} + +/* + * Check consistency of termcap extensions related to "screen". + */ +static void +check_screen(TERMTYPE2 *tp) +{ + if (_nc_user_definable) { + int have_XT = tigetflag("XT"); + int have_XM = tigetflag("XM"); + int have_bce = back_color_erase; + bool have_kmouse = FALSE; + bool use_sgr_39_49 = FALSE; + const char *name_39_49 = "orig_pair or orig_colors"; + char *name = _nc_first_name(tp->term_names); + bool is_screen = !strncmp(name, "screen", 6); + bool screen_base = (is_screen + && strchr(name, '.') == NULL); + + if (!VALID_BOOLEAN(have_bce)) { + have_bce = FALSE; + } + if (!VALID_BOOLEAN(have_XM)) { + have_XM = FALSE; + } + if (!VALID_BOOLEAN(have_XT)) { + have_XT = FALSE; + } + if (VALID_STRING(key_mouse)) { + have_kmouse = !strcmp("\033[M", key_mouse); + } + if (have_bce) { + if (VALID_STRING(orig_pair)) { + name_39_49 = "orig_pair"; + use_sgr_39_49 = uses_SGR_39_49(orig_pair); + } + if (!use_sgr_39_49 && VALID_STRING(orig_colors)) { + name_39_49 = "orig_colors"; + use_sgr_39_49 = uses_SGR_39_49(orig_colors); + } + } + + if (have_XM && have_XT) { + _nc_warning("screen's XT capability conflicts with XM"); + } else if (have_XT && screen_base) { + _nc_warning("screen's \"screen\" entries should not have XT set"); + } else if (have_XT) { + char *s; + + if (!have_kmouse && is_screen) { + if (VALID_STRING(key_mouse)) { + _nc_warning("value of kmous inconsistent with screen's usage"); + } else { + _nc_warning("expected kmous capability with XT"); + } + } + if (max_colors > 0) { + if (!have_bce) { + _nc_warning("expected bce capability with XT"); + } else if (!use_sgr_39_49) { + _nc_warning("expected %s capability with XT " + "to have 39/49 parameters", name_39_49); + } + } + if (VALID_STRING(to_status_line) + && (s = strchr(to_status_line, ';')) != NULL + && *++s == '\0') + _nc_warning("\"tsl\" capability is redundant, given XT"); + } else { + if (have_kmouse + && !have_XM + && !screen_base && strchr(name, '+') == NULL) { + _nc_warning("expected XT to be set, given kmous"); + } + } + } +} +#else +#define check_screen(tp) /* nothing */ +#endif + +/* + * Returns the expected number of parameters for the given capability. + */ +static int +expected_params(const char *name) +{ +#define DATA(name,count) { { name }, count } + /* *INDENT-OFF* */ + static const struct { + const char name[9]; + int count; + } table[] = { + DATA( "S0", 1 ), /* 'screen' extension */ + DATA( "birep", 2 ), + DATA( "chr", 1 ), + DATA( "colornm", 1 ), + DATA( "cpi", 1 ), + DATA( "csnm", 1 ), + DATA( "csr", 2 ), + DATA( "cub", 1 ), + DATA( "cud", 1 ), + DATA( "cuf", 1 ), + DATA( "cup", 2 ), + DATA( "cuu", 1 ), + DATA( "cvr", 1 ), + DATA( "cwin", 5 ), + DATA( "dch", 1 ), + DATA( "defc", 3 ), + DATA( "dial", 1 ), + DATA( "dispc", 1 ), + DATA( "dl", 1 ), + DATA( "ech", 1 ), + DATA( "getm", 1 ), + DATA( "hpa", 1 ), + DATA( "ich", 1 ), + DATA( "il", 1 ), + DATA( "indn", 1 ), + DATA( "initc", 4 ), + DATA( "initp", 7 ), + DATA( "lpi", 1 ), + DATA( "mc5p", 1 ), + DATA( "mrcup", 2 ), + DATA( "mvpa", 1 ), + DATA( "pfkey", 2 ), + DATA( "pfloc", 2 ), + DATA( "pfx", 2 ), + DATA( "pfxl", 3 ), + DATA( "pln", 2 ), + DATA( "qdial", 1 ), + DATA( "rcsd", 1 ), + DATA( "rep", 2 ), + DATA( "rin", 1 ), + DATA( "sclk", 3 ), + DATA( "scp", 1 ), + DATA( "scs", 1 ), + DATA( "scsd", 2 ), + DATA( "setab", 1 ), + DATA( "setaf", 1 ), + DATA( "setb", 1 ), + DATA( "setcolor", 1 ), + DATA( "setf", 1 ), + DATA( "sgr", 9 ), + DATA( "sgr1", 6 ), + DATA( "slength", 1 ), + DATA( "slines", 1 ), + DATA( "smgbp", 1 ), /* 2 if smgtp is not given */ + DATA( "smglp", 1 ), + DATA( "smglr", 2 ), + DATA( "smgrp", 1 ), + DATA( "smgtb", 2 ), + DATA( "smgtp", 1 ), + DATA( "tsl", 1 ), + DATA( "u6", -1 ), + DATA( "vpa", 1 ), + DATA( "wind", 4 ), + DATA( "wingo", 1 ), + }; + /* *INDENT-ON* */ +#undef DATA + + unsigned n; + int result = 0; /* function-keys, etc., use none */ + + for (n = 0; n < SIZEOF(table); n++) { + if (!strcmp(name, table[n].name)) { + result = table[n].count; + break; + } + } + + return result; +} + +/* + * Check for user-capabilities that happen to be used in ncurses' terminal + * database. + */ +#if NCURSES_XNAMES +static struct user_table_entry const * +lookup_user_capability(const char *name) +{ + struct user_table_entry const *result = 0; + if (*name != 'k') { + result = _nc_find_user_entry(name); + } + return result; +} +#endif + +/* + * If a given name is likely to be a user-capability, return the number of + * parameters it would be used with. If not, return -1. + * + * ncurses assumes that u6 could be used for getting the cursor-position, but + * that is not implemented. Make a special case for that, to quiet needless + * warnings. + * + * The other string-capability extensions (see terminfo.src) which could have + * parameters such as "Ss", "%u", are not used by ncurses. But we check those + * anyway, to validate the terminfo database. + */ +static int +is_user_capability(const char *name) +{ + int result = -1; + if (name[0] == 'u' && + (name[1] >= '0' && name[1] <= '9') && + name[2] == '\0') { + result = (name[1] == '6') ? 2 : 0; + } +#if NCURSES_XNAMES + else if (using_extensions) { + struct user_table_entry const *p = lookup_user_capability(name); + if (p != 0) { + result = (int) p->ute_argc; + } + } +#endif + return result; +} + +static bool +line_capability(const char *name) +{ + bool result = FALSE; + static const char *table[] = + { + "csr", /* change_scroll_region */ + "clear", /* clear_screen */ + "ed", /* clr_eos */ + "cwin", /* create_window */ + "cup", /* cursor_address */ + "cud1", /* cursor_down */ + "home", /* cursor_home */ + "mrcup", /* cursor_mem_address */ + "ll", /* cursor_to_ll */ + "cuu1", /* cursor_up */ + "dl1", /* delete_line */ + "hd", /* down_half_line */ + "flash", /* flash_screen */ + "ff", /* form_feed */ + "il1", /* insert_line */ + "nel", /* newline */ + "dl", /* parm_delete_line */ + "cud", /* parm_down_cursor */ + "indn", /* parm_index */ + "il", /* parm_insert_line */ + "rin", /* parm_rindex */ + "cuu", /* parm_up_cursor */ + "mc0", /* print_screen */ + "vpa", /* row_address */ + "ind", /* scroll_forward */ + "ri", /* scroll_reverse */ + "hu", /* up_half_line */ + }; + size_t n; + for (n = 0; n < SIZEOF(table); ++n) { + if (!strcmp(name, table[n])) { + result = TRUE; + break; + } + } + return result; +} + +/* + * Make a quick sanity check for the parameters which are used in the given + * strings. If there are no "%p" tokens, then there should be no other "%" + * markers. + */ +static void +check_params(TERMTYPE2 *tp, const char *name, const char *value, int extended) +{ + int expected = expected_params(name); + int actual = 0; + int n; + bool params[1 + NUM_PARM]; + const char *s = value; + +#ifdef set_left_margin_parm + if (!strcmp(name, "smgrp") + && !VALID_STRING(set_left_margin_parm)) + expected = 2; +#endif +#ifdef set_right_margin_parm + if (!strcmp(name, "smglp") + && !VALID_STRING(set_right_margin_parm)) + expected = 2; +#endif +#ifdef set_top_margin_parm + if (!strcmp(name, "smgbp") + && !VALID_STRING(set_top_margin_parm)) + expected = 2; +#endif +#ifdef set_bottom_margin_parm + if (!strcmp(name, "smgtp") + && !VALID_STRING(set_bottom_margin_parm)) expected = 2; #endif - for (n = 0; n < 10; n++) + for (n = 0; n <= NUM_PARM; n++) params[n] = FALSE; while (*s != 0) { @@ -1164,7 +2026,7 @@ check_params(TERMTYPE *tp, const char *name, char *value) _nc_warning("expected character after %% in %s", name); break; } else if (*s == 'p') { - if (*++s == '\0' || !isdigit(UChar(*s))) { + if (*++s == '\0' || !isdigit((int) *s)) { _nc_warning("expected digit after %%p in %s", name); return; } else { @@ -1178,6 +2040,22 @@ check_params(TERMTYPE *tp, const char *name, char *value) s++; } +#if NCURSES_XNAMES + if (extended) { + int check = is_user_capability(name); + if (check != actual && (check >= 0 && actual >= 0)) { + _nc_warning("extended %s capability has %d parameters, expected %d", + name, actual, check); + } else if (debug_level > 1) { + _nc_warning("extended %s capability has %d parameters, as expected", + name, actual); + } + expected = actual; + } +#else + (void) extended; +#endif + if (params[0]) { _nc_warning("%s refers to parameter 0 (%%p0), which is not allowed", name); } @@ -1191,6 +2069,441 @@ check_params(TERMTYPE *tp, const char *name, char *value) _nc_warning("%s omits parameter %d", name, n); } } + + /* + * Counting "%p" markers does not account for termcap expressions which + * may not have been fully translated. Also, tparm does its own analysis. + * Report differences here. + */ + _nc_reset_tparm(NULL); + if (actual >= 0) { + char *p_is_s[NUM_PARM]; + int popcount; + int analyzed = _nc_tparm_analyze(NULL, value, p_is_s, &popcount); + if (analyzed < popcount) { + analyzed = popcount; + } + if (actual != analyzed && expected != analyzed) { +#if NCURSES_XNAMES + int user_cap = is_user_capability(name); + if ((user_cap == analyzed) && using_extensions) { + ; /* ignore */ + } else if (user_cap >= 0) { + _nc_warning("tparm will use %d parameters for %s, expected %d", + analyzed, name, user_cap); + } else +#endif + { + _nc_warning("tparm analyzed %d parameters for %s, expected %d", + analyzed, name, actual); + } + } else if (expected > 0 + && actual == expected + && guess_tparm_type(expected, p_is_s) == Numbers) { + int limit = 1; + + if (!strcmp(name, "setf") + || !strcmp(name, "setb") + || !strcmp(name, "setaf") + || !strcmp(name, "setab")) { + if ((limit = max_colors) > 256) + limit = 256; + } else if (line_capability(name)) { + limit = 24; + } else if (is_user_capability(name) < 0) { + limit = 80; + } + for (n = 0; n < limit; ++n) { + _nc_reset_tparm(NULL); + (void) TPARM_9(value, n, n, n, n, n, n, n, n, n); + if (_nc_tparm_err) { + _nc_warning("problem%s in tparm(%s, %d, ...)", + (_nc_tparm_err == 1) ? "" : "s", + name, n); + if (debug_level < 2) + break; + } + } + } + } +} + +/* + * Check for DEC VT100 private mode for reverse video. + */ +static const char * +skip_DECSCNM(const char *value, int *flag) +{ + *flag = -1; + if (value != 0) { + int skip = csi_length(value); + if (skip > 0 && + value[skip++] == '?' && + value[skip++] == '5') { + if (value[skip] == 'h') { + *flag = 1; + } else if (value[skip] == 'l') { + *flag = 0; + } + value += skip + 1; + } + } + return value; +} + +static void +check_delays(TERMTYPE2 *tp, const char *name, const char *value) +{ + const char *p, *q; + const char *first = 0; + const char *last = 0; + + for (p = value; *p != '\0'; ++p) { + if (p[0] == '$' && p[1] == '<') { + const char *base = p + 2; + const char *mark = 0; + bool mixed = FALSE; + int proportional = 0; + int mandatory = 0; + + first = p; + + for (q = base; *q != '\0'; ++q) { + if (*q == '>') { + if (mark == NULL) + mark = q; + break; + } else if (*q == '*' || *q == '/') { + if (*q == '*') + ++proportional; + if (*q == '/') + ++mandatory; + if (mark == NULL) + mark = q; + } else if (!(isalnum(UChar(*q)) || strchr("+-.", *q) != 0)) { + break; + } else if (proportional || mandatory) { + mixed = TRUE; + } + } + last = *q ? (q + 1) : q; + if (*q != '\0') { + float check_f; + char check_c; + int rc = sscanf(base, "%f%c", &check_f, &check_c); + if ((rc != 2) || (mark != NULL && (check_c != *mark)) || mixed) { + _nc_warning("syntax error in %s delay '%.*s'", name, + (int) (q - base), base); + } else if (*name == 'k') { + _nc_warning("function-key %s has delay", name); + } else if (proportional && !line_capability(name)) { + _nc_warning("non-line capability using proportional delay: %s", name); + } else if (!xon_xoff && + !mandatory && + strchr(_nc_first_name(tp->term_names), '+') == NULL) { + _nc_warning("%s in %s is used since no xon/xoff", + (proportional + ? "proportional delay" + : "delay"), + name); + } + } else { + p = q - 1; /* restart scan */ + } + } + } + + if (!strcmp(name, "flash") || + !strcmp(name, "beep")) { + + if (first != 0) { + if (first == value || *last == 0) { + /* + * Delay is on one end or the other. + */ + _nc_warning("expected delay embedded within %s", name); + } + } else { + int flag; + + /* + * Check for missing delay when using VT100 reverse-video. + * A real VT100 might not need this, but terminal emulators do. + */ + if ((p = skip_DECSCNM(value, &flag)) != 0 && + flag > 0 && + skip_DECSCNM(p, &flag) != 0 && + flag == 0) { + _nc_warning("expected a delay in %s", name); + } + } + } +} + +static char * +check_1_infotocap(const char *name, NCURSES_CONST char *value, int count) +{ + int k; + int ignored; + long numbers[1 + NUM_PARM]; + char *strings[1 + NUM_PARM]; + char *p_is_s[NUM_PARM]; + char *result; + char blob[NUM_PARM * 10]; + char *next = blob; + TParams expect; + TParams actual; + int nparam; + + *next++ = '\0'; + for (k = 1; k <= NUM_PARM; k++) { + numbers[k] = count; + _nc_SPRINTF(next, + _nc_SLIMIT(sizeof(blob) - (size_t) (next - blob)) + "XYZ%d", count); + strings[k] = next; + next += strlen(next) + 1; + } + + _nc_reset_tparm(NULL); + expect = tparm_type(name); + nparam = _nc_tparm_analyze(NULL, value, p_is_s, &ignored); + actual = guess_tparm_type(nparam, p_is_s); + + if (expect != actual) { + _nc_warning("%s has mismatched parameters", name); + actual = Other; + } + + _nc_reset_tparm(NULL); + switch (actual) { + case Str: + result = TPARM_1(value, strings[1]); + break; + case Num_Str: + result = TPARM_2(value, numbers[1], strings[2]); + break; + case Str_Str: + result = TPARM_2(value, strings[1], strings[2]); + break; + case Num_Str_Str: + result = TPARM_3(value, numbers[1], strings[2], strings[3]); + break; + case Numbers: +#define myParam(n) numbers[n] + result = TIPARM_9(value, + myParam(1), + myParam(2), + myParam(3), + myParam(4), + myParam(5), + myParam(6), + myParam(7), + myParam(8), + myParam(9)); +#undef myParam + break; + case Other: + default: +#define myParam(n) (p_is_s[n - 1] != 0 ? ((TPARM_ARG) strings[n]) : numbers[n]) + result = TPARM_9(value, + myParam(1), + myParam(2), + myParam(3), + myParam(4), + myParam(5), + myParam(6), + myParam(7), + myParam(8), + myParam(9)); +#undef myParam + break; + } + return strdup(result); +} + +#define IsDelay(ch) ((ch) == '.' || isdigit(UChar(ch))) + +static const char * +parse_delay_value(const char *src, double *delays, int *always) +{ + int star = 0; + + *delays = 0.0; + if (always) + *always = 0; + + while (isdigit(UChar(*src))) { + (*delays) = (*delays) * 10 + (*src++ - '0'); + } + if (*src == '.') { + int gotdot = 1; + + ++src; + while (isdigit(UChar(*src))) { + gotdot *= 10; + (*delays) += (*src++ - '0') / gotdot; + } + } + while (*src == '*' || *src == '/') { + if (always == NULL && *src == '/') + break; + if (*src++ == '*') { + star = 1; + } else { + *always = 1; + } + } + if (star) + *delays = -(*delays); + return src; +} + +static const char * +parse_ti_delay(const char *ti, double *delays) +{ + *delays = 0.0; + while (*ti != '\0') { + if (*ti == '\\') { + ++ti; + } + if (ti[0] == '$' + && ti[1] == '<' + && IsDelay(UChar(ti[2]))) { + int ignored; + const char *last = parse_delay_value(ti + 2, delays, &ignored); + if (*last == '>') { + ti = last; + } + } else { + ++ti; + } + } + return ti; +} + +static const char * +parse_tc_delay(const char *tc, double *delays) +{ + return parse_delay_value(tc, delays, (int *) 0); +} + +/* + * Compare terminfo- and termcap-strings, factoring out delays. + */ +static bool +same_ti_tc(const char *ti, const char *tc, bool * embedded) +{ + bool same = TRUE; + double ti_delay = 0.0; + double tc_delay = 0.0; + const char *ti_last; + + *embedded = FALSE; + ti_last = parse_ti_delay(ti, &ti_delay); + tc = parse_tc_delay(tc, &tc_delay); + + while ((ti < ti_last) && *tc) { + if (*ti == '\\' && ispunct(UChar(ti[1]))) { + ++ti; + if ((*ti == '^') && !strncmp(tc, "\\136", 4)) { + ti += 1; + tc += 4; + continue; + } + } else if (ti[0] == '$' && ti[1] == '<') { + double no_delay; + const char *ss = parse_ti_delay(ti, &no_delay); + if (ss != ti) { + *embedded = TRUE; + ti = ss; + continue; + } + } + if (*tc == '\\' && ispunct(UChar(tc[1]))) { + ++tc; + } + if (*ti++ != *tc++) { + same = FALSE; + break; + } + } + + if (*embedded) { + if (same) { + same = FALSE; + } else { + *embedded = FALSE; /* report only one problem */ + } + } + + return same; +} + +/* + * Check terminfo to termcap translation. + */ +static void +check_infotocap(TERMTYPE2 *tp, int i, const char *value) +{ + const char *name = ExtStrname(tp, i, strnames); + char *ti_value = NULL; + + assert(SIZEOF(parametrized) == STRCOUNT); + if (!VALID_STRING(value) || (ti_value = strdup(value)) == NULL) { + _nc_warning("tic-expansion of %s failed", name); + } else { + char *tc_value; + bool embedded; + int params = ((i < (int) SIZEOF(parametrized)) + ? parametrized[i] + : ((*value == 'k') + ? 0 + : has_params(value, FALSE))); + + if ((tc_value = _nc_infotocap(name, ti_value, params)) == ABSENT_STRING) { + _nc_warning("tic-conversion of %s failed", name); + } else if (params > 0) { + int limit = 5; + int count; + bool first = TRUE; + + if (!strcmp(name, "setf") + || !strcmp(name, "setb") + || !strcmp(name, "setaf") + || !strcmp(name, "setab")) { + if ((limit = max_colors) > 256) + limit = 256; + } + for (count = 0; count < limit; ++count) { + char *ti_check = check_1_infotocap(name, ti_value, count); + char *tc_check = check_1_infotocap(name, tc_value, count); + + if (strcmp(ti_check, tc_check)) { + if (first) { + fprintf(stderr, "check_infotocap(%s)\n", name); + fprintf(stderr, "...ti '%s'\n", _nc_visbuf2(0, ti_value)); + fprintf(stderr, "...tc '%s'\n", _nc_visbuf2(0, tc_value)); + first = FALSE; + } + _nc_warning("tparm-conversion of %s(%d) differs between\n\tterminfo %s\n\ttermcap %s", + name, count, + _nc_visbuf2(0, ti_check), + _nc_visbuf2(1, tc_check)); + } + free(ti_check); + free(tc_check); + } + } else if (params == 0 && !same_ti_tc(ti_value, tc_value, &embedded)) { + if (embedded) { + _nc_warning("termcap equivalent of %s cannot use embedded delay", name); + } else { + _nc_warning("tic-conversion of %s changed value\n\tfrom %s\n\tto %s", + name, ti_value, tc_value); + } + } + free(ti_value); + } } static char * @@ -1238,6 +2551,23 @@ ignore_delays(char *s) return s; } +#define DATA(name) { #name } +static const char sgr_names[][11] = +{ + DATA(none), + DATA(standout), + DATA(underline), + DATA(reverse), + DATA(blink), + DATA(dim), + DATA(bold), + DATA(invis), + DATA(protect), + DATA(altcharset), + "" +}; +#undef DATA + /* * An sgr string may contain several settings other than the one we're * interested in, essentially sgr0 + rmacs + whatever. As long as the @@ -1247,19 +2577,6 @@ ignore_delays(char *s) static bool similar_sgr(int num, char *a, char *b) { - static const char *names[] = - { - "none" - ,"standout" - ,"underline" - ,"reverse" - ,"blink" - ,"dim" - ,"bold" - ,"invis" - ,"protect" - ,"altcharset" - }; char *base_a = a; char *base_b = b; int delaying = 0; @@ -1267,12 +2584,14 @@ similar_sgr(int num, char *a, char *b) while (*b != 0) { while (*a != *b) { if (*a == 0) { - if (b[0] == '$' - && b[1] == '<') { - _nc_warning("Did not find delay %s", _nc_visbuf(b)); + if (num < 0) { + ; + } else if (b[0] == '$' + && b[1] == '<') { + _nc_warning("did not find delay %s", _nc_visbuf(b)); } else { _nc_warning("checking sgr(%s) %s\n\tcompare to %s\n\tunmatched %s", - names[num], _nc_visbuf2(1, base_a), + sgr_names[num], _nc_visbuf2(1, base_a), _nc_visbuf2(2, base_b), _nc_visbuf2(3, b)); } @@ -1280,6 +2599,8 @@ similar_sgr(int num, char *a, char *b) } else if (delaying) { a = skip_delay(a); b = skip_delay(b); + } else if ((*b == '0' || (*b == ';')) && *a == 'm') { + b++; } else { a++; } @@ -1305,22 +2626,29 @@ similar_sgr(int num, char *a, char *b) return ((num != 0) || (*a == 0)); } +static void +check_tparm_err(int num) +{ + if (_nc_tparm_err) + _nc_warning("tparam error in sgr(%d): %s", num, sgr_names[num]); +} + static char * -check_sgr(TERMTYPE *tp, char *zero, int num, char *cap, const char *name) +check_sgr(TERMTYPE2 *tp, char *zero, int num, char *cap, const char *name) { char *test; _nc_tparm_err = 0; - test = TPARM_9(set_attributes, - num == 1, - num == 2, - num == 3, - num == 4, - num == 5, - num == 6, - num == 7, - num == 8, - num == 9); + test = TIPARM_9(set_attributes, + num == 1, + num == 2, + num == 3, + num == 4, + num == 5, + num == 6, + num == 7, + num == 8, + num == 9); if (test != 0) { if (PRESENT(cap)) { if (!similar_sgr(num, test, cap)) { @@ -1335,8 +2663,7 @@ check_sgr(TERMTYPE *tp, char *zero, int num, char *cap, const char *name) } else if (PRESENT(cap)) { _nc_warning("sgr(%d) missing, but %s present", num, name); } - if (_nc_tparm_err) - _nc_warning("stack error in sgr(%d) string", num); + check_tparm_err(num); return test; } @@ -1353,9 +2680,9 @@ static void show_where(unsigned level) { if (_nc_tracing >= DEBUG_LEVEL(level)) { - char my_name[256]; + char my_name[MAX_NAME_SIZE]; _nc_get_type(my_name); - fprintf(stderr, "\"%s\", line %d, '%s' ", + _tracef("\"%s\", line %d, '%s'", _nc_get_source(), _nc_curr_line, my_name); } @@ -1365,65 +2692,557 @@ show_where(unsigned level) #define show_where(level) /* nothing */ #endif -/* other sanity-checks (things that we don't want in the normal - * logic that reads a terminfo entry) - */ +typedef struct { + int keycode; + const char *name; + const char *value; +} NAME_VALUE; + +static NAME_VALUE * +get_fkey_list(TERMTYPE2 *tp) +{ + NAME_VALUE *result = typeMalloc(NAME_VALUE, NUM_STRINGS(tp) + 1); + const struct tinfo_fkeys *all_fkeys = _nc_tinfo_fkeys; + int used = 0; + unsigned j; + + if (result == NULL) + failed("get_fkey_list"); + + for (j = 0; all_fkeys[j].code; j++) { + char *a = tp->Strings[all_fkeys[j].offset]; + if (VALID_STRING(a)) { + result[used].keycode = (int) all_fkeys[j].code; + result[used].name = strnames[all_fkeys[j].offset]; + result[used].value = a; + ++used; + } + } +#if NCURSES_XNAMES + for (j = STRCOUNT; j < NUM_STRINGS(tp); ++j) { + const char *name = ExtStrname(tp, (int) j, strnames); + if (*name == 'k') { + result[used].keycode = -1; + result[used].name = name; + result[used].value = tp->Strings[j]; + ++used; + } + } +#endif + result[used].keycode = 0; + return result; +} + static void -check_termtype(TERMTYPE *tp, bool literal) +show_fkey_name(NAME_VALUE * data) { - bool conflict = FALSE; - unsigned j, k; - char fkeys[STRCOUNT]; + if (data->keycode > 0) { + fprintf(stderr, " %s", keyname(data->keycode)); + fprintf(stderr, " (capability \"%s\")", data->name); + } else { + fprintf(stderr, " capability \"%s\"", data->name); + } +} - /* - * A terminal entry may contain more than one keycode assigned to - * a given string (e.g., KEY_END and KEY_LL). But curses will only - * return one (the last one assigned). - */ +/* + * A terminal entry may contain more than one keycode assigned to a given + * string (e.g., KEY_END and KEY_LL). But curses will only return one (the + * last one assigned). + */ +static void +check_conflict(TERMTYPE2 *tp) +{ if (!(_nc_syntax == SYN_TERMCAP && capdump)) { - memset(fkeys, 0, sizeof(fkeys)); - for (j = 0; _nc_tinfo_fkeys[j].code; j++) { - char *a = tp->Strings[_nc_tinfo_fkeys[j].offset]; + char *check = calloc((size_t) (NUM_STRINGS(tp) + 1), sizeof(char)); + NAME_VALUE *given = get_fkey_list(tp); + unsigned j, k; + bool conflict = FALSE; + + if (check == NULL) + failed("check_conflict"); + + for (j = 0; given[j].keycode; ++j) { + const char *a = given[j].value; bool first = TRUE; + if (!VALID_STRING(a)) continue; - for (k = j + 1; _nc_tinfo_fkeys[k].code; k++) { - char *b = tp->Strings[_nc_tinfo_fkeys[k].offset]; - if (!VALID_STRING(b) - || fkeys[k]) + + for (k = j + 1; given[k].keycode; k++) { + const char *b = given[k].value; + + if (!VALID_STRING(b)) + continue; + if (check[k]) continue; + if (!_nc_capcmp(a, b)) { - fkeys[j] = 1; - fkeys[k] = 1; + check[j] = 1; + check[k] = 1; if (first) { if (!conflict) { - _nc_warning("Conflicting key definitions (using the last)"); + _nc_warning("conflicting key definitions (using the last)"); conflict = TRUE; } - fprintf(stderr, "... %s is the same as %s", - keyname((int) _nc_tinfo_fkeys[j].code), - keyname((int) _nc_tinfo_fkeys[k].code)); + fprintf(stderr, "..."); + show_fkey_name(given + j); + fprintf(stderr, " is the same as"); + show_fkey_name(given + k); first = FALSE; } else { - fprintf(stderr, ", %s", - keyname((int) _nc_tinfo_fkeys[k].code)); + fprintf(stderr, ", "); + show_fkey_name(given + k); } } } if (!first) fprintf(stderr, "\n"); } +#if NCURSES_XNAMES + if (using_extensions) { + /* *INDENT-OFF* */ + static struct { + const char *xcurses; + const char *shifted; + } table[] = { + { "kDC", NULL }, + { "kDN", "kind" }, + { "kEND", NULL }, + { "kHOM", NULL }, + { "kLFT", NULL }, + { "kNXT", NULL }, + { "kPRV", NULL }, + { "kRIT", NULL }, + { "kUP", "kri" }, + { NULL, NULL }, + }; + /* *INDENT-ON* */ + /* + * SVr4 curses defines the "xcurses" names listed above except for + * the special cases in the "shifted" column. When using these + * names for xterm's extensions, that was confusing, and resulted + * in adding extended capabilities with "2" (shift) suffix. This + * check warns about unnecessary use of extensions for this quirk. + */ + for (j = 0; given[j].keycode; ++j) { + const char *find = given[j].name; + int value; + char ch; + + if (!VALID_STRING(given[j].value)) + continue; + + for (k = 0; table[k].xcurses; ++k) { + const char *test = table[k].xcurses; + size_t size = strlen(test); + + if (!strncmp(find, test, size) && strcmp(find, test)) { + switch (sscanf(find + size, "%d%c", &value, &ch)) { + case 1: + if (value == 2) { + _nc_warning("expected '%s' rather than '%s'", + (table[k].shifted + ? table[k].shifted + : test), find); + } else if (value < 2 || value > 15) { + _nc_warning("expected numeric 2..15 '%s'", find); + } + break; + default: + _nc_warning("expected numeric suffix for '%s'", find); + break; + } + break; + } + } + } + } +#endif + free(given); + free(check); + } +} + +/* + * Exiting a video mode should not duplicate sgr0 + */ +static void +check_exit_attribute(const char *name, char *test, char *trimmed, char *untrimmed) +{ + if (VALID_STRING(test) && (trimmed != 0)) { + if (similar_sgr(-1, trimmed, test) || + similar_sgr(-1, untrimmed, test)) { + _nc_warning("%s matches exit_attribute_mode", name); + } + } +} + +/* + * Returns true if the string looks like a standard SGR string. + */ +static bool +is_sgr_string(char *value) +{ + bool result = FALSE; + + if (VALID_STRING(value)) { + int skip = csi_length(value); + + if (skip) { + int ch; + + result = TRUE; + value += skip; + while ((ch = UChar(*value++)) != '\0') { + if (isdigit(ch) || ch == ';') { + ; + } else if (ch == 'm' && *value == '\0') { + ; + } else { + result = FALSE; + break; + } + } + } } + return result; +} - for (j = 0; j < NUM_STRINGS(tp); j++) { +/* + * Check if the given capability contains a given SGR attribute. + */ +static void +check_sgr_param(TERMTYPE2 *tp, int code, const char *name, char *value) +{ + if (VALID_STRING(value)) { + int ncv = ((code != 0) ? (1 << (code - 1)) : 0); + char *test = tgoto(value, 0, 0); + if (is_sgr_string(test)) { + int param = 0; + int count = 0; + int skips = 0; + int color = (value == set_a_foreground || + value == set_a_background || + value == set_foreground || + value == set_background); + while (*test != 0) { + if (isdigit(UChar(*test))) { + param = 10 * param + (*test - '0'); + ++count; + } else { + if (count) { + /* + * Avoid unnecessary warning for xterm 256color codes. + */ + if (color && (param == 38 || param == 48)) + skips = 3; + if ((skips-- <= 0) && (param == code)) + break; + } + count = 0; + param = 0; + } + ++test; + } + if (count != 0 && param == code) { + if (code == 0 || + no_color_video < 0 || + !(no_color_video & ncv)) { + _nc_warning("\"%s\" SGR-attribute used in %s", + sgr_names[code], + name); + } + } + } + } +} + +#if NCURSES_XNAMES +static int +standard_type(const char *name) +{ + int result = -1; + const struct name_table_entry *np; + + if ((np = _nc_find_entry(name, _nc_get_hash_table(0))) != 0) { + result = np->nte_type; + } + return result; +} + +static const char * +name_of_type(int type) +{ + const char *result = "unknown"; + switch (type) { + case BOOLEAN: + result = "boolean"; + break; + case NUMBER: + result = "number"; + break; + case STRING: + result = "string"; + break; + } + return result; +} + +static void +check_user_capability_type(const char *name, int actual) +{ + if (lookup_user_capability(name) == 0) { + int expected = standard_type(name); + if (expected >= 0) { + _nc_warning("expected %s to be %s, but actually %s", + name, + name_of_type(actual), + name_of_type(expected) + ); + } else if (*name != 'k') { + _nc_warning("undocumented %s capability %s", + name_of_type(actual), + name); + } + } +} +#endif + +#define IN_DELAY "0123456789*/." + +static bool +check_ANSI_cap(const char *value, int nparams, char final) +{ + bool result = FALSE; + if (VALID_STRING(value) && csi_length(value) > 0) { + char *p_is_s[NUM_PARM]; + int popcount; + int analyzed = _nc_tparm_analyze(NULL, value, p_is_s, &popcount); + if (analyzed < popcount) { + analyzed = popcount; + } + if (analyzed == nparams) { + bool numbers = TRUE; + int p; + for (p = 0; p < nparams; ++p) { + if (p_is_s[p]) { + numbers = FALSE; + break; + } + } + if (numbers) { + int in_delay = 0; + p = (int) strlen(value); + while (p-- > 0) { + char ch = value[p]; + if (ch == final) { + result = TRUE; + break; + } + switch (in_delay) { + case 0: + if (ch == '>') + in_delay = 1; + break; + case 1: + if (strchr(IN_DELAY, value[p]) != NULL) + break; + if (ch != '<') + p = 0; + in_delay = 2; + break; + case 2: + if (ch != '$') + p = 0; + in_delay = 0; + break; + } + } + } + } + } + return result; +} + +static const char * +skip_Delay(const char *value) +{ + const char *result = value; + + if (*value == '$') { + ++result; + if (*result++ == '<') { + while (strchr(IN_DELAY, *result) != NULL) + ++result; + if (*result++ != '>') { + result = value; + } + } else { + result = value; + } + } + return result; +} + +static bool +isValidString(const char *value, const char *expect) +{ + bool result = FALSE; + if (VALID_STRING(value)) { + if (!strcmp(value, expect)) + result = TRUE; + } + return result; +} + +static bool +isValidEscape(const char *value, const char *expect) +{ + bool result = FALSE; + if (VALID_STRING(value)) { + if (*value == '\033') { + size_t need = strlen(expect); + size_t have = strlen(value) - 1; + if (have >= need && !strncmp(value + 1, expect, need)) { + if (*skip_Delay(value + need + 1) == '\0') { + result = TRUE; + } + } + } + } + return result; +} + +static int +guess_ANSI_VTxx(TERMTYPE2 *tp) +{ + int result = -1; + int checks = 0; + + /* VT100s have scrolling region, but ANSI (ECMA-48) does not specify */ + if (check_ANSI_cap(change_scroll_region, 2, 'r') && + (isValidEscape(scroll_forward, "D") || + isValidString(scroll_forward, "\n") || + isValidEscape(scroll_forward, "6")) && + (isValidEscape(scroll_reverse, "M") || + isValidEscape(scroll_reverse, "9"))) { + checks |= 2; + } + if (check_ANSI_cap(cursor_address, 2, 'H') && + check_ANSI_cap(cursor_up, 0, 'A') && + (check_ANSI_cap(cursor_down, 0, 'B') || + isValidString(cursor_down, "\n")) && + check_ANSI_cap(cursor_right, 0, 'C') && + (check_ANSI_cap(cursor_left, 0, 'D') || + isValidString(cursor_left, "\b")) && + check_ANSI_cap(clr_eos, 0, 'J') && + check_ANSI_cap(clr_bol, 0, 'K') && + check_ANSI_cap(clr_eol, 0, 'K')) { + checks |= 1; + } + if (checks == 3) + result = 1; + if (checks == 1) + result = 0; + return result; +} + +/* + * u6/u7 and u8/u9 are query/response extensions which most terminals support. + * In particular, any ECMA-48 terminal should support these, though the details + * for u9 are implementation dependent. + */ +static void +check_user_6789(TERMTYPE2 *tp) +{ + /* + * Check if the terminal is known to not + */ +#define NO_QUERY(longname,shortname) \ + if (PRESENT(longname)) _nc_warning(#shortname " is not supported") + if (tigetflag("NQ") > 0) { + NO_QUERY(user6, u6); + NO_QUERY(user7, u7); + NO_QUERY(user8, u8); + NO_QUERY(user9, u9); + return; + } + + PAIRED(user6, user7); + PAIRED(user8, user9); + + if (strchr(tp->term_names, '+') != NULL) + return; + + switch (guess_ANSI_VTxx(tp)) { + case 1: + if (!PRESENT(user8)) { + _nc_warning("expected u8/u9 for device-attributes"); + } + /* FALLTHRU */ + case 0: + if (!PRESENT(user6)) { + _nc_warning("expected u6/u7 for cursor-position"); + } + break; + } +} + +/* other sanity-checks (things that we don't want in the normal + * logic that reads a terminfo entry) + */ +static void +check_termtype(TERMTYPE2 *tp, bool literal) +{ + unsigned j; + + check_conflict(tp); + + for_each_string(j, tp) { char *a = tp->Strings[j]; - if (VALID_STRING(a)) - check_params(tp, ExtStrname(tp, j, strnames), a); + if (VALID_STRING(a)) { + const char *name = ExtStrname(tp, (int) j, strnames); + /* + * If we expect parameters, or if there might be parameters, + * check for consistent number of parameters. + */ + if (j >= SIZEOF(parametrized) || + is_user_capability(name) >= 0 || + parametrized[j] > 0) { + check_params(tp, name, a, (j >= STRCOUNT)); + } + check_delays(tp, ExtStrname(tp, (int) j, strnames), a); + if (capdump) { + check_infotocap(tp, (int) j, a); + } + } } +#if NCURSES_XNAMES + /* in extended mode, verify that each extension is expected type */ + for_each_ext_boolean(j, tp) { + check_user_capability_type(ExtBoolname(tp, (int) j, strnames), BOOLEAN); + } + for_each_ext_number(j, tp) { + check_user_capability_type(ExtNumname(tp, (int) j, strnames), NUMBER); + } + for_each_ext_string(j, tp) { + check_user_capability_type(ExtStrname(tp, (int) j, strnames), STRING); + } +#endif /* NCURSES_XNAMES */ check_acs(tp); check_colors(tp); + check_cursor(tp); check_keypad(tp); + check_printer(tp); + check_screen(tp); + check_user_6789(tp); + + /* + * These are probably both or none. + */ + PAIRED(parm_index, parm_rindex); + PAIRED(parm_ich, parm_dch); /* * These may be mismatched because the terminal description relies on @@ -1444,6 +3263,11 @@ check_termtype(TERMTYPE *tp, bool literal) ANDMISSING(change_scroll_region, save_cursor); ANDMISSING(change_scroll_region, restore_cursor); + /* + * If we can clear tabs, we should be able to initialize them. + */ + ANDMISSING(clear_all_tabs, set_tab); + if (PRESENT(set_attributes)) { char *zero = 0; @@ -1451,10 +3275,9 @@ check_termtype(TERMTYPE *tp, bool literal) if (PRESENT(exit_attribute_mode)) { zero = strdup(CHECK_SGR(0, exit_attribute_mode)); } else { - zero = strdup(TPARM_9(set_attributes, 0, 0, 0, 0, 0, 0, 0, 0, 0)); + zero = strdup(TIPARM_9(set_attributes, 0, 0, 0, 0, 0, 0, 0, 0, 0)); } - if (_nc_tparm_err) - _nc_warning("stack error in sgr(0) string"); + check_tparm_err(0); if (zero != 0) { CHECK_SGR(1, enter_standout_mode); @@ -1475,11 +3298,11 @@ check_termtype(TERMTYPE *tp, bool literal) if (_nc_syntax == SYN_TERMINFO) _nc_warning("missing sgr string"); } - +#define CHECK_SGR0(name) check_exit_attribute(#name, name, check_sgr0, exit_attribute_mode) if (PRESENT(exit_attribute_mode)) { char *check_sgr0 = _nc_trim_sgr0(tp); - if (check_sgr0 == 0 || *check_sgr0 == '\0') { + if (check_sgr0 == NULL || *check_sgr0 == '\0') { _nc_warning("trimmed sgr0 is empty"); } else { show_where(2); @@ -1488,13 +3311,27 @@ check_termtype(TERMTYPE *tp, bool literal) ("will trim sgr0\n\toriginal sgr0=%s\n\ttrimmed sgr0=%s", _nc_visbuf2(1, exit_attribute_mode), _nc_visbuf2(2, check_sgr0))); - free(check_sgr0); } else { DEBUG(2, ("will not trim sgr0\n\toriginal sgr0=%s", _nc_visbuf(exit_attribute_mode))); } } +#if defined(exit_italics_mode) + CHECK_SGR0(exit_italics_mode); +#endif + CHECK_SGR0(exit_standout_mode); + CHECK_SGR0(exit_underline_mode); + if (check_sgr0 != exit_attribute_mode) { + free(check_sgr0); + } + } +#define CHECK_SGR_PARAM(code, name) check_sgr_param(tp, (int)code, #name, name) + for (j = 0; *sgr_names[j] != '\0'; ++j) { + CHECK_SGR_PARAM(j, set_a_foreground); + CHECK_SGR_PARAM(j, set_a_background); + CHECK_SGR_PARAM(j, set_foreground); + CHECK_SGR_PARAM(j, set_background); } #ifdef TRACE show_where(2); @@ -1521,7 +3358,7 @@ check_termtype(TERMTYPE *tp, bool literal) * ncurses handles it. */ if ((PRESENT(enter_insert_mode) || PRESENT(exit_insert_mode)) - && PRESENT(parm_ich)) { + && PRESENT(insert_character)) { _nc_warning("non-curses applications may be confused by ich1 with smir/rmir"); } diff --git a/usr.bin/tic/tparm_type.c b/usr.bin/tic/tparm_type.c new file mode 100644 index 00000000000..817447dcce4 --- /dev/null +++ b/usr.bin/tic/tparm_type.c @@ -0,0 +1,109 @@ +/**************************************************************************** + * Copyright 2020,2023 Thomas E. Dickey * + * Copyright 2014,2015 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey * + ****************************************************************************/ + +#include + +MODULE_ID("$Id: tparm_type.c,v 1.1 2023/10/17 09:52:10 nicm Exp $") + +/* + * Lookup the type of call we should make to tparm(). This ignores the actual + * terminfo capability (bad, because it is not extensible), but makes this + * code portable to platforms where sizeof(int) != sizeof(char *). + */ +TParams +tparm_type(const char *name) +{ +#define TD(code, longname, ti, tc) \ + {code, {longname} }, \ + {code, {ti} }, \ + {code, {tc} } +#define XD(code, onlyname) TD(code, onlyname, onlyname, onlyname) + TParams result = Numbers; + /* *INDENT-OFF* */ + static const struct { + TParams code; + const char name[12]; + } table[] = { + TD(Num_Str, "pkey_key", "pfkey", "pk"), + TD(Num_Str, "pkey_local", "pfloc", "pl"), + TD(Num_Str, "pkey_xmit", "pfx", "px"), + TD(Num_Str, "plab_norm", "pln", "pn"), + TD(Num_Str_Str, "pkey_plab", "pfxl", "xl"), +#if NCURSES_XNAMES + XD(Str, "Cs"), + XD(Str_Str, "Ms"), +#endif + }; + /* *INDENT-ON* */ + + unsigned n; + for (n = 0; n < SIZEOF(table); n++) { + if (!strcmp(name, table[n].name)) { + result = table[n].code; + break; + } + } + return result; +} + +TParams +guess_tparm_type(int nparam, char **p_is_s) +{ + TParams result = Other; + switch (nparam) { + case 0: + case 1: + if (!p_is_s[0]) + result = Numbers; + if (p_is_s[0]) + result = Str; + break; + case 2: + if (!p_is_s[0] && !p_is_s[1]) + result = Numbers; + if (!p_is_s[0] && p_is_s[1]) + result = Num_Str; + if (p_is_s[0] && p_is_s[1]) + result = Str_Str; + break; + case 3: + if (!p_is_s[0] && !p_is_s[1] && !p_is_s[2]) + result = Numbers; + if (!p_is_s[0] && p_is_s[1] && p_is_s[2]) + result = Num_Str_Str; + break; + default: + break; + } + return result; +} diff --git a/usr.bin/tic/tparm_type.h b/usr.bin/tic/tparm_type.h new file mode 100644 index 00000000000..9ef4f8e033e --- /dev/null +++ b/usr.bin/tic/tparm_type.h @@ -0,0 +1,57 @@ +/**************************************************************************** + * Copyright 2020,2023 Thomas E. Dickey * + * Copyright 2014 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey * + ****************************************************************************/ + +/* + * $Id: tparm_type.h,v 1.1 2023/10/17 09:52:10 nicm Exp $ + * + * determine expected/actual number of parameters to setup for tparm + */ +#ifndef TPARM_TYPE_H +#define TPARM_TYPE_H 1 + +#define USE_LIBTINFO +#include + +typedef enum { + Other = -1 + ,Numbers = 0 + ,Str + ,Num_Str + ,Num_Str_Str + ,Str_Str +} TParams; + +extern TParams tparm_type(const char *name); +extern TParams guess_tparm_type(int nparam, char **p_is_s); + +#endif /* TPARM_TYPE_H */ diff --git a/usr.bin/tic/transform.c b/usr.bin/tic/transform.c new file mode 100644 index 00000000000..79c5704bf28 --- /dev/null +++ b/usr.bin/tic/transform.c @@ -0,0 +1,80 @@ +/**************************************************************************** + * Copyright 2020 Thomas E. Dickey * + * Copyright 2009-2010,2011 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey * + ****************************************************************************/ +#include +#include + +#include + +MODULE_ID("$Id: transform.c,v 1.1 2023/10/17 09:52:10 nicm Exp $") + +#ifdef SUFFIX_IGNORED +static void +trim_suffix(const char *a, size_t *len) +{ + const char ignore[] = SUFFIX_IGNORED; + + if (sizeof(ignore) != 0) { + bool trim = FALSE; + size_t need = (sizeof(ignore) - 1); + + if (*len > need) { + size_t first = *len - need; + size_t n; + trim = TRUE; + for (n = first; n < *len; ++n) { + if (tolower(UChar(a[n])) != tolower(UChar(ignore[n - first]))) { + trim = FALSE; + break; + } + } + if (trim) { + *len -= need; + } + } + } +} +#else +#define trim_suffix(a, len) /* nothing */ +#endif + +bool +same_program(const char *a, const char *b) +{ + size_t len_a = strlen(a); + size_t len_b = strlen(b); + + trim_suffix(a, &len_a); + trim_suffix(b, &len_b); + + return (len_a == len_b) && (strncmp(a, b, len_a) == 0); +} diff --git a/usr.bin/tic/transform.h b/usr.bin/tic/transform.h index 40ed900b2f1..ad1d0264338 100644 --- a/usr.bin/tic/transform.h +++ b/usr.bin/tic/transform.h @@ -1,6 +1,12 @@ -/* $OpenBSD: transform.h,v 1.2 2001/01/29 01:58:24 niklas Exp $ */ +/* $OpenBSD: transform.h,v 1.3 2023/10/17 09:52:10 nicm Exp $ */ +#ifndef __TRANSFORM_H +#define __TRANSFORM_H 1 +#include +extern bool same_program(const char *, const char *); #define PROG_CAPTOINFO "captoinfo" #define PROG_INFOTOCAP "infotocap" +#define PROG_CLEAR "clear" #define PROG_RESET "reset" #define PROG_INIT "init" +#endif /* __TRANSFORM_H */ diff --git a/usr.bin/tic/tty_settings.c b/usr.bin/tic/tty_settings.c new file mode 100644 index 00000000000..fa4d2c644d7 --- /dev/null +++ b/usr.bin/tic/tty_settings.c @@ -0,0 +1,107 @@ +/**************************************************************************** + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 2016,2017 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey * + ****************************************************************************/ + +#define USE_LIBTINFO +#include + +#include + +MODULE_ID("$Id: tty_settings.c,v 1.1 2023/10/17 09:52:10 nicm Exp $") + +static int my_fd; +static TTY original_settings; +static bool can_restore = FALSE; + +static void +failed(const char *msg) +{ + int code = errno; + + (void) fprintf(stderr, "%s: %s: %s\n", _nc_progname, msg, strerror(code)); + restore_tty_settings(); + (void) fprintf(stderr, "\n"); + ExitProgram(ErrSystem(code)); + /* NOTREACHED */ +} + +static bool +get_tty_settings(int fd, TTY * tty_settings) +{ + bool success = TRUE; + my_fd = fd; + if (fd < 0 || GET_TTY(my_fd, tty_settings) < 0) { + success = FALSE; + } + return success; +} + +/* + * Open a file descriptor on the current terminal, to obtain its settings. + * stderr is less likely to be redirected than stdout; try that first. + */ +int +save_tty_settings(TTY * tty_settings, bool need_tty) +{ + if (!get_tty_settings(STDERR_FILENO, tty_settings) && + !get_tty_settings(STDOUT_FILENO, tty_settings) && + !get_tty_settings(STDIN_FILENO, tty_settings)) { + if (need_tty) { + int fd = open("/dev/tty", O_RDWR); + if (!get_tty_settings(fd, tty_settings)) { + failed("terminal attributes"); + } + } else { + my_fd = fileno(stdout); + } + } else { + can_restore = TRUE; + original_settings = *tty_settings; + } + return my_fd; +} + +void +restore_tty_settings(void) +{ + if (can_restore) + SET_TTY(my_fd, &original_settings); +} + +/* Set the modes if they've changed. */ +void +update_tty_settings(TTY * old_settings, TTY * new_settings) +{ + if (memcmp(new_settings, old_settings, sizeof(TTY))) { + SET_TTY(my_fd, new_settings); + } +} diff --git a/usr.bin/tic/tty_settings.h b/usr.bin/tic/tty_settings.h new file mode 100644 index 00000000000..8fe3e8f3a24 --- /dev/null +++ b/usr.bin/tic/tty_settings.h @@ -0,0 +1,51 @@ +/**************************************************************************** + * Copyright 2020 Thomas E. Dickey * + * Copyright 2016,2017 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E Dickey * + ****************************************************************************/ + +/* + * $Id: tty_settings.h,v 1.1 2023/10/17 09:52:10 nicm Exp $ + * + * Utility functions for saving/restoring terminal settings. + */ +#ifndef TTY_SETTINGS_H +#define TTY_SETTINGS_H 1 +/* *INDENT-OFF* */ + +#include + +extern int save_tty_settings(TTY * /* tty_settings */, bool /* need_tty */ ); +extern void restore_tty_settings(void); +extern void update_tty_settings(TTY * /* old_settings */, TTY * /* new_settings */ ); + +/* *INDENT-ON* */ + +#endif /* TTY_SETTINGS_H */ diff --git a/usr.bin/tput/Makefile b/usr.bin/tput/Makefile index 22a02630600..7b261e36c7f 100644 --- a/usr.bin/tput/Makefile +++ b/usr.bin/tput/Makefile @@ -1,8 +1,18 @@ -# $OpenBSD: Makefile,v 1.12 2016/03/30 06:38:46 jmc Exp $ +# $OpenBSD: Makefile,v 1.13 2023/10/17 09:52:11 nicm Exp $ PROG= tput +SRCS= clear_cmd.c reset_cmd.c tparm_type.c tput.c transform.c \ + tty_settings.c +CURSES= ${.CURDIR}/../../lib/libcurses DPADD= ${LIBCURSES} LDADD= -lcurses -LINKS= ${BINDIR}/tput ${BINDIR}/clear +LINKS= ${BINDIR}/tput ${BINDIR}/clear +TIC= ${.CURDIR}/../tic +CFLAGS+= -I${CURSES} -I${TIC} -I${.CURDIR} -I. +.PATH: ${TIC} +CLEANFILES+= termsort.h + +termsort.h: ${TIC}/MKtermsort.sh + sh ${TIC}/MKtermsort.sh awk ${CURSES}/Caps > ${.TARGET} .include diff --git a/usr.bin/tput/tput.1 b/usr.bin/tput/tput.1 index 2f800d55179..d4e2561fa47 100644 --- a/usr.bin/tput/tput.1 +++ b/usr.bin/tput/tput.1 @@ -1,188 +1,618 @@ -.\" $OpenBSD: tput.1,v 1.26 2022/12/22 19:53:24 kn Exp $ -.\" $NetBSD: tput.1,v 1.4 1994/12/07 08:49:10 jtc Exp $ +'\" t +.\" $OpenBSD: tput.1,v 1.27 2023/10/17 09:52:11 nicm Exp $ +.\"*************************************************************************** +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2016,2017 Free Software Foundation, Inc. * +.\" * +.\" Permission is hereby granted, free of charge, to any person obtaining a * +.\" copy of this software and associated documentation files (the * +.\" "Software"), to deal in the Software without restriction, including * +.\" without limitation the rights to use, copy, modify, merge, publish, * +.\" distribute, distribute with modifications, sublicense, and/or sell * +.\" copies of the Software, and to permit persons to whom the Software is * +.\" furnished to do so, subject to the following conditions: * +.\" * +.\" The above copyright notice and this permission notice shall be included * +.\" in all copies or substantial portions of the Software. * +.\" * +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * +.\" IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * +.\" DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * +.\" OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * +.\" THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +.\" * +.\" Except as contained in this notice, the name(s) of the above copyright * +.\" holders shall not be used in advertising or otherwise to promote the * +.\" sale, use or other dealings in this Software without prior written * +.\" authorization. * +.\"*************************************************************************** .\" -.\" Copyright (c) 1989, 1990, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)tput.1 8.2 (Berkeley) 3/19/94 -.\" -.Dd $Mdocdate: December 22 2022 $ -.Dt TPUT 1 -.Os -.Sh NAME -.Nm tput , -.Nm clear -.Nd terminal capability interface -.Sh SYNOPSIS -.Nm tput -.Op Fl T Ar term -.Ar attribute -.Op Ar attribute-arg ... -.Ar ... -.Nm tput -.Op Fl T Ar term -.Fl S -.Nm clear -.Op Fl T Ar term -.Sh DESCRIPTION -The -.Nm -utility makes terminal-dependent information available to users or shell -applications. -When invoked as -.Nm clear , -it provides the same functionality as -.Nm tput Cm clear . -.Pp -The options are as follows: -.Bl -tag -width Ds -.It Fl S -The attributes are read from stdin instead of the command line. -.It Fl T -The terminal name as found in the -.Xr terminfo 5 -database; for example, -.Dq vt100 -or -.Dq xterm . -If not specified, -.Nm -retrieves the -.Ev TERM -variable from the environment. -.El -.Pp -.Nm -outputs a string if the -.Ar attribute -is of type string or a number if it is of type integer. -If the -.Ar attribute -is of type boolean, -.Nm -exits 0 if the terminal has the capability or 1 if it -does not. -Each -.Ar attribute -should be a string defined in either -.Xr terminfo 5 -or -.Xr termcap 5 . -.Pp -If the -.Ar attribute -is of type string and takes arguments (e.g., cursor movement, -the -.Xr terminfo 5 -.Dq cup -sequence) the arguments are taken from the command line immediately -following the attribute. -.Pp -The following special attributes are available: -.Bl -tag -width Ar -.It clear -Clear the screen (the -.Xr terminfo 5 -.Dq clear -sequence). -.It init -Print the -.Xr terminfo 5 -initialization strings for the specified terminal. -.It longname -Print the descriptive name of the user's terminal type. -.It reset -Reset the terminal (using the -.Xr terminfo 5 -reset sequences). -.El -.Sh ENVIRONMENT -.Bl -tag -width Ds -.It Ev TERM -Determine the terminal type. -.El -.Sh EXIT STATUS -The exit value of -.Nm -is based on the last attribute specified. -If the attribute is of type string or of type integer, the exit -value is as follows: -.Pp -.Bl -tag -offset indent -width Ds -compact -.It 0 -The requested string was written successfully. -.It 2 -Usage error. -.It 3 -Unknown terminal type. -.It 4 -Unknown attribute name. -.It >4 -An error occurred. -.El -.Pp -If the attribute is of type boolean, -.Nm -exits with a value of 0 if the terminal has this attribute or -1 if it does not. -.Sh EXAMPLES -Clear the screen and go to line 5 column 10: -.Pp -.Dl $ tput clear cup 5 10 -.Pp -Go to line 6 column 11 and delete 6 characters: -.Pp -.Dl $ tput cup 6 11 dch 6 -.Sh SEE ALSO -.Xr terminfo 3 , -.Xr terminfo 5 -.Sh STANDARDS -The -.Nm -utility is compliant with the -.St -p1003.1-2008 -specification. -.Pp -The flag -.Op Fl S -and the attribute -.Cm longname -are extensions to that specification. -.Sh HISTORY -The -.Nm clear -utility first appeared in -.Bx 2 . -The -.Nm -utility first appeared in -.At V.2 -and was reimplemented for -.Bx 4.3 Reno . -.Sh BUGS -.Nm -can't really distinguish between different types of attributes. + +.TH tput 1 2023-07-01 "ncurses 6.4" "User commands" +.ds d /usr/share/terminfo +.ds n 1 +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.SH NAME +\fBtput\fP, \fBreset\fP \- initialize a terminal or query terminfo database +.SH SYNOPSIS +\fBtput\fR [\fB\-T\fItype\fR] \fIcapname\fR [\fIparameters\fR] +.br +\fBtput\fR [\fB\-T\fItype\fR] [\fB\-x\fR] \fBclear\fR +.br +\fBtput\fR [\fB\-T\fItype\fR] \fBinit\fR +.br +\fBtput\fR [\fB\-T\fItype\fR] \fBreset\fR +.br +\fBtput\fR [\fB\-T\fItype\fR] \fBlongname\fR +.br +\fBtput \-S\fP \fB<<\fP +.br +\fBtput \-V\fP +.SH DESCRIPTION +The \fBtput\fP utility uses the \fBterminfo\fP database to make the +values of terminal-dependent capabilities and information available to +the shell (see \fBsh\fP(1)), to initialize or reset the terminal, or +return the long name of the requested terminal type. +The result depends upon the capability's type: +.RS 3 +.TP 5 +string +\fBtput\fP writes the string to the standard output. +No trailing newline is supplied. +.TP +integer +\fBtput\fP writes the decimal value to the standard output, +with a trailing newline. +.TP +boolean +\fBtput\fP simply sets the exit code +(\fB0\fP for TRUE if the terminal has the capability, +\fB1\fP for FALSE if it does not), +and writes nothing to the standard output. +.RE +.PP +Before using a value returned on the standard output, +the application should test the exit code +(e.g., \fB$?\fP, see \fBsh\fP(1)) to be sure it is \fB0\fP. +(See the \fBEXIT CODES\fP and \fBDIAGNOSTICS\fP sections.) +For a complete list of capabilities +and the \fIcapname\fP associated with each, see \fBterminfo\fP(5). +.SS Options +.TP +\fB\-S\fP +allows more than one capability per invocation of \fBtput\fP. The +capabilities must be passed to \fBtput\fP from the standard input +instead of from the command line (see example). +Only one \fIcapname\fP is allowed per line. +The \fB\-S\fP option changes the +meaning of the \fB0\fP and \fB1\fP boolean and string exit codes (see the +EXIT CODES section). +.IP +Because some capabilities may use +\fIstring\fP parameters rather than \fInumbers\fP, +\fBtput\fP uses a table and the presence of parameters in its input +to decide whether to use \fBtparm\fP(3), +and how to interpret the parameters. +.TP +\fB\-T\fItype\fR +indicates the \fItype\fP of terminal. +Normally this option is +unnecessary, because the default is taken from the environment +variable \fBTERM\fP. +If \fB\-T\fP is specified, then the shell +variables \fBLINES\fP and \fBCOLUMNS\fP will also be ignored. +.TP +\fB\-V\fP +reports the version of ncurses which was used in this program, and exits. +.TP +.B \-x +do not attempt to clear the terminal's scrollback buffer +using the extended \*(``E3\*('' capability. +.SS Commands +A few commands (\fBinit\fP, \fBreset\fP and \fBlongname\fP) are +special; they are defined by the \fBtput\fP program. +The others are the names of \fIcapabilities\fP from the terminal database +(see \fBterminfo\fP(5) for a list). +Although \fBinit\fP and \fBreset\fP resemble capability names, +\fBtput\fP uses several capabilities to perform these special functions. +.TP +\fIcapname\fP +indicates the capability from the terminal database. +.IP +If the capability is a string that takes parameters, the arguments +following the capability will be used as parameters for the string. +.IP +Most parameters are numbers. +Only a few terminal capabilities require string parameters; +\fBtput\fP uses a table to decide which to pass as strings. +Normally \fBtput\fP uses \fBtparm\fP(3) to perform the substitution. +If no parameters are given for the capability, +\fBtput\fP writes the string without performing the substitution. +.TP +\fBinit\fP +If the terminal database is present and an entry for the user's +terminal exists (see \fB\-T\fItype\fR, above), the following will +occur: +.RS +.TP 5 +(1) +first, \fBtput\fP retrieves the current terminal mode settings +for your terminal. +It does this by successively testing +.RS +.bP +the standard error, +.bP +standard output, +.bP +standard input and +.bP +ultimately \*(``/dev/tty\*('' +.RE +.IP +to obtain terminal settings. +Having retrieved these settings, \fBtput\fP remembers which +file descriptor to use when updating settings. +.TP +(2) +if the window size cannot be obtained from the operating system, +but the terminal description (or environment, e.g., \fBLINES\fP +and \fBCOLUMNS\fP variables specify this), +update the operating system's notion of the window size. +.TP +(3) +the terminal modes will be updated: +.RS +.bP +any delays (e.g., newline) specified in the entry will +be set in the tty driver, +.bP +tabs expansion will be turned on or off according to +the specification in the entry, and +.bP +if tabs are not expanded, +standard tabs will be set (every 8 spaces). +.RE +.TP +(4) +if present, the terminal's initialization strings will be +output as detailed in the \fBterminfo\fP(5) section on +.IR "Tabs and Initialization" , +.TP +(5) +output is flushed. +.RE +.IP +If an entry does not +contain the information needed for any of these activities, +that activity will silently be skipped. +.TP +\fBreset\fP +This is similar to \fBinit\fP, with two differences: +.RS +.TP 5 +(1) +before any other initialization, +the terminal modes will be reset to a \*(``sane\*('' state: +.RS +.bP +set cooked and echo modes, +.bP +turn off cbreak and raw modes, +.bP +turn on newline translation and +.bP +reset any unset special characters to their default values +.RE +.TP 5 +(2) +Instead of putting out \fIinitialization\fP strings, the terminal's +\fIreset\fP strings will be output if present +(\fBrs1\fP, \fBrs2\fP, \fBrs3\fP, \fBrf\fP). +If the \fIreset\fP strings are not present, but \fIinitialization\fP +strings are, the \fIinitialization\fP strings will be output. +.RE +.IP +Otherwise, \fBreset\fP acts identically to \fBinit\fP. +.TP +\fBlongname\fP +If the terminal database is present and an entry for the +user's terminal exists (see \fB\-T\fItype\fR above), then the long name +of the terminal will be put out. +The long name is the last +name in the first line of the terminal's description in the +\fBterminfo\fP database [see \fBterm\fP(5)]. +.SS Aliases +\fBtput\fP handles the \fBclear\fP, \fBinit\fP and \fBreset\fP +commands specially: +it allows for the possibility that it is invoked by a link with those names. +.PP +If \fBtput\fP is invoked by a link named \fBreset\fP, this has the +same effect as \fBtput reset\fP. +The \fBtset\fP(\*n) utility also treats a link named \fBreset\fP specially. +.PP +Before ncurses 6.1, the two utilities were different from each other: +.bP +\fBtset\fP utility reset the terminal modes and special characters +(not done with \fBtput\fP). +.bP +On the other hand, \fBtset\fP's repertoire of terminal capabilities for +resetting the terminal was more limited, +i.e., only \fBreset_1string\fP, \fBreset_2string\fP and \fBreset_file\fP +in contrast to the tab-stops and margins which are set by this utility. +.bP +The \fBreset\fP program is usually an alias for \fBtset\fP, +because of this difference with resetting terminal modes and special characters. +.PP +With the changes made for ncurses 6.1, the \fIreset\fP feature of the +two programs is (mostly) the same. +A few differences remain: +.bP +The \fBtset\fP program waits one second when resetting, +in case it happens to be a hardware terminal. +.bP +The two programs write the terminal initialization strings +to different streams (i.e., the standard error for \fBtset\fP and the +standard output for \fBtput\fP). +.IP +\fBNote:\fP although these programs write to different streams, +redirecting their output to a file will capture only part of their actions. +The changes to the terminal modes are not affected by redirecting the output. +.PP +If \fBtput\fP is invoked by a link named \fBinit\fP, this has the +same effect as \fBtput init\fP. +Again, you are less likely to use that link because another program +named \fBinit\fP has a more well-established use. +.SS Terminal Size +Besides the special commands (e.g., \fBclear\fP), +tput treats certain terminfo capabilities specially: +\fBlines\fP and \fBcols\fP. +tput calls \fBsetupterm\fP(3) to obtain the terminal size: +.bP +first, it gets the size from the terminal database +(which generally is not provided for terminal emulators +which do not have a fixed window size) +.bP +then it asks the operating system for the terminal's size +(which generally works, unless connecting via a serial line which +does not support \fINAWS\fP: negotiations about window size). +.bP +finally, it inspects the environment variables \fBLINES\fP and \fBCOLUMNS\fP +which may override the terminal size. +.PP +If the \fB\-T\fP option is given +tput ignores the environment variables by calling \fBuse_tioctl(TRUE)\fP, +relying upon the operating system (or finally, the terminal database). +.SH EXAMPLES +.TP 5 +\fBtput init\fP +Initialize the terminal according to the type of +terminal in the environmental variable \fBTERM\fP. This +command should be included in everyone's .profile after +the environmental variable \fBTERM\fP has been exported, as +illustrated on the \fBprofile\fP(5) manual page. +.TP 5 +\fBtput \-T5620 reset\fP +Reset an AT&T 5620 terminal, overriding the type of +terminal in the environmental variable \fBTERM\fP. +.TP 5 +\fBtput cup 0 0\fP +Send the sequence to move the cursor to row \fB0\fP, column \fB0\fP +(the upper left corner of the screen, usually known as the \*(``home\*('' +cursor position). +.TP 5 +\fBtput clear\fP +Echo the clear-screen sequence for the current terminal. +.TP 5 +\fBtput cols\fP +Print the number of columns for the current terminal. +.TP 5 +\fBtput \-T450 cols\fP +Print the number of columns for the 450 terminal. +.TP 5 +\fBbold=`tput smso` offbold=`tput rmso`\fP +Set the shell variables \fBbold\fP, to begin stand-out mode +sequence, and \fBoffbold\fP, to end standout mode sequence, +for the current terminal. +This might be followed by a +prompt: \fBecho "${bold}Please type in your name: ${offbold}\\c"\fP +.TP 5 +\fBtput hc\fP +Set exit code to indicate if the current terminal is a hard copy terminal. +.TP 5 +\fBtput cup 23 4\fP +Send the sequence to move the cursor to row 23, column 4. +.TP 5 +\fBtput cup\fP +Send the terminfo string for cursor-movement, with no parameters substituted. +.TP 5 +\fBtput longname\fP +Print the long name from the \fBterminfo\fP database for the +type of terminal specified in the environmental +variable \fBTERM\fP. +.PP +.RS 5 +\fBtput \-S < clear\fP +.br +\fB> cup 10 10\fP +.br +\fB> bold\fP +.br +\fB> !\fP +.RE +.TP 5 +\& +This example shows \fBtput\fP processing several capabilities +in one invocation. +It clears the screen, +moves the cursor to position 10, 10 +and turns on bold (extra bright) mode. +The list is terminated by an exclamation mark (\fB!\fP) on a line by itself. +.SH FILES +.TP +\fB\*d\fP +compiled terminal description database +.TP +\fB/usr/share/tabset/*\fP +tab settings for some terminals, in a format +appropriate to be output to the terminal (escape +sequences that set margins and tabs); for more +information, see the +.IR "Tabs and Initialization" , +section of \fBterminfo\fP(5) +.SH EXIT CODES +If the \fB\-S\fP option is used, +\fBtput\fP checks for errors from each line, +and if any errors are found, will set the exit code to 4 plus the +number of lines with errors. +If no errors are found, the exit code is \fB0\fP. +No indication of which line failed can be given so +exit code \fB1\fP will never appear. +Exit codes \fB2\fP, \fB3\fP, and +\fB4\fP retain their usual interpretation. +If the \fB\-S\fP option is not used, +the exit code depends on the type of \fIcapname\fP: +.RS 3 +.TP +.I boolean +a value of \fB0\fP is set for TRUE and \fB1\fP for FALSE. +.TP +.I string +a value of \fB0\fP is set if the +\fIcapname\fP is defined for this terminal \fItype\fP (the value of +\fIcapname\fP is returned on standard output); +a value of \fB1\fP is set if \fIcapname\fP +is not defined for this terminal \fItype\fP +(nothing is written to standard output). +.TP +.I integer +a value of \fB0\fP is always set, +whether or not \fIcapname\fP is defined for this terminal \fItype\fP. +To determine if \fIcapname\fP is defined for this terminal \fItype\fP, +the user must test the value written to standard output. +A value of \fB\-1\fP +means that \fIcapname\fP is not defined for this terminal \fItype\fP. +.TP +.I other +\fBreset\fP or \fBinit\fP may fail to find their respective files. +In that case, the exit code is set to 4 + \fBerrno\fP. +.RE +.PP +Any other exit code indicates an error; see the DIAGNOSTICS section. +.SH DIAGNOSTICS +\fBtput\fP prints the following error messages and sets the corresponding exit +codes. +.PP +.ne 15 +.TS +l l. +exit code error message += +\fB0\fP T{ +(\fIcapname\fP is a numeric variable that is not specified in the +\fBterminfo\fP(5) database for this terminal type, e.g. +\fBtput \-T450 lines\fP and \fBtput \-Thp2621 xmc\fP) +T} +\fB1\fP no error message is printed, see the \fBEXIT CODES\fP section. +\fB2\fP usage error +\fB3\fP unknown terminal \fItype\fP or no \fBterminfo\fP database +\fB4\fP unknown \fBterminfo\fP capability \fIcapname\fP +\fB>4\fP error occurred in \-S += +.TE +.SH HISTORY +The \fBtput\fP command was begun by Bill Joy in 1980. +The initial version only cleared the screen. +.PP +AT&T System V provided a different \fBtput\fP command: +.bP +SVr2 provided a rudimentary \fBtput\fP +which checked the parameter against each +predefined capability and returned the corresponding value. +This version of \fBtput\fP did not use \fBtparm\fP(3) for +the capabilities which are parameterized. +.bP +SVr3 replaced that, a year later, by a more extensive program +whose \fBinit\fP and \fBreset\fP subcommands +(more than half the program) were incorporated from +the \fBreset\fP feature of BSD \fBtset\fP written by Eric Allman. +.bP +SVr4 added color initialization using the \fBorig_colors\fP and +\fBorig_pair\fP capabilities in the \fBinit\fP subcommand. +.PP +Keith Bostic replaced the BSD \fBtput\fP command in 1989 +with a new implementation +based on the AT&T System V program \fBtput\fP. +Like the AT&T program, Bostic's version +accepted some parameters named for \fIterminfo\fP capabilities +(\fBclear\fP, \fBinit\fP, \fBlongname\fP and \fBreset\fP). +However (because he had only \fItermcap\fP available), +it accepted \fItermcap\fP names for other capabilities. +Also, Bostic's BSD \fBtput\fP did not modify the terminal I/O modes +as the earlier BSD \fBtset\fP had done. +.PP +At the same time, Bostic added a shell script named \*(``clear\*('', +which used \fBtput\fP to clear the screen. +.PP +Both of these appeared in 4.4BSD, +becoming the \*(``modern\*('' BSD implementation of \fBtput\fP. +.PP +This implementation of \fBtput\fP began from a different source than +AT&T or BSD: Ross Ridge's \fImytinfo\fP package, published on +\fIcomp.sources.unix\fP in December 1992. +Ridge's program made more sophisticated use of the terminal capabilities +than the BSD program. +Eric Raymond used that \fBtput\fP program +(and other parts of \fImytinfo\fP) in ncurses in June 1995. +Using the portions dealing with terminal capabilities +almost without change, +Raymond made improvements to the way the command-line parameters +were handled. +.SH PORTABILITY +This implementation of \fBtput\fP differs from AT&T \fBtput\fP in +two important areas: +.bP +\fBtput\fP \fIcapname\fP writes to the standard output. +That need not be a regular terminal. +However, the subcommands which manipulate terminal modes +may not use the standard output. +.IP +The AT&T implementation's \fBinit\fP and \fBreset\fP commands +use the BSD (4.1c) \fBtset\fP source, which manipulates terminal modes. +It successively tries standard output, standard error, standard input +before falling back to \*(``/dev/tty\*('' and finally just assumes +a 1200Bd terminal. +When updating terminal modes, it ignores errors. +.IP +Until changes made after ncurses 6.0, +\fBtput\fP did not modify terminal modes. +\fBtput\fP now uses a similar scheme, +using functions shared with \fBtset\fP +(and ultimately based on the 4.4BSD \fBtset\fP). +If it is not able to open a terminal, e.g., when running in \fBcron\fP(1), +\fBtput\fP will return an error. +.bP +AT&T \fBtput\fP guesses the type of its \fIcapname\fP operands by seeing if +all of the characters are numeric, or not. +.IP +Most implementations which provide support for \fIcapname\fP operands +use the \fBtparm\fP function to expand parameters in it. +That function expects a mixture of numeric and string parameters, +requiring \fBtput\fP to know which type to use. +.IP +This implementation uses a table to determine the parameter types for +the standard \fIcapname\fP operands, and an internal library +function to analyze nonstandard \fIcapname\fP operands. +.IP +Besides providing more reliable operation than AT&T's utility, +a portability problem is introduced by this analysis: +An OpenBSD developer adapted the internal library function from ncurses +to port NetBSD's termcap-based \fBtput\fP to terminfo. +That had been modified to interpret multiple commands on a line. +Portable applications should not rely upon this feature; +ncurses provides it to support applications written +specifically for OpenBSD. +.PP +This implementation (unlike others) can accept both \fItermcap\fP +and \fIterminfo\fP names for the \fIcapname\fP feature, +if +\fItermcap\fP support is compiled in. +However, the predefined \fItermcap\fP and \fIterminfo\fP names have two +ambiguities in this case (and the \fIterminfo\fP name is assumed): +.bP +The \fItermcap\fP name \fBdl\fP corresponds to +the \fIterminfo\fP name \fBdl1\fP (delete one line). +.br +The \fIterminfo\fP name \fBdl\fP corresponds to +the \fItermcap\fP name \fBDL\fP (delete a given number of lines). +.bP +The \fItermcap\fP name \fBed\fP corresponds to +the \fIterminfo\fP name \fBrmdc\fP (end delete mode). +.br +The \fIterminfo\fP name \fBed\fP corresponds to +the \fItermcap\fP name \fBcd\fP (clear to end of screen). +.PP +The \fBlongname\fP and \fB\-S\fP options, and the parameter-substitution +features used in the \fBcup\fP example, +were not supported in BSD curses before 4.3reno (1989) or in +AT&T/USL curses before SVr4 (1988). +.PP +IEEE Std 1003.1/The Open Group Base Specifications Issue 7 (POSIX.1-2008) +documents only the operands for \fBclear\fP, \fBinit\fP and \fBreset\fP. +There are a few interesting observations to make regarding that: +.bP +In this implementation, \fBclear\fP is part of the \fIcapname\fP support. +The others (\fBinit\fP and \fBlongname\fP) do not correspond to terminal +capabilities. +.bP +Other implementations of \fBtput\fP on +SVr4-based systems such as Solaris, IRIX64 and HPUX +as well as others such as AIX and Tru64 +provide support for \fIcapname\fP operands. +.bP +A few platforms such as FreeBSD recognize termcap names rather +than terminfo capability names in their respective \fBtput\fP commands. +Since 2010, NetBSD's \fBtput\fP uses terminfo names. +Before that, it (like FreeBSD) recognized termcap names. +.IP +Beginning in 2021, FreeBSD uses the ncurses \fBtput\fP, +configured for both terminfo (tested first) and termcap (as a fallback). +.PP +Because (apparently) \fIall\fP of the certified Unix systems +support the full set of capability names, the reasoning for documenting +only a few may not be apparent. +.bP +X/Open Curses Issue 7 documents \fBtput\fP differently, with \fIcapname\fP +and the other features used in this implementation. +.bP +That is, there are two standards for \fBtput\fP: +POSIX (a subset) and X/Open Curses (the full implementation). +POSIX documents a subset to avoid the complication of including X/Open Curses +and the terminal capabilities database. +.bP +While it is certainly possible to write a \fBtput\fP program +without using curses, +none of the systems which have a curses implementation provide +a \fBtput\fP utility which does not provide the \fIcapname\fP feature. +.PP +X/Open Curses Issue 7 (2009) is the first version to document utilities. +However that part of X/Open Curses does not follow existing practice +(i.e., Unix features documented in SVID 3): +.bP +It assigns exit code 4 to \*(``invalid operand\*('', +which may be the same as \fIunknown capability\fP. +For instance, the source code for Solaris' xcurses uses the term +\*(``invalid\*('' in this case. +.bP +It assigns exit code 255 to a numeric variable that is not specified in +the terminfo database. +That likely is a documentation error, +confusing the \fB\-1\fP written to the standard output for an absent +or cancelled numeric value versus an (unsigned) exit code. +.PP +The various Unix systems (AIX, HPUX, Solaris) use the same exit-codes +as ncurses. +.PP +NetBSD curses documents different exit codes which do not correspond +to either ncurses or X/Open. +.SH SEE ALSO +\fB?\fP(\*n), +\fBstty\fP(1), +\fB?\fP(\*n), +\fBtset\fP(\*n), +\fBtermcap\fP(3), +\fBterminfo\fP(5). +.PP +This describes \fBncurses\fP +version 6.4 (patch 20230826). diff --git a/usr.bin/tput/tput.c b/usr.bin/tput/tput.c index b2e4e0a7aa4..9aae2e2708c 100644 --- a/usr.bin/tput/tput.c +++ b/usr.bin/tput/tput.c @@ -1,366 +1,507 @@ -/* $OpenBSD: tput.c,v 1.29 2023/09/06 05:04:07 jsg Exp $ */ +/* $OpenBSD: tput.c,v 1.30 2023/10/17 09:52:11 nicm Exp $ */ + +/**************************************************************************** + * Copyright 2018-2022,2023 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Zeyd M. Ben-Halim 1992,1995 * + * and: Eric S. Raymond * + * and: Thomas E. Dickey 1996-on * + ****************************************************************************/ /* - * Copyright (c) 1999 Todd C. Miller + * tput.c -- shellscript access to terminal capabilities * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -/*- - * Copyright (c) 1980, 1988, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * by Eric S. Raymond , portions based on code from + * Ross Ridge's mytinfo package. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include -#define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) +#include +#include -#define NUM_PARM 9 /* must match tic.h */ -static void init(void); -static char **process(char *, char *, char **); -static void reset(void); -static void set_margins(void); -static void usage(void); -extern char *__progname; -extern int _nc_tparm_analyze(const char *string, char *p_is_s[NUM_PARM], int *popcount); +#define PUTS(s) fputs(s, stdout) -int -main(int argc, char *argv[]) -{ - int ch, exitval, n, Sflag; - size_t len; - char *p, *term, *str; - char **oargv; - - if (pledge("stdio rpath wpath tty", NULL) == -1) - err(1, "pledge"); - - oargv = argv; - term = NULL; - Sflag = exitval = 0; - while ((ch = getopt(argc, argv, "ST:")) != -1) - switch(ch) { - case 'T': - term = optarg; - break; - case 'S': - Sflag = 1; - break; - default: - usage(); - } - argc -= optind; - argv += optind; +const char *_nc_progname = "tput"; - if (Sflag && argc > 0) - usage(); - - if (!term && !(term = getenv("TERM"))) - errx(2, "No value for $TERM and no -T specified"); - - /* - * NOTE: tgetent() will call setupterm() and set ospeed for us - * (this is ncurses-specific behavior) - */ - if (tgetent(NULL, term) != 1) - errx(3, "Unknown terminal type `%s'", term); - - if (strcmp(__progname, "clear") == 0) { - if (Sflag) - usage(); - argv = oargv; - *argv = __progname; - *(argv+1) = NULL; - } - if (Sflag) { - char **av; - - /* Build new argv based on stdin */ - argc = n = 0; - av = NULL; - while ((str = fgetln(stdin, &len)) != NULL) { - if (str[len-1] != '\n') - errx(1, "premature EOF"); - str[len-1] = '\0'; - while ((p = strsep(&str, " \t")) != NULL) { - /* grow av as needed */ - if (argc + 1 >= n) { - n += 64; - av = reallocarray(av, n, - sizeof(char *)); - if (av == NULL) - errx(1, "out of memory"); - } - if (*p != '\0' && - (av[argc++] = strdup(p)) == NULL) - errx(1, "out of memory"); - } - } - if (argc > 0) { - av[argc] = NULL; - argv = av; - } - } - while ((p = *argv++)) { - switch (*p) { - case 'i': - if (!strcmp(p, "init")) { - init(); - continue; - } - break; - case 'l': - if (!strcmp(p, "longname")) { - puts(longname()); - continue; - } - break; - case 'r': - if (!strcmp(p, "reset")) { - reset(); - continue; - } - break; - } +static bool opt_v = FALSE; /* quiet, do not show warnings */ +static bool opt_x = FALSE; /* clear scrollback if possible */ - /* First try as terminfo */ - if ((str = tigetstr(p)) && str != (char *)-1) - argv = process(p, str, argv); - else if ((n = tigetnum(p)) != -2) - (void)printf("%d\n", n); - else if ((n = tigetflag(p)) != -1) - exitval = !n; - /* Then fall back on termcap */ - else if ((str = tgetstr(p, NULL))) - argv = process(p, str, argv); - else if ((n = tgetnum(p)) != -1) - (void)printf("%d\n", n); - else if ((exitval = tgetflag(p)) != 0) - exitval = !exitval; - else { - warnx("Unknown terminfo capability `%s'", p); - exitval = 4; - } - } - exit(exitval); +static bool is_init = FALSE; +static bool is_reset = FALSE; +static bool is_clear = FALSE; + +static GCC_NORETURN void +quit(int status, const char *fmt, ...) +{ + va_list argp; + + va_start(argp, fmt); + fprintf(stderr, "%s: ", _nc_progname); + vfprintf(stderr, fmt, argp); + fprintf(stderr, "\n"); + va_end(argp); + ExitProgram(status); } -static char ** -process(char *cap, char *str, char **argv) +static GCC_NORETURN void +usage(const char *optstring) { - char *s, *nargv[NUM_PARM] = {0}; - char *p_is_s[NUM_PARM]; - int arg_need, i; - - /* Count how many values we need for this capability. */ - i = _nc_tparm_analyze(str, p_is_s, &arg_need); - if (arg_need == 0) - arg_need = i; - if (arg_need > NUM_PARM) - errx(2, "too many arguments (%d) for capability `%s'", - arg_need, cap); - - for (i = 0; i < arg_need; i++) { - const char *errstr; - long l; - - if (argv[i] == NULL) - errx(2, "not enough arguments (%d) for capability `%s'", - arg_need, cap); - - if (p_is_s[i] != 0) { - nargv[i] = argv[i]; - } else { - /* convert ascii representation of numbers to longs */ - l = strtonum(argv[i], LONG_MIN, LONG_MAX, &errstr); - if (errstr != NULL) - errx(2, "capability `%s' is %s", cap, errstr); - nargv[i] = (char *)l; - } +#define KEEP(s) s "\n" + static const char msg[] = + { + KEEP("") + KEEP("Options:") + KEEP(" -S << read commands from standard input") + KEEP(" -T TERM use this instead of $TERM") + KEEP(" -V print curses-version") + KEEP(" -v verbose, show warnings") + KEEP(" -x do not try to clear scrollback") + KEEP("") + KEEP("Commands:") + KEEP(" clear clear the screen") + KEEP(" init initialize the terminal") + KEEP(" reset reinitialize the terminal") + KEEP(" capname unlike clear/init/reset, print value for capability \"capname\"") + }; +#undef KEEP + (void) fprintf(stderr, "Usage: %s [options] [command]\n", _nc_progname); + if (optstring != NULL) { + const char *s = msg; + while (*s != '\0') { + fputc(UChar(*s), stderr); + if (!strncmp(s, " -", 3)) { + if (strchr(optstring, s[3]) == NULL) + s = strchr(s, '\n') + 1; + } else if (!strncmp(s, "\n\nC", 3)) + break; + ++s; } + } else { + fputs(msg, stderr); + } + ExitProgram(ErrUsage); +} - s = tparm(str, nargv[0], nargv[1], nargv[2], nargv[3], - nargv[4], nargv[5], nargv[6], nargv[7], nargv[8]); - putp(s); - fflush(stdout); +static char * +check_aliases(char *name, bool program) +{ + static char my_init[] = "init"; + static char my_reset[] = "reset"; + static char my_clear[] = "clear"; + + char *result = name; + if ((is_init = same_program(name, program ? PROG_INIT : my_init))) + result = my_init; + if ((is_reset = same_program(name, program ? PROG_RESET : my_reset))) + result = my_reset; + if ((is_clear = same_program(name, program ? PROG_CLEAR : my_clear))) + result = my_clear; + return result; +} - return (argv + arg_need); +static int +exit_code(int token, int value) +{ + int result = 99; + + switch (token) { + case BOOLEAN: + result = !value; /* TRUE=0, FALSE=1 */ + break; + case NUMBER: + result = 0; /* always zero */ + break; + case STRING: + result = value; /* 0=normal, 1=missing */ + break; + } + return result; } -static void -init(void) +/* + * Returns nonzero on error. + */ +static int +tput_cmd(int fd, TTY * settings, int argc, char **argv, int *used) { - FILE *ifile; - size_t len; - char *buf; - int wstatus; - pid_t pid; - - if (init_prog && !issetugid()) { - switch (pid = vfork()) { - case -1: - err(4, "vfork"); - break; - case 0: - /* child */ - execl(init_prog, init_prog, (char *)NULL); - _exit(127); - break; - default: - while (waitpid(pid, &wstatus, 0) == -1) { - if (errno != EINTR) - break; - } - /* parent */ - break; - } + NCURSES_CONST char *name; + char *s; + int status; +#if !PURE_TERMINFO + bool termcap = FALSE; +#endif + + name = check_aliases(argv[0], FALSE); + *used = 1; + if (is_reset || is_init) { + TTY oldmode = *settings; + + int terasechar = -1; /* new erase character */ + int intrchar = -1; /* new interrupt character */ + int tkillchar = -1; /* new kill character */ + + if (is_reset) { + reset_start(stdout, TRUE, FALSE); + reset_tty_settings(fd, settings, FALSE); + } else { + reset_start(stdout, FALSE, TRUE); } - if (init_1string) - putp(init_1string); - if (init_2string) - putp(init_2string); - set_margins(); - /* always use 8 space tabs */ - if (init_tabs != 8 && clear_all_tabs && set_tab) { - int i; - - putp(clear_all_tabs); - for (i = 0; i < (columns - 1) / 8; i++) { - if (parm_right_cursor) - putp(tparm(parm_right_cursor, 8)); - else - fputs(" ", stdout); - putp(set_tab); - } + +#if HAVE_SIZECHANGE + set_window_size(fd, &lines, &columns); +#else + (void) fd; +#endif + set_control_chars(settings, terasechar, intrchar, tkillchar); + set_conversions(settings); + + if (send_init_strings(fd, &oldmode)) { + reset_flush(); } - if (init_file && !issetugid() && (ifile = fopen(init_file, "r"))) { - while ((buf = fgetln(ifile, &len)) != NULL) { - if (buf[len-1] != '\n') - errx(1, "premature EOF reading %s", init_file); - buf[len-1] = '\0'; - putp(buf); + + update_tty_settings(&oldmode, settings); + return 0; + } + + if (strcmp(name, "longname") == 0) { + PUTS(longname()); + return 0; + } +#if !PURE_TERMINFO + retry: +#endif + if (strcmp(name, "clear") == 0) { + return (clear_cmd(opt_x) == ERR) ? ErrUsage : 0; + } else if ((status = tigetflag(name)) != -1) { + return exit_code(BOOLEAN, status); + } else if ((status = tigetnum(name)) != CANCELLED_NUMERIC) { + (void) printf("%d\n", status); + return exit_code(NUMBER, 0); + } else if ((s = tigetstr(name)) == CANCELLED_STRING) { +#if !PURE_TERMINFO + if (!termcap) { + const struct name_table_entry *np; + + termcap = TRUE; + if ((np = _nc_find_entry(name, _nc_get_hash_table(termcap))) != 0) { + switch (np->nte_type) { + case BOOLEAN: + name = boolnames[np->nte_index]; + break; + + case NUMBER: + name = numnames[np->nte_index]; + break; + + case STRING: + name = strnames[np->nte_index]; + break; } - fclose(ifile); + goto retry; + } } - if (init_3string) - putp(init_3string); - fflush(stdout); -} - -static void -reset(void) -{ - FILE *rfile; - size_t len; - char *buf; - - if (reset_1string) - putp(reset_1string); - if (reset_2string) - putp(reset_2string); - set_margins(); - if (reset_file && !issetugid() && (rfile = fopen(reset_file, "r"))) { - while ((buf = fgetln(rfile, &len)) != NULL) { - if (buf[len-1] != '\n') - errx(1, "premature EOF reading %s", reset_file); - buf[len-1] = '\0'; - putp(buf); +#endif + quit(ErrCapName, "unknown terminfo capability '%s'", name); + } else if (VALID_STRING(s)) { + if (argc > 1) { + int k; + int narg; + int analyzed; + int provided; + int popcount; + long numbers[1 + NUM_PARM]; + char *strings[1 + NUM_PARM]; + char *p_is_s[NUM_PARM]; + TParams paramType; + + /* Nasty hack time. The tparm function needs to see numeric + * parameters as numbers, not as pointers to their string + * representations + */ + + for (k = 1; (k < argc) && (k <= NUM_PARM); k++) { + char *tmp = 0; + strings[k] = argv[k]; + numbers[k] = strtol(argv[k], &tmp, 0); + if (tmp == 0 || *tmp != 0) + numbers[k] = 0; + } + for (k = argc; k <= NUM_PARM; k++) { + numbers[k] = 0; + strings[k] = 0; + } + + paramType = tparm_type(name); +#if NCURSES_XNAMES + /* + * If the capability is an extended one, analyze the string. + */ + if (paramType == Numbers) { + struct name_table_entry const *entry_ptr; + entry_ptr = _nc_find_type_entry(name, STRING, FALSE); + if (entry_ptr == NULL) { + paramType = Other; } - fclose(rfile); + } +#endif + + popcount = 0; + _nc_reset_tparm(NULL); + /* + * Count the number of numeric parameters which are provided. + */ + provided = 0; + for (narg = 1; narg < argc; ++narg) { + char *ending = NULL; + long check = strtol(argv[narg], &ending, 10); + if (check < 0 || ending == argv[narg] || *ending != '\0') + break; + provided = narg; + } + switch (paramType) { + case Str: + s = TPARM_1(s, strings[1]); + analyzed = 1; + if (provided == 0 && argc >= 1) + provided++; + break; + case Str_Str: + s = TPARM_2(s, strings[1], strings[2]); + analyzed = 2; + if (provided == 0 && argc >= 1) + provided++; + if (provided == 1 && argc >= 2) + provided++; + break; + case Num_Str: + s = TPARM_2(s, numbers[1], strings[2]); + analyzed = 2; + if (provided == 1 && argc >= 2) + provided++; + break; + case Num_Str_Str: + s = TPARM_3(s, numbers[1], strings[2], strings[3]); + analyzed = 3; + if (provided == 1 && argc >= 2) + provided++; + if (provided == 2 && argc >= 3) + provided++; + break; + case Numbers: + analyzed = _nc_tparm_analyze(NULL, s, p_is_s, &popcount); +#define myParam(n) numbers[n] + s = TIPARM_9(s, + myParam(1), + myParam(2), + myParam(3), + myParam(4), + myParam(5), + myParam(6), + myParam(7), + myParam(8), + myParam(9)); +#undef myParam + break; + case Other: + /* FALLTHRU */ + default: + analyzed = _nc_tparm_analyze(NULL, s, p_is_s, &popcount); +#define myParam(n) (p_is_s[n - 1] != 0 ? ((TPARM_ARG) strings[n]) : numbers[n]) + s = TPARM_9(s, + myParam(1), + myParam(2), + myParam(3), + myParam(4), + myParam(5), + myParam(6), + myParam(7), + myParam(8), + myParam(9)); +#undef myParam + break; + } + if (analyzed < popcount) { + analyzed = popcount; + } + if (opt_v && (analyzed != provided)) { + fprintf(stderr, "%s: %s parameters for \"%s\"\n", + _nc_progname, + (analyzed < provided ? "extra" : "missing"), + argv[0]); + } + *used += provided; } - if (reset_3string) - putp(reset_3string); - fflush(stdout); + + /* use putp() in order to perform padding */ + putp(s); + return exit_code(STRING, 0); + } + return exit_code(STRING, 1); } -static void -set_margins(void) +int +main(int argc, char **argv) { + char *term; + int errret; + bool cmdline = TRUE; + int c; + char buf[BUFSIZ]; + int result = 0; + int fd; + int used; + TTY old_settings; + TTY tty_settings; + bool is_alias; + bool need_tty; + + if (pledge("stdio rpath wpath tty", NULL) == -1) { + perror("pledge"); + exit(1); + } + + _nc_progname = check_aliases(_nc_rootname(argv[0]), TRUE); + is_alias = (is_clear || is_reset || is_init); + + term = getenv("TERM"); + + while ((c = getopt(argc, argv, is_alias ? "T:Vvx" : "ST:Vvx")) != -1) { + switch (c) { + case 'S': + cmdline = FALSE; + break; + case 'T': + use_env(FALSE); + use_tioctl(TRUE); + term = optarg; + break; + case 'V': + puts(curses_version()); + ExitProgram(EXIT_SUCCESS); + case 'v': /* verbose */ + opt_v = TRUE; + break; + case 'x': /* do not try to clear scrollback */ + opt_x = TRUE; + break; + default: + usage(is_alias ? "TVx" : NULL); + /* NOTREACHED */ + } + } + + need_tty = ((is_reset || is_init) || + (optind < argc && + (!strcmp(argv[optind], "reset") || + !strcmp(argv[optind], "init")))); + + /* + * Modify the argument list to omit the options we processed. + */ + if (is_alias) { + if (optind-- < argc) { + argc -= optind; + argv += optind; + } + argv[0] = strdup(_nc_progname); + } else { + argc -= optind; + argv += optind; + } + + if (term == 0 || *term == '\0') + quit(ErrUsage, "No value for $TERM and no -T specified"); + + fd = save_tty_settings(&tty_settings, need_tty); + old_settings = tty_settings; + + if (setupterm(term, fd, &errret) != OK && errret <= 0) + quit(ErrTermType, "unknown terminal \"%s\"", term); + + if (cmdline) { + int code = 0; + if ((argc <= 0) && !is_alias) + usage(NULL); + while (argc > 0) { + tty_settings = old_settings; + code = tput_cmd(fd, &tty_settings, argc, argv, &used); + if (code != 0) + break; + argc -= used; + argv += used; + } + ExitProgram(code); + } + + while (fgets(buf, sizeof(buf), stdin) != 0) { + size_t need = strlen(buf); + char **argvec = typeCalloc(char *, need + 1); + char **argnow; + int argnum = 0; + char *cp; + + if (argvec == NULL) { + quit(ErrSystem(1), strerror(errno)); + } - /* - * Four possibilities: - * 1) we have set_lr_margin and can set things with one call - * 2) we have set_{left,right}_margin_parm, use two calls - * 3) we have set_{left,right}_margin, set based on position - * 4) none of the above, leave things the way they are - */ - if (set_lr_margin) { - putp(tparm(set_lr_margin, 0, columns - 1)); - } else if (set_left_margin_parm && set_right_margin_parm) { - putp(tparm(set_left_margin_parm, 0)); - putp(tparm(set_right_margin_parm, columns - 1)); - } else if (set_left_margin && set_right_margin && clear_margins) { - putp(clear_margins); - - /* go to column 0 and set the left margin */ - putp(carriage_return ? carriage_return : "\r"); - putp(set_left_margin); - - /* go to last column and set the right margin */ - if (parm_right_cursor) - putp(tparm(parm_right_cursor, columns - 1)); - else - printf("%*s", columns - 1, " "); - putp(set_right_margin); - putp(carriage_return ? carriage_return : "\r"); + /* split the buffer into tokens */ + for (cp = buf; *cp; cp++) { + if (isspace(UChar(*cp))) { + *cp = '\0'; + } else if (cp == buf || cp[-1] == '\0') { + argvec[argnum++] = cp; + if (argnum >= (int) need) + break; + } } - fflush(stdout); -} -static void -usage(void) -{ + argnow = argvec; + while (argnum > 0) { + int code; + tty_settings = old_settings; + code = tput_cmd(fd, &tty_settings, argnum, argnow, &used); + if (code != 0) { + if (result == 0) + result = ErrSystem(0); /* will return value >4 */ + ++result; + } + argnum -= used; + argnow += used; + } + free(argvec); + } - if (strcmp(__progname, "clear") == 0) - (void)fprintf(stderr, "usage: %s [-T term]\n", __progname); - else - (void)fprintf(stderr, - "usage: %s [-T term] attribute [attribute-arg ...] ...\n" - " %s [-T term] -S\n", __progname, __progname); - exit(1); + ExitProgram(result); } diff --git a/usr.bin/tset/Makefile b/usr.bin/tset/Makefile index b7b86036f47..ab0eca74c8b 100644 --- a/usr.bin/tset/Makefile +++ b/usr.bin/tset/Makefile @@ -1,19 +1,14 @@ -# $OpenBSD: Makefile,v 1.12 2019/12/21 21:40:01 espie Exp $ +# $OpenBSD: Makefile,v 1.13 2023/10/17 09:52:11 nicm Exp $ PROG= tset -SRCS= tset.c dump_entry.c +SRCS= reset_cmd.c transform.c tset.c tty_settings.c +CURSES= ${.CURDIR}/../../lib/libcurses DPADD= ${LIBCURSES} LDADD= -lcurses -CURSES= ${.CURDIR}/../../lib/libcurses +LINKS= ${BINDIR}/tset ${BINDIR}/reset TIC= ${.CURDIR}/../tic -CFLAGS+= -I${CURSES} -I${TIC} -I${.CURDIR} -I. -DHAVE_GETTTYNAM -DHAVE_TTYENT_H -CLEANFILES+= termsort.c +CFLAGS+= -I${CURSES} -I${TIC} -I${.CURDIR} -I. .PATH: ${TIC} -LINKS= ${BINDIR}/tset ${BINDIR}/reset - -dump_entry.o: termsort.c - -termsort.c: ${TIC}/MKtermsort.sh - sh ${TIC}/MKtermsort.sh awk ${CURSES}/Caps > ${.TARGET} +CLEANFILES+= termsort.h .include diff --git a/usr.bin/tset/tset.1 b/usr.bin/tset/tset.1 index 3ff51025368..9c9b55a2062 100644 --- a/usr.bin/tset/tset.1 +++ b/usr.bin/tset/tset.1 @@ -1,456 +1,437 @@ -.\" $OpenBSD: tset.1,v 1.24 2022/10/13 21:37:05 jmc Exp $ +.\" $OpenBSD: tset.1,v 1.25 2023/10/17 09:52:11 nicm Exp $ .\" -.\" Copyright (c) 1985, 1990, 1993 -.\" The Regents of the University of California. All rights reserved. +.\"*************************************************************************** +.\" Copyright 2018-2022,2023 Thomas E. Dickey * +.\" Copyright 1998-2016,2017 Free Software Foundation, Inc. * +.\" * +.\" Permission is hereby granted, free of charge, to any person obtaining a * +.\" copy of this software and associated documentation files (the * +.\" "Software"), to deal in the Software without restriction, including * +.\" without limitation the rights to use, copy, modify, merge, publish, * +.\" distribute, distribute with modifications, sublicense, and/or sell * +.\" copies of the Software, and to permit persons to whom the Software is * +.\" furnished to do so, subject to the following conditions: * +.\" * +.\" The above copyright notice and this permission notice shall be included * +.\" in all copies or substantial portions of the Software. * +.\" * +.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * +.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * +.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * +.\" IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * +.\" DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * +.\" OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * +.\" THE USE OR OTHER DEALINGS IN THE SOFTWARE. * +.\" * +.\" Except as contained in this notice, the name(s) of the above copyright * +.\" holders shall not be used in advertising or otherwise to promote the * +.\" sale, use or other dealings in this Software without prior written * +.\" authorization. * +.\"*************************************************************************** .\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)tset.1 8.1 (Berkeley) 6/9/93 -.\" -.Dd $Mdocdate: October 13 2022 $ -.Dt TSET 1 -.Os -.Sh NAME -.Nm tset , -.Nm reset -.Nd terminal initialization -.Sh SYNOPSIS -.Nm tset -.Op Fl cIQqrsVw -.Op Fl -.Op Fl e Ar ch -.Op Fl i Ar ch -.Op Fl k Ar ch -.Op Fl m Ar mapping -.Op Ar terminal -.Nm reset -.Op Fl cIQqrsVw -.Op Fl -.Op Fl e Ar ch -.Op Fl i Ar ch -.Op Fl k Ar ch -.Op Fl m Ar mapping -.Op Ar terminal -.Sh DESCRIPTION -.Nm tset -initializes terminals. -.Nm tset -first determines the type of terminal that you are using. -This determination is done as follows, using the first terminal type found: -.Bl -enum -offset indent -.It -The -.Ar terminal -argument specified on the command line. -.It -The value of the -.Ev TERM -environment variable. -.It -The terminal type associated with the standard error output device in the -.Pa /etc/ttys -file. -.It -The default terminal type, -.Dq unknown . -.El -.Pp -If the terminal type was not specified on the command line, the -.Fl m -option mappings are then applied (see the -.Sx TERMINAL TYPE MAPPING -section below for more information). -Then, if the terminal type begins with a question mark -.Pq Ql \&? , -the user is prompted for confirmation of the terminal type. -An empty response confirms the type, or another type can be entered to -specify a new type. -Once the terminal type has been determined, the terminfo entry for the terminal -is retrieved. -If no terminfo entry is found for the type, the user is prompted for another -terminal type. -.Pp -Once the terminfo entry is retrieved, the window size, backspace, interrupt, -and line kill characters (among many other things) are set and the terminal -and tab initialization strings are sent to the standard error output. + +.TH tset 1 2023-07-01 "ncurses 6.4" "User commands" +.ie \n(.g .ds `` \(lq +.el .ds `` `` +.ie \n(.g .ds '' \(rq +.el .ds '' '' +.de bP +.ie n .IP \(bu 4 +.el .IP \(bu 2 +.. +.SH NAME +\fBtset\fP, \fB?\fP \- terminal initialization +.SH SYNOPSIS +\fBtset\fP [\fB\-IQVcqrsw\fP] [\fB\-\fP] [\fB\-e\fP \fIch\fP] [\fB\-i\fP \fIch\fP] [\fB\-k\fP \fIch\fP] [\fB\-m\fP \fImapping\fP] [\fIterminal\fP] +.br +\fB?\fP [\fB\-IQVcqrsw\fP] [\fB\-\fP] [\fB\-e\fP \fIch\fP] [\fB\-i\fP \fIch\fP] [\fB\-k\fP \fIch\fP] [\fB\-m\fP \fImapping\fP] [\fIterminal\fP] +.SH DESCRIPTION +.SS tset - initialization +This program initializes terminals. +.PP +First, \fBtset\fP retrieves the current terminal mode settings +for your terminal. +It does this by successively testing +.bP +the standard error, +.bP +standard output, +.bP +standard input and +.bP +ultimately \*(``/dev/tty\*('' +.PP +to obtain terminal settings. +Having retrieved these settings, \fBtset\fP remembers which +file descriptor to use when updating settings. +.PP +Next, \fBtset\fP determines the type of terminal that you are using. +This determination is done as follows, using the first terminal type found. +.PP +1. The \fBterminal\fP argument specified on the command line. +.PP +2. The value of the \fBTERM\fP environmental variable. +.PP +3. (BSD systems only.) The terminal type associated with the standard +error output device in the \fI/etc/ttys\fP file. +(On System\-V-like UNIXes and systems using that convention, +\fBgetty\fP(1) does this job by setting +\fBTERM\fP according to the type passed to it by \fI/etc/inittab\fP.) +.PP +4. The default terminal type, \*(``unknown\*('', +is not suitable for curses applications. +.PP +If the terminal type was not specified on the command-line, the \fB\-m\fP +option mappings are then applied (see the section +.B TERMINAL TYPE MAPPING +for more information). +Then, if the terminal type begins with a question mark (\*(``?\*(''), the +user is prompted for confirmation of the terminal type. +An empty +response confirms the type, or, another type can be entered to specify +a new type. +Once the terminal type has been determined, +the terminal description for the terminal is retrieved. +If no terminal description is found +for the type, the user is prompted for another terminal type. +.PP +Once the terminal description is retrieved, +.bP +if the \*(``\fB\-w\fP\*('' option is enabled, \fBtset\fP may update +the terminal's window size. +.IP +If the window size cannot be obtained from the operating system, +but the terminal description (or environment, e.g., \fBLINES\fP +and \fBCOLUMNS\fP variables specify this), +use this to set the operating system's notion of the window size. +.bP +if the \*(``\fB\-c\fP\*('' option is enabled, +the backspace, interrupt and line kill characters +(among many other things) are set +.bP +unless the \*(``\fB\-I\fP\*('' option is enabled, +the terminal +and tab \fIinitialization\fP strings are sent to the standard error output, +and \fBtset\fP waits one second (in case a hardware reset was issued). +.bP Finally, if the erase, interrupt and line kill characters have changed, or are not set to their default values, their values are displayed to the standard error output. -Use the -.Fl c -or -.Fl w -option to select only the window sizing versus the other initialization. -If neither option is given, both are assumed. -.Pp -When invoked as -.Nm reset , -.Nm tset -sets cooked and echo modes, turns off cbreak and raw modes, turns on -newline translation and resets any unset special characters to their -default values before doing the terminal initialization described above. -This is useful after a program dies leaving a terminal in an abnormal state. -Note, you may have to type -.Dq reset +.SS reset - reinitialization +When invoked as \fB?\fP, \fBtset\fP sets the terminal +modes to \*(``sane\*('' values: +.bP +sets cooked and echo modes, +.bP +turns off cbreak and raw modes, +.bP +turns on newline translation and +.bP +resets any unset special characters to their default values +.PP +before +doing the terminal initialization described above. +Also, rather than using the terminal \fIinitialization\fP strings, +it uses the terminal \fIreset\fP strings. +.PP +The \fB?\fP command is useful +after a program dies leaving a terminal in an abnormal state: +.bP +you may have to type +.sp + \fI\fB?\fI\fR +.sp (the line-feed character is normally control-J) to get the terminal to work, as carriage-return may no longer work in the abnormal state. +.bP Also, the terminal will often not echo the command. -.Pp +.SH OPTIONS The options are as follows: -.Bl -tag -width Ds -.It Fl -The terminal type is displayed to the standard output, and the terminal is -not initialized in any way. -This option has been deprecated in favor of the -.Fl q -flag. -.It Fl c +.TP 5 +.B \-c Set control characters and modes. -.It Fl e Ar ch -Set the erase character to -.Ar ch . -.It Fl I +.TP 5 +.BI \-e\ ch +Set the erase character to \fIch\fP. +.TP +.B \-I Do not send the terminal or tab initialization strings to the terminal. -.It Fl i Ar ch -Set the interrupt character to -.Ar ch . -.It Fl k Ar ch -Set the line kill character to -.Ar ch . -.It Fl m Ar mapping +.TP +.BI \-i\ ch +Set the interrupt character to \fIch\fP. +.TP +.BI \-k\ ch +Set the line kill character to \fIch\fP. +.TP +.BI \-m\ mapping Specify a mapping from a port type to a terminal. -See the -.Sx TERMINAL TYPE MAPPING -section below for more information. -.It Fl Q -Don't display any values for the erase, interrupt and line kill characters. -Normally -.Nm -displays the values for control characters which differ from the system's -default values. -.It Fl q +See the section +.B TERMINAL TYPE MAPPING +for more information. +.TP +.B \-Q +Do not display any values for the erase, interrupt and line kill characters. +Normally \fBtset\fP displays the values for control characters which +differ from the system's default values. +.TP +.B \-q The terminal type is displayed to the standard output, and the terminal is not initialized in any way. -.It Fl r +The option \*(``\-\*('' by itself is equivalent but archaic. +.TP +.B \-r Print the terminal type to the standard error output. -.It Fl s +.TP +.B \-s Print the sequence of shell commands to initialize the environment variable -.Ev TERM -to the standard output. -See the -.Sx SETTING THE ENVIRONMENT -section below for details. -.It Fl V -Report the version of ncurses which was used in this program, and exit. -.It Fl w -Resize the window to match the size deduced via -.Xr setupterm 3 . -Normally this has no effect, unless -.Xr setupterm 3 -is not able to detect the window size. -.El -.Pp -The arguments for the -.Fl e , -.Fl i , -and -.Fl k -options may either be entered as actual characters or by using the -.Dq hat -notation, i.e., control-H may be specified as -.Dq ^H -or -.Dq ^h . -.Sh SETTING THE ENVIRONMENT +\fBTERM\fP to the standard output. +See the section +.B SETTING THE ENVIRONMENT +for details. +.TP +.B \-V +reports the version of ncurses which was used in this program, and exits. +.TP +.B \-w +Resize the window to match the size deduced via \fBsetupterm\fP(3). +Normally this has no effect, +unless \fBsetupterm\fP is not able to detect the window size. +.PP +The arguments for the \fB\-e\fP, \fB\-i\fP, and \fB\-k\fP +options may either be entered as actual characters +or by using the \*(``hat\*('' +notation, i.e., control-h may be specified as \*(``^H\*('' or \*(``^h\*(''. +.PP +If neither \fB\-c\fP or \fB\-w\fP is given, both options are assumed. +. +.SH SETTING THE ENVIRONMENT It is often desirable to enter the terminal type and information about the terminal's capabilities into the shell's environment. -This is done using the -.Fl s -option. -.Pp -When the -.Fl s -option is specified, the commands to enter the information into the -shell's environment are written to the standard output. -If the -.Ev SHELL -environment variable ends in -.Dq csh , -the commands are for -.Xr csh 1 , -otherwise, they are for -.Xr sh 1 . -Note, the -.Xr csh 1 -commands set and unset the shell variable -.Dq noglob , -leaving it unset. -The following line in the -.Pa .login -or -.Pa .profile -files will initialize the environment correctly: -.Bd -literal -offset indent -eval \`tset -s options ... \` -.Ed -.Sh TERMINAL TYPE MAPPING -When the terminal is not hardwired into the system (or the current system -information is incorrect), the terminal type derived from the -.Pa /etc/ttys -file or the -.Ev TERM -environment variable is often something generic like -.Dq network , -.Dq dialup , -or -.Dq unknown . -When -.Nm tset -is used in a startup script -.Pf ( Pa .profile -for -.Xr sh 1 -users or -.Pa .login -for -.Xr csh 1 -users), it is often desirable to provide information about the type of -terminal used on such ports. -.Pp -The purpose of the -.Fl m -option is to -.Dq map +This is done using the \fB\-s\fP option. +.PP +When the \fB\-s\fP option is specified, the commands to enter the information +into the shell's environment are written to the standard output. +If +the \fBSHELL\fP environmental variable ends in \*(``csh\*('', the commands +are for \fBcsh\fP, otherwise, they are for \fBsh\fP(1). +Note, the \fBcsh\fP commands set and unset the shell variable +\fBnoglob\fP, leaving it unset. +The following line in the \fB.login\fP +or \fB.profile\fP files will initialize the environment correctly: +.sp + eval \`tset \-s options ... \` +. +.SH TERMINAL TYPE MAPPING +When the terminal is not hardwired into the system (or the current +system information is incorrect) the terminal type derived from the +\fI/etc/ttys\fP file or the \fBTERM\fP environmental variable is often +something generic like \fBnetwork\fP, \fBdialup\fP, or \fBunknown\fP. +When \fBtset\fP is used in a startup script it is often desirable to +provide information about the type of terminal used on such ports. +.PP +The \fB\-m\fP options maps from some set of conditions to a terminal type, that is, to -tell -.Nm tset : -.Do -If I'm on this port at a particular speed, guess that I'm on that -kind of terminal -.Dc . -.Pp -The argument to the -.Fl m -option consists of an optional port type, an optional operator, an optional -baud rate specification, an optional colon -.Pq Ql \&: -character, and a terminal type. -The port type is a string (delimited by either the operator or the colon -character). -The operator may be any combination of: -.Ql > , -.Ql < , -.Ql @ , -and -.Ql \&! ; -.Ql > -means greater than, -.Ql < -means less than, -.Ql @ -means equal to, -and -.Ql \&! -inverts the sense of the test. +tell \fBtset\fP +\*(``If I'm on this port at a particular speed, +guess that I'm on that kind of terminal\*(''. +.PP +The argument to the \fB\-m\fP option consists of an optional port type, an +optional operator, an optional baud rate specification, an optional +colon (\*(``:\*('') character and a terminal type. +The port type is a +string (delimited by either the operator or the colon character). +The operator may be any combination of +\*(``>\*('', +\*(``<\*('', +\*(``@\*('', +and \*(``!\*(''; +\*(``>\*('' means greater than, +\*(``<\*('' means less than, +\*(``@\*('' means equal to and +\*(``!\*('' inverts the sense of the test. The baud rate is specified as a number and is compared with the speed -of the standard error output (which should be the controlling terminal). +of the standard error output (which should be the control terminal). The terminal type is a string. -.Pp -If the terminal type is not specified on the command line, the -.Fl m +.PP +If the terminal type is not specified on the command line, the \fB\-m\fP mappings are applied to the terminal type. -If the port type and baud rate match the mapping, the terminal type specified -in the mapping replaces the current type. -If more than one mapping is specified, the first applicable mapping is used. -.Pp -For example, consider the following mapping: -.Dq dialup>9600:vt100 . -The port type is -.Dq dialup , -the operator is -.Dq > , -the baud rate specification is -.Dq 9600 , -and the terminal type is -.Dq vt100 . -The result of this mapping is to specify that if the terminal type is -.Dq dialup , +If the port type and baud +rate match the mapping, the terminal type specified in the mapping +replaces the current type. +If more than one mapping is specified, the +first applicable mapping is used. +.PP +For example, consider the following mapping: \fBdialup>9600:vt100\fP. +The port type is dialup , the operator is >, the baud rate +specification is 9600, and the terminal type is vt100. +The result of +this mapping is to specify that if the terminal type is \fBdialup\fP, and the baud rate is greater than 9600 baud, a terminal type of -.Dq vt100 -will be used. -.Pp -If no port type is specified, the terminal type will match any port type, -for example, -.Dq -m dialup:vt100 -m :?xterm +\fBvt100\fP will be used. +.PP +If no baud rate is specified, the terminal type will match any baud rate. +If no port type is specified, the terminal type will match any port type. +For example, \fB\-m dialup:vt100 \-m :?xterm\fP will cause any dialup port, regardless of baud rate, to match the terminal -type -.Dq vt100 , -and any non-dialup port type to match the terminal type -.Dq ?xterm . +type vt100, and any non-dialup port type to match the terminal type ?xterm. Note, because of the leading question mark, the user will be -queried on a default port as to whether they are actually using an -.Ar xterm +queried on a default port as to whether they are actually using an xterm terminal. -.Pp -No whitespace characters are permitted in the -.Fl m -option argument. -Also, to avoid problems with meta-characters, it is suggested that the entire -.Fl m -option argument be placed within single quote characters, and that -.Xr csh 1 -users insert a backslash character -.Pq Ql \e -before any exclamation marks -.Pq Ql \&! . -.Sh ENVIRONMENT -The -.Nm tset -command utilizes the -.Ev SHELL -and -.Ev TERM -environment variables. -.Sh FILES -.Bl -tag -width /usr/share/terminfo -compact -.It Pa /etc/ttys -port name to terminal type mapping database -.It Pa /usr/share/terminfo +.PP +No whitespace characters are permitted in the \fB\-m\fP option argument. +Also, to avoid problems with meta-characters, it is suggested that the +entire \fB\-m\fP option argument be placed within single quote characters, +and that \fBcsh\fP users insert a backslash character (\*(``\e\*('') before +any exclamation marks (\*(``!\*(''). +.SH HISTORY +A \fBreset\fP command appeared in 1BSD (March 1978), written by Kurt Shoens. +This program set the \fIerase\fP and \fIkill\fP characters +to \fB^H\fP (backspace) and \fB@\fP respectively. +Mark Horton improved that in 3BSD (October 1979), adding +\fIintr\fP, \fIquit\fP, \fIstart\fP/\fIstop\fP and \fIeof\fP characters +as well as changing the program to avoid modifying any user settings. +That version of \fBreset\fP did not use the termcap database. +.PP +A separate \fBtset\fP command was provided in 1BSD by Eric Allman, +using the termcap database. +Allman's comments in the source code indicate +that he began work in October 1977, +continuing development over the next few years. +.PP +According to comments in the source code, +the \fBtset\fP program was modified in September 1980, +to use logic copied from the 3BSD \*(``reset\*('' +when it was invoked as \fBreset\fP. +This version appeared in 4.1cBSD, late in 1982. +.PP +Other developers (e.g., Keith Bostic and Jim Bloom) +continued to modify \fBtset\fP until 4.4BSD was released in 1993. +.PP +The \fBncurses\fP implementation +was lightly adapted from the 4.4BSD sources for a terminfo environment by Eric +S. Raymond . +.SH COMPATIBILITY +Neither IEEE Std 1003.1/The Open Group Base Specifications Issue 7 +(POSIX.1-2008) nor +X/Open Curses Issue 7 documents \fBtset\fP or \fB?\fP. +.PP +The AT&T \fBtput\fP utility (AIX, HPUX, Solaris) +incorporated the terminal-mode manipulation as well as termcap-based features +such as resetting tabstops from \fBtset\fP in BSD (4.1c), +presumably with the intention of making \fBtset\fP obsolete. +However, each of those systems still provides \fBtset\fP. +In fact, the commonly-used \fBreset\fP utility +is always an alias for \fBtset\fP. +.PP +The \fBtset\fP utility provides for backward-compatibility with BSD +environments (under most modern UNIXes, \fB/etc/inittab\fP and \fBgetty\fP(1) +can set \fBTERM\fP appropriately for each dial-up line; this obviates what was +\fBtset\fP's most important use). +This implementation behaves like 4.4BSD +\fBtset\fP, with a few exceptions specified here. +.PP +A few options are different +because the \fBTERMCAP\fP variable +is no longer supported under terminfo-based \fBncurses\fP: +.bP +The \fB\-S\fP option of BSD \fBtset\fP no longer works; +it prints an error message to the standard error and dies. +.bP +The \fB\-s\fP option only sets \fBTERM\fP, not \fBTERMCAP\fP. +.PP +There was an undocumented 4.4BSD feature +that invoking \fBtset\fP via a link named +\*(``TSET\*('' (or via any other name beginning with an upper-case letter) +set the terminal to use upper-case only. +This feature has been omitted. +.PP +The \fB\-A\fP, \fB\-E\fP, \fB\-h\fP, \fB\-u\fP and \fB\-v\fP +options were deleted from the \fBtset\fP +utility in 4.4BSD. +None of them were documented in 4.3BSD and all are +of limited utility at best. +The \fB\-a\fP, \fB\-d\fP, and \fB\-p\fP options are similarly +not documented or useful, but were retained as they appear to be in +widespread use. +It is strongly recommended that any usage of these +three options be changed to use the \fB\-m\fP option instead. +The \fB\-a\fP, \fB\-d\fP, and \fB\-p\fP options +are therefore omitted from the usage summary above. +.PP +Very old systems, e.g., 3BSD, used a different terminal driver which +was replaced in 4BSD in the early 1980s. +To accommodate these older systems, the 4BSD \fBtset\fP provided a +\fB\-n\fP option to specify that the new terminal driver should be used. +This implementation does not provide that choice. +.PP +It is still permissible to specify the \fB\-e\fP, \fB\-i\fP, +and \fB\-k\fP options without arguments, +although it is strongly recommended that such usage be fixed to +explicitly specify the character. +.PP +As of 4.4BSD, +executing \fBtset\fP as \fB?\fP no longer implies the \fB\-Q\fP option. +Also, the interaction between the \- option and the \fIterminal\fP +argument in some historic implementations of \fBtset\fP has been removed. +.PP +The \fB\-c\fP and \fB\-w\fP options are not found in earlier implementations. +However, a different window size-change feature was provided in 4.4BSD. +.bP +In 4.4BSD, \fBtset\fP uses the window size from the termcap description +to set the window size if \fBtset\fP is not able to obtain the window +size from the operating system. +.bP +In ncurses, \fBtset\fP obtains the window size using +\fBsetupterm\fP, which may be from +the operating system, +the \fBLINES\fP and \fBCOLUMNS\fP environment variables or +the terminal description. +.PP +Obtaining the window size from the terminal description is common to +both implementations, but considered obsolescent. +Its only practical use is for hardware terminals. +Generally speaking, a window size would be unset only if there were +some problem obtaining the value from the operating system +(and \fBsetupterm\fP would still fail). +For that reason, the \fBLINES\fP and \fBCOLUMNS\fP environment variables +may be useful for working around window-size problems. +Those have the drawback that if the window is resized, +those variables must be recomputed and reassigned. +To do this more easily, use the \fBresize\fP(1) program. +.SH ENVIRONMENT +The \fBtset\fP command uses these environment variables: +.TP 5 +SHELL +tells \fBtset\fP whether to initialize \fBTERM\fP using \fBsh\fP(1) or +\fBcsh\fP(1) syntax. +.TP 5 +TERM +Denotes your terminal type. +Each terminal type is distinct, though many are similar. +.TP 5 +TERMCAP +may denote the location of a termcap database. +If it is not an absolute pathname, e.g., begins with a \*(``/\*('', +\fBtset\fP removes the variable from the environment before looking +for the terminal description. +.SH FILES +.TP 5 +/etc/ttys +system port name to terminal type mapping database (BSD versions only). +.TP +/usr/share/terminfo terminal capability database -.El -.Sh SEE ALSO -.Xr csh 1 , -.Xr sh 1 , -.Xr stty 1 , -.Xr tty 4 , -.Xr terminfo 5 , -.Xr ttys 5 , -.Xr environ 7 -.Sh STANDARDS -The -.Nm tset -command now uses the -.Xr terminfo 5 -database where previous versions used -.Xr termcap 5 . -.Pp -Historic versions of the -.Xr termcap 3 -library limited entries to 1023 bytes. -Modern -.Xr terminfo 3 -entries are often much larger, making it impossible to -store the full entry in the -.Ev TERMCAP -environment variable. -Because of this, the -.Fl S -option is no longer supported (it prints an error message to the standard -error and exits) and the -.Fl s -option only sets -.Ev TERM , -not -.Ev TERMCAP . -.Pp -The -.Fl A , -.Fl E , -.Fl h , -.Fl u , -and -.Fl v -options have been deleted from the -.Nm tset -utility. -None of them were documented in -.Bx 4.3 -and all are of limited utility at best. -The -.Fl a , -.Fl d -and -.Fl p -options are similarly not documented or useful, but were retained as they -appear to be in widespread use. -It is strongly recommended that any usage of these three options be -changed to use the -.Fl m -option instead. -The -.Fl n -option remains, but has no effect. -It is still permissible to specify the -.Fl e , -.Fl i -and -.Fl k -options without arguments, although it is strongly recommended that such -usage be fixed to explicitly specify the character. -.Pp -Executing -.Nm tset -as -.Nm reset -no longer implies the -.Fl Q -option. -Also, the interaction between the -.Fl -option and the -.Ar terminal -argument in some historic implementations of -.Nm tset -has been removed. -.Pp -Finally, the -.Nm tset -implementation has been completely redone (as part of the addition to the -system of a -.St -p1003.1-88 -compliant terminal interface) and will no longer compile on systems with -older terminal interfaces. -.Sh HISTORY -The -.Nm tset -and -.Nm reset -utilities first appeared in -.Bx 1 . -.Sh AUTHORS -.An -nosplit -The original version of -.Nm tset -was written by -.An Eric P. Allman -in October 1977, and -.Nm reset -was originally written by -.An Kurt Shoens . -The current version also contains code by -.An Zeyd M. Ben-Halim , -.An Eric S. Raymond , -and -.An Thomas E. Dickey . +.SH SEE ALSO +.hy 0 +\fBcsh\fP(1), +\fBsh\fP(1), +\fBstty\fP(1), +\fBterminfo\fP(3), +\fBtty\fP(4), +\fBterminfo\fP(5), +\fBttys\fP(5), +\fBenviron\fP(7) +.hy +.PP +This describes \fBncurses\fP +version 6.4 (patch 20230826). diff --git a/usr.bin/tset/tset.c b/usr.bin/tset/tset.c index fe4440fb8dc..556750f639a 100644 --- a/usr.bin/tset/tset.c +++ b/usr.bin/tset/tset.c @@ -1,7 +1,8 @@ -/* $OpenBSD: tset.c,v 1.44 2022/12/04 23:50:49 cheloha Exp $ */ +/* $OpenBSD: tset.c,v 1.45 2023/10/17 09:52:11 nicm Exp $ */ /**************************************************************************** - * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * + * Copyright 2020,2021 Thomas E. Dickey * + * Copyright 1998-2016,2017 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -34,6 +35,22 @@ * and: Thomas E. Dickey 1996-on * ****************************************************************************/ +/* + * Notes: + * The initial adaptation from 4.4BSD Lite sources in September 1995 used 686 + * lines from that version, and made changes/additions for 150 lines. There + * was no reformatting, so with/without ignoring whitespace, the amount of + * change is the same. + * + * Comparing with current (2009) source, excluding this comment: + * a) 209 lines match identically to the 4.4BSD Lite sources, with 771 lines + * changed/added. + * a) Ignoring whitespace, the current version still uses 516 lines from the + * 4.4BSD Lite sources, with 402 lines changed/added. + * + * Raymond's original comment on this follows... + */ + /* * tset.c - terminal initialization utility * @@ -71,61 +88,30 @@ * SUCH DAMAGE. */ -#define USE_LIBTINFO -#define __INTERNAL_CAPS_VISIBLE /* we need to see has_hardware_tabs */ -#include - -#include -#include +#include #include -#include +#include +#include -#if HAVE_GETTTYNAM && HAVE_TTYENT_H +#if HAVE_GETTTYNAM #include #endif #ifdef NeXT char *ttyname(int fd); #endif -#if HAVE_SIZECHANGE -# if !defined(sun) || !TERMIOS -# if HAVE_SYS_IOCTL_H -# include -# endif -# endif -#endif - -#if NEED_PTEM_H -/* they neglected to define struct winsize in termios.h -- it's only - in termio.h */ -#include -#include -#endif -#include -#include +#ifndef environ extern char **environ; +#endif -#undef CTRL -#define CTRL(x) ((x) & 0x1f) - -const char *_nc_progname; - -static TTY mode, oldmode, original; - -static bool opt_c; /* set control-chars */ -static bool opt_w; /* set window-size */ - -static bool can_restore = FALSE; -static bool isreset = FALSE; /* invoked as reset */ -static int terasechar = -1; /* new erase character */ -static int intrchar = -1; /* new interrupt character */ -static int tkillchar = -1; /* new kill character */ -static int tlines, tcolumns; /* window size */ +const char *_nc_progname = "tset"; #define LOWERCASE(c) ((isalpha(UChar(c)) && isupper(UChar(c))) ? tolower(UChar(c)) : (c)) +static GCC_NORETURN void exit_error(void); + static int CaselessCmp(const char *a, const char *b) { /* strcasecmp isn't portable */ @@ -138,19 +124,18 @@ CaselessCmp(const char *a, const char *b) return LOWERCASE(*a) - LOWERCASE(*b); } -static void +static GCC_NORETURN void exit_error(void) { - if (can_restore) - tcsetattr(STDERR_FILENO, TCSADRAIN, &original); + restore_tty_settings(); (void) fprintf(stderr, "\n"); fflush(stderr); ExitProgram(EXIT_FAILURE); /* NOTREACHED */ } -static void -err(const char *fmt,...) +static GCC_NORETURN void +err(const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -161,37 +146,24 @@ err(const char *fmt,...) /* NOTREACHED */ } -static void +static GCC_NORETURN void failed(const char *msg) { - fprintf(stderr, "%s: ", _nc_progname); - perror(msg); + char temp[BUFSIZ]; + size_t len = strlen(_nc_progname) + 2; + + if ((int) len < (int) sizeof(temp) - 12) { + _nc_STRCPY(temp, _nc_progname, sizeof(temp)); + _nc_STRCAT(temp, ": ", sizeof(temp)); + } else { + _nc_STRCPY(temp, "tset: ", sizeof(temp)); + } + _nc_STRNCAT(temp, msg, sizeof(temp), sizeof(temp) - strlen(temp) - 2); + perror(temp); exit_error(); /* NOTREACHED */ } -static void -cat(char *file) -{ - FILE *fp; - size_t nr; - char buf[BUFSIZ]; - - if ((fp = fopen(file, "r")) == 0) - failed(file); - - while ((nr = fread(buf, sizeof(char), sizeof(buf), fp)) != 0) - if (fwrite(buf, sizeof(char), nr, stderr) != nr) - failed("write to stderr"); - fclose(fp); -} - -static int -outc(int c) -{ - return putc(c, stderr); -} - /* Prompt the user for a terminal type. */ static const char * askuser(const char *dflt) @@ -205,14 +177,17 @@ askuser(const char *dflt) exit_error(); /* NOTREACHED */ } + for (;;) { + char *p; + if (dflt) (void) fprintf(stderr, "Terminal type? [%s] ", dflt); else (void) fprintf(stderr, "Terminal type? "); (void) fflush(stderr); - if (fgets(answer, sizeof(answer), stdin) == NULL) { + if (fgets(answer, sizeof(answer), stdin) == 0) { if (dflt == 0) { exit_error(); /* NOTREACHED */ @@ -220,7 +195,8 @@ askuser(const char *dflt) return (dflt); } - answer[strcspn(answer, "\n")] = '\0'; + if ((p = strchr(answer, '\n')) != 0) + *p = '\0'; if (answer[0]) return (answer); if (dflt != 0) @@ -252,87 +228,142 @@ typedef struct map { static MAP *cur, *maplist; +#define DATA(name,value) { { name }, value } + typedef struct speeds { - const char *string; + const char string[8]; int speed; } SPEEDS; +#if defined(EXP_WIN32_DRIVER) static const SPEEDS speeds[] = { - {"0", B0}, - {"50", B50}, - {"75", B75}, - {"110", B110}, - {"134", B134}, - {"134.5", B134}, - {"150", B150}, - {"200", B200}, - {"300", B300}, - {"600", B600}, - {"1200", B1200}, - {"1800", B1800}, - {"2400", B2400}, - {"4800", B4800}, - {"9600", B9600}, + {"0", 0} +}; +#else +static const SPEEDS speeds[] = +{ + DATA("0", B0), + DATA("50", B50), + DATA("75", B75), + DATA("110", B110), + DATA("134", B134), + DATA("134.5", B134), + DATA("150", B150), + DATA("200", B200), + DATA("300", B300), + DATA("600", B600), + DATA("1200", B1200), + DATA("1800", B1800), + DATA("2400", B2400), + DATA("4800", B4800), + DATA("9600", B9600), /* sgttyb may define up to this point */ #ifdef B19200 - {"19200", B19200}, + DATA("19200", B19200), #endif #ifdef B38400 - {"38400", B38400}, + DATA("38400", B38400), #endif #ifdef B19200 - {"19200", B19200}, + DATA("19200", B19200), #endif #ifdef B38400 - {"38400", B38400}, + DATA("38400", B38400), #endif #ifdef B19200 - {"19200", B19200}, + DATA("19200", B19200), #else #ifdef EXTA - {"19200", EXTA}, + DATA("19200", EXTA), #endif #endif #ifdef B38400 - {"38400", B38400}, + DATA("38400", B38400), #else #ifdef EXTB - {"38400", EXTB}, + DATA("38400", EXTB), #endif #endif #ifdef B57600 - {"57600", B57600}, + DATA("57600", B57600), +#endif +#ifdef B76800 + DATA("76800", B57600), #endif #ifdef B115200 - {"115200", B115200}, + DATA("115200", B115200), +#endif +#ifdef B153600 + DATA("153600", B153600), #endif #ifdef B230400 - {"230400", B230400}, + DATA("230400", B230400), +#endif +#ifdef B307200 + DATA("307200", B307200), #endif #ifdef B460800 - {"460800", B460800}, + DATA("460800", B460800), +#endif +#ifdef B500000 + DATA("500000", B500000), +#endif +#ifdef B576000 + DATA("576000", B576000), +#endif +#ifdef B921600 + DATA("921600", B921600), +#endif +#ifdef B1000000 + DATA("1000000", B1000000), +#endif +#ifdef B1152000 + DATA("1152000", B1152000), +#endif +#ifdef B1500000 + DATA("1500000", B1500000), +#endif +#ifdef B2000000 + DATA("2000000", B2000000), +#endif +#ifdef B2500000 + DATA("2500000", B2500000), +#endif +#ifdef B3000000 + DATA("3000000", B3000000), +#endif +#ifdef B3500000 + DATA("3500000", B3500000), +#endif +#ifdef B4000000 + DATA("4000000", B4000000), #endif - {(char *) 0, 0} }; +#undef DATA +#endif static int tbaudrate(char *rate) { - const SPEEDS *sp; - int found = FALSE; + const SPEEDS *sp = 0; + size_t n; /* The baudrate number can be preceded by a 'B', which is ignored. */ if (*rate == 'B') ++rate; - for (sp = speeds; sp->string; ++sp) { - if (!CaselessCmp(rate, sp->string)) { - found = TRUE; + for (n = 0; n < SIZEOF(speeds); ++n) { + if (n > 0 && (speeds[n].speed <= speeds[n - 1].speed)) { + /* if the speeds are not increasing, likely a numeric overflow */ + break; + } + if (!CaselessCmp(rate, speeds[n].string)) { + sp = speeds + n; break; } } - if (!found) + if (sp == 0) err("unknown baud rate %s", rate); return (sp->speed); } @@ -351,9 +382,13 @@ add_mapping(const char *port, char *arg) char *base = 0; copy = strdup(arg); - mapp = malloc(sizeof(MAP)); + mapp = typeMalloc(MAP, 1); if (copy == 0 || mapp == 0) failed("malloc"); + + assert(copy != 0); + assert(mapp != 0); + mapp->next = 0; if (maplist == 0) cur = maplist = mapp; @@ -415,9 +450,6 @@ add_mapping(const char *port, char *arg) mapp->speed = tbaudrate(p); } - if (arg == (char *) 0) /* Non-optional type. */ - goto badmopt; - mapp->type = arg; /* Terminate porttype, if specified. */ @@ -475,19 +507,19 @@ mapped(const char *type) match = TRUE; break; case EQ: - match = (ospeed == mapp->speed); + match = ((int) ospeed == mapp->speed); break; case GE: - match = (ospeed >= mapp->speed); + match = ((int) ospeed >= mapp->speed); break; case GT: - match = (ospeed > mapp->speed); + match = ((int) ospeed > mapp->speed); break; case LE: - match = (ospeed <= mapp->speed); + match = ((int) ospeed <= mapp->speed); break; case LT: - match = (ospeed < mapp->speed); + match = ((int) ospeed < mapp->speed); break; default: match = FALSE; @@ -510,17 +542,21 @@ mapped(const char *type) * its termcap entry. */ static const char * -get_termcap_entry(char *userarg) +get_termcap_entry(int fd, char *userarg) { int errret; char *p; const char *ttype; +#if HAVE_PATH_TTYS #if HAVE_GETTTYNAM struct ttyent *t; #else FILE *fp; #endif char *ttypath; +#endif /* HAVE_PATH_TTYS */ + + (void) fd; if (userarg) { ttype = userarg; @@ -531,7 +567,8 @@ get_termcap_entry(char *userarg) if ((ttype = getenv("TERM")) != 0) goto map; - if ((ttypath = ttyname(STDERR_FILENO)) != 0) { +#if HAVE_PATH_TTYS + if ((ttypath = ttyname(fd)) != 0) { p = _nc_basename(ttypath); #if HAVE_GETTTYNAM /* @@ -549,7 +586,7 @@ get_termcap_entry(char *userarg) char buffer[BUFSIZ]; char *s, *t, *d; - while (fgets(buffer, sizeof(buffer), fp) != NULL) { + while (fgets(buffer, sizeof(buffer) - 1, fp) != 0) { for (s = buffer, t = d = 0; *s; s++) { if (isspace(UChar(*s))) *s = '\0'; @@ -568,6 +605,7 @@ get_termcap_entry(char *userarg) } #endif /* HAVE_GETTTYNAM */ } +#endif /* HAVE_PATH_TTYS */ /* If still undefined, use "unknown". */ ttype = "unknown"; @@ -579,13 +617,14 @@ get_termcap_entry(char *userarg) * real entry from /etc/termcap. This prevents us from being fooled * by out of date stuff in the environment. */ - found:if ((p = getenv("TERMCAP")) != 0 && !_nc_is_abs_path(p)) { + found: + if ((p = getenv("TERMCAP")) != 0 && !_nc_is_abs_path(p)) { /* 'unsetenv("TERMCAP")' is not portable. * The 'environ' array is better. */ int n; for (n = 0; environ[n] != 0; n++) { - if (!strncmp("TERMCAP=", environ[n], 8)) { + if (!strncmp("TERMCAP=", environ[n], (size_t) 8)) { while ((environ[n] = environ[n + 1]) != 0) { n++; } @@ -605,7 +644,7 @@ get_termcap_entry(char *userarg) ttype = askuser(0); } /* Find the terminfo entry. If it doesn't exist, ask the user. */ - while (setupterm((NCURSES_CONST char *) ttype, STDOUT_FILENO, &errret) + while (setupterm((NCURSES_CONST char *) ttype, fd, &errret) != OK) { if (errret == 0) { (void) fprintf(stderr, "%s: unknown terminal type %s\n", @@ -625,438 +664,12 @@ get_termcap_entry(char *userarg) return (ttype); } -/************************************************************************** - * - * Mode-setting logic - * - **************************************************************************/ - -/* some BSD systems have these built in, some systems are missing - * one or more definitions. The safest solution is to override unless the - * commonly-altered ones are defined. - */ -#if !(defined(CERASE) && defined(CINTR) && defined(CKILL) && defined(CQUIT)) -#undef CEOF -#undef CERASE -#undef CINTR -#undef CKILL -#undef CLNEXT -#undef CRPRNT -#undef CQUIT -#undef CSTART -#undef CSTOP -#undef CSUSP -#endif - -/* control-character defaults */ -#ifndef CEOF -#define CEOF CTRL('D') -#endif -#ifndef CERASE -#define CERASE CTRL('H') -#endif -#ifndef CINTR -#define CINTR 127 /* ^? */ -#endif -#ifndef CKILL -#define CKILL CTRL('U') -#endif -#ifndef CLNEXT -#define CLNEXT CTRL('v') -#endif -#ifndef CRPRNT -#define CRPRNT CTRL('r') -#endif -#ifndef CQUIT -#define CQUIT CTRL('\\') -#endif -#ifndef CSTART -#define CSTART CTRL('Q') -#endif -#ifndef CSTOP -#define CSTOP CTRL('S') -#endif -#ifndef CSUSP -#define CSUSP CTRL('Z') -#endif - -#if defined(_POSIX_VDISABLE) -#define DISABLED(val) (((_POSIX_VDISABLE != -1) \ - && ((val) == _POSIX_VDISABLE)) \ - || ((val) <= 0)) -#else -#define DISABLED(val) ((int)(val) <= 0) -#endif - -#define CHK(val, dft) (DISABLED(val) ? dft : val) - -static bool set_tabs(void); - -/* - * Reset the terminal mode bits to a sensible state. Very useful after - * a child program dies in raw mode. - */ -static void -reset_mode(void) -{ -#ifdef TERMIOS - tcgetattr(STDERR_FILENO, &mode); -#else - stty(STDERR_FILENO, &mode); -#endif - -#ifdef TERMIOS -#if defined(VDISCARD) && defined(CDISCARD) - mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD); -#endif - mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF); - mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE); -#if defined(VFLUSH) && defined(CFLUSH) - mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH); -#endif - mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR); - mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL); -#if defined(VLNEXT) && defined(CLNEXT) - mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT); -#endif - mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT); -#if defined(VREPRINT) && defined(CRPRNT) - mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT); -#endif -#if defined(VSTART) && defined(CSTART) - mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART); -#endif -#if defined(VSTOP) && defined(CSTOP) - mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP); -#endif -#if defined(VSUSP) && defined(CSUSP) - mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP); -#endif -#if defined(VWERASE) && defined(CWERASE) - mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE); -#endif - - mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR -#ifdef IUCLC - | IUCLC -#endif -#ifdef IXANY - | IXANY -#endif - | IXOFF); - - mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON -#ifdef IMAXBEL - | IMAXBEL -#endif - ); - - mode.c_oflag &= ~(0 -#ifdef OLCUC - | OLCUC -#endif -#ifdef OCRNL - | OCRNL -#endif -#ifdef ONOCR - | ONOCR -#endif -#ifdef ONLRET - | ONLRET -#endif -#ifdef OFILL - | OFILL -#endif -#ifdef OFDEL - | OFDEL -#endif -#ifdef NLDLY - | NLDLY -#endif -#ifdef CRDLY - | CRDLY -#endif -#ifdef TABDLY - | TABDLY -#endif -#ifdef BSDLY - | BSDLY -#endif -#ifdef VTDLY - | VTDLY -#endif -#ifdef FFDLY - | FFDLY -#endif - ); - - mode.c_oflag |= (OPOST -#ifdef ONLCR - | ONLCR -#endif - ); - - mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL); - mode.c_cflag |= (CS8 | CREAD); - mode.c_lflag &= ~(ECHONL | NOFLSH -#ifdef TOSTOP - | TOSTOP -#endif -#ifdef ECHOPTR - | ECHOPRT -#endif -#ifdef XCASE - | XCASE -#endif - ); - - mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK -#ifdef ECHOCTL - | ECHOCTL -#endif -#ifdef ECHOKE - | ECHOKE -#endif - ); -#endif - - tcsetattr(STDERR_FILENO, TCSADRAIN, &mode); -} - -/* - * Returns a "good" value for the erase character. This is loosely based on - * the BSD4.4 logic. - */ -#ifdef TERMIOS -static int -default_erase(void) -{ - int result; - - if (over_strike - && key_backspace != 0 - && strlen(key_backspace) == 1) - result = key_backspace[0]; - else - result = CERASE; - - return result; -} -#endif - -/* - * Update the values of the erase, interrupt, and kill characters in 'mode'. - * - * SVr4 tset (e.g., Solaris 2.5) only modifies the intr, quit or erase - * characters if they're unset, or if we specify them as options. This differs - * from BSD 4.4 tset, which always sets erase. - */ -static void -set_control_chars(void) -{ -#ifdef TERMIOS - if (DISABLED(mode.c_cc[VERASE]) || terasechar >= 0) - mode.c_cc[VERASE] = (terasechar >= 0) ? terasechar : default_erase(); - - if (DISABLED(mode.c_cc[VINTR]) || intrchar >= 0) - mode.c_cc[VINTR] = (intrchar >= 0) ? intrchar : CINTR; - - if (DISABLED(mode.c_cc[VKILL]) || tkillchar >= 0) - mode.c_cc[VKILL] = (tkillchar >= 0) ? tkillchar : CKILL; -#endif -} - -/* - * Set up various conversions in 'mode', including parity, tabs, returns, - * echo, and case, according to the termcap entry. If the program we're - * running was named with a leading upper-case character, map external - * uppercase to internal lowercase. - */ -static void -set_conversions(void) -{ -#ifdef __OBSOLETE__ - /* - * Conversion logic for some *really* ancient terminal glitches, - * not supported in terminfo. Left here for succeeding generations - * to marvel at. - */ - if (tgetflag("UC")) { -#ifdef IUCLC - mode.c_iflag |= IUCLC; - mode.c_oflag |= OLCUC; -#endif - } else if (tgetflag("LC")) { -#ifdef IUCLC - mode.c_iflag &= ~IUCLC; - mode.c_oflag &= ~OLCUC; -#endif - } - mode.c_iflag &= ~(PARMRK | INPCK); - mode.c_lflag |= ICANON; - if (tgetflag("EP")) { - mode.c_cflag |= PARENB; - mode.c_cflag &= ~PARODD; - } - if (tgetflag("OP")) { - mode.c_cflag |= PARENB; - mode.c_cflag |= PARODD; - } -#endif /* __OBSOLETE__ */ - -#ifdef TERMIOS -#ifdef ONLCR - mode.c_oflag |= ONLCR; -#endif - mode.c_iflag |= ICRNL; - mode.c_lflag |= ECHO; -#ifdef OXTABS - mode.c_oflag |= OXTABS; -#endif /* OXTABS */ - - /* test used to be tgetflag("NL") */ - if (newline != (char *) 0 && newline[0] == '\n' && !newline[1]) { - /* Newline, not linefeed. */ -#ifdef ONLCR - mode.c_oflag &= ~ONLCR; -#endif - mode.c_iflag &= ~ICRNL; - } -#ifdef __OBSOLETE__ - if (tgetflag("HD")) /* Half duplex. */ - mode.c_lflag &= ~ECHO; -#endif /* __OBSOLETE__ */ -#ifdef OXTABS - /* test used to be tgetflag("pt") */ - if (VALID_STRING(set_tab) && VALID_STRING(clear_all_tabs)) - mode.c_oflag &= ~OXTABS; -#endif /* OXTABS */ - mode.c_lflag |= (ECHOE | ECHOK); -#endif -} - -/* Output startup string. */ -static void -set_init(void) -{ - char *p; - bool settle; - -#ifdef __OBSOLETE__ - if (pad_char != (char *) 0) /* Get/set pad character. */ - PC = pad_char[0]; -#endif /* OBSOLETE */ - -#ifdef TAB3 - if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) { - oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET); - tcsetattr(STDERR_FILENO, TCSADRAIN, &oldmode); - } -#endif - settle = set_tabs(); - - if (isreset) { - if ((p = reset_1string) != 0) { - tputs(p, 0, outc); - settle = TRUE; - } - if ((p = reset_2string) != 0) { - tputs(p, 0, outc); - settle = TRUE; - } - /* What about rf, rs3, as per terminfo man page? */ - /* also might be nice to send rmacs, rmul, rmm */ - if ((p = reset_file) != 0 - || (p = init_file) != 0) { - cat(p); - settle = TRUE; - } - } - - if (settle) { - (void) putc('\r', stderr); - (void) fflush(stderr); - (void) napms(1000); /* Settle the terminal. */ - } -} - -/* - * Set the hardware tabs on the terminal, using the ct (clear all tabs), - * st (set one tab) and ch (horizontal cursor addressing) capabilities. - * This is done before if and is, so they can patch in case we blow this. - * Return TRUE if we set any tab stops, FALSE if not. - */ -static bool -set_tabs(void) -{ - if (set_tab && clear_all_tabs) { - int c; - - (void) putc('\r', stderr); /* Force to left margin. */ - tputs(clear_all_tabs, 0, outc); - - for (c = 8; c < tcolumns; c += 8) { - /* Get to the right column. In BSD tset, this - * used to try a bunch of half-clever things - * with cup and hpa, for an average saving of - * somewhat less than two character times per - * tab stop, less than .01 sec at 2400cps. We - * lost all this cruft because it seemed to be - * introducing some odd bugs. - * -----------12345678----------- */ - (void) fputs(" ", stderr); - tputs(set_tab, 0, outc); - } - putc('\r', stderr); - return (TRUE); - } - return (FALSE); -} - /************************************************************************** * * Main sequence * **************************************************************************/ -/* - * Tell the user if a control key has been changed from the default value. - */ -#ifdef TERMIOS -static void -report(const char *name, int which, unsigned def) -{ - unsigned older, newer; - char *p; - - newer = mode.c_cc[which]; - older = oldmode.c_cc[which]; - - if (older == newer && older == def) - return; - - (void) fprintf(stderr, "%s %s ", name, older == newer ? "is" : "set to"); - - if (DISABLED(newer)) - (void) fprintf(stderr, "undef.\n"); - /* - * Check 'delete' before 'backspace', since the key_backspace value - * is ambiguous. - */ - else if (newer == 0177) - (void) fprintf(stderr, "delete.\n"); - else if ((p = key_backspace) != 0 - && newer == (unsigned char) p[0] - && p[1] == '\0') - (void) fprintf(stderr, "backspace.\n"); - else if (newer < 040) { - newer ^= 0100; - (void) fprintf(stderr, "control-%c (^%c).\n", UChar(newer), UChar(newer)); - } else - (void) fprintf(stderr, "%c.\n", UChar(newer)); -} -#endif - /* * Convert the obsolete argument forms into something that getopt can handle. * This means that -e, -i and -k get default arguments supplied for them. @@ -1092,13 +705,58 @@ obsolete(char **argv) } static void -usage(void) +print_shell_commands(const char *ttype) { - (void) fprintf(stderr, "usage: %s [-cIQqrsVw] [-] " - "[-e ch] [-i ch] [-k ch] [-m mapping] [terminal]", - _nc_progname); + const char *p; + int len; + char *var; + char *leaf; + /* + * Figure out what shell we're using. A hack, we look for an + * environmental variable SHELL ending in "csh". + */ + if ((var = getenv("SHELL")) != 0 + && ((len = (int) strlen(leaf = _nc_basename(var))) >= 3) + && !strcmp(leaf + len - 3, "csh")) + p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n"; + else + p = "TERM=%s;\n"; + (void) printf(p, ttype); +} - exit_error(); +static void +usage(void) +{ +#define SKIP(s) /* nothing */ +#define KEEP(s) s "\n" + static const char msg[] = + { + KEEP("") + KEEP("Options:") + SKIP(" -a arpanet (obsolete)") + KEEP(" -c set control characters") + SKIP(" -d dialup (obsolete)") + KEEP(" -e ch erase character") + KEEP(" -I no initialization strings") + KEEP(" -i ch interrupt character") + KEEP(" -k ch kill character") + KEEP(" -m mapping map identifier to type") + SKIP(" -p plugboard (obsolete)") + KEEP(" -Q do not output control key settings") + KEEP(" -q display term only, do no changes") + KEEP(" -r display term on stderr") + SKIP(" -S (obsolete)") + KEEP(" -s output TERM set command") + KEEP(" -V print curses-version") + KEEP(" -w set window-size") + KEEP("") + KEEP("If neither -c/-w are given, both are assumed.") + }; +#undef KEEP +#undef SKIP + (void) fprintf(stderr, "Usage: %s [options] [terminal]\n", _nc_progname); + fputs(msg, stderr); + ExitProgram(EXIT_FAILURE); /* NOTREACHED */ } @@ -1114,8 +772,14 @@ int main(int argc, char **argv) { int ch, noinit, noset, quiet, Sflag, sflag, showterm; - const char *p; const char *ttype; + int terasechar = -1; /* new erase character */ + int intrchar = -1; /* new interrupt character */ + int tkillchar = -1; /* new kill character */ + int my_fd; + bool opt_c = FALSE; /* set control-chars */ + bool opt_w = FALSE; /* set window-size */ + TTY mode, oldmode; _nc_progname = _nc_rootname(*argv); @@ -1124,7 +788,7 @@ main(int argc, char **argv) obsolete(argv); noinit = noset = quiet = Sflag = sflag = showterm = 0; - while ((ch = getopt(argc, argv, "a:cd:e:Ii:k:m:np:qQSrsVw")) != -1) { + while ((ch = getopt(argc, argv, "a:cd:e:Ii:k:m:np:qQrSsVw")) != -1) { switch (ch) { case 'c': /* set control-chars */ opt_c = TRUE; @@ -1176,10 +840,12 @@ main(int argc, char **argv) case 'w': /* set window-size */ opt_w = TRUE; break; + case '?': default: usage(); } } + argc -= optind; argv += optind; @@ -1189,95 +855,66 @@ main(int argc, char **argv) if (!opt_c && !opt_w) opt_c = opt_w = TRUE; - if (tcgetattr(STDERR_FILENO, &mode) < 0) - failed("standard error"); - can_restore = TRUE; - original = oldmode = mode; + my_fd = save_tty_settings(&mode, TRUE); + oldmode = mode; #ifdef TERMIOS ospeed = (NCURSES_OSPEED) cfgetospeed(&mode); +#elif defined(EXP_WIN32_DRIVER) + ospeed = 0; #else ospeed = (NCURSES_OSPEED) mode.sg_ospeed; #endif - if (!strcmp(_nc_progname, PROG_RESET)) { - isreset = TRUE; - reset_mode(); + if (same_program(_nc_progname, PROG_RESET)) { + reset_start(stderr, TRUE, FALSE); + reset_tty_settings(my_fd, &mode, noset); + } else { + reset_start(stderr, FALSE, TRUE); } - ttype = get_termcap_entry(*argv); + ttype = get_termcap_entry(my_fd, *argv); if (!noset) { - tcolumns = columns; - tlines = lines; - #if HAVE_SIZECHANGE if (opt_w) { - struct winsize win; - /* Set window size if not set already */ - if (ioctl(STDERR_FILENO, TIOCGWINSZ, &win) == 0) { - if (win.ws_row == 0 && - win.ws_col == 0 && - tlines > 0 && tcolumns > 0) { - win.ws_row = tlines; - win.ws_col = tcolumns; - (void) ioctl(STDERR_FILENO, TIOCSWINSZ, &win); - } - } + set_window_size(my_fd, &lines, &columns); } #endif if (opt_c) { - set_control_chars(); - set_conversions(); - - if (!noinit) - set_init(); - - /* Set the modes if they've changed. */ - if (memcmp(&mode, &oldmode, sizeof(mode))) { - tcsetattr(STDERR_FILENO, TCSADRAIN, &mode); + set_control_chars(&mode, terasechar, intrchar, tkillchar); + set_conversions(&mode); + + if (!noinit) { + if (send_init_strings(my_fd, &oldmode)) { + (void) putc('\r', stderr); + (void) fflush(stderr); + (void) napms(1000); /* Settle the terminal. */ + } } + + update_tty_settings(&oldmode, &mode); } } - /* Get the terminal name from the entry. */ - ttype = _nc_first_name(cur_term->type.term_names); - - if (noset) + if (noset) { (void) printf("%s\n", ttype); - else { + } else { if (showterm) (void) fprintf(stderr, "Terminal type is %s.\n", ttype); /* * If erase, kill and interrupt characters could have been * modified and not -Q, display the changes. */ -#ifdef TERMIOS if (!quiet) { - report("Erase", VERASE, CERASE); - report("Kill", VKILL, CKILL); - report("Interrupt", VINTR, CINTR); + print_tty_chars(&oldmode, &mode); } -#endif } if (Sflag) err("The -S option is not supported under terminfo."); if (sflag) { - int len; - char *var; - char *leaf; - /* - * Figure out what shell we're using. A hack, we look for an - * environmental variable SHELL ending in "csh". - */ - if ((var = getenv("SHELL")) != 0 - && ((len = (int) strlen(leaf = _nc_basename(var))) >= 3) - && !strcmp(leaf + len - 3, "csh")) - p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n"; - else - p = "TERM=%s;\n"; - (void) printf(p, ttype); + print_shell_commands(ttype); } ExitProgram(EXIT_SUCCESS);