📄 lystrings.c
字号:
#include "HTUtils.h"#include "tcp.h"#include "HTCJK.h"#include "LYCurses.h"#include "LYUtils.h"#include "LYStrings.h"#include "LYGlobalDefs.h"#include "GridText.h"#include "LYKeymap.h"#include "LYSignal.h"#include "LYClean.h"#include "LYMail.h"#include "LYNews.h"#include "LYOptions.h"#include "LYCharSets.h"#include "HTString.h"#include <ctype.h>#include "LYLeaks.h"#define FREE(x) if (x) {free(x); x = NULL;}extern BOOL HTPassHighCtrlRaw;extern HTCJKlang HTCJK;/* If you want to add mouse support for some new platform, it's fairly** simple to do. Once you've determined the X and Y coordinates of** the mouse event, loop through the elements in the links[] array and** see if the coordinates fall within a highlighted link area. If so,** the code must set mouse_link to the index of the chosen link,** and return a key value that corresponds to LYK_ACTIVATE. The** LYK_ACTIVATE code in LYMainLoop.c will then check mouse_link** and activate that link. If the mouse event didn't fall within a** link, the code should just set mouse_link to -1 and return -1. --AMK**//* The number of the link selected w/ the mouse (-1 if none) */static int mouse_link = -1;/* Return the value of mouse_link, erasing it */PUBLIC int get_mouse_link NOARGS{ int t; t=mouse_link; mouse_link = -1; return t;}/* Given X and Y coordinates of a mouse event, set mouse_link to the** index of the corresponding hyperlink, or set mouse_link to -1 if no** link matches the event. Returns -1 if no link matched the click,** or a keycode that must be returned from LYgetch() to activate the** link.**/PRIVATE int set_clicked_link ARGS2(int,x,int,y){ int i; /* Loop over the links and see if we can get a match */ for(i=0; i < nlinks && mouse_link == -1; i++) { /* Check the first line of the link */ if ( links[i].hightext != NULL && links[i].ly == y && (x - links[i].lx) < (int)strlen(links[i].hightext ) ) { mouse_link=i; } /* Check the second line */ if (links[i].hightext2 != NULL && 1+links[i].ly == y && (x - links[i].hightext2_offset) < (int)strlen(links[i].hightext2) ) { mouse_link=i; } } /* If no link was found, just return a do-nothing code */ if (mouse_link == -1) return -1; /* If a link was hit, we must look for a key which will activate LYK_ACTIVATE ** XXX The 127 in the following line will depend on the size of the keymap[] ** array. However, usually we'll find LYK_ACTIVATE somewhere in the first ** 127 keys (it's usually mapped to the Enter key) **/ for (i=0; i<127; i++) { if (LYisNonAlnumKeyname(i, LYK_ACTIVATE)) { return i; } } /* Whoops! Nothing's defined as LYK_ACTIVATE! Well, who are we to argue with the user? Forget about the mouse click */ mouse_link = -1; return -1;}/* * LYstrncpy() terminates strings with a null byte. * Writes a null byte into the n+1 byte of dst. */PUBLIC char *LYstrncpy ARGS3( char *, dst, CONST char *, src, int, n){ char *val; int len=strlen(src); if (n < 0) n = 0; val = strncpy(dst, src, n); if (len < n) *(dst+len) = '\0'; else *(dst+n) = '\0'; return val;}#define IS_NEW_GLYPH(ch) (utf_flag && ((unsigned char)(ch)&0xc0) != 0x80)#define IS_UTF_EXTRA(ch) (utf_flag && ((unsigned char)(ch)&0xc0) == 0x80)/* * LYmbcsstrncpy() terminates strings with a null byte. * It takes account of multibyte characters. * The src string is copied until either end of string or max number of * either bytes or glyphs (mbcs sequences) (CJK or UTF8). The utf_flag * argument should be TRUE for UTF8. - KW & FM */PUBLIC char * LYmbcsstrncpy ARGS5( char *, dst, CONST char *, src, int, n_bytes, int, n_glyphs, BOOL, utf_flag){ char *val = dst; int i_bytes = 0, i_glyphs = 0; if (n_bytes < 0) n_bytes = 0; if (n_glyphs < 0) n_glyphs = 0; for (; *src != '\0' && i_bytes < n_bytes; i_bytes++) { if (IS_NEW_GLYPH(*src)) { if (i_glyphs++ >= n_glyphs) { *dst = '\0'; return val; } } *(dst++) = *(src++); } *dst = '\0'; return val;}/* * LYmbcs_skip_glyphs() skips a given number of display positions * in a string and returns the resulting pointer. It takes account * of UTF-8 encoded characters. - KW */PUBLIC char * LYmbcs_skip_glyphs ARGS3( char *, data, int, n_glyphs, BOOL, utf_flag){ int i_glyphs = 0; if (n_glyphs < 0) n_glyphs = 0; if (!data) return NULL; if (!utf_flag) return (data + n_glyphs); while (*data) { if (IS_NEW_GLYPH(*data)) { if (i_glyphs++ >= n_glyphs) { return data; } } data++; } return data;}/* * LYmbcsstrlen() returns the printable length of a string * that might contain IsSpecial or multibyte (CJK or UTF8) * characters. - FM */PUBLIC int LYmbcsstrlen ARGS2( char *, str, BOOL, utf_flag){ int i, j, len = 0; if (!str && *str) return(len); for (i = 0; str[i] != '\0'; i++) { if (IsSpecialAttrChar(str[i])) { continue; } else { len++; } if (IS_NEW_GLYPH(str[i])) { j = 0; while (str[(i + 1)] != '\0' && !IsSpecialAttrChar(str[(i + 1)]) && j < 5 && IS_UTF_EXTRA(str[(i + 1)])) { i++; j++; } } else if (!utf_flag && HTCJK != NOCJK && !isascii(str[i]) && str[(i + 1)] != '\0' && !IsSpecialAttrChar(str[(i + 1)])) { i++; } } return(len);}#undef GetChar#ifdef USE_SLANG#ifdef VMS#define GetChar() ttgetc()#else#define GetChar (int)SLang_getkey#endif /* VMS */#endif /* USE_SLANG */#if !defined(GetChar) && defined(NCURSES)#define GetChar() wgetch(my_subwindow ? my_subwindow : stdscr)#endif#if !defined(GetChar) && defined(SNAKE)#define GetChar() wgetch(stdscr)#endif#if !defined(GetChar) && defined(VMS)#define GetChar() ttgetc()#endif#if !defined(GetChar)#if HAVE_KEYPAD#define GetChar getch#else#ifndef USE_GETCHAR#define USE_GETCHAR#endif /* !USE_GETCHAR */#define GetChar() getchar() /* used to be "getc(stdin)" and "getch()" */#endif /* HAVE_KEYPAD */#endif /* !defined(GetChar) */#if defined(NCURSES)/* * Workaround a bug in ncurses order-of-refresh by setting a pointer to * the topmost window that should be displayed. */PRIVATE WINDOW *my_subwindow;PUBLIC void LYsubwindow ARGS1(WINDOW *, param){ my_subwindow = param;}#endif#ifdef USE_SLANG_MOUSEPRIVATE int sl_parse_mouse_event ARGS3(int *, x, int *, y, int *, button){ /* "ESC [ M" has already been processed. There more characters are * expected: BUTTON X Y */ *button = SLang_getkey (); switch (*button) { case 040: /* left button */ case 041: /* middle button */ case 042: /* right button */ *button -= 040; break; default: /* Hmmm.... */ SLang_flush_input (); return -1; } *x = SLang_getkey () - 33; *y = SLang_getkey () - 33; return 0;}#endif#if defined(USE_SLANG_MOUSE) || defined(NCURSES_MOUSE_VERSION)PRIVATE int map_function_to_key ARGS1(char, keysym){ int i; /* I would prefer to use sizeof keymap but its size is not available. * A better method would be to declare it as some fixed size. */ for (i = 1; i < 256; i++) { if (keymap[i] == keysym) return i - 1; } return -1;}#endifPRIVATE BOOLEAN csi_is_csi = TRUE;PUBLIC void ena_csi ARGS1( BOOLEAN, flag){ csi_is_csi = flag;}/* * LYgetch() translates some escape sequences and may fake noecho. */PUBLIC int LYgetch NOARGS{ int a, b, c, d = -1;#if defined(IGNORE_CTRL_C) || defined(USE_GETCHAR) || !defined(NCURSES)re_read:#endif /* IGNORE_CTRL_C || USE_GETCHAR */#ifndef USE_SLANG clearerr(stdin); /* needed here for ultrix and SOCKETSHR, but why? - FM */#endif /* !USE_SLANG */#if !defined(USE_SLANG) || defined(VMS) c = GetChar();#else if (LYCursesON) { c = GetChar(); } else { c = getchar(); if (c == EOF && errno == EINTR) /* Ctrl-Z causes EINTR in getchar() */ clearerr(stdin); if (feof(stdin) || ferror(stdin) || c == EOF) {#ifdef IGNORE_CTRL_C if (sigint) sigint = FALSE;#endif /* IGNORE_CTRL_C */ return(7); /* use ^G to cancel whatever called us. */ } }#endif /* !USE_SLANG || VMS */#ifdef RAWDOSKEYHACK if (raw_dos_key_hack) { if (c == 0) c = '/'; if (c > 255) { /* handle raw dos keys */ switch (c) { case 464: c = '-'; break; /* keypad minus*/ case 465: c = '+'; break; /* keypad plus*/ case 459: c = 13; break; /* keypad enter*/ case 463: c = '*'; break; /* keypad * */ case 440: c = 'Q'; break; /* alt x */ case 265: c = 'H'; break; /* F1 */ default: break; } } }#endif /* RAWDOSKEYHACK */#ifdef USE_GETCHAR if (c == EOF && errno == EINTR) /* Ctrl-Z causes EINTR in getchar() */ goto re_read;#endif /* USE_GETCHAR */#ifdef USE_SLANG if (c == 0xFFFF && LYCursesON) {#ifdef IGNORE_CTRL_C if (sigint) { sigint = FALSE; goto re_read; }#endif /* IGNORE_CTRL_C */ return(7); /* use ^G to cancel whatever called us. */ }#else if (feof(stdin) || ferror(stdin) || c == EOF) { if (recent_sizechange) return(7); /* use ^G to cancel whatever called us. */#ifdef IGNORE_CTRL_C if (sigint) { sigint = FALSE; /* clearerr(stdin); don't need here if stays above - FM */ goto re_read; }#endif /* IGNORE_CTRL_C */#if !defined(USE_GETCHAR) && !defined(VMS) && !defined(NCURSES) if (c == ERR && errno == EINTR) /* may have been handled signal - kw */ goto re_read;#endif /* USE_GETCHAR */ cleanup();#ifndef NOSIGHUP (void) signal(SIGHUP, SIG_DFL);#endif /* NOSIGHUP */ (void) signal(SIGTERM, SIG_DFL);#ifndef VMS (void) signal(SIGINT, SIG_DFL);#endif /* !VMS */#ifdef SIGTSTP if (no_suspend) (void) signal(SIGTSTP,SIG_DFL);#endif /* SIGTSTP */ exit(0); }#endif /* USE_SLANG */ if (c == 27 || (csi_is_csi && c == 155)) { /* handle escape sequence */ b = GetChar(); if (b == '[' || b == 'O') { a = GetChar(); } else { a = b; } switch (a) { case 'A': c = UPARROW; break; case 'x': c = UPARROW; break; /* keypad up on pc ncsa telnet */ case 'B': c = DNARROW; break; case 'r': c = DNARROW; break; /* keypad down on pc ncsa telnet */ case 'C': c = RTARROW; break; case 'v': c = RTARROW; break; /* keypad right on pc ncsa telnet */ case 'D': c = LTARROW; break; case 't': c = LTARROW; break; /* keypad left on pc ncsa telnet */ case 'y': c = PGUP; break; /* keypad on pc ncsa telnet */ case 's': c = PGDOWN; break; /* keypad on pc ncsa telnet */ case 'w': c = HOME; break; /* keypad on pc ncsa telnet */ case 'q': c = END; break; /* keypad on pc ncsa telnet */ case 'M':#ifdef USE_SLANG_MOUSE if ((c == 27) && (b == '[')) { int mouse_x, mouse_y, button; mouse_link = -1; c = -1; if (-1 != sl_parse_mouse_event (&mouse_x, &mouse_y, &button)) { if (button == 0) /* left */ c = set_clicked_link (mouse_x, mouse_y); else if (button == 2) /* right */ { /* Right button: go back to prev document. * The problem is that we need to determine * what to return to achieve this. */ c = map_function_to_key (LYK_PREV_DOC); } } } else#endif c = '\n'; /* keypad enter on pc ncsa telnet */ break; case 'm':#ifdef VMS if (b != 'O')#endif /* VMS */ c = '-'; /* keypad on pc ncsa telnet */ break; case 'k': if (b == 'O') c = '+'; /* keypad + on my xterminal :) */ break; case 'l':#ifdef VMS if (b != 'O')#endif /* VMS */ c = '+'; /* keypad on pc ncsa telnet */ break; case 'P':#ifdef VMS if (b != 'O')#endif /* VMS */ c = F1; break; case 'u':#ifdef VMS if (b != 'O')#endif /* VMS */ c = F1; /* macintosh help button */ break; case 'p':#ifdef VMS if (b == 'O')#endif /* VMS */ c = '0'; /* keypad 0 */ break; case '1': /** VTxxx Find **/ if ((b == '[' || c == 155) && (d=GetChar()) == '~') c = FIND_KEY; break; case '2': if (b == '[' || c == 155) { if ((d=GetChar())=='~') /** VTxxx Insert **/ c = INSERT_KEY; else if ((d == '8' || d == '9') && GetChar() == '~') { if (d == '8') /** VTxxx Help **/ c = F1; else if (d == '9') /** VTxxx Do **/ c = DO_KEY; d = -1; } } break; case '3': /** VTxxx Delete **/ if ((b == '[' || c == 155) && (d=GetChar()) == '~') c = REMOVE_KEY; break; case '4': /** VTxxx Select **/ if ((b == '[' || c == 155) && (d=GetChar()) == '~') c = SELECT_KEY; break; case '5': /** VTxxx PrevScreen **/ if ((b == '[' || c == 155) && (d=GetChar()) == '~') c = PGUP; break; case '6': /** VTxxx NextScreen **/ if ((b == '[' || c == 155) && (d=GetChar()) == '~') c = PGDOWN; break; case '[': /** Linux F1-F5: ^[[[A etc. **/ if (b == '[' || c == 155) { if ((d=GetChar()) == 'A') c = F1; break; } default: if (TRACE) { fprintf(stderr,"Unknown key sequence: %d:%d:%d\n",c,b,a); if (!LYTraceLogFP) { sleep(MessageSecs); } } } if (isdigit(a) && (b == '[' || c == 155) && d != -1 && d != '~') d = GetChar(); }#if HAVE_KEYPAD else { /* * Convert keypad() mode keys into Lynx defined keys. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -