st-flexipatch

My st-flexipatch configuration
git clone git://git.ethandl.dev/st-flexipatch
Log | Files | Refs | README | LICENSE

openurlonclick.c (5295B)


      1 #if !REFLOW_PATCH
      2 #if SCROLLBACK_PATCH
      3 #define TLINEURL(y) TLINE(y)
      4 #else
      5 #define TLINEURL(y) term.line[y]
      6 #endif // SCROLLBACK_PATCH
      7 #endif // REFLOW_PATCH
      8 
      9 int url_x1, url_y1, url_x2, url_y2 = -1;
     10 int url_draw, url_click, url_maxcol;
     11 
     12 static int
     13 isvalidurlchar(Rune u)
     14 {
     15 	/* () and [] can appear in urls, but excluding them here will reduce false
     16 	 * positives when figuring out where a given url ends. See copyurl patch.
     17 	 */
     18 	static char urlchars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
     19 		"abcdefghijklmnopqrstuvwxyz"
     20 		"0123456789-._~:/?#@!$&'*+,;=%";
     21 	return u < 128 && strchr(urlchars, (int)u) != NULL;
     22 }
     23 
     24 /* find the end of the wrapped line */
     25 #if REFLOW_PATCH
     26 static int
     27 findeowl(Line line)
     28 {
     29 	int i = term.col - 1;
     30 
     31 	do {
     32 		if (line[i].mode & ATTR_WRAP)
     33 			return i;
     34 	} while (!(line[i].mode & ATTR_SET) && --i >= 0);
     35 
     36 	return -1;
     37 }
     38 #else
     39 static int
     40 findeowl(int row)
     41 {
     42 	#if COLUMNS_PATCH
     43 	int col = term.maxcol - 1;
     44 	#else
     45 	int col = term.col - 1;
     46 	#endif // COLUMNS_PATCH
     47 
     48 	do {
     49 		if (TLINEURL(row)[col].mode & ATTR_WRAP)
     50 			return col;
     51 	} while (TLINEURL(row)[col].u == ' ' && --col >= 0);
     52 	return -1;
     53 }
     54 #endif // REFLOW_PATCH
     55 
     56 void
     57 clearurl(void)
     58 {
     59 	while (url_y1 <= url_y2 && url_y1 < term.row)
     60 		term.dirty[url_y1++] = 1;
     61 	url_y2 = -1;
     62 }
     63 
     64 #if REFLOW_PATCH
     65 char *
     66 detecturl(int col, int row, int draw)
     67 {
     68 	static char url[2048];
     69 	Line line;
     70 	int x1, y1, x2, y2;
     71 	int i = sizeof(url)/2+1, j = sizeof(url)/2;
     72 	int row_start = row, col_start = col;
     73 	int minrow = tisaltscr() ? 0 : term.scr - term.histf;
     74 	int maxrow = tisaltscr() ? term.row - 1 : term.scr + term.row - 1;
     75 
     76 	/* clear previously underlined url */
     77 	if (draw)
     78 		clearurl();
     79 
     80 	url_maxcol = 0;
     81 	line = TLINE(row);
     82 
     83 	if (!isvalidurlchar(line[col].u))
     84 		return NULL;
     85 
     86 	/* find the first character of url */
     87 	do {
     88 		x1 = col_start, y1 = row_start;
     89 		url_maxcol = MAX(url_maxcol, x1);
     90 		url[--i] = line[col_start].u;
     91 		if (--col_start < 0) {
     92 			if (--row_start < minrow || (col_start = findeowl(TLINE(row_start))) < 0)
     93 				break;
     94 			line = TLINE(row_start);
     95 		}
     96 	} while (isvalidurlchar(line[col_start].u) && i > 0);
     97 
     98 	/* early detection */
     99 	if (url[i] != 'h')
    100 		return NULL;
    101 
    102 	/* find the last character of url */
    103 	line = TLINE(row);
    104 	do {
    105 		x2 = col, y2 = row;
    106 		url_maxcol = MAX(url_maxcol, x2);
    107 		url[j++] = line[col].u;
    108 		if (line[col++].mode & ATTR_WRAP) {
    109 			if (++row > maxrow)
    110 				break;
    111 			col = 0;
    112 			line = TLINE(row);
    113 		}
    114 	} while (col < term.col && isvalidurlchar(line[col].u) && j < sizeof(url)-1);
    115 
    116 	url[j] = 0;
    117 
    118 	if (strncmp("https://", &url[i], 8) && strncmp("http://", &url[i], 7))
    119 		return NULL;
    120 
    121 	/* Ignore some trailing characters to improve detection. */
    122 	/* Alacritty and many other terminals also ignore these. */
    123 	if (strchr(",.;:?!", (int)(url[j-1])) != NULL) {
    124 		x2 = MAX(x2-1, 0);
    125 		url[j-1] = 0;
    126 	}
    127 
    128 	/* underline url (see xdrawglyphfontspecs() in x.c) */
    129 	if (draw) {
    130 		url_x1 = (y1 >= 0) ? x1 : 0;
    131 		url_x2 = (y2 < term.row) ? x2 : url_maxcol;
    132 		url_y1 = MAX(y1, 0);
    133 		url_y2 = MIN(y2, term.row-1);
    134 		url_draw = 1;
    135 		for (y1 = url_y1; y1 <= url_y2; y1++)
    136 			term.dirty[y1] = 1;
    137 	}
    138 
    139 	return &url[i];
    140 }
    141 #else
    142 char *
    143 detecturl(int col, int row, int draw)
    144 {
    145 	static char url[2048];
    146 	int x1, y1, x2, y2, wrapped;
    147 	int row_start = row;
    148 	int col_start = col;
    149 	int i = sizeof(url)/2+1, j = sizeof(url)/2;
    150 
    151 	#if SCROLLBACK_PATCH
    152 	int minrow = term.scr - term.histn, maxrow = term.scr + term.row - 1;
    153 	/* Fixme: MODE_ALTSCREEN is not defined here, I had to use the magic number 1<<2 */
    154 	if ((term.mode & (1 << 2)) != 0)
    155 		minrow = 0, maxrow = term.row - 1;
    156 	#else
    157 	int minrow = 0, maxrow = term.row - 1;
    158 	#endif // SCROLLBACK_PATCH
    159 	url_maxcol = 0;
    160 
    161 	/* clear previously underlined url */
    162 	if (draw)
    163 		clearurl();
    164 
    165 	if (!isvalidurlchar(TLINEURL(row)[col].u))
    166 		return NULL;
    167 
    168 	/* find the first character of url */
    169 	do {
    170 		x1 = col_start, y1 = row_start;
    171 		url_maxcol = MAX(url_maxcol, x1);
    172 		url[--i] = TLINEURL(row_start)[col_start].u;
    173 		if (--col_start < 0) {
    174 			if (--row_start < minrow || (col_start = findeowl(row_start)) < 0)
    175 				break;
    176 		}
    177 	} while (i > 0 && isvalidurlchar(TLINEURL(row_start)[col_start].u));
    178 
    179 	/* early detection */
    180 	if (url[i] != 'h')
    181 		return NULL;
    182 
    183 	/* find the last character of url */
    184 	do {
    185 		x2 = col, y2 = row;
    186 		url_maxcol = MAX(url_maxcol, x2);
    187 		url[j++] = TLINEURL(row)[col].u;
    188 		wrapped = TLINEURL(row)[col].mode & ATTR_WRAP;
    189 		#if COLUMNS_PATCH
    190 		if (++col >= term.maxcol || wrapped) {
    191 		#else
    192 		if (++col >= term.col || wrapped) {
    193 		#endif // COLUMNS_PATCH
    194 			col = 0;
    195 			if (++row > maxrow || !wrapped)
    196 				break;
    197 		}
    198 	} while (j < sizeof(url)-1 && isvalidurlchar(TLINEURL(row)[col].u));
    199 
    200 	url[j] = 0;
    201 
    202 	if (strncmp("https://", &url[i], 8) && strncmp("http://", &url[i], 7))
    203 		return NULL;
    204 
    205 	/* underline url (see xdrawglyphfontspecs() in x.c) */
    206 	if (draw) {
    207 		url_x1 = (y1 >= 0) ? x1 : 0;
    208 		url_x2 = (y2 < term.row) ? x2 : url_maxcol;
    209 		url_y1 = MAX(y1, 0);
    210 		url_y2 = MIN(y2, term.row-1);
    211 		url_draw = 1;
    212 		for (y1 = url_y1; y1 <= url_y2; y1++)
    213 			term.dirty[y1] = 1;
    214 	}
    215 
    216 	return &url[i];
    217 }
    218 #endif // REFLOW_PATCH
    219 
    220 void
    221 openUrlOnClick(int col, int row, char* url_opener)
    222 {
    223 	char *url = detecturl(col, row, 1);
    224 	if (url) {
    225 		extern char **environ;
    226 		pid_t junk;
    227 		char *argv[] = { url_opener, url, NULL };
    228 		posix_spawnp(&junk, argv[0], NULL, NULL, argv, environ);
    229 	}
    230 }