Karsten Hopp 5c71fd
To: vim-dev@vim.org
Karsten Hopp 5c71fd
Subject: Patch 7.2.080
Karsten Hopp 5c71fd
Fcc: outbox
Karsten Hopp 5c71fd
From: Bram Moolenaar <Bram@moolenaar.net>
Karsten Hopp 5c71fd
Mime-Version: 1.0
Karsten Hopp 5c71fd
Content-Type: text/plain; charset=ISO-8859-1
Karsten Hopp 5c71fd
Content-Transfer-Encoding: 8bit
Karsten Hopp 5c71fd
------------
Karsten Hopp 5c71fd
Karsten Hopp 5c71fd
Patch 7.2.080
Karsten Hopp 5c71fd
Problem:    When typing a composing character just after starting completion
Karsten Hopp 5c71fd
	    may access memory before its allocation point. (Dominique Pelle)
Karsten Hopp 5c71fd
Solution:   Don't delete before the completion start column.  Add extra checks
Karsten Hopp 5c71fd
	    for the offset not being negative.
Karsten Hopp 5c71fd
Files:	    src/edit.c
Karsten Hopp 5c71fd
Karsten Hopp 5c71fd
Karsten Hopp 5c71fd
*** ../vim-7.2.079/src/edit.c	Wed Aug  6 18:56:55 2008
Karsten Hopp 5c71fd
--- src/edit.c	Tue Jan 13 12:05:57 2009
Karsten Hopp 5c71fd
***************
Karsten Hopp 5c71fd
*** 147,152 ****
Karsten Hopp 5c71fd
--- 147,153 ----
Karsten Hopp 5c71fd
  static int  ins_compl_bs __ARGS((void));
Karsten Hopp 5c71fd
  static void ins_compl_new_leader __ARGS((void));
Karsten Hopp 5c71fd
  static void ins_compl_addleader __ARGS((int c));
Karsten Hopp 5c71fd
+ static int ins_compl_len __ARGS((void));
Karsten Hopp 5c71fd
  static void ins_compl_restart __ARGS((void));
Karsten Hopp 5c71fd
  static void ins_compl_set_original_text __ARGS((char_u *str));
Karsten Hopp 5c71fd
  static void ins_compl_addfrommatch __ARGS((void));
Karsten Hopp 5c71fd
***************
Karsten Hopp 5c71fd
*** 197,203 ****
Karsten Hopp 5c71fd
  static void mb_replace_pop_ins __ARGS((int cc));
Karsten Hopp 5c71fd
  #endif
Karsten Hopp 5c71fd
  static void replace_flush __ARGS((void));
Karsten Hopp 5c71fd
! static void replace_do_bs __ARGS((void));
Karsten Hopp 5c71fd
  #ifdef FEAT_CINDENT
Karsten Hopp 5c71fd
  static int cindent_on __ARGS((void));
Karsten Hopp 5c71fd
  #endif
Karsten Hopp 5c71fd
--- 198,205 ----
Karsten Hopp 5c71fd
  static void mb_replace_pop_ins __ARGS((int cc));
Karsten Hopp 5c71fd
  #endif
Karsten Hopp 5c71fd
  static void replace_flush __ARGS((void));
Karsten Hopp 5c71fd
! static void replace_do_bs __ARGS((int limit_col));
Karsten Hopp 5c71fd
! static int del_char_after_col __ARGS((int limit_col));
Karsten Hopp 5c71fd
  #ifdef FEAT_CINDENT
Karsten Hopp 5c71fd
  static int cindent_on __ARGS((void));
Karsten Hopp 5c71fd
  #endif
Karsten Hopp 5c71fd
***************
Karsten Hopp 5c71fd
*** 1933,1938 ****
Karsten Hopp 5c71fd
--- 1935,1942 ----
Karsten Hopp 5c71fd
  /*
Karsten Hopp 5c71fd
   * Backspace the cursor until the given column.  Handles REPLACE and VREPLACE
Karsten Hopp 5c71fd
   * modes correctly.  May also be used when not in insert mode at all.
Karsten Hopp 5c71fd
+  * Will attempt not to go before "col" even when there is a composing
Karsten Hopp 5c71fd
+  * character.
Karsten Hopp 5c71fd
   */
Karsten Hopp 5c71fd
      void
Karsten Hopp 5c71fd
  backspace_until_column(col)
Karsten Hopp 5c71fd
***************
Karsten Hopp 5c71fd
*** 1942,1954 ****
Karsten Hopp 5c71fd
      {
Karsten Hopp 5c71fd
  	curwin->w_cursor.col--;
Karsten Hopp 5c71fd
  	if (State & REPLACE_FLAG)
Karsten Hopp 5c71fd
! 	    replace_do_bs();
Karsten Hopp 5c71fd
! 	else
Karsten Hopp 5c71fd
! 	    (void)del_char(FALSE);
Karsten Hopp 5c71fd
      }
Karsten Hopp 5c71fd
  }
Karsten Hopp 5c71fd
  #endif
Karsten Hopp 5c71fd
  
Karsten Hopp 5c71fd
  #if defined(FEAT_INS_EXPAND) || defined(PROTO)
Karsten Hopp 5c71fd
  /*
Karsten Hopp 5c71fd
   * CTRL-X pressed in Insert mode.
Karsten Hopp 5c71fd
--- 1946,1994 ----
Karsten Hopp 5c71fd
      {
Karsten Hopp 5c71fd
  	curwin->w_cursor.col--;
Karsten Hopp 5c71fd
  	if (State & REPLACE_FLAG)
Karsten Hopp 5c71fd
! 	    replace_do_bs(col);
Karsten Hopp 5c71fd
! 	else if (!del_char_after_col(col))
Karsten Hopp 5c71fd
! 	    break;
Karsten Hopp 5c71fd
      }
Karsten Hopp 5c71fd
  }
Karsten Hopp 5c71fd
  #endif
Karsten Hopp 5c71fd
  
Karsten Hopp 5c71fd
+ /*
Karsten Hopp 5c71fd
+  * Like del_char(), but make sure not to go before column "limit_col".
Karsten Hopp 5c71fd
+  * Only matters when there are composing characters.
Karsten Hopp 5c71fd
+  * Return TRUE when something was deleted.
Karsten Hopp 5c71fd
+  */
Karsten Hopp 5c71fd
+    static int
Karsten Hopp 5c71fd
+ del_char_after_col(limit_col)
Karsten Hopp 5c71fd
+     int limit_col;
Karsten Hopp 5c71fd
+ {
Karsten Hopp 5c71fd
+ #ifdef FEAT_MBYTE
Karsten Hopp 5c71fd
+     if (enc_utf8 && limit_col >= 0)
Karsten Hopp 5c71fd
+     {
Karsten Hopp 5c71fd
+ 	int ecol = curwin->w_cursor.col + 1;
Karsten Hopp 5c71fd
+ 
Karsten Hopp 5c71fd
+ 	/* Make sure the cursor is at the start of a character, but
Karsten Hopp 5c71fd
+ 	 * skip forward again when going too far back because of a
Karsten Hopp 5c71fd
+ 	 * composing character. */
Karsten Hopp 5c71fd
+ 	mb_adjust_cursor();
Karsten Hopp 5c71fd
+ 	while (curwin->w_cursor.col < limit_col)
Karsten Hopp 5c71fd
+ 	{
Karsten Hopp 5c71fd
+ 	    int l = utf_ptr2len(ml_get_cursor());
Karsten Hopp 5c71fd
+ 
Karsten Hopp 5c71fd
+ 	    if (l == 0)  /* end of line */
Karsten Hopp 5c71fd
+ 		break;
Karsten Hopp 5c71fd
+ 	    curwin->w_cursor.col += l;
Karsten Hopp 5c71fd
+ 	}
Karsten Hopp 5c71fd
+ 	if (*ml_get_cursor() == NUL || curwin->w_cursor.col == ecol)
Karsten Hopp 5c71fd
+ 	    return FALSE;
Karsten Hopp 5c71fd
+ 	del_bytes((long)(ecol - curwin->w_cursor.col), FALSE, TRUE);
Karsten Hopp 5c71fd
+     }
Karsten Hopp 5c71fd
+     else
Karsten Hopp 5c71fd
+ #endif
Karsten Hopp 5c71fd
+ 	(void)del_char(FALSE);
Karsten Hopp 5c71fd
+     return TRUE;
Karsten Hopp 5c71fd
+ }
Karsten Hopp 5c71fd
+ 
Karsten Hopp 5c71fd
  #if defined(FEAT_INS_EXPAND) || defined(PROTO)
