*** art.c.orig	Thu Nov  5 18:05:15 1998
--- art.c	Mon Apr  5 20:18:06 1999
***************
*** 1008,1013 ****
--- 1008,1032 ----
  
  /*}}}*/
  
+ /* work out how wide a character will appear on the display */
+ static unsigned int slrn_char_display_width( unsigned int pos, unsigned char ch ) /*{{{*/
+ {
+    if ((ch == '\t') && (SLsmg_Tab_Width > 0))
+      return SLsmg_Tab_Width - pos % SLsmg_Tab_Width;
+ #if 1
+    else
+      return 1; /* slrn 0.9.4.0 displays unknown chars as "?" */
+ #else
+    else if (((ch >= ' ') && (ch < 127))
+ 	    || (ch >= (unsigned char) SLsmg_Display_Eight_Bit))
+      return 1;
+    else
+      return (ch & 0x80) ? 3 : 2;
+ #endif
+ }
+ 
+ /*}}}*/
+ 
  int Slrn_Wrap_Mode = 3;
  
  static void unwrap_article (void)
***************
*** 1077,1096 ****
  	ch = *buf;
  	while (ch != 0)
  	  {
! 	     if ((ch == '\t') && (SLsmg_Tab_Width > 0))
! 	       {
! 		  len += SLsmg_Tab_Width;
! 		  len -= len % SLsmg_Tab_Width;
! 	       }
! 	     else if (((ch >= ' ') && (ch < 127))
! 		      || (ch >= (unsigned char) SLsmg_Display_Eight_Bit))
! 	       len++;
! 	     else
! 	       {
! 		  len += 2;
! 		  if (ch & 0x80) len++;
! 	       }
! 
  	     if (len > (unsigned int) SLtt_Screen_Cols)
  	       {
  		  Slrn_Article_Line_Type *new_l;
--- 1096,1102 ----
  	ch = *buf;
  	while (ch != 0)
  	  {
!  	     len += slrn_char_display_width( len, ch );
  	     if (len > (unsigned int) SLtt_Screen_Cols)
  	       {
  		  Slrn_Article_Line_Type *new_l;
***************
*** 1296,1321 ****
  	     
  	     switch (ch)
  	       {
- 		case '.':
- 		  ptr++;
- 		  ch = *ptr;
- 		  if ((ch == ' ') || (ch == '\t') 
- 		      || (ch == '\n') || (ch == 0))
- 		    {
- 		       ptr--;
- 		       again = 0;
- 		    }
- 		  break;
- 
  		case ' ':
  		case '\t':
  		case '\n':
  		case '\"':
  		case '}':
  		case '{':
  		case ')':
- 		case ',':
- 		case ';':
  		case '>':
  		case '<':
  		  
--- 1302,1315 ----
  	     
  	     switch (ch)
  	       {
  		case ' ':
  		case '\t':
  		case '\n':
  		case '\"':
+ 		case '\'':
  		case '}':
  		case '{':
  		case ')':
  		case '>':
  		case '<':
  		  
***************
*** 1328,1334 ****
  		  break;
  	       }
  	  }
! 	     
  	l_buf = ptr;
  
  	if ((*p_len = (unsigned int) (ptr - tmp)) < 7)
--- 1322,1333 ----
  		  break;
  	       }
  	  }
! 
! 	/* allow ".", ",", and ";" in URLs, except as the last character - in
! 	 * that case they're almost certainly punctuation
! 	 */
!         while (ptr > tmp && strchr(".,;", ptr[-1])) ptr--;
! 	
  	l_buf = ptr;
  
  	if ((*p_len = (unsigned int) (ptr - tmp)) < 7)
***************
*** 6530,6535 ****
--- 6529,6537 ----
     
     if (r - 2 > Header_Window_Nrows)
       {
+ 	/* quick prototype to fix warnings */
+ 	static int click_on_url( int r, int c );
+ 	if (click_on_url( r, c )) return;
  	if (NULL != normal_region) (*normal_region) ();
   	return;
       }
***************
*** 7792,7801 ****
     return 0;
  }
  
  static void display_article_line (Slrn_Article_Line_Type *l)
  {
     char *lbuf = l->buf;
!    
     if (l->flags & HEADER_LINE)
       {
  	if ((unsigned char)*lbuf > (unsigned char)' ')
--- 7794,7827 ----
     return 0;
  }
  
+ /* write out a string, colouring in any URLs */
+ static void art_write_string ( int color, char *str )
+ {
+    for (;;) {
+       char *p_url;
+       int len;
+       p_url = find_url ( str, &len );
+       if (NULL == p_url) break;
+       if (p_url != str)
+ 	{
+ 	   slrn_set_color ( color );
+ 	   smg_write_nchars ( str, p_url-str );
+ 	}
+       if (len > 0)
+ 	{
+ 	   slrn_set_color ( URL_COLOR );
+ 	   smg_write_nchars ( p_url, len );
+ 	}
+       str = p_url + len;
+    }
+    slrn_set_color ( color );
+    smg_write_string ( str );
+ }
+ 
  static void display_article_line (Slrn_Article_Line_Type *l)
  {
     char *lbuf = l->buf;
! 
     if (l->flags & HEADER_LINE)
       {
  	if ((unsigned char)*lbuf > (unsigned char)' ')
***************
*** 7809,7831 ****
  	       }
  	     else lbuf = l->buf;
  	  }
! 	slrn_set_color (HEADER_COLOR);
! 	smg_write_string (lbuf);
       }
     else
       {
  	if (l->flags & QUOTE_LINE)
! 	  slrn_set_color (QUOTE_COLOR);
  	else if (l->flags & SIGNATURE_LINE)
! 	  slrn_set_color (SIGNATURE_COLOR);
! 	else slrn_set_color (ARTICLE_COLOR);
  #if SLRN_HAS_SPOILERS
  	if (l->flags & SPOILER_LINE)
! 	  write_spoiler ((unsigned char *) lbuf);
  	else
  #endif
! 	  if (Do_Rot13) write_rot13 ((unsigned char *) lbuf);
! 	else smg_write_string (lbuf);
       }
  }
  
