Improve window dividers code.
[bpt/emacs.git] / src / w32term.c
index a66aca1..b77d017 100644 (file)
@@ -1,6 +1,6 @@
 /* Implementation of GUI terminal on the Microsoft Windows API.
 
-Copyright (C) 1989, 1993-2013 Free Software Foundation, Inc.
+Copyright (C) 1989, 1993-2014 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -628,26 +628,38 @@ static void
 w32_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  RECT r;
-  HDC hdc;
-  struct face *face;
-
-  r.left = x0;
-  r.right = x1;
-  r.top = y0;
-  r.bottom = y1;
-
-  hdc = get_frame_dc (f);
-  face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
-  if (face)
-    w32_fill_rect (f, hdc, face->foreground, &r);
+  HDC hdc = get_frame_dc (f);
+  struct face *face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
+  struct face *face_first = FACE_FROM_ID (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
+  struct face *face_last = FACE_FROM_ID (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
+  unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
+  unsigned long color_first = (face_first
+                              ? face_first->foreground
+                              : FRAME_FOREGROUND_PIXEL (f));
+  unsigned long color_last = (face_last
+                             ? face_last->foreground
+                             : FRAME_FOREGROUND_PIXEL (f));
+
+  if (y1 - y0 > x1 - x0 && x1 - x0 > 2)
+    /* Vertical.  */
+    {
+      w32_fill_area_abs (f, hdc, color_first, x0, y0, x0 + 1, y1);
+      w32_fill_area_abs (f, hdc, color, x0 + 1, y0, x1 - 1, y1);
+      w32_fill_area_abs (f, hdc, color_last, x1 - 1, y0, x1, y1);
+    }
+  else if (x1 - x0 > y1 - y0 && y1 - y0 > 3)
+    /* Horizontal.  */
+    {
+      w32_fill_area_abs (f, hdc, color_first, x0, y0, x1, y0 + 1);
+      w32_fill_area_abs (f, hdc, color, x0, y0 + 1, x1, y1 - 1);
+      w32_fill_area_abs (f, hdc, color_last, x0, y1 - 1, x1, y1);
+    }
   else
-    w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
+    w32_fill_area_abs (f, hdc, color, x0, y0, x1, y1);
 
   release_frame_dc (f, hdc);
 }
 
-
 /* End update of window W.
 
    Draw vertical borders between horizontally adjacent windows, and
@@ -792,62 +804,13 @@ w32_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
 
   hdc = get_frame_dc (f);
 
-  if (!p->overlay_p)
-    {
-      int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
-
-      /* If the fringe is adjacent to the left (right) scroll bar of a
-        leftmost (rightmost, respectively) window, then extend its
-        background to the gap between the fringe and the bar.  */
-      if ((WINDOW_LEFTMOST_P (w)
-          && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
-         || (WINDOW_RIGHTMOST_P (w)
-             && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
-       {
-         int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-
-         if (sb_width > 0)
-           {
-             int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
-             int bar_area_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-
-             if (bx < 0)
-               {
-                 /* Bitmap fills the fringe.  */
-                 if (bar_area_x + bar_area_width == p->x)
-                   bx = bar_area_x + sb_width;
-                 else if (p->x + p->wd == bar_area_x)
-                   bx = bar_area_x;
-                 if (bx >= 0)
-                   {
-                     int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
-
-                     nx = bar_area_width - sb_width;
-                     by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
-                                                           row->y));
-                     ny = row->visible_height;
-                   }
-               }
-             else
-               {
-                 if (bar_area_x + bar_area_width == bx)
-                   {
-                     bx = bar_area_x + sb_width;
-                     nx += bar_area_width - sb_width;
-                   }
-                 else if (bx + nx == bar_area_x)
-                   nx += bar_area_width - sb_width;
-               }
-           }
-       }
-
-      if (bx >= 0 && nx > 0)
-       w32_fill_area (f, hdc, face->background, bx, by, nx, ny);
-    }
-
   /* Must clip because of partially visible lines.  */
   w32_clip_to_row (w, row, ANY_AREA, hdc);
 