Karsten Hopp 5c71fd
  /*
Karsten Hopp 5c71fd
   * CTRL-X pressed in Insert mode.
Karsten Hopp 5c71fd
***************
Karsten Hopp 5c71fd
*** 2418,2424 ****
Karsten Hopp 5c71fd
  	{
Karsten Hopp 5c71fd
  	    had_match = (curwin->w_cursor.col > compl_col);
Karsten Hopp 5c71fd
  	    ins_compl_delete();
Karsten Hopp 5c71fd
! 	    ins_bytes(compl_leader + curwin->w_cursor.col - compl_col);
Karsten Hopp 5c71fd
  	    ins_redraw(FALSE);
Karsten Hopp 5c71fd
  
Karsten Hopp 5c71fd
  	    /* When the match isn't there (to avoid matching itself) remove it
Karsten Hopp 5c71fd
--- 2458,2464 ----
Karsten Hopp 5c71fd
  	{
Karsten Hopp 5c71fd
  	    had_match = (curwin->w_cursor.col > compl_col);
Karsten Hopp 5c71fd
  	    ins_compl_delete();
Karsten Hopp 5c71fd
! 	    ins_bytes(compl_leader + ins_compl_len());
Karsten Hopp 5c71fd
  	    ins_redraw(FALSE);
Karsten Hopp 5c71fd
  
Karsten Hopp 5c71fd
  	    /* When the match isn't there (to avoid matching itself) remove it
Karsten Hopp 5c71fd
***************
Karsten Hopp 5c71fd
*** 2470,2476 ****
Karsten Hopp 5c71fd
  	    *p = NUL;
Karsten Hopp 5c71fd
  	    had_match = (curwin->w_cursor.col > compl_col);
Karsten Hopp 5c71fd
  	    ins_compl_delete();
Karsten Hopp 5c71fd
! 	    ins_bytes(compl_leader + curwin->w_cursor.col - compl_col);
Karsten Hopp 5c71fd
  	    ins_redraw(FALSE);
Karsten Hopp 5c71fd
  
Karsten Hopp 5c71fd
  	    /* When the match isn't there (to avoid matching itself) remove it
Karsten Hopp 5c71fd
--- 2510,2516 ----
Karsten Hopp 5c71fd
  	    *p = NUL;
Karsten Hopp 5c71fd
  	    had_match = (curwin->w_cursor.col > compl_col);
Karsten Hopp 5c71fd
  	    ins_compl_delete();
Karsten Hopp 5c71fd
! 	    ins_bytes(compl_leader + ins_compl_len());
Karsten Hopp 5c71fd
  	    ins_redraw(FALSE);
Karsten Hopp 5c71fd
  
Karsten Hopp 5c71fd
  	    /* When the match isn't there (to avoid matching itself) remove it
Karsten Hopp 5c71fd
***************
Karsten Hopp 5c71fd
*** 3209,3215 ****
Karsten Hopp 5c71fd
  {
Karsten Hopp 5c71fd
      ins_compl_del_pum();
Karsten Hopp 5c71fd
      ins_compl_delete();
Karsten Hopp 5c71fd
!     ins_bytes(compl_leader + curwin->w_cursor.col - compl_col);
Karsten Hopp 5c71fd
      compl_used_match = FALSE;
Karsten Hopp 5c71fd
  
Karsten Hopp 5c71fd
      if (compl_started)
Karsten Hopp 5c71fd
--- 3249,3255 ----
Karsten Hopp 5c71fd
  {
Karsten Hopp 5c71fd
      ins_compl_del_pum();
Karsten Hopp 5c71fd
      ins_compl_delete();
Karsten Hopp 5c71fd
!     ins_bytes(compl_leader + ins_compl_len());
Karsten Hopp 5c71fd
      compl_used_match = FALSE;
Karsten Hopp 5c71fd
  
Karsten Hopp 5c71fd
      if (compl_started)
Karsten Hopp 5c71fd
***************
Karsten Hopp 5c71fd
*** 3264,3269 ****
Karsten Hopp 5c71fd
--- 3304,3323 ----
Karsten Hopp 5c71fd
  }
Karsten Hopp 5c71fd
  
Karsten Hopp 5c71fd
  /*
Karsten Hopp 5c71fd
+  * Return the length of the completion, from the completion start column to
Karsten Hopp 5c71fd
+  * the cursor column.  Making sure it never goes below zero.
Karsten Hopp 5c71fd
+  */
Karsten Hopp 5c71fd
+     static int
Karsten Hopp 5c71fd
+ ins_compl_len()
Karsten Hopp 5c71fd
+ {
Karsten Hopp 5c71fd
+     int off = curwin->w_cursor.col - compl_col;
Karsten Hopp 5c71fd
+ 
Karsten Hopp 5c71fd
+     if (off < 0)
Karsten Hopp 5c71fd
+ 	return 0;
Karsten Hopp 5c71fd
+     return off;
Karsten Hopp 5c71fd
+ }
Karsten Hopp 5c71fd
+ 
Karsten Hopp 5c71fd
+ /*
Karsten Hopp 5c71fd
   * Append one character to the match leader.  May reduce the number of
Karsten Hopp 5c71fd
   * matches.
Karsten Hopp 5c71fd
   */