--- 7835,7864 ----
  	       }
  	     else lbuf = l->buf;
  	  }
!  	art_write_string ( HEADER_COLOR, lbuf );
       }
     else
       {
+  	int color = ARTICLE_COLOR;
  	if (l->flags & QUOTE_LINE)
!  	  color = QUOTE_COLOR;
  	else if (l->flags & SIGNATURE_LINE)
!  	  color = SIGNATURE_COLOR;
  #if SLRN_HAS_SPOILERS
  	if (l->flags & SPOILER_LINE)
!  	  {
!  	     slrn_set_color (color);
!  	     write_spoiler ((unsigned char *) lbuf);
!  	  }
  	else
  #endif
!  	  if (Do_Rot13)
!  	    {
!  	       slrn_set_color (color);
!  	       write_rot13 ((unsigned char *) lbuf);
!  	    }
!     	  else
!  	    art_write_string ( color, lbuf );
       }
  }
  
***************
*** 8025,8030 ****
--- 8058,8154 ----
  
  /*}}}*/
  
+ static int click_on_url( int r, int c )
+ {
+    int old_row, old_col;
+    old_row = SLsmg_get_row();
+    old_col = SLsmg_get_column();
+ 
+    SLsmg_gotorc ( r-1, c-1 );
+    if ((unsigned)SLsmg_char_at()>>8 == URL_COLOR)
+      {
+ 	/* the user has clicked on something painted "URL color" */
+ 	int row = (r - 2) - Header_Window_Nrows; /* counting from 1 */
+ 	int col = c - 1 + Article_Window_HScroll;
+ 	int pos;
+ 	Slrn_Article_Line_Type *l;
+ 	char *p, *str;
+ 	
+ 	/* Find the corresponding line from the article */
+ 	l = (Slrn_Article_Line_Type*)Slrn_Article_Window.top_window_line;
+ 	while (--row)
+ 	  {
+ 	     do {
+ 		l = l->next;
+ 		if (NULL == l) return 0; /* didn't find URL */
+ 	     } while (l->flags & HIDDEN_LINE);
+  	  }
+ 	
+ #if 0
+ 	/* This is broken if there are tabs (or other wide characters) around */
+ 	p = l->buf + c - 1 + HScroll; /* ptr to character clicked on */
+ #else
+ 	pos = 0;
+ 	p = l->buf;
+ 	while (pos < col)
+ 	  {
+ 	     if (*p == '\0') break;
+ 	     pos += slrn_char_display_width( pos, *p++ );
+ 	  }
+ 	if (pos > col) p--;
+ #endif
+ 	
+ 	/* now repeat the same scan for URLs we used when colouring */
+ 	str = l->buf;
+ 	for (;;) {
+ 	   char *p_url;
+ 	   unsigned int len;
+ 	   p_url = find_url ( str, &len );
+ 	   if (NULL == p_url) break;
+ 	   if (len > 0)
+ 	     {
+ 		if (p_url <= p && p < p_url + len)
+ 		  {
+ 		     /* found it */
+ 		     char temp;
+ 		     int color;
+ 		     slrn_push_suspension (0);
+ 		     /* flash URL */
+ 		     color = URL_PRESS_COLOR;
+ #if 0
+ 		     /* This is broken if there are tabs (or other wide characters) around */
+ 		     col = p_url - l->buf - HScroll;
+ #else
+ 		     /* !HACK! This is broken if there are 'wide' chars in the URL before the point clicked */
+ 		     col = c-1 - (p-p_url);
+ #endif
+ 		     while (1)
+ 		       {
+ 			  /* A quick prototype to fix warnings */
+ 			  static void smg_write_nchars (char *s, unsigned int n);
+ 			  slrn_set_color (color);
+ 			  SLsmg_gotorc ( r-1, col );
+ 			  smg_write_nchars (p_url, len);
+ 			  SLsmg_gotorc ( old_row, old_col );
+ 			  slrn_smg_refresh ();
+ 			  if (color == URL_COLOR) break;
+ 			  (void) SLang_input_pending (1); /* 1/10 sec */
+ 			  color = URL_COLOR;
+ 		       }
+ 		     slrn_set_color (0);
+ 		     slrn_pop_suspension ();
+ 		     temp = p_url[len];
+ 		     p_url[len] = '\0'; /* yuck */
+ 		     launch_url( p_url );
+ 		     p_url[len] = temp; /* unyuck */
+ 		     return 1; /* URL found */
+ 		  }
+ 	     }
+ 	   str = p_url + len;
+ 	}
+       }
+    return 0; /* didn't find URL */
+ }
  
  /*}}}*/
  
*** slrn.h.orig	Thu Nov  5 18:05:16 1998
--- slrn.h	Mon Apr  5 20:00:15 1999
***************
*** 109,112 ****
--- 109,114 ----
  #define RESPONSE_CHAR_COLOR	22
  #define FRAME_COLOR		23
  #define SELECT_COLOR		24
+ #define URL_COLOR       25
+ #define URL_PRESS_COLOR       26
  #endif				       /* _SLRN_SLRN_H_ */
*** startup.c.orig	Thu Nov  5 18:05:16 1998
--- startup.c	Mon Apr  5 20:00:15 1999
***************
*** 718,723 ****
--- 718,725 ----
       {"box", BOX_COLOR,"black", "white", 0},
       {"frame", FRAME_COLOR,"yellow", "blue", SLTT_REV_MASK},
       {"selection", SELECT_COLOR,"yellow", "blue", SLTT_BOLD_MASK},
+      {"url",            URL_COLOR,       "white",       "blue", SLTT_REV_MASK},
+      {"url_press",      URL_PRESS_COLOR, "blue",        "white", 0},
     
       {NULL, -1, NULL, NULL, 0}
  };
