Patch 9.0.1121
Problem:    Cursor positioning and display problems with 'smoothscroll' and
            using "zt", "zb" or "zz".
Solution:   Adjust computations and conditions. (Yee Cheng Chin,
            closes #11764)
Files:      src/macros.h, src/move.c, src/testdir/test_scroll_opt.vim,
            src/testdir/dumps/Test_smooth_long_10.dump,
            src/testdir/dumps/Test_smooth_long_11.dump,
            src/testdir/dumps/Test_smooth_long_12.dump,
            src/testdir/dumps/Test_smooth_long_13.dump,
            src/testdir/dumps/Test_smooth_long_14.dump,
            src/testdir/dumps/Test_smooth_long_15.dump,
            src/testdir/dumps/Test_smooth_long_8.dump,
            src/testdir/dumps/Test_smooth_long_9.dump


*** ../vim-9.0.1120/src/macros.h        2022-09-17 21:57:35.860822365 +0100
--- src/macros.h        2022-12-31 15:02:24.217129374 +0000
***************
*** 253,260 ****
--- 253,262 ----
  
  #ifdef FEAT_DIFF
  # define PLINES_NOFILL(x) plines_nofill(x)
+ # define PLINES_WIN_NOFILL(w, l, h) plines_win_nofill((w), (l), (h))
  #else
  # define PLINES_NOFILL(x) plines(x)
+ # define PLINES_WIN_NOFILL(w, l, h) plines_win((w), (l), (h))
  #endif
  
  #if defined(FEAT_JOB_CHANNEL) || defined(FEAT_CLIENTSERVER)
*** ../vim-9.0.1120/src/move.c  2022-12-18 12:28:54.330332513 +0000
--- src/move.c  2022-12-31 15:08:56.259795435 +0000
***************
*** 222,227 ****
--- 222,244 ----
  }
  
  /*
+  * Calculates the skipcol offset for window "wp" given how many
+  * physical lines we want to scroll down.
+  */
+     static int
+ skipcol_from_plines(win_T *wp, int plines_off)
+ {
+     int width1 = wp->w_width - win_col_off(wp);
+ 
+     int skipcol = 0;
+     if (plines_off > 0)
+       skipcol += width1;
+     if (plines_off > 1)
+       skipcol += (width1 + win_col_off2(wp)) * (plines_off - 1);
+     return skipcol;
+ }
+ 
+ /*
   * Set curwin->s_skipcol to zero and redraw later if needed.
   */
      static void
***************
*** 2149,2155 ****
   * Lines above the first one are incredibly high: MAXCOL.
   */
      static void
! topline_back(lineoff_T *lp)
  {
  #ifdef FEAT_DIFF
      if (lp->fill < diff_check_fill(curwin, lp->lnum))
--- 2166,2174 ----
   * Lines above the first one are incredibly high: MAXCOL.
   */
      static void
! topline_back_winheight(
!     lineoff_T *lp,
!     int               winheight)      // when TRUE limit to window height
  {
  #ifdef FEAT_DIFF
      if (lp->fill < diff_check_fill(curwin, lp->lnum))
***************
*** 2174,2183 ****
            lp->height = 1;
        else
  #endif
!           lp->height = PLINES_NOFILL(lp->lnum);
      }
  }
  
  /*
   * Add one line below "lp->lnum".  This can be a filler line, a closed fold or
   * a (wrapped) text line.  Uses and sets "lp->fill".
--- 2193,2209 ----
            lp->height = 1;
        else
  #endif
!           lp->height = PLINES_WIN_NOFILL(curwin, lp->lnum, winheight);
      }
  }
  
+     static void
+ topline_back(lineoff_T *lp)
+ {
+     topline_back_winheight(lp, TRUE);
+ }
+ 
+ 
  /*
   * Add one line below "lp->lnum".  This can be a filler line, a closed fold or
   * a (wrapped) text line.  Uses and sets "lp->fill".
***************
*** 2317,2322 ****
--- 2343,2356 ----
        else
  #endif
            i = PLINES_NOFILL(top);
+       if (top < curwin->w_topline)
+           scrolled += i;
+ 
+       // If scrolling is needed, scroll at least 'sj' lines.
+       if ((new_topline >= curwin->w_topline || scrolled > min_scroll)
+               && extra >= off)
+           break;
+ 
        used += i;
        if (extra + i <= off && bot < curbuf->b_ml.ml_line_count)
        {
***************
*** 2330,2344 ****
        }
        if (used > curwin->w_height)
            break;
-       if (top < curwin->w_topline)
-           scrolled += i;
- 
-       /*
-        * If scrolling is needed, scroll at least 'sj' lines.
-        */
-       if ((new_topline >= curwin->w_topline || scrolled > min_scroll)
-               && extra >= off)
-           break;
  
        extra += i;
        new_topline = top;
--- 2364,2369 ----
***************
*** 2436,2441 ****
--- 2461,2467 ----
      int               i;
      linenr_T  line_count;
      linenr_T  old_topline = curwin->w_topline;
+     int               old_skipcol = curwin->w_skipcol;
      lineoff_T loff;
      lineoff_T boff;
  #ifdef FEAT_DIFF
***************
*** 2451,2456 ****
--- 2477,2484 ----
      cln = curwin->w_cursor.lnum;
      if (set_topbot)
      {
+       int set_skipcol = FALSE;
+ 
        used = 0;
        curwin->w_botline = cln + 1;
  #ifdef FEAT_DIFF
***************
*** 2461,2469 ****
                curwin->w_topline = loff.lnum)
        {
            loff.lnum = curwin->w_topline;
!           topline_back(&loff);
!           if (loff.height == MAXCOL || used + loff.height > curwin->w_height)
                break;
            used += loff.height;
  #ifdef FEAT_DIFF
            curwin->w_topfill = loff.fill;
--- 2489,2520 ----
                curwin->w_topline = loff.lnum)
        {
            loff.lnum = curwin->w_topline;
!           topline_back_winheight(&loff, FALSE);
!           if (loff.height == MAXCOL)
!               break;
!           if (used + loff.height > curwin->w_height)
!           {
!               if (curwin->w_p_sms && curwin->w_p_wrap)
!               {
!                   // 'smoothscroll' and 'wrap' are set.  The above line is
!                   // too long to show in its entirety, so we show just a part
!                   // of it.
!                   if (used < curwin->w_height)
!                   {
!                       int plines_offset = used + loff.height
!                                                           - curwin->w_height;
!                       used = curwin->w_height;
! #ifdef FEAT_DIFF
!                       curwin->w_topfill = loff.fill;
! #endif
!                       curwin->w_topline = loff.lnum;
!                       curwin->w_skipcol = skipcol_from_plines(
!                                                       curwin, plines_offset);
!                       set_skipcol = TRUE;
!                   }
!               }
                break;
+           }
            used += loff.height;
  #ifdef FEAT_DIFF
            curwin->w_topfill = loff.fill;
***************
*** 2475,2482 ****
  #ifdef FEAT_DIFF
                || curwin->w_topfill != old_topfill
  #endif
!               )
            curwin->w_valid &= ~(VALID_WROW|VALID_CROW);
      }
      else
        validate_botline();
--- 2526,2540 ----
  #ifdef FEAT_DIFF
                || curwin->w_topfill != old_topfill
  #endif
!               || set_skipcol
!               || curwin->w_skipcol != 0)
!       {
            curwin->w_valid &= ~(VALID_WROW|VALID_CROW);
+           if (set_skipcol)
+               redraw_later(UPD_NOT_VALID);
+           else
+               reset_skipcol();
+       }
      }
      else
        validate_botline();
***************
*** 2680,2686 ****
       * (we changed them).
       * If topline did change, update_screen() will set botline.
       */
!     if (curwin->w_topline == old_topline && set_topbot)
      {
        curwin->w_botline = old_botline;
        curwin->w_empty_rows = old_empty_rows;
--- 2738,2746 ----
       * (we changed them).
       * If topline did change, update_screen() will set botline.
       */
!     if (curwin->w_topline == old_topline
!           && curwin->w_skipcol == old_skipcol
!           && set_topbot)
      {
        curwin->w_botline = old_botline;
        curwin->w_empty_rows = old_empty_rows;
***************
*** 2698,2703 ****
--- 2758,2765 ----
  {
      int               above = 0;
      linenr_T  topline;
+     colnr_T   skipcol = 0;
+     int               set_skipcol = FALSE;
  #ifdef FEAT_DIFF
      int               topfill = 0;
  #endif
***************
*** 2725,2732 ****
--- 2787,2843 ----
      used = plines(loff.lnum);
  #endif
      topline = loff.lnum;
+ 
+     int half_height = 0;
+     int smooth_scroll = FALSE;
+     if (curwin->w_p_sms && curwin->w_p_wrap)
+     {
+       // 'smoothscroll' and 'wrap' are set
+       smooth_scroll = TRUE;
+       half_height = (curwin->w_height - used) / 2;
+       used = 0;
+     }
+ 
      while (topline > 1)
      {
+       // If using smoothscroll, we can precisely scroll to the
+       // exact point where the cursor is halfway down the screen.
+       if (smooth_scroll)
+       {
+           topline_back_winheight(&loff, FALSE);
+           if (loff.height == MAXCOL)
+               break;
+           else
+               used += loff.height;
+           if (used > half_height)
+           {
+               if (used - loff.height < half_height)
+               {
+                   int plines_offset = used - half_height;
+                   loff.height -= plines_offset;
+                   used = half_height;
+ 
+                   topline = loff.lnum;
+ #ifdef FEAT_DIFF
+                   topfill = loff.fill;
+ #endif
+                   skipcol = skipcol_from_plines(curwin, plines_offset);
+                   set_skipcol = TRUE;
+               }
+               break;
+           }
+           topline = loff.lnum;
+ #ifdef FEAT_DIFF
+           topfill = loff.fill;
+ #endif
+           continue;
+       }
+ 
+       // If not using smoothscroll, we have to iteratively find how many
+       // lines to scroll down to roughly fit the cursor.
+       // This may not be right in the middle if the lines' physical height >
+       // 1 (e.g. 'wrap' is on).
+ 
        if (below <= above)         // add a line below the cursor first
        {
            if (boff.lnum < curbuf->b_ml.ml_line_count)
***************
*** 2764,2770 ****
  #ifdef FEAT_FOLDING
      if (!hasFolding(topline, &curwin->w_topline, NULL))
  #endif
!       curwin->w_topline = topline;
  #ifdef FEAT_DIFF
      curwin->w_topfill = topfill;
      if (old_topline > curwin->w_topline + curwin->w_height)
--- 2875,2895 ----
  #ifdef FEAT_FOLDING
      if (!hasFolding(topline, &curwin->w_topline, NULL))
  #endif
!     {
!       if (curwin->w_topline != topline
!               || set_skipcol
!               || curwin->w_skipcol != 0)
!       {
!           curwin->w_topline = topline;
!           if (set_skipcol)
!           {
!               curwin->w_skipcol = skipcol;
!               redraw_later(UPD_NOT_VALID);
!           }
!           else
!               reset_skipcol();
!       }
!     }
  #ifdef FEAT_DIFF
      curwin->w_topfill = topfill;
      if (old_topline > curwin->w_topline + curwin->w_height)
*** ../vim-9.0.1120/src/testdir/test_scroll_opt.vim     2022-12-03 
18:35:04.244951282 +0000
--- src/testdir/test_scroll_opt.vim     2022-12-31 14:57:51.897227088 +0000
***************
*** 296,301 ****
--- 296,309 ----
    call term_sendkeys(buf, "0j")
    call VerifyScreenDump(buf, 'Test_smooth_long_10', {})
  
+   " Test zt/zz/zb that they work properly when a long line is above it
+   call term_sendkeys(buf, "zb")
+   call VerifyScreenDump(buf, 'Test_smooth_long_11', {})
+   call term_sendkeys(buf, "zz")
+   call VerifyScreenDump(buf, 'Test_smooth_long_12', {})
+   call term_sendkeys(buf, "zt")
+   call VerifyScreenDump(buf, 'Test_smooth_long_13', {})
+ 
    " Repeat the step and move the cursor down again.
    " This time, use a shorter long line that is barely long enough to span more
    " than one window. Note that the cursor is at the bottom this time because
***************
*** 303,309 ****
    call term_sendkeys(buf, ":call setline(1, ['one', 'two', 'Line' .. (' with 
lots of text'->repeat(10)) .. ' end', 'four'])\<CR>")
    call term_sendkeys(buf, "3Gzt")
    call term_sendkeys(buf, "j")
!   call VerifyScreenDump(buf, 'Test_smooth_long_11', {})
  
    " Repeat the step but this time start it when the line is smooth-scrolled by
    " one line. This tests that the offset calculation is still correct and
--- 311,317 ----
    call term_sendkeys(buf, ":call setline(1, ['one', 'two', 'Line' .. (' with 
lots of text'->repeat(10)) .. ' end', 'four'])\<CR>")
    call term_sendkeys(buf, "3Gzt")
    call term_sendkeys(buf, "j")
!   call VerifyScreenDump(buf, 'Test_smooth_long_14', {})
  
    " Repeat the step but this time start it when the line is smooth-scrolled by
    " one line. This tests that the offset calculation is still correct and
***************
*** 311,317 ****
    " screen.
    call term_sendkeys(buf, "3Gzt")
    call term_sendkeys(buf, "\<C-E>j")
!   call VerifyScreenDump(buf, 'Test_smooth_long_12', {})
    
    call StopVimInTerminal(buf)
  endfunc
--- 319,325 ----
    " screen.
    call term_sendkeys(buf, "3Gzt")
    call term_sendkeys(buf, "\<C-E>j")
!   call VerifyScreenDump(buf, 'Test_smooth_long_15', {})
    
    call StopVimInTerminal(buf)
  endfunc
*** ../vim-9.0.1120/src/testdir/dumps/Test_smooth_long_10.dump  2022-11-19 
12:24:39.758174328 +0000
--- src/testdir/dumps/Test_smooth_long_10.dump  2022-12-31 14:57:51.897227088 
+0000
***************
*** 1,6 ****
! >f+0&#ffffff0|o|u|r| @35
  |~+0#4040ff13&| @38
  |~| @38
- |~| @38
- |~| @38
  |:+0#0000000&|s|e|t| |s|c|r|o|l@1|o| @9|4|,|1| @10|B|o|t| 
--- 1,6 ----
! |<+0#4040ff13#ffffff0@2|o+0#0000000&|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| 
|t|e|x|t| |w|i|t|h| |l|o|t|s| |o
! |f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |e|n|d| @11
! >f|o|u|r| @35
  |~+0#4040ff13&| @38
  |~| @38
  |:+0#0000000&|s|e|t| |s|c|r|o|l@1|o| @9|4|,|1| @10|B|o|t| 
*** ../vim-9.0.1120/src/testdir/dumps/Test_smooth_long_11.dump  2022-11-19 
12:24:39.758174328 +0000
--- src/testdir/dumps/Test_smooth_long_11.dump  2022-12-31 14:57:51.897227088 
+0000
***************
*** 3,6 ****
  |t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| 
|o
  |f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |e|n|d| @11
  >f|o|u|r| @35
! @22|4|,|1| @10|B|o|t| 
--- 3,6 ----
  |t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| 
|o
  |f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |e|n|d| @11
  >f|o|u|r| @35
! |:|s|e|t| |s|c|r|o|l@1|o| @9|4|,|1| @10|B|o|t| 
*** ../vim-9.0.1120/src/testdir/dumps/Test_smooth_long_12.dump  2022-11-19 
12:24:39.758174328 +0000
--- src/testdir/dumps/Test_smooth_long_12.dump  2022-12-31 14:57:51.897227088 
+0000
***************
*** 1,6 ****
! |<+0#4040ff13#ffffff0@2|t+0#0000000&|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| 
|l|o|t|s| |o|f| |t|e|x|t| |w|i|t
! |h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| 
|l|o
! |t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| 
|o
  |f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |e|n|d| @11
! |f|o|u>r| @35
! @22|4|,|4| @10|B|o|t| 
--- 1,6 ----
! |<+0#4040ff13#ffffff0@2|o+0#0000000&|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| 
|t|e|x|t| |w|i|t|h| |l|o|t|s| |o
  |f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |e|n|d| @11
! >f|o|u|r| @35
! |~+0#4040ff13&| @38
! |~| @38
! |:+0#0000000&|s|e|t| |s|c|r|o|l@1|o| @9|4|,|1| @10|B|o|t| 
*** ../vim-9.0.1120/src/testdir/dumps/Test_smooth_long_13.dump  2022-12-31 
15:12:22.742782213 +0000
--- src/testdir/dumps/Test_smooth_long_13.dump  2022-12-31 14:57:51.897227088 
+0000
***************
*** 0 ****
--- 1,6 ----
+ >f+0&#ffffff0|o|u|r| @35
+ |~+0#4040ff13&| @38
+ |~| @38
+ |~| @38
+ |~| @38
+ | +0#0000000&@21|4|,|1| @10|B|o|t| 
*** ../vim-9.0.1120/src/testdir/dumps/Test_smooth_long_14.dump  2022-12-31 
15:12:22.746782194 +0000
--- src/testdir/dumps/Test_smooth_long_14.dump  2022-12-31 14:57:51.897227088 
+0000
***************
*** 0 ****
--- 1,6 ----
+ |<+0#4040ff13#ffffff0@2|t+0#0000000&|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| 
|l|o|t|s| |o|f| |t|e|x|t| |w|i|t
+ |h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| 
|l|o
+ |t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| 
|o
+ |f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |e|n|d| @11
+ >f|o|u|r| @35
+ @22|4|,|1| @10|B|o|t| 
*** ../vim-9.0.1120/src/testdir/dumps/Test_smooth_long_15.dump  2022-12-31 
15:12:22.750782180 +0000
--- src/testdir/dumps/Test_smooth_long_15.dump  2022-12-31 14:57:51.897227088 
+0000
***************
*** 0 ****
--- 1,6 ----
+ |<+0#4040ff13#ffffff0@2|t+0#0000000&|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| 
|l|o|t|s| |o|f| |t|e|x|t| |w|i|t
+ |h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| 
|l|o
+ |t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| 
|o
+ |f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |e|n|d| @11
+ |f|o|u>r| @35
+ @22|4|,|4| @10|B|o|t| 
*** ../vim-9.0.1120/src/testdir/dumps/Test_smooth_long_8.dump   2022-11-19 
12:24:39.758174328 +0000
--- src/testdir/dumps/Test_smooth_long_8.dump   2022-12-31 14:57:51.897227088 
+0000
***************
*** 3,6 ****
  |t|s| |o|f| |t|e|x>t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| 
|o
  |f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| 
|t|e
  |x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| 
|w
! |:|s|e|t| |s|c|r|o|l@1|o| @9|3|,|1|3|0| @8|6@1|%| 
--- 3,6 ----
  |t|s| |o|f| |t|e|x>t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| 
|o
  |f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| 
|t|e
  |x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| 
|w
! | @21|3|,|1|3|0| @8|6@1|%| 
*** ../vim-9.0.1120/src/testdir/dumps/Test_smooth_long_9.dump   2022-12-03 
18:35:04.244951282 +0000
--- src/testdir/dumps/Test_smooth_long_9.dump   2022-12-31 14:57:51.897227088 
+0000
***************
*** 3,6 ****
  |t|s| |o|f| |t|e|x>t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| 
|o
  |f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| 
|t|e
  |x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| 
|w
! |:|s|e|t| |s|c|r|o|l@1|o| @9|3|,|1|3|0| @8|6@1|%| 
--- 3,6 ----
  |t|s| |o|f| |t|e|x>t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| 
|o
  |f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| 
|t|e
  |x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| |w|i|t|h| |l|o|t|s| |o|f| |t|e|x|t| 
|w
! | @21|3|,|1|3|0| @8|6@1|%| 
*** ../vim-9.0.1120/src/version.c       2022-12-31 14:46:49.805459113 +0000
--- src/version.c       2022-12-31 15:00:07.117178641 +0000
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     1121,
  /**/

-- 
Dogs must have a permit signed by the mayor in order to congregate in groups
of three or more on private property.
                [real standing law in Oklahoma, United States of America]

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20221231151403.7AD201C0AA3%40moolenaar.net.

Raspunde prin e-mail lui