2016-04-30 02:01:36 +00:00
|
|
|
// This file only contains fallback implementations of functions which have been found to be missing
|
|
|
|
// or broken by the configuration scripts.
|
|
|
|
//
|
2020-07-08 00:58:21 +00:00
|
|
|
// Many of these functions are more or less broken and incomplete.
|
2006-02-28 13:17:16 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
2016-04-21 06:00:54 +00:00
|
|
|
// IWYU likes to recommend adding term.h when we want ncurses.h.
|
2022-08-21 06:14:48 +00:00
|
|
|
// IWYU pragma: no_include "term.h"
|
2016-04-30 02:01:36 +00:00
|
|
|
#include <errno.h> // IWYU pragma: keep
|
|
|
|
#include <fcntl.h> // IWYU pragma: keep
|
|
|
|
#include <limits.h> // IWYU pragma: keep
|
2022-09-13 13:56:52 +00:00
|
|
|
#include <unistd.h> // IWYU pragma: keep
|
2006-02-28 13:17:16 +00:00
|
|
|
#include <wctype.h>
|
2019-10-13 22:50:48 +00:00
|
|
|
|
2022-09-13 01:34:19 +00:00
|
|
|
#include <cstdlib>
|
2023-02-24 23:54:46 +00:00
|
|
|
#include <cwchar>
|
2013-04-17 04:41:58 +00:00
|
|
|
#if HAVE_GETTEXT
|
|
|
|
#include <libintl.h>
|
|
|
|
#endif
|
2022-08-21 06:14:48 +00:00
|
|
|
#if defined(TPARM_SOLARIS_KLUDGE)
|
2018-02-04 08:59:37 +00:00
|
|
|
#if HAVE_CURSES_H
|
2022-08-21 21:51:33 +00:00
|
|
|
#include <curses.h> // IWYU pragma: keep
|
2018-02-04 08:59:37 +00:00
|
|
|
#elif HAVE_NCURSES_H
|
2016-04-21 06:00:54 +00:00
|
|
|
#include <ncurses.h> // IWYU pragma: keep
|
2014-12-07 08:41:15 +00:00
|
|
|
#elif HAVE_NCURSES_CURSES_H
|
2022-08-21 21:51:33 +00:00
|
|
|
#include <ncurses/curses.h> // IWYU pragma: keep
|
2006-02-28 13:17:16 +00:00
|
|
|
#endif
|
|
|
|
#if HAVE_TERM_H
|
2016-04-21 06:00:54 +00:00
|
|
|
#include <term.h> // IWYU pragma: keep
|
2006-02-28 13:17:16 +00:00
|
|
|
#elif HAVE_NCURSES_TERM_H
|
|
|
|
#include <ncurses/term.h>
|
|
|
|
#endif
|
2022-08-21 06:14:48 +00:00
|
|
|
#endif
|
2016-04-21 06:00:54 +00:00
|
|
|
#include <signal.h> // IWYU pragma: keep
|
2019-10-13 22:50:48 +00:00
|
|
|
|
2016-10-09 21:38:26 +00:00
|
|
|
#include "common.h" // IWYU pragma: keep
|
2016-04-21 06:00:54 +00:00
|
|
|
#include "fallback.h" // IWYU pragma: keep
|
2006-03-02 11:30:29 +00:00
|
|
|
|
2018-12-11 15:48:11 +00:00
|
|
|
#if defined(TPARM_SOLARIS_KLUDGE)
|
2019-05-05 10:09:25 +00:00
|
|
|
char *tparm_solaris_kludge(char *str, long p1, long p2, long p3, long p4, long p5, long p6, long p7,
|
|
|
|
long p8, long p9) {
|
2017-10-31 08:48:35 +00:00
|
|
|
return tparm(str, p1, p2, p3, p4, p5, p6, p7, p8, p9);
|
2007-08-22 07:57:41 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2023-02-24 23:54:46 +00:00
|
|
|
/// Fallback implementations of wcsncasecmp and wcscasecmp. On systems where these are not needed
|
|
|
|
/// (e.g. building on Linux) these should end up just being stripped, as they are static functions
|
|
|
|
/// that are not referenced in this file.
|
2017-05-05 05:42:42 +00:00
|
|
|
// cppcheck-suppress unusedFunction
|
2019-02-10 12:20:01 +00:00
|
|
|
[[gnu::unused]] static int wcscasecmp_fallback(const wchar_t *a, const wchar_t *b) {
|
2016-04-30 02:01:36 +00:00
|
|
|
if (*a == 0) {
|
2016-05-04 22:19:47 +00:00
|
|
|
return *b == 0 ? 0 : -1;
|
2016-04-30 02:01:36 +00:00
|
|
|
} else if (*b == 0) {
|
2012-11-19 00:30:30 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2016-04-30 02:01:36 +00:00
|
|
|
int diff = towlower(*a) - towlower(*b);
|
2016-05-04 22:19:47 +00:00
|
|
|
if (diff != 0) {
|
2012-11-19 00:30:30 +00:00
|
|
|
return diff;
|
2016-05-04 22:19:47 +00:00
|
|
|
}
|
|
|
|
return wcscasecmp_fallback(a + 1, b + 1);
|
2006-02-28 13:17:16 +00:00
|
|
|
}
|
|
|
|
|
2019-05-05 10:09:25 +00:00
|
|
|
[[gnu::unused]] static int wcsncasecmp_fallback(const wchar_t *a, const wchar_t *b, size_t count) {
|
2016-04-30 02:01:36 +00:00
|
|
|
if (count == 0) return 0;
|
2013-05-17 02:44:21 +00:00
|
|
|
|
2016-04-30 02:01:36 +00:00
|
|
|
if (*a == 0) {
|
2016-05-04 22:19:47 +00:00
|
|
|
return *b == 0 ? 0 : -1;
|
2016-04-30 02:01:36 +00:00
|
|
|
} else if (*b == 0) {
|
2013-05-17 02:44:21 +00:00
|
|
|
return 1;
|
|
|
|
}
|
2016-04-30 02:01:36 +00:00
|
|
|
int diff = towlower(*a) - towlower(*b);
|
2016-05-04 22:19:47 +00:00
|
|
|
if (diff != 0) return diff;
|
|
|
|
return wcsncasecmp_fallback(a + 1, b + 1, count - 1);
|
2013-05-17 02:44:21 +00:00
|
|
|
}
|
|
|
|
|
2016-12-08 00:21:08 +00:00
|
|
|
#ifndef HAVE_WCSCASECMP
|
2017-03-06 13:23:24 +00:00
|
|
|
#ifndef HAVE_STD__WCSCASECMP
|
2016-12-08 00:21:08 +00:00
|
|
|
int wcscasecmp(const wchar_t *a, const wchar_t *b) { return wcscasecmp_fallback(a, b); }
|
|
|
|
#endif
|
2017-03-06 13:23:24 +00:00
|
|
|
#endif
|
|
|
|
|
2016-12-08 00:21:08 +00:00
|
|
|
#ifndef HAVE_WCSNCASECMP
|
2017-03-06 13:23:24 +00:00
|
|
|
#ifndef HAVE_STD__WCSNCASECMP
|
2016-12-08 00:21:08 +00:00
|
|
|
int wcsncasecmp(const wchar_t *a, const wchar_t *b, size_t n) {
|
|
|
|
return wcsncasecmp_fallback(a, b, n);
|
|
|
|
}
|
|
|
|
#endif
|
2016-12-11 04:48:07 +00:00
|
|
|
#endif
|
2016-12-08 00:21:08 +00:00
|
|
|
|
2013-04-08 17:20:56 +00:00
|
|
|
#if HAVE_GETTEXT
|
2019-11-30 07:57:19 +00:00
|
|
|
char *fish_gettext(const char *msgid) { return gettext(msgid); }
|
2013-04-08 17:20:56 +00:00
|
|
|
|
2016-04-30 02:01:36 +00:00
|
|
|
char *fish_bindtextdomain(const char *domainname, const char *dirname) {
|
2013-04-08 17:20:56 +00:00
|
|
|
return bindtextdomain(domainname, dirname);
|
|
|
|
}
|
|
|
|
|
2016-04-30 02:01:36 +00:00
|
|
|
char *fish_textdomain(const char *domainname) { return textdomain(domainname); }
|
2013-04-08 17:20:56 +00:00
|
|
|
#else
|
2016-04-30 02:01:36 +00:00
|
|
|
char *fish_gettext(const char *msgid) { return (char *)msgid; }
|
2016-10-09 21:38:26 +00:00
|
|
|
char *fish_bindtextdomain(const char *domainname, const char *dirname) {
|
|
|
|
UNUSED(domainname);
|
|
|
|
UNUSED(dirname);
|
2022-08-21 06:14:48 +00:00
|
|
|
return nullptr;
|
2016-10-09 21:38:26 +00:00
|
|
|
}
|
|
|
|
char *fish_textdomain(const char *domainname) {
|
|
|
|
UNUSED(domainname);
|
2022-08-21 06:14:48 +00:00
|
|
|
return nullptr;
|
2016-10-09 21:38:26 +00:00
|
|
|
}
|
2006-07-19 23:11:49 +00:00
|
|
|
#endif
|
2006-07-19 22:55:49 +00:00
|
|
|
|
2006-07-30 20:59:41 +00:00
|
|
|
#ifndef HAVE_KILLPG
|
2016-04-30 02:01:36 +00:00
|
|
|
int killpg(int pgr, int sig) {
|
2012-11-19 00:30:30 +00:00
|
|
|
assert(pgr > 1);
|
|
|
|
return kill(-pgr, sig);
|
2006-07-30 20:59:41 +00:00
|
|
|
}
|
|
|
|
#endif
|
2006-08-28 11:43:05 +00:00
|
|
|
|
2020-09-08 20:04:44 +00:00
|
|
|
static int fish_get_emoji_width(wchar_t c) {
|
2018-04-01 00:06:13 +00:00
|
|
|
(void)c;
|
2023-05-16 19:09:30 +00:00
|
|
|
return FISH_EMOJI_WIDTH;
|
2018-02-26 01:43:29 +00:00
|
|
|
}
|
|
|
|
|
2016-05-15 23:19:27 +00:00
|
|
|
// Big hack to use our versions of wcswidth where we know them to be broken, which is
|
|
|
|
// EVERYWHERE (https://github.com/fish-shell/fish-shell/issues/2199)
|
2018-07-10 01:25:35 +00:00
|
|
|
#include "widecharwidth/widechar_width.h"
|
2012-07-15 17:45:18 +00:00
|
|
|
|
2018-02-25 23:05:39 +00:00
|
|
|
int fish_wcwidth(wchar_t wc) {
|
2019-01-30 02:00:09 +00:00
|
|
|
// The system version of wcwidth should accurately reflect the ability to represent characters
|
|
|
|
// in the console session, but knows nothing about the capabilities of other terminal emulators
|
|
|
|
// or ttys. Use it from the start only if we are logged in to the physical console.
|
|
|
|
if (is_console_session()) {
|
|
|
|
return wcwidth(wc);
|
|
|
|
}
|
|
|
|
|
2018-07-10 01:25:35 +00:00
|
|
|
// Check for VS16 which selects emoji presentation. This "promotes" a character like U+2764
|
|
|
|
// (width 1) to an emoji (probably width 2). So treat it as width 1 so the sums work. See #2652.
|
2019-02-19 12:21:29 +00:00
|
|
|
// VS15 selects text presentation.
|
|
|
|
const wchar_t variation_selector_16 = L'\uFE0F', variation_selector_15 = L'\uFE0E';
|
2019-05-05 10:09:25 +00:00
|
|
|
if (wc == variation_selector_16)
|
|
|
|
return 1;
|
|
|
|
else if (wc == variation_selector_15)
|
|
|
|
return 0;
|
2018-07-10 01:25:35 +00:00
|
|
|
|
2021-09-10 01:06:59 +00:00
|
|
|
// Check for Emoji_Modifier property. Only the Fitzpatrick modifiers have this, in range
|
|
|
|
// 1F3FB..1F3FF. This is a hack because such an emoji appearing on its own would be drawn as
|
|
|
|
// width 2, but that's unlikely to be useful. See #8275.
|
|
|
|
if (wc >= 0x1F3FB && wc <= 0x1F3FF) return 0;
|
|
|
|
|
2018-07-10 01:25:35 +00:00
|
|
|
int width = widechar_wcwidth(wc);
|
2019-01-30 02:00:09 +00:00
|
|
|
|
2018-07-10 01:25:35 +00:00
|
|
|
switch (width) {
|
2022-08-12 15:25:31 +00:00
|
|
|
case widechar_non_character:
|
2018-07-10 01:25:35 +00:00
|
|
|
case widechar_nonprint:
|
|
|
|
case widechar_combining:
|
|
|
|
case widechar_unassigned:
|
|
|
|
// Fall back to system wcwidth in this case.
|
|
|
|
return wcwidth(wc);
|
|
|
|
case widechar_ambiguous:
|
|
|
|
case widechar_private_use:
|
2018-08-18 22:38:05 +00:00
|
|
|
// TR11: "All private-use characters are by default classified as Ambiguous".
|
2023-05-16 19:09:30 +00:00
|
|
|
return FISH_AMBIGUOUS_WIDTH;
|
2018-07-10 01:25:35 +00:00
|
|
|
case widechar_widened_in_9:
|
|
|
|
return fish_get_emoji_width(wc);
|
|
|
|
default:
|
|
|
|
assert(width > 0 && "Unexpectedly nonpositive width");
|
|
|
|
return width;
|
|
|
|
}
|
2018-02-25 23:05:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int fish_wcswidth(const wchar_t *str, size_t n) {
|
|
|
|
int result = 0;
|
|
|
|
for (size_t i = 0; i < n && str[i] != L'\0'; i++) {
|
|
|
|
int w = fish_wcwidth(str[i]);
|
2016-04-30 02:01:36 +00:00
|
|
|
if (w < 0) {
|
2018-02-25 23:05:39 +00:00
|
|
|
result = -1;
|
2013-10-16 08:02:15 +00:00
|
|
|
break;
|
|
|
|
}
|
2018-02-25 23:05:39 +00:00
|
|
|
result += w;
|
2013-10-16 08:02:15 +00:00
|
|
|
}
|
2018-02-25 23:05:39 +00:00
|
|
|
return result;
|
2012-07-15 17:45:18 +00:00
|
|
|
}
|