1 /*        $NetBSD: curses_private.h,v 1.82 2024/07/11 07:13:41 blymn Exp $      */
2 
3 /*-
4  * Copyright (c) 1998-2000 Brett Lymn
5  *                         (blymn@baea.com.au, brett_lymn@yahoo.com.au)
6  * All rights reserved.
7  *
8  * This code has been donated to The NetBSD Foundation by the Author.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *
30  */
31 
32 /* Modified by Ruibiao Qiu <ruibiao@arl.wustl.edu,ruibiao@gmail.com>
33  * to add support for wide characters
34  * Changes:
35  * - Add a compiler variable HAVE_WCHAR for wide character only code
36  * - Add a pointer to liked list of non-spacing characters in __ldata
37  *   and the macro to access the width field in the attribute field
38  * - Add a circular input character buffer in __screen to handle
39  *   wide-character input (used in get_wch())
40  */
41 
42 #include <term.h>
43 #include <termios.h>
44 
45 /* Private structure definitions for curses. */
46 
47 /* Termcap capabilities. */
48 #ifdef HAVE_WCHAR
49 /*
50  * Add a list of non-spacing characters to each spacing
51  * character in a singly linked list
52  */
53 typedef struct nschar_t {
54           wchar_t                       ch;                 /* Non-spacing character */
55           struct nschar_t     *next;    /* Next non-spacing character */
56 } nschar_t;
57 #endif /* HAVE_WCHAR */
58 
59 /*
60  * A window is an array of __LINE structures pointed to by the 'lines' pointer.
61  * A line is an array of __LDATA structures pointed to by the 'line' pointer.
62  *
63  * IMPORTANT: the __LDATA structure must NOT induce any padding, so if new
64  * fields are added -- padding fields with *constant values* should ensure
65  * that the compiler will not generate any padding when storing an array of
66  *  __LDATA structures.  This is to enable consistent use of memcmp, and memcpy
67  * for comparing and copying arrays.
68  */
69 
70 struct __ldata {
71           wchar_t   ch;                           /* Character */
72           attr_t    attr;                         /* Attributes */
73 #define CA_CONTINUATION                 0x0001    /* a continuation cell */
74 #define CA_BACKGROUND                   0x0002    /* background char */
75           int16_t             cflags;             /* internal attributes for wide char */
76 #ifdef HAVE_WCHAR
77           nschar_t  *nsp;     /* Foreground non-spacing character pointer */
78           int16_t             wcols;              /* display width of a wide char */
79 #endif /* HAVE_WCHAR */
80 };
81 
82 #define __LDATASIZE (sizeof(__LDATA))
83 
84 struct __line {
85 #ifdef DEBUG
86 #define SENTINEL_VALUE 0xaac0ffee
87 
88           unsigned int sentinel;          /* try to catch line overflows */
89 #endif
90 #define   __ISDIRTY 0x01                /* Line is dirty. */
91 #define __ISPASTEOL 0x02                /* Cursor is past end of line */
92 #define __ISFORCED  0x04                /* Force update, no optimisation */
93           unsigned int flags;
94           unsigned int hash;            /* Hash value for the line. */
95           int *firstchp, *lastchp;      /* First and last chngd columns ptrs */
96           int firstch, lastch;                    /* First and last changed columns. */
97           __LDATA *line;                          /* Pointer to the line text. */
98 };
99 
100 struct __window {             /* Window structure. */
101           struct __window     *nextp, *orig;      /* Subwindows list and parent. */
102           int begy, begx;                         /* Window home. */
103           int cury, curx;                         /* Current x, y coordinates. */
104           int maxy, maxx;                         /* Maximum values for curx, cury. */
105           int reqy, reqx;                         /* Size requested when created */
106           int ch_off;                             /* x offset for firstch/lastch. */
107           __LINE **alines;              /* Array of pointers to the lines */
108           __LINE  *lspace;              /* line space (for cleanup) */
109           __LDATA *wspace;              /* window space (for cleanup) */
110 
111 #define   __ENDLINE 0x00000001          /* End of screen. */
112 #define   __FLUSH             0x00000002          /* Fflush(stdout) after refresh. */
113 #define   __FULLWIN 0x00000004          /* Window is a screen. */
114 #define   __IDLINE  0x00000008          /* Insert/delete sequences. */
115 #define   __SCROLLWIN         0x00000010          /* Last char will scroll window. */
116 #define   __SCROLLOK          0x00000020          /* Scrolling ok. */
117 #define   __CLEAROK 0x00000040          /* Clear on next refresh. */
118 #define   __LEAVEOK 0x00000100          /* If cursor left */
119 #define   __KEYPAD  0x00010000          /* If interpreting keypad codes */
120 #define   __NOTIMEOUT         0x00020000          /* Wait indefinitely for func keys */
121 #define __IDCHAR    0x00040000          /* insert/delete char sequences */
122 #define __ISPAD               0x00080000          /* "window" is a pad */
123 #define __ISDERWIN  0x00100000          /* "window" is derived from parent */
124 #define __IMMEDOK   0x00200000          /* refreshed when changed */
125 #define __SYNCOK    0x00400000          /* sync when changed */
126 #define __HALFDELAY 0x00800000          /* In half delay mode */
127           unsigned int flags;
128           int       delay;                        /* delay for getch() */
129           attr_t    wattr;                        /* Character attributes */
130           wchar_t   bch;                          /* Background character */
131           attr_t    battr;                        /* Background attributes */
132           uint32_t wcols;                         /* Background column width */
133           int       scr_t, scr_b;                 /* Scrolling region top, bottom */
134           SCREEN    *screen;            /* Screen for this window */
135           int       pbegy, pbegx,
136                     sbegy, sbegx,
137                     smaxy, smaxx;                 /* Saved prefresh() values */
138           int       dery, derx;                   /* derived window coordinates
139                                                      - top left corner of source
140                                                      relative to parent win */
141 #ifdef HAVE_WCHAR
142           nschar_t *bnsp;                         /* Background non-spacing char list */
143 #endif /* HAVE_WCHAR */
144           FILE      *fp;                          /* for window formatted printf */
145           char      *buf;                         /* buffer for window formatted printf */
146           size_t     buflen;            /* length of above buffer */
147 };
148 
149 /* Set of attributes unset by 'me' - 'mb', 'md', 'mh', 'mk', 'mp' and 'mr'. */
150 #ifndef HAVE_WCHAR
151 #define   __TERMATTR \
152           (__REVERSE | __BLINK | __DIM | __BOLD | __BLANK | __PROTECT)
153 #else
154 #define   __TERMATTR \
155           (__REVERSE | __BLINK | __DIM | __BOLD | __BLANK | __PROTECT \
156           | WA_TOP | WA_LOW | WA_LEFT | WA_RIGHT | WA_HORIZONTAL | WA_VERTICAL)
157 #endif /* HAVE_WCHAR */
158 
159 struct __winlist {
160           struct __window               *winp;    /* The window. */
161           struct __winlist    *nextp;   /* Next window. */
162 };
163 
164 struct __color {
165           short     num;
166           short     red;
167           short     green;
168           short     blue;
169           int       flags;
170 };
171 
172 /* List of colour pairs */
173 struct __pair {
174           short     fore;
175           short     back;
176           int       flags;
177 };
178 
179 /* Maximum colours */
180 #define   MAX_COLORS          256
181 /* Maximum colour pairs - determined by number of colour bits in attr_t */
182 #define   MAX_PAIRS PAIR_NUMBER(__COLOR)
183 
184 typedef struct keymap keymap_t;
185 
186 /* POSIX allows up to 8 columns in a label. */
187 #define   MAX_SLK_COLS        8
188 #ifdef HAVE_WCHAR
189 #define   MAX_SLK_LABEL       sizeof(wchar_t) * MAX_SLK_COLS
190 #else
191 #define   MAX_SLK_LABEL       MAX_SLK_COLS
192 #endif
193 struct __slk_label {
194           char      *text;
195           int        justify;
196 #define   SLK_JUSTIFY_LEFT    0
197 #define   SLK_JUSTIFY_CENTER  1
198 #define   SLK_JUSTIFY_RIGHT   2
199           char       label[MAX_SLK_LABEL + 1];
200           int        x;
201 };
202 
203 #define   MAX_RIPS  5
204 struct __ripoff {
205           int       nlines;
206           WINDOW    *win;
207 };
208 
209 /* this is the encapsulation of the terminal definition, one for
210  * each terminal that curses talks to.
211  */
212 struct __screen {
213           FILE    *infd, *outfd;  /* input and output file descriptors */
214           WINDOW    *curscr;  /* Current screen. */
215           WINDOW    *stdscr;  /* Standard screen. */
216           WINDOW    *__virtscr;         /* Virtual screen (for doupdate()). */
217           int      curwin;        /* current window for refresh */
218           int      lx, ly;        /* loop parameters for refresh */
219           int        COLS;              /* Columns on the screen. */
220           int        LINES;             /* Lines on the screen. */
221           int        nripped; /* Number of ripofflines. */
222           struct __ripoff ripped[MAX_RIPS];       /* ripofflines. */
223           int        ESCDELAY;          /* Delay between keys in esc seq's. */
224 #define   ESCDELAY_DEFAULT    300 /* milliseconds. */
225           int        TABSIZE; /* Size of a tab. */
226 #define   TABSIZE_DEFAULT               8   /* spaces. */
227           int        COLORS;  /* Maximum colors on the screen */
228           int        COLOR_PAIRS;       /* Maximum color pairs on the screen */
229           short      curpair; /* current colour pair set on the terminal */
230           int        My_term; /* Use Def_term regardless. */
231           char       GT;                /* Gtty indicates tabs. */
232           char       NONL;              /* Term can't hack LF doing a CR. */
233           char       UPPERCASE;         /* Terminal is uppercase only. */
234 
235           chtype acs_char[NUM_ACS];
236 #ifdef HAVE_WCHAR
237           cchar_t wacs_char[ NUM_ACS ];
238 #endif /* HAVE_WCHAR */
239           struct __color colours[MAX_COLORS];
240           struct __pair  colour_pairs[MAX_PAIRS];
241           attr_t    nca;
242 
243 /* Style of colour manipulation */
244 #define COLOR_NONE  0
245 #define COLOR_ANSI  1         /* ANSI/DEC-style colour manipulation */
246 #define COLOR_HP    2         /* HP-style colour manipulation */
247 #define COLOR_TEK   3         /* Tektronix-style colour manipulation */
248 #define COLOR_OTHER 4         /* None of the others but can set fore/back */
249           int color_type;
250 
251           attr_t mask_op;
252           attr_t mask_me;
253           attr_t mask_ue;
254           attr_t mask_se;
255           TERMINAL *term;
256           int old_mode; /* old cursor visibility state for terminal */
257           keymap_t *base_keymap;
258           int echoit;
259           int pfast;
260           int rawmode;
261           int nl;
262           int noqch;
263           int clearok;
264           int useraw;
265           struct __winlist *winlistp;
266           struct   termios cbreakt, rawt, *curt, save_termios;
267           struct termios orig_termios, baset, savedtty;
268           int ovmin;
269           int ovtime;
270           char *stdbuf;
271           unsigned int len;
272           int meta_state;
273           char padchar;
274           int endwin;
275           int notty;
276           int resized;
277           wchar_t *unget_list;
278           int unget_len, unget_pos;
279           int filtered;
280           int checkfd;
281 
282           /* soft label key */
283           bool                 is_term_slk;
284           WINDOW              *slk_window;
285           int                  slk_format;
286 #define   SLK_FMT_INVAL       -1
287 #define   SLK_FMT_3_2_3       0
288 #define   SLK_FMT_4_4         1
289           int                  slk_nlabels;
290           int                  slk_label_len;
291           bool                 slk_hidden;
292           struct __slk_label *slk_labels;
293 
294 #define MAX_CBUF_SIZE 8
295 #ifdef HAVE_WCHAR
296           int                 cbuf_head;                    /* header to cbuf */
297           int                 cbuf_tail;                    /* tail to cbuf */
298           int                 cbuf_cur;           /* the current char in cbuf */
299           mbstate_t sp;                           /* wide char processing state */
300           char                cbuf[ MAX_CBUF_SIZE ];        /* input character buffer */
301 #endif /* HAVE_WCHAR */
302 };
303 
304 
305 extern char          __GT;                        /* Gtty indicates tabs. */
306 extern char          __NONL;            /* Term can't hack LF doing a CR. */
307 extern char          __UPPERCASE;                 /* Terminal is uppercase only. */
308 extern int           My_term;           /* Use Def_term regardless. */
309 extern const char   *Def_term;          /* Default terminal type. */
310 extern SCREEN   *_cursesi_screen;       /* The current screen in use */
311 
312 /* Debugging options/functions. */
313 #ifdef DEBUG
314 #define __CTRACE_TSTAMP                 0x00000001
315 #define __CTRACE_MISC                   0x00000002
316 #define __CTRACE_INIT                   0x00000004
317 #define __CTRACE_SCREEN                 0x00000008
318 #define __CTRACE_WINDOW                 0x00000010
319 #define __CTRACE_REFRESH      0x00000020
320 #define __CTRACE_COLOR                  0x00000040
321 #define __CTRACE_INPUT                  0x00000080
322 #define __CTRACE_OUTPUT                 0x00000100
323 #define __CTRACE_LINE                   0x00000200
324 #define __CTRACE_ATTR                   0x00000400
325 #define __CTRACE_ERASE                  0x00000800
326 #define __CTRACE_FILEIO                 0x00001000
327 #define __CTRACE_ALL                    0x7fffffff
328 void       __CTRACE(int, const char *, ...) __attribute__((__format__(__printf__, 2, 3)));
329 #else
330 #define   __CTRACE(area, fmt, ...)      __nothing
331 #endif
332 
333 /* Common erase logic */
334 #ifdef HAVE_WCHAR
335 #define __NEED_ERASE(_sp, _bch, _battr)                               \
336           ((_sp)->ch != (_bch) ||                                               \
337           (((_sp)->cflags & CA_BACKGROUND) != CA_BACKGROUND) ||       \
338               ((_sp)->attr & WA_ATTRIBUTES) != (_battr) ||  \
339               (_sp)->nsp != NULL ||                                   \
340               (_sp)->wcols < 0)
341 #else
342 #define __NEED_ERASE(_sp, _bch, _battr)                               \
343           ((_sp)->ch != (_bch) || (_sp)->attr != (_battr))
344 #endif
345 
346 /* Private functions. */
347 int     __cputchar_args(int, void *);
348 void     _cursesi_free_keymap(keymap_t *);
349 int      _cursesi_gettmode(SCREEN *);
350 void     _cursesi_reset_acs(SCREEN *);
351 int       _cursesi_addbyte(WINDOW *, __LINE **, int *, int *, int , attr_t, int);
352 int       _cursesi_addwchar(WINDOW *, __LINE **, int *, int *, const cchar_t *,
353                                 int);
354 int       _cursesi_waddbytes(WINDOW *, const char *, int, attr_t, int);
355 #ifdef HAVE_WCHAR
356 void     _cursesi_reset_wacs(SCREEN *);
357 #endif /* HAVE_WCHAR */
358 void     _cursesi_resetterm(SCREEN *);
359 int      _cursesi_setterm(const char *, SCREEN *);
360 int        __delay(void);
361 unsigned int         __hash_more(const void *, size_t, unsigned int);
362 unsigned int         __hash_line(const __LDATA *, int);
363 #define   __hash(s, len)      __hash_more((s), (len), 0u)
364 void       __id_subwins(WINDOW *);
365 void       __init_getch(SCREEN *);
366 void       __init_acs(SCREEN *);
367 int        _cursesi_celleq(__LDATA *, __LDATA *);
368 #ifdef HAVE_WCHAR
369 void       __init_get_wch(SCREEN *);
370 void       __init_wacs(SCREEN *);
371 int       __cputwchar_args( wchar_t, void * );
372 void      _cursesi_copy_wchar(__LDATA *, __LDATA *);
373 int     _cursesi_copy_nsp(nschar_t *, struct __ldata *);
374 void      __cursesi_free_nsp(nschar_t *);
375 void      __cursesi_win_free_nsp(WINDOW *);
376 void      __cursesi_putnsp(nschar_t *, const int, const int);
377 void      __cursesi_chtype_to_cchar(chtype, cchar_t *);
378 #endif /* HAVE_WCHAR */
379 int        __fgetc_resize(FILE *);
380 int        __unget(wint_t);
381 int        __mvcur(int, int, int, int, int);
382 WINDOW  *__newwin(SCREEN *, int, int, int, int, int, int);
383 int        __nodelay(void);
384 int        __notimeout(void);
385 void       __restartwin(void);
386 void       __restore_colors(void);
387 void     __restore_cursor_vis(void);
388 void     __restore_meta_state(void);
389 void       __restore_termios(void);
390 void       __restore_stophandler(void);
391 void       __restore_winchhandler(void);
392 int        __ripoffscreen(SCREEN *);
393 int        __ripoffresize(SCREEN *);
394 void       __ripofftouch(SCREEN *);
395 int        __rippedlines(const SCREEN *, int);
396 void       __save_termios(void);
397 void       __set_color(WINDOW *win, attr_t attr);
398 void       __set_stophandler(void);
399 void       __set_winchhandler(void);
400 void       __set_subwin(WINDOW *, WINDOW *);
401 int        __slk_init(SCREEN *);
402 void       __slk_free(SCREEN *);
403 int        __slk_resize(SCREEN *, int cols);
404 int        __slk_noutrefresh(SCREEN *);
405 void       __startwin(SCREEN *);
406 void       __stop_signal_handler(int);
407 int        __stopwin(void);
408 void       __swflags(WINDOW *);
409 void       __sync(WINDOW *);
410 int        __timeout(int);
411 int        __touchline(WINDOW *, int, int, int);
412 int        __touchwin(WINDOW *, int);
413 int        __unripoffline(int (*)(WINDOW *, int));
414 void       __unsetattr(int);
415 void       __unset_color(WINDOW *win);
416 int        __waddch(WINDOW *, __LDATA *);
417 int        __wgetnstr(WINDOW *, char *, int);
418 void       __winch_signal_handler(int);
419 
420 /* Private #defines. */
421 #define   min(a,b)  ((a) < (b) ? (a) : (b))
422 #define   max(a,b)  ((a) > (b) ? (a ): (b))
423 
424 /* Private externs. */
425 extern int                     __echoit;
426 extern int                     __endwin;
427 extern int                     __pfast;
428 extern int                     __rawmode;
429 extern int                     __noqch;
430 extern attr_t                  __mask_op, __mask_me, __mask_ue, __mask_se;
431 extern WINDOW                 *__virtscr;
432 extern int                     __using_color;
433 extern int                     __do_color_init;
434 extern attr_t                  __default_color;
435