Karsten Hopp 5c71fd
***************
Karsten Hopp 5c71fd
*** 3621,3630 ****
Karsten Hopp 5c71fd
  	    {
Karsten Hopp 5c71fd
  		ins_compl_delete();
Karsten Hopp 5c71fd
  		if (compl_leader != NULL)
Karsten Hopp 5c71fd
! 		    ins_bytes(compl_leader + curwin->w_cursor.col - compl_col);
Karsten Hopp 5c71fd
  		else if (compl_first_match != NULL)
Karsten Hopp 5c71fd
! 		    ins_bytes(compl_orig_text
Karsten Hopp 5c71fd
! 					  + curwin->w_cursor.col - compl_col);
Karsten Hopp 5c71fd
  		retval = TRUE;
Karsten Hopp 5c71fd
  	    }
Karsten Hopp 5c71fd
  
Karsten Hopp 5c71fd
--- 3675,3683 ----
Karsten Hopp 5c71fd
  	    {
Karsten Hopp 5c71fd
  		ins_compl_delete();
Karsten Hopp 5c71fd
  		if (compl_leader != NULL)
Karsten Hopp 5c71fd
! 		    ins_bytes(compl_leader + ins_compl_len());
Karsten Hopp 5c71fd
  		else if (compl_first_match != NULL)
Karsten Hopp 5c71fd
! 		    ins_bytes(compl_orig_text + ins_compl_len());
Karsten Hopp 5c71fd
  		retval = TRUE;
Karsten Hopp 5c71fd
  	    }
Karsten Hopp 5c71fd
  
Karsten Hopp 5c71fd
***************
Karsten Hopp 5c71fd
*** 4256,4262 ****
Karsten Hopp 5c71fd
      static void
Karsten Hopp 5c71fd
  ins_compl_insert()
Karsten Hopp 5c71fd
  {
Karsten Hopp 5c71fd
!     ins_bytes(compl_shown_match->cp_str + curwin->w_cursor.col - compl_col);
Karsten Hopp 5c71fd
      if (compl_shown_match->cp_flags & ORIGINAL_TEXT)
Karsten Hopp 5c71fd
  	compl_used_match = FALSE;
Karsten Hopp 5c71fd
      else
Karsten Hopp 5c71fd
--- 4309,4315 ----
Karsten Hopp 5c71fd
      static void
Karsten Hopp 5c71fd
  ins_compl_insert()
Karsten Hopp 5c71fd
  {
Karsten Hopp 5c71fd
!     ins_bytes(compl_shown_match->cp_str + ins_compl_len());
Karsten Hopp 5c71fd
      if (compl_shown_match->cp_flags & ORIGINAL_TEXT)
Karsten Hopp 5c71fd
  	compl_used_match = FALSE;
Karsten Hopp 5c71fd
      else
Karsten Hopp 5c71fd
***************
Karsten Hopp 5c71fd
*** 4425,4431 ****
Karsten Hopp 5c71fd
  	if (!compl_get_longest || compl_used_match)
Karsten Hopp 5c71fd
  	    ins_compl_insert();
Karsten Hopp 5c71fd
  	else
Karsten Hopp 5c71fd
! 	    ins_bytes(compl_leader + curwin->w_cursor.col - compl_col);
Karsten Hopp 5c71fd
      }
Karsten Hopp 5c71fd
      else
Karsten Hopp 5c71fd
  	compl_used_match = FALSE;
Karsten Hopp 5c71fd
--- 4478,4484 ----
Karsten Hopp 5c71fd
  	if (!compl_get_longest || compl_used_match)
Karsten Hopp 5c71fd
  	    ins_compl_insert();
Karsten Hopp 5c71fd
  	else
Karsten Hopp 5c71fd
! 	    ins_bytes(compl_leader + ins_compl_len());
Karsten Hopp 5c71fd
      }