+  if (p->bx >= 0 && !p->overlay_p)
+    w32_fill_area (f, hdc, face->background,
+                  p->bx, p->by, p->nx, p->ny);
+
   if (p->which && p->which < max_fringe_bmp)
     {
       HBITMAP pixmap = fringe_bmp[p->which];
@@ -2693,31 +2656,6 @@ x_scroll_run (struct window *w, struct run *run)
      fringes of W.  */
   window_box (w, ANY_AREA, &x, &y, &width, &height);
 
-  /* If the fringe is adjacent to the left (right) scroll bar of a
-     leftmost (rightmost, respectively) window, then extend its
-     background to the gap between the fringe and the bar.  */
-  if ((WINDOW_LEFTMOST_P (w)
-       && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
-      || (WINDOW_RIGHTMOST_P (w)
-         && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
-    {
-      int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-
-      if (sb_width > 0)
-       {
-         int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
-         int bar_area_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-
-         if (bar_area_x + bar_area_width == x)
-           {
-             x = bar_area_x + sb_width;
-             width += bar_area_width - sb_width;
-           }
-         else if (x + width == bar_area_x)
-           width += bar_area_width - sb_width;
-       }
-    }
-
   from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
   to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
   bottom_y = y + height;
@@ -3451,9 +3389,7 @@ w32_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
               = x_window_to_scroll_bar (WindowFromPoint (pt));
 
            if (bar)
-             {
-               f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
-             }
+             f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
          }
 
        if (f1 == 0 && insist > 0)
@@ -3560,10 +3496,10 @@ w32_set_scroll_bar_thumb (struct scroll_bar *bar,
   /* We use the whole scroll-bar height in the calculations below, to
      avoid strange effects like scrolling backwards when just clicking
      on the handle (without moving it).  */
-  double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height))
+  double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height)
                  + VERTICAL_SCROLL_BAR_MIN_HANDLE;
   int sb_page, sb_pos;
-  BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
+  BOOL draggingp = bar->dragging ? TRUE : FALSE;
   SCROLLINFO si;
 
   /* We used to change the nPage setting while dragging the handle,
@@ -3708,20 +3644,19 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
   HWND hwnd;
   SCROLLINFO si;
   struct scroll_bar *bar
-    = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, fringe_extended_p, PVEC_OTHER);
+    = ALLOCATE_PSEUDOVECTOR (struct scroll_bar, top, PVEC_OTHER);
   Lisp_Object barobj;
 
   block_input ();
 
   XSETWINDOW (bar->window, w);
-  XSETINT (bar->top, top);
-  XSETINT (bar->left, left);
-  XSETINT (bar->width, width);
-  XSETINT (bar->height, height);
-  XSETINT (bar->start, 0);
-  XSETINT (bar->end, 0);
-  bar->dragging = Qnil;
-  bar->fringe_extended_p = 0;
+  bar->top = top;
+  bar->left = left;
+  bar->width = width;
+  bar->height = height;
+  bar->start = 0;
+  bar->end = 0;
+  bar->dragging = 0;
 
   /* Requires geometry to be set before call to create the real window */
 
@@ -3783,33 +3718,17 @@ w32_set_vertical_scroll_bar (struct window *w,
   struct frame *f = XFRAME (w->frame);
   Lisp_Object barobj;
   struct scroll_bar *bar;
-  int top, height, left, sb_left, width, sb_width;
+  int top, height, left, width;
   int window_y, window_height;
-  bool fringe_extended_p;
 
   /* Get window dimensions.  */
   window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
   top  = window_y;
-  width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
   height = window_height;
 
-  /* Compute the left edge of the scroll bar area.  */
+  /* Compute the left edge and the width of the scroll bar area.  */
   left = WINDOW_SCROLL_BAR_AREA_X (w);
-
-  /* Compute the width of the scroll bar which might be less than
-     the width of the area reserved for the scroll bar.  */
-  if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
-    sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
-  else
-    sb_width = width;
-
-  /* Compute the left edge of the scroll bar.  */
-  if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
-    sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
-  else
-    sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
-
-  fringe_extended_p = WINDOW_FRINGE_EXTENDED_P (w);
+  width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
 
   /* Does the scroll bar exist yet?  */
   if (NILP (w->vertical_scroll_bar))
@@ -3819,15 +3738,12 @@ w32_set_vertical_scroll_bar (struct window *w,
       if (width > 0 && height > 0)
        {
          hdc = get_frame_dc (f);
-         if (fringe_extended_p)
-           w32_clear_area (f, hdc, sb_left, top, sb_width, height);
-         else
-           w32_clear_area (f, hdc, left, top, width, height);
+         w32_clear_area (f, hdc, left, top, width, height);
          release_frame_dc (f, hdc);
        }
       unblock_input ();
 
-      bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
+      bar = x_scroll_bar_create (w, top, left, width, height);
     }
   else
     {
@@ -3838,11 +3754,10 @@ w32_set_vertical_scroll_bar (struct window *w,
       hwnd = SCROLL_BAR_W32_WINDOW (bar);
 
       /* If already correctly positioned, do nothing.  */
-      if (XINT (bar->left) == sb_left
-         && XINT (bar->top) == top
-         && XINT (bar->width) == sb_width
-         && XINT (bar->height) == height
-         && bar->fringe_extended_p == fringe_extended_p)
+      if (bar->left == left
+         && bar->top == top
+         && bar->width == width
+         && bar->height == height)
         {
           /* Redraw after clear_frame. */
           if (!my_show_window (f, hwnd, SW_NORMAL))
@@ -3859,17 +3774,13 @@ w32_set_vertical_scroll_bar (struct window *w,
              hdc = get_frame_dc (f);
              /* Since Windows scroll bars are smaller than the space reserved
                 for them on the frame, we have to clear "under" them.  */
-             if (fringe_extended_p)
-               w32_clear_area (f, hdc, sb_left, top, sb_width, height);
-             else
-               w32_clear_area (f, hdc, left, top, width, height);
+             w32_clear_area (f, hdc, left, top, width, height);
              release_frame_dc (f, hdc);
            }
           /* Make sure scroll bar is "visible" before moving, to ensure the
              area of the parent window now exposed will be refreshed.  */
           my_show_window (f, hwnd, SW_HIDE);
-          MoveWindow (hwnd, sb_left, top, sb_width,
-                     max (height, 1), TRUE);
+          MoveWindow (hwnd, left, top, width, max (height, 1), TRUE);
 
          si.cbSize = sizeof (si);
          si.fMask = SIF_RANGE;
@@ -3883,16 +3794,14 @@ w32_set_vertical_scroll_bar (struct window *w,
           /* InvalidateRect (w, NULL, FALSE);  */
 
           /* Remember new settings.  */
-          XSETINT (bar->left, sb_left);
-          XSETINT (bar->top, top);
-          XSETINT (bar->width, sb_width);
-          XSETINT (bar->height, height);
+          bar->left = left;
+          bar->top = top;
+          bar->width = width;
+          bar->height = height;
 
           unblock_input ();
         }
     }
-  bar->fringe_extended_p = fringe_extended_p;
-
   w32_set_scroll_bar_thumb (bar, portion, position, whole);
   XSETVECTOR (barobj, bar);
   wset_vertical_scroll_bar (w, barobj);
@@ -4026,9 +3935,9 @@ w32_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg,
   emacs_event->timestamp = msg->msg.time;
 
   {
-    int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
+    int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
     int y;
-    int dragging = !NILP (bar->dragging);
+    int dragging = bar->dragging;
     SCROLLINFO si;
 
     si.cbSize = sizeof (si);
@@ -4037,7 +3946,7 @@ w32_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg,
     GetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
     y = si.nPos;
 
-    bar->dragging = Qnil;
+    bar->dragging = 0;
     FRAME_DISPLAY_INFO (f)->last_mouse_scroll_bar_pos = msg->msg.wParam;
 
     switch (LOWORD (msg->msg.wParam))
@@ -4064,9 +3973,9 @@ w32_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg,
        break;
       case SB_THUMBTRACK:
       case SB_THUMBPOSITION:
-       if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
+       if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height) <= 0xffff)
           y = HIWORD (msg->msg.wParam);
-       bar->dragging = Qt;
+       bar->dragging = 1; /* ??????? */
        emacs_event->part = scroll_bar_handle;
 
        /* "Silently" update current position.  */
@@ -4090,8 +3999,8 @@ w32_scroll_bar_handle_click (struct scroll_bar *bar, W32Msg *msg,
        if (dragging)
          {
            SCROLLINFO si;
-           int start = XINT (bar->start);
-           int end = XINT (bar->end);
+           int start = bar->start;
+           int end = bar->end;
 
            si.cbSize = sizeof (si);
            si.fMask = SIF_PAGE | SIF_POS;
@@ -4126,7 +4035,7 @@ x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
   Window w = SCROLL_BAR_W32_WINDOW (bar);
   struct frame *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
   int pos;
-  int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
+  int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height);
   SCROLLINFO si;
 
   block_input ();
@@ -4146,7 +4055,7 @@ x_scroll_bar_report_motion (struct frame **fp, Lisp_Object *bar_window,
   case SB_THUMBPOSITION:
   case SB_THUMBTRACK:
       *part = scroll_bar_handle;
-      if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
+      if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, bar->height) <= 0xffff)
        pos = HIWORD (dpyinfo->last_mouse_scroll_bar_pos);
       break;
   case SB_LINEDOWN:
@@ -4944,6 +4853,10 @@ w32_read_socket (struct terminal *terminal,
          if (f)
            {
              dpyinfo->n_cbits = msg.msg.wParam;
+             /* The new display could have a different resolution, in
+                which case we must reconsider what fullscreen
+                means.  */
+             x_check_fullscreen (f);
              DebPrint (("display change: %d %d\n",
                         (short) LOWORD (msg.msg.lParam),
                         (short) HIWORD (msg.msg.lParam)));
@@ -5464,6 +5377,7 @@ Lisp_Object
 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
 {
   struct font *font = XFONT_OBJECT (font_object);
+  int unit;
 
   if (fontset < 0)
     fontset = fontset_from_font (font_object);
@@ -5475,22 +5389,21 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
 
   FRAME_FONT (f) = font;
   FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
-  FRAME_COLUMN_WIDTH (f) = font->average_width;
+  FRAME_COLUMN_WIDTH (f) = unit = font->average_width;
   FRAME_LINE_HEIGHT (f) = font->height;
 
   compute_fringe_widths (f, 1);
 
-  /* Compute the scroll bar width in character columns.  */
+  /* Compute number of scrollbar columns.  */
+  unit = FRAME_COLUMN_WIDTH (f);
   if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
-    {
-      int wid = FRAME_COLUMN_WIDTH (f);
-      FRAME_CONFIG_SCROLL_BAR_COLS (f)
-       = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
-    }
+    FRAME_CONFIG_SCROLL_BAR_COLS (f)
+      = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + unit - 1) / unit;
   else
     {
-      int wid = FRAME_COLUMN_WIDTH (f);
-      FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
+      FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + unit - 1) / unit;
+      FRAME_CONFIG_SCROLL_BAR_WIDTH (f) =
+       FRAME_CONFIG_SCROLL_BAR_COLS (f) * unit;
     }
 
   /* Now make the frame display the given font.  */
@@ -5667,18 +5580,22 @@ w32fullscreen_hook (struct frame *f)
       if (FRAME_PREV_FSMODE (f) == FULLSCREEN_BOTH)
         {
           SetWindowLong (hwnd, GWL_STYLE, dwStyle | WS_OVERLAPPEDWINDOW);
-          SetWindowPos (hwnd, NULL, 0, 0, 0, 0,
-                        SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
-                        SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
-        }
+         SetWindowPlacement (hwnd, &FRAME_NORMAL_PLACEMENT (f));
+       }
+      else if (FRAME_PREV_FSMODE (f) == FULLSCREEN_HEIGHT
+              || FRAME_PREV_FSMODE (f) == FULLSCREEN_WIDTH)
+       SetWindowPlacement (hwnd, &FRAME_NORMAL_PLACEMENT (f));
 
-      w32_fullscreen_rect (hwnd, f->want_fullscreen,
-                           FRAME_NORMAL_PLACEMENT (f).rcNormalPosition, &rect);
       FRAME_PREV_FSMODE (f) = f->want_fullscreen;
-      if (f->want_fullscreen == FULLSCREEN_MAXIMIZED)
-       PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, 0xf030, 0);
+
+      if (f->want_fullscreen == FULLSCREEN_NONE)
+       ShowWindow (hwnd, SW_SHOWNORMAL);
+      else if (f->want_fullscreen == FULLSCREEN_MAXIMIZED)
+       ShowWindow (hwnd, SW_MAXIMIZE);
       else if (f->want_fullscreen == FULLSCREEN_BOTH)
         {
+         w32_fullscreen_rect (hwnd, f->want_fullscreen,
+                              FRAME_NORMAL_PLACEMENT (f).rcNormalPosition, &rect);
           SetWindowLong (hwnd, GWL_STYLE, dwStyle & ~WS_OVERLAPPEDWINDOW);
           SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
                         rect.right - rect.left, rect.bottom - rect.top,
@@ -5686,6 +5603,9 @@ w32fullscreen_hook (struct frame *f)
         }
       else
         {
+         ShowWindow (hwnd, SW_SHOWNORMAL);
+         w32_fullscreen_rect (hwnd, f->want_fullscreen,
+                              FRAME_NORMAL_PLACEMENT (f).rcNormalPosition, &rect);
           SetWindowPos (hwnd, HWND_TOP, rect.left, rect.top,
                         rect.right - rect.left, rect.bottom - rect.top, 0);
         }
@@ -5710,8 +5630,6 @@ x_set_window_size (struct frame *f, int change_gravity, int width, int height, b
   block_input ();
 
   check_frame_size (f, &width, &height, pixelwise);
-  f->scroll_bar_actual_width
-    = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
 
   compute_fringe_widths (f, 0);
 
@@ -6515,9 +6433,8 @@ w32_initialize (void)
   Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
 
   {
-    DWORD input_locale_id = ((DWORD_PTR) GetKeyboardLayout (0) & 0xffffffff);
-    w32_keyboard_codepage =
-      codepage_for_locale ((LCID) (input_locale_id & 0xffff));
+    LCID input_locale_id = LOWORD (GetKeyboardLayout (0));
+    w32_keyboard_codepage = codepage_for_locale (input_locale_id);
   }
 
   /* Create the window thread - it will terminate itself when the app