Karsten Hopp 5c71fd
      else
Karsten Hopp 5c71fd
  	compl_used_match = FALSE;
Karsten Hopp 5c71fd
***************
Karsten Hopp 5c71fd
*** 7123,7131 ****
Karsten Hopp 5c71fd
   * cc == 0: character was inserted, delete it
Karsten Hopp 5c71fd
   * cc > 0: character was replaced, put cc (first byte of original char) back
Karsten Hopp 5c71fd
   * and check for more characters to be put back
Karsten Hopp 5c71fd
   */
Karsten Hopp 5c71fd
      static void
Karsten Hopp 5c71fd
! replace_do_bs()
Karsten Hopp 5c71fd
  {
Karsten Hopp 5c71fd
      int		cc;
Karsten Hopp 5c71fd
  #ifdef FEAT_VREPLACE
Karsten Hopp 5c71fd
--- 7176,7187 ----
Karsten Hopp 5c71fd
   * cc == 0: character was inserted, delete it
Karsten Hopp 5c71fd
   * cc > 0: character was replaced, put cc (first byte of original char) back
Karsten Hopp 5c71fd
   * and check for more characters to be put back
Karsten Hopp 5c71fd
+  * When "limit_col" is >= 0, don't delete before this column.  Matters when
Karsten Hopp 5c71fd
+  * using composing characters, use del_char_after_col() instead of del_char().
Karsten Hopp 5c71fd
   */
Karsten Hopp 5c71fd
      static void
Karsten Hopp 5c71fd
! replace_do_bs(limit_col)
Karsten Hopp 5c71fd
!     int		limit_col;
Karsten Hopp 5c71fd
  {
Karsten Hopp 5c71fd
      int		cc;
Karsten Hopp 5c71fd
  #ifdef FEAT_VREPLACE
Karsten Hopp 5c71fd
***************
Karsten Hopp 5c71fd
*** 7153,7159 ****
Karsten Hopp 5c71fd
  #ifdef FEAT_MBYTE
Karsten Hopp 5c71fd
  	if (has_mbyte)
Karsten Hopp 5c71fd
  	{
Karsten Hopp 5c71fd
! 	    del_char(FALSE);
Karsten Hopp 5c71fd
  # ifdef FEAT_VREPLACE
Karsten Hopp 5c71fd
  	    if (State & VREPLACE_FLAG)
Karsten Hopp 5c71fd
  		orig_len = (int)STRLEN(ml_get_cursor());
Karsten Hopp 5c71fd
--- 7209,7215 ----
Karsten Hopp 5c71fd
  #ifdef FEAT_MBYTE
Karsten Hopp 5c71fd
  	if (has_mbyte)
Karsten Hopp 5c71fd
  	{
Karsten Hopp 5c71fd
! 	    (void)del_char_after_col(limit_col);
Karsten Hopp 5c71fd
  # ifdef FEAT_VREPLACE
Karsten Hopp 5c71fd
  	    if (State & VREPLACE_FLAG)
Karsten Hopp 5c71fd
  		orig_len = (int)STRLEN(ml_get_cursor());
Karsten Hopp 5c71fd
***************
Karsten Hopp 5c71fd
*** 7203,7209 ****
Karsten Hopp 5c71fd
  	changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
Karsten Hopp 5c71fd
      }
Karsten Hopp 5c71fd
      else if (cc == 0)
Karsten Hopp 5c71fd
! 	(void)del_char(FALSE);
Karsten Hopp 5c71fd
  }
Karsten Hopp 5c71fd
  
Karsten Hopp 5c71fd
  #ifdef FEAT_CINDENT
Karsten Hopp 5c71fd
--- 7259,7265 ----
Karsten Hopp 5c71fd
  	changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
Karsten Hopp 5c71fd
      }
Karsten Hopp 5c71fd
      else if (cc == 0)
Karsten Hopp 5c71fd
! 	(void)del_char_after_col(limit_col);
Karsten Hopp 5c71fd
  }
Karsten Hopp 5c71fd
  
Karsten Hopp 5c71fd
  #ifdef FEAT_CINDENT
Karsten Hopp 5c71fd
***************
Karsten Hopp 5c71fd
*** 8239,8245 ****
Karsten Hopp 5c71fd
  	 * Replace mode */
Karsten Hopp 5c71fd
  	if (curwin->w_cursor.lnum != Insstart.lnum
Karsten Hopp 5c71fd
  		|| curwin->w_cursor.col >= Insstart.col)
Karsten Hopp 5c71fd
! 	    replace_do_bs();
Karsten Hopp 5c71fd
      }
Karsten Hopp 5c71fd
      else
Karsten Hopp 5c71fd
  	(void)del_char(FALSE);
Karsten Hopp 5c71fd
--- 8295,8301 ----
Karsten Hopp 5c71fd
  	 * Replace mode */
Karsten Hopp 5c71fd
  	if (curwin->w_cursor.lnum != Insstart.lnum
Karsten Hopp 5c71fd
  		|| curwin->w_cursor.col >= Insstart.col)
Karsten Hopp 5c71fd
! 	    replace_do_bs(-1);
Karsten Hopp 5c71fd
      }
Karsten Hopp 5c71fd
      else
Karsten Hopp 5c71fd
  	(void)del_char(FALSE);
Karsten Hopp 5c71fd
***************
Karsten Hopp 5c71fd
*** 8556,8562 ****
Karsten Hopp 5c71fd
  		break;
Karsten Hopp 5c71fd
  	    }
Karsten Hopp 5c71fd
  	    if (State & REPLACE_FLAG)
Karsten Hopp 5c71fd
! 		replace_do_bs();
Karsten Hopp 5c71fd
  	    else
Karsten Hopp 5c71fd
  	    {
Karsten Hopp 5c71fd
  #ifdef FEAT_MBYTE
Karsten Hopp 5c71fd
--- 8612,8618 ----
Karsten Hopp 5c71fd
  		break;
Karsten Hopp 5c71fd
  	    }
Karsten Hopp 5c71fd
  	    if (State & REPLACE_FLAG)
Karsten Hopp 5c71fd
! 		replace_do_bs(-1);
Karsten Hopp 5c71fd
  	    else
Karsten Hopp 5c71fd
  	    {
Karsten Hopp 5c71fd
  #ifdef FEAT_MBYTE
Karsten Hopp 5c71fd
*** ../vim-7.2.079/src/version.c	Tue Jan  6 16:13:42 2009
Karsten Hopp 5c71fd
--- src/version.c	Tue Jan 13 12:25:29 2009
Karsten Hopp 5c71fd
***************
Karsten Hopp 5c71fd
*** 678,679 ****
Karsten Hopp 5c71fd
--- 678,681 ----
Karsten Hopp 5c71fd
  {   /* Add new patch number below this line */
Karsten Hopp 5c71fd
+ /**/
Karsten Hopp 5c71fd
+     80,
Karsten Hopp 5c71fd
  /**/
Karsten Hopp 5c71fd
Karsten Hopp 5c71fd
-- 
Karsten Hopp 5c71fd
At some point in the project somebody will start whining about the need to
Karsten Hopp 5c71fd
determine the project "requirements".  This involves interviewing people who
Karsten Hopp 5c71fd
don't know what they want but, curiously, know exactly when they need it.
Karsten Hopp 5c71fd
				(Scott Adams - The Dilbert principle)
Karsten Hopp 5c71fd
Karsten Hopp 5c71fd
 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net   \\\
Karsten Hopp 5c71fd
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
Karsten Hopp 5c71fd
\\\        download, build and distribute -- http://www.A-A-P.org        ///
Karsten Hopp 5c71fd
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///