home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / e20313sr.zip / emacs / 20.3.1 / src / w32term.c < prev    next >
C/C++ Source or Header  |  1999-07-31  |  132KB  |  4,628 lines

  1. /* Implementation of GUI terminal on the Microsoft W32 API.
  2.    Copyright (C) 1989, 1993, 1994, 1995 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU Emacs.
  5.  
  6. GNU Emacs is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU Emacs is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Emacs; see the file COPYING.  If not, write to the
  18. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  19. Boston, MA 02111-1307, USA.  */
  20.  
  21. /* Added by Kevin Gallo */
  22.  
  23. #include <signal.h>
  24. #include <config.h>
  25. #include <stdio.h>
  26. #include "lisp.h"
  27. #include "charset.h"
  28. #include "blockinput.h"
  29.  
  30. #include "w32term.h"
  31. #include <shellapi.h>
  32.  
  33. #include "systty.h"
  34. #include "systime.h"
  35.  
  36. #include <ctype.h>
  37. #include <errno.h>
  38. #include <setjmp.h>
  39. #include <sys/stat.h>
  40.  
  41. #include "frame.h"
  42. #include "dispextern.h"
  43. #include "termhooks.h"
  44. #include "termopts.h"
  45. #include "termchar.h"
  46. #include "gnu.h"
  47. #include "disptab.h"
  48. #include "buffer.h"
  49. #include "window.h"
  50. #include "keyboard.h"
  51. #include "intervals.h"
  52. #include "coding.h"
  53.  
  54. #undef min
  55. #undef max
  56. #define min(x, y) (((x) < (y)) ? (x) : (y))
  57. #define max(x, y) (((x) > (y)) ? (x) : (y))
  58.  
  59. extern unsigned int msh_mousewheel;
  60.  
  61. extern void free_frame_menubar ();
  62.  
  63. extern Lisp_Object Vwindow_system;
  64.  
  65. #define x_any_window_to_frame x_window_to_frame
  66. #define x_top_window_to_frame x_window_to_frame
  67.  
  68.  
  69. /* This is display since w32 does not support multiple ones.  */
  70. struct w32_display_info one_w32_display_info;
  71.  
  72. /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
  73.    one for each element of w32_display_list and in the same order.
  74.    NAME is the name of the frame.
  75.    FONT-LIST-CACHE records previous values returned by x-list-fonts.  */
  76. Lisp_Object w32_display_name_list;
  77.  
  78. /* Frame being updated by update_frame.  This is declared in term.c.
  79.    This is set by update_begin and looked at by all the
  80.    w32 functions.  It is zero while not inside an update.
  81.    In that case, the w32 functions assume that `selected_frame'
  82.    is the frame to apply to.  */
  83. extern struct frame *updating_frame;
  84.  
  85. /* This is a frame waiting to be autoraised, within w32_read_socket.  */
  86. struct frame *pending_autoraise_frame;
  87.  
  88. /* During an update, maximum vpos for ins/del line operations to affect.  */
  89.  
  90. static int flexlines;
  91.  
  92. /* During an update, nonzero if chars output now should be highlighted.  */
  93.  
  94. static int highlight;
  95.  
  96. /* Nominal cursor position -- where to draw output.
  97.    During an update, these are different from the cursor-box position.  */
  98.  
  99. static int curs_x;
  100. static int curs_y;
  101.  
  102. DWORD dwWindowsThreadId = 0;
  103. HANDLE hWindowsThread = NULL;
  104. DWORD dwMainThreadId = 0;
  105. HANDLE hMainThread = NULL;
  106.  
  107. #ifndef SIF_ALL
  108. /* These definitions are new with Windows 95. */
  109. #define SIF_RANGE           0x0001
  110. #define SIF_PAGE            0x0002
  111. #define SIF_POS             0x0004
  112. #define SIF_DISABLENOSCROLL 0x0008
  113. #define SIF_TRACKPOS        0x0010
  114. #define SIF_ALL             (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
  115.  
  116. typedef struct tagSCROLLINFO
  117. {
  118.     UINT    cbSize;
  119.     UINT    fMask;
  120.     int     nMin;
  121.     int     nMax;
  122.     UINT    nPage;
  123.     int     nPos;
  124.     int     nTrackPos;
  125. }   SCROLLINFO, FAR *LPSCROLLINFO;
  126. typedef SCROLLINFO CONST FAR *LPCSCROLLINFO;
  127. #endif /* SIF_ALL */
  128.  
  129. /* Dynamic linking to new proportional scroll bar functions. */
  130. int (PASCAL *pfnSetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw);
  131. BOOL (PASCAL *pfnGetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi);
  132.  
  133. int vertical_scroll_bar_min_handle;
  134. int vertical_scroll_bar_top_border;
  135. int vertical_scroll_bar_bottom_border;
  136.  
  137. int last_scroll_bar_drag_pos;
  138.  
  139. /* Mouse movement. */
  140.  
  141. /* Where the mouse was last time we reported a mouse event.  */
  142. static FRAME_PTR last_mouse_frame;
  143. static RECT last_mouse_glyph;
  144.  
  145. Lisp_Object Vw32_num_mouse_buttons;
  146.  
  147. Lisp_Object Vw32_swap_mouse_buttons;
  148.  
  149. /* Control whether x_raise_frame also sets input focus.  */
  150. Lisp_Object Vw32_grab_focus_on_raise;
  151.  
  152. /* Control whether Caps Lock affects non-ascii characters.  */
  153. Lisp_Object Vw32_capslock_is_shiftlock;
  154.  
  155. /* Control whether right-alt and left-ctrl should be recognized as AltGr.  */
  156. Lisp_Object Vw32_recognize_altgr;
  157.  
  158. /* The scroll bar in which the last motion event occurred.
  159.  
  160.    If the last motion event occurred in a scroll bar, we set this
  161.    so w32_mouse_position can know whether to report a scroll bar motion or
  162.    an ordinary motion.
  163.  
  164.    If the last motion event didn't occur in a scroll bar, we set this
  165.    to Qnil, to tell w32_mouse_position to return an ordinary motion event.  */
  166. Lisp_Object last_mouse_scroll_bar;
  167. int last_mouse_scroll_bar_pos;
  168.  
  169. /* This is a hack.  We would really prefer that w32_mouse_position would
  170.    return the time associated with the position it returns, but there
  171.    doesn't seem to be any way to wrest the timestamp from the server
  172.    along with the position query.  So, we just keep track of the time
  173.    of the last movement we received, and return that in hopes that
  174.    it's somewhat accurate.  */
  175. Time last_mouse_movement_time;
  176.  
  177. /* Incremented by w32_read_socket whenever it really tries to read events.  */
  178. #ifdef __STDC__
  179. static int volatile input_signal_count;
  180. #else
  181. static int input_signal_count;
  182. #endif
  183.  
  184. extern Lisp_Object Vcommand_line_args, Vsystem_name;
  185.  
  186. extern Lisp_Object Qface, Qmouse_face;
  187.  
  188. extern int errno;
  189.  
  190. /* A mask of extra modifier bits to put into every keyboard char.  */
  191. extern int extra_keyboard_modifiers;
  192.  
  193. static Lisp_Object Qvendor_specific_keysyms;
  194.  
  195. void w32_delete_display ();
  196.  
  197. static void redraw_previous_char ();
  198. static void redraw_following_char ();
  199. static unsigned int w32_get_modifiers ();
  200.  
  201. static int fast_find_position ();
  202. static void note_mouse_highlight ();
  203. static void clear_mouse_face ();
  204. static void show_mouse_face ();
  205. static void do_line_dance ();
  206.  
  207. /* Forward declarations for term hooks.  Consistency with the rest of Emacs
  208.    requires the use of K&R functions prototypes.  However, MSVC does not
  209.    pick up the function prototypes correctly with K&R function definitions,
  210.    and so we declare them first to give a little help to MSVC.  */
  211. static void w32_clear_frame ();
  212. static void w32_clear_end_of_line (int);
  213. static void w32_ins_del_lines (int, int);
  214. static void w32_change_line_highlight (int, int, int);
  215. static void w32_insert_glyphs (GLYPH *, int);
  216. static void w32_write_glyphs (GLYPH *, int);
  217. static void w32_delete_glyphs (int);
  218. static void w32_ring_bell ();
  219. static void w32_reset_terminal_modes ();
  220. static void w32_set_terminal_modes ();
  221. static void w32_update_begin (FRAME_PTR);
  222. static void w32_update_end (FRAME_PTR);
  223. static void w32_set_terminal_window (int);
  224. extern int  w32_read_socket (int, struct input_event *, int, int);
  225. static void w32_frame_up_to_date (FRAME_PTR);
  226. static void w32_cursor_to (int, int);
  227. static void w32_reassert_line_highlight (int, int);
  228. static void w32_mouse_position (FRAME_PTR *, int, Lisp_Object *,
  229.         enum scroll_bar_part *, Lisp_Object *,
  230.         Lisp_Object *, unsigned long *);
  231. static void w32_frame_rehighlight (FRAME_PTR);
  232. static void w32_frame_raise_lower (FRAME_PTR, int);
  233. static void w32_set_vertical_scroll_bar (struct window *, int, int, int);
  234. static void w32_condemn_scroll_bars (FRAME_PTR);
  235. static void w32_redeem_scroll_bar (struct window *);
  236. static void w32_judge_scroll_bars (FRAME_PTR);
  237.  
  238. #if 0
  239. /* This is a function useful for recording debugging information
  240.    about the sequence of occurrences in this file.  */
  241.  
  242. struct record 
  243. {
  244.   char *locus;
  245.   int type;
  246. };
  247.  
  248. struct record event_record[100];
  249.  
  250. int event_record_index;
  251.  
  252. record_event (locus, type)
  253.      char *locus;
  254.      int type;
  255. {
  256.   if (event_record_index == sizeof (event_record) / sizeof (struct record))
  257.     event_record_index = 0;
  258.  
  259.   event_record[event_record_index].locus = locus;
  260.   event_record[event_record_index].type = type;
  261.   event_record_index++;
  262. }
  263.  
  264. #endif /* 0 */
  265.  
  266. /* Return the struct w32_display_info.  */
  267.  
  268. struct w32_display_info *
  269. w32_display_info_for_display ()
  270. {
  271.   return (&one_w32_display_info);
  272. }
  273.  
  274. void 
  275. w32_fill_rect (f, _hdc, pix, lprect)
  276.      FRAME_PTR f;
  277.      HDC _hdc;
  278.      COLORREF pix;
  279.      RECT * lprect;
  280. {
  281.   HDC hdc;
  282.   HBRUSH hb;
  283.   RECT rect;
  284.   
  285.   if (_hdc)
  286.     hdc = _hdc;
  287.   else 
  288.     {
  289.       if (!f) return;
  290.       hdc = get_frame_dc (f);
  291.     }
  292.   
  293.   hb = CreateSolidBrush (pix);
  294.   FillRect (hdc, lprect, hb);
  295.   DeleteObject (hb);
  296.   
  297.   if (!_hdc)
  298.     release_frame_dc (f, hdc);
  299. }
  300.  
  301. void 
  302. w32_clear_window (f)
  303.      FRAME_PTR f;
  304. {
  305.   RECT rect;
  306.  
  307.   GetClientRect (FRAME_W32_WINDOW (f), &rect);
  308.   w32_clear_rect (f, NULL, &rect);
  309. }
  310.  
  311.  
  312. /* Starting and ending updates.
  313.  
  314.    These hooks are called by update_frame at the beginning and end
  315.    of a frame update.  We record in `updating_frame' the identity
  316.    of the frame being updated, so that the w32_... functions do not
  317.    need to take a frame as argument.  Most of the w32_... functions
  318.    should never be called except during an update, the only exceptions
  319.    being w32_cursor_to, w32_write_glyphs and w32_reassert_line_highlight.  */
  320.  
  321. static void
  322. w32_update_begin (f)
  323.      struct frame *f;
  324. {
  325.   if (f == 0)
  326.     abort ();
  327.  
  328.   flexlines = f->height;
  329.   highlight = 0;
  330.  
  331.   BLOCK_INPUT;
  332.  
  333.   /* Regenerate display palette before drawing if list of requested
  334.      colors has changed. */
  335.   if (FRAME_W32_DISPLAY_INFO (f)->regen_palette)
  336.   {
  337.     w32_regenerate_palette (f);
  338.     FRAME_W32_DISPLAY_INFO (f)->regen_palette = FALSE;
  339.   }
  340.  
  341.   if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
  342.     {
  343.       /* Don't do highlighting for mouse motion during the update.  */
  344.       FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 1;
  345.  
  346.       /* If the frame needs to be redrawn,
  347.      simply forget about any prior mouse highlighting.  */
  348.       if (FRAME_GARBAGED_P (f))
  349.     FRAME_W32_DISPLAY_INFO (f)->mouse_face_window = Qnil;
  350.  
  351.       if (!NILP (FRAME_W32_DISPLAY_INFO (f)->mouse_face_window))
  352.     {
  353.       int firstline, lastline, i;
  354.       struct window *w = XWINDOW (FRAME_W32_DISPLAY_INFO (f)->mouse_face_window);
  355.  
  356.       /* Find the first, and the last+1, lines affected by redisplay.  */
  357.       for (firstline = 0; firstline < f->height; firstline++)
  358.         if (FRAME_DESIRED_GLYPHS (f)->enable[firstline])
  359.           break;
  360.  
  361.       lastline = f->height;
  362.       for (i = f->height - 1; i >= 0; i--)
  363.         {
  364.           if (FRAME_DESIRED_GLYPHS (f)->enable[i])
  365.         break;
  366.           else
  367.         lastline = i;
  368.         }
  369.  
  370.       /* Can we tell that this update does not affect the window
  371.          where the mouse highlight is?  If so, no need to turn off.
  372.          Likewise, don't do anything if the frame is garbaged;
  373.          in that case, the FRAME_CURRENT_GLYPHS that we would use
  374.          are all wrong, and we will redisplay that line anyway.  */
  375.       if (! (firstline > (XFASTINT (w->top) + window_internal_height (w))
  376.          || lastline < XFASTINT (w->top)))
  377.         clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
  378.     }
  379.     }
  380.  
  381.   UNBLOCK_INPUT;
  382. }
  383.  
  384. static void
  385. w32_update_end (f)
  386.      struct frame *f;
  387. {
  388.   BLOCK_INPUT;
  389.  
  390.   do_line_dance ();
  391.   x_display_cursor (f, 1);
  392.  
  393.   if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
  394.     FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
  395.  
  396.   UNBLOCK_INPUT;
  397. }
  398.  
  399. /* This is called after a redisplay on frame F.  */
  400.  
  401. static void
  402. w32_frame_up_to_date (f)
  403.      FRAME_PTR f;
  404. {
  405.   BLOCK_INPUT;
  406.   if (FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc
  407.       || f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame)
  408.     {
  409.       note_mouse_highlight (FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame,
  410.                 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_x,
  411.                 FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_y);
  412.       FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 0;
  413.     }
  414.   UNBLOCK_INPUT;
  415. }
  416.  
  417. /* External interface to control of standout mode.
  418.    Call this when about to modify line at position VPOS
  419.    and not change whether it is highlighted.  */
  420.  
  421. static void
  422. w32_reassert_line_highlight (new, vpos)
  423.      int new, vpos;
  424. {
  425.   highlight = new;
  426. }
  427.  
  428. /* Call this when about to modify line at position VPOS
  429.    and change whether it is highlighted.  */
  430.  
  431. static void
  432. w32_change_line_highlight (new_highlight, vpos, first_unused_hpos)
  433.      int new_highlight, vpos, first_unused_hpos;
  434. {
  435.   highlight = new_highlight;
  436.   w32_cursor_to (vpos, 0);
  437.   w32_clear_end_of_line (updating_frame->width);
  438. }
  439.  
  440. /* This is used when starting Emacs and when restarting after suspend.
  441.    When starting Emacs, no window is mapped.  And nothing must be done
  442.    to Emacs's own window if it is suspended (though that rarely happens).  */
  443.  
  444. static void
  445. w32_set_terminal_modes (void)
  446. {
  447. }
  448.  
  449. /* This is called when exiting or suspending Emacs.
  450.    Exiting will make the W32 windows go away, and suspending
  451.    requires no action.  */
  452.  
  453. static void
  454. w32_reset_terminal_modes (void)
  455. {
  456. }
  457.  
  458. /* Set the nominal cursor position of the frame.
  459.    This is where display update commands will take effect.
  460.    This does not affect the place where the cursor-box is displayed.  */
  461.  
  462. static void
  463. w32_cursor_to (row, col)
  464.      register int row, col;
  465. {
  466.   int orow = row;
  467.  
  468.   curs_x = col;
  469.   curs_y = row;
  470.  
  471.   if (updating_frame == 0)
  472.     {
  473.       BLOCK_INPUT;
  474.       x_display_cursor (selected_frame, 1);
  475.       UNBLOCK_INPUT;
  476.     }
  477. }
  478.  
  479. /* Display a sequence of N glyphs found at GP.
  480.    WINDOW is the window to output to.  LEFT and TOP are starting coords.
  481.    HL is 1 if this text is highlighted, 2 if the cursor is on it,
  482.    3 if should appear in its mouse-face.
  483.    JUST_FOREGROUND if 1 means draw only the foreground;
  484.    don't alter the background.
  485.  
  486.    FONT is the default font to use (for glyphs whose font-code is 0).
  487.  
  488.    Since the display generation code is responsible for calling
  489.    compute_char_face and compute_glyph_face on everything it puts in
  490.    the display structure, we can assume that the face code on each
  491.    glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
  492.    to which we can actually apply intern_face.
  493.    Call this function with input blocked.  */
  494.  
  495. static void
  496. dumpglyphs (f, left, top, gp, n, hl, just_foreground, cmpcharp)
  497.      struct frame *f;
  498.      int left, top;
  499.      register GLYPH *gp; /* Points to first GLYPH. */
  500.      register int n;  /* Number of glyphs to display. */
  501.      int hl;
  502.      int just_foreground;
  503.      struct cmpchar_info *cmpcharp;
  504. {
  505.   /* Holds characters to be displayed. */
  506.   char *buf = (char *) alloca (f->width * sizeof (*buf));
  507.   register char *cp;            /* Steps through buf[]. */
  508.   register int tlen = GLYPH_TABLE_LENGTH;
  509.   register Lisp_Object *tbase = GLYPH_TABLE_BASE;
  510.   Window window = FRAME_W32_WINDOW (f);
  511.   int orig_left = left;
  512.   HDC hdc;
  513.  
  514.   hdc = get_frame_dc (f);
  515.  
  516.   while (n > 0)
  517.     {
  518.       /* Get the face-code of the next GLYPH.  */
  519.       int cf, len;
  520.       GLYPH g = *gp;
  521.       int ch, charset;
  522.  
  523.       GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
  524.       cf = (cmpcharp ? cmpcharp->face_work : FAST_GLYPH_FACE (g));
  525.       ch = FAST_GLYPH_CHAR (g);
  526.       charset = CHAR_CHARSET (ch);
  527.       if (charset == CHARSET_COMPOSITION)
  528.     {
  529.         struct face *face = FRAME_DEFAULT_FACE (f);
  530.       XFontStruct *font = FACE_FONT (face);
  531.       /* We must draw components of the composite character on the
  532.          same column */
  533.       cmpcharp = cmpchar_table[COMPOSITE_CHAR_ID (ch)];
  534.  
  535.       /* Set the face in the slot for work. */
  536.       cmpcharp->face_work = cf;
  537.  
  538.       dumpglyphs (f, left, top, cmpcharp->glyph, cmpcharp->glyph_len,
  539.               hl, just_foreground, cmpcharp);
  540.       left += FONT_WIDTH (font) * cmpcharp->width;
  541.       ++gp, --n;
  542.       while (gp && (*gp & GLYPH_MASK_PADDING)) ++gp, --n;
  543.       cmpcharp = NULL;
  544.       continue;
  545.     }
  546.       /* Find the run of consecutive glyphs with the same face-code.
  547.      Extract their character codes into BUF.  */
  548.       cp = buf;
  549.       while (n > 0)
  550.     {
  551.       int this_charset, c[2];
  552.  
  553.       g = *gp;
  554.       GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
  555.       ch = FAST_GLYPH_CHAR (g);
  556.       SPLIT_CHAR (ch, this_charset, c[0], c[1]);
  557.       if (this_charset != charset
  558.           || (cmpcharp == NULL && FAST_GLYPH_FACE (g) != cf))
  559.         break;
  560.  
  561.       if ( c[1] > 0 )
  562.         {
  563.           int consumed, produced;
  564.           /* Handle multibyte characters (still assuming user
  565.              selects correct font themselves for now */
  566.           produced = encode_terminal_code(gp, cp, 1,
  567.               (f->width*sizeof(*buf))-(cp-buf), &consumed);
  568.           /* If we can't display this glyph, skip it */
  569.           if (consumed == 0)
  570.                 gp++,n--;
  571.           else
  572.             gp += consumed, n-= consumed;
  573.           cp += produced;
  574.         }
  575.       else
  576.         {
  577.           *cp++ = c[0];
  578.           ++gp, --n;
  579.         }
  580.       while (gp && (*gp & GLYPH_MASK_PADDING))
  581.         ++gp, --n;
  582.     }
  583.  
  584.       /* LEN gets the length of the run.  */
  585.       len = cp - buf;
  586.       /* Now output this run of chars, with the font and pixel values
  587.      determined by the face code CF.  */
  588.       {
  589.     int stippled = 0;
  590.     struct face *face = FRAME_DEFAULT_FACE (f);
  591.     XFontStruct *font = FACE_FONT (face);
  592.     COLORREF fg;
  593.     COLORREF bg;
  594.  
  595.     /* HL = 3 means use a mouse face previously chosen.  */
  596.     if (hl == 3)
  597.       cf = FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id;
  598.  
  599.     /* First look at the face of the text itself.  */
  600.     if (cf != 0)
  601.       {
  602.         /* It's possible for the display table to specify
  603.            a face code that is out of range.  Use 0 in that case.  */
  604.         if (cf < 0 || cf >= FRAME_N_COMPUTED_FACES (f)
  605.         || FRAME_COMPUTED_FACES (f) [cf] == 0)
  606.           cf = 0;
  607.  
  608.         if (cf == 1)
  609.           face = FRAME_MODE_LINE_FACE (f);
  610.         else
  611.           face = intern_face (f, FRAME_COMPUTED_FACES (f) [cf]);
  612.         font = FACE_FONT (face);
  613.         if (FACE_STIPPLE (face))
  614.           stippled = 1;
  615.       }
  616.  
  617.     /* Then comes the distinction between modeline and normal text.  */
  618.     else if (hl == 0)
  619.      ;
  620.     else if (hl == 1)
  621.       {
  622.         face = FRAME_MODE_LINE_FACE (f);
  623.         font = FACE_FONT (face);
  624.         if (FACE_STIPPLE (face))
  625.           stippled = 1;
  626.       }
  627.  
  628.     fg = face->foreground;
  629.     bg = face->background;
  630.  
  631.     /* Now override that if the cursor's on this character.  */
  632.     if (hl == 2)
  633.       {
  634.         /* The cursor overrides stippling.  */
  635.         stippled = 0;
  636.  
  637.         if ((!face->font
  638.          || face->font == (XFontStruct *) FACE_DEFAULT
  639.          || face->font == f->output_data.w32->font)
  640.         && face->background == f->output_data.w32->background_pixel
  641.         && face->foreground == f->output_data.w32->foreground_pixel)
  642.           {
  643.         bg = f->output_data.w32->cursor_pixel;
  644.         fg = face->background;
  645.           }
  646.         /* Cursor on non-default face: must merge.  */
  647.         else
  648.           {
  649.         bg = f->output_data.w32->cursor_pixel;
  650.         fg = face->background;
  651.         /* If the glyph would be invisible,
  652.            try a different foreground.  */
  653.         if (fg == bg)
  654.           fg = face->foreground;
  655.         if (fg == bg)
  656.           fg = f->output_data.w32->cursor_foreground_pixel;
  657.         if (fg == bg)
  658.           fg = face->foreground;
  659.         /* Make sure the cursor is distinct from text in this face.  */
  660.         if (bg == face->background
  661.             && fg == face->foreground)
  662.           {
  663.             bg = face->foreground;
  664.             fg = face->background;
  665.           }
  666.           }
  667.       }
  668.  
  669.     if (font == (XFontStruct *) FACE_DEFAULT)
  670.       font = f->output_data.w32->font;
  671.  
  672.     SetBkMode (hdc, just_foreground ? TRANSPARENT : OPAQUE);
  673.  
  674.     SetTextColor (hdc, fg);
  675.     SetBkColor (hdc, bg);
  676.  
  677.     SelectObject (hdc, font->hfont);
  678.         
  679.     TextOut (hdc, left, top, buf, len);
  680.  
  681.     if (!just_foreground)
  682.       {
  683.         /* Clear the rest of the line's height.  */
  684.         if (f->output_data.w32->line_height != FONT_HEIGHT (font))
  685.         w32_fill_area (f, hdc, bg,
  686.                  left,
  687.                  top + FONT_HEIGHT (font),
  688.                  FONT_WIDTH (font) * len,
  689.                  f->output_data.w32->line_height - FONT_HEIGHT (font));
  690.       }
  691.  
  692.     {
  693.       int underline_position = 1;
  694.  
  695.       if (font->tm.tmDescent <= underline_position)
  696.           underline_position = font->tm.tmDescent - 1;
  697.  
  698.       if (face->underline)
  699.           w32_fill_area (f, hdc, fg,
  700.                    left, (top
  701.                       + FONT_BASE (font)
  702.                       + underline_position),
  703.                    len * FONT_WIDTH (font), 1);
  704.     }
  705.  
  706.     left += len * FONT_WIDTH (font);
  707.       }
  708.     }
  709.  
  710.   release_frame_dc (f, hdc);
  711. }
  712.  
  713.  
  714. /* Output some text at the nominal frame cursor position.
  715.    Advance the cursor over the text.
  716.    Output LEN glyphs at START.
  717.  
  718.    `highlight', set up by w32_reassert_line_highlight or w32_change_line_highlight,
  719.    controls the pixel values used for foreground and background.  */
  720.  
  721. static void
  722. w32_write_glyphs (start, len)
  723.      register GLYPH *start;
  724.      int len;
  725. {
  726.   register int temp_length;
  727.   struct frame *f;
  728.  
  729.   BLOCK_INPUT;
  730.  
  731.   do_line_dance ();
  732.   f = updating_frame;
  733.   if (f == 0)
  734.     {
  735.       f = selected_frame;
  736.       /* If not within an update,
  737.      output at the frame's visible cursor.  */
  738.       curs_x = f->cursor_x;
  739.       curs_y = f->cursor_y;
  740.     }
  741.  
  742.   dumpglyphs (f,
  743.           CHAR_TO_PIXEL_COL (f, curs_x),
  744.           CHAR_TO_PIXEL_ROW (f, curs_y),
  745.           start, len, highlight, 0, NULL);
  746.  
  747.   /* If we drew on top of the cursor, note that it is turned off.  */
  748.   if (curs_y == f->phys_cursor_y
  749.       && curs_x <= f->phys_cursor_x
  750.       && curs_x + len > f->phys_cursor_x)
  751.     f->phys_cursor_x = -1;
  752.  
  753.   if (updating_frame == 0)
  754.     {
  755.       f->cursor_x += len;
  756.       x_display_cursor (f, 1);
  757.       f->cursor_x -= len;
  758.     }
  759.   else
  760.     curs_x += len;
  761.  
  762.   UNBLOCK_INPUT;
  763. }
  764.  
  765. /* Clear to the end of the line.
  766.    Erase the current text line from the nominal cursor position (inclusive)
  767.    to column FIRST_UNUSED (exclusive).  The idea is that everything
  768.    from FIRST_UNUSED onward is already erased.  */
  769.  
  770. static void
  771. w32_clear_end_of_line (first_unused)
  772.      register int first_unused;
  773. {
  774.   struct frame *f = updating_frame;
  775.  
  776.   if (f == 0)
  777.     abort ();
  778.  
  779.   if (curs_y < 0 || curs_y >= f->height)
  780.     return;
  781.   if (first_unused <= 0)
  782.     return;
  783.  
  784.   if (first_unused >= f->width)
  785.     first_unused = f->width;
  786.  
  787.   first_unused += FRAME_LEFT_SCROLL_BAR_WIDTH (f);
  788.  
  789.   BLOCK_INPUT;
  790.  
  791.   do_line_dance ();
  792.  
  793.   /* Notice if the cursor will be cleared by this operation.  */
  794.   if (curs_y == f->phys_cursor_y
  795.       && curs_x <= f->phys_cursor_x
  796.       && f->phys_cursor_x < first_unused)
  797.     f->phys_cursor_x = -1;
  798.  
  799.   w32_clear_area (f, NULL,
  800.             CHAR_TO_PIXEL_COL (f, curs_x),
  801.             CHAR_TO_PIXEL_ROW (f, curs_y),
  802.             FONT_WIDTH (f->output_data.w32->font) * (first_unused - curs_x),
  803.             f->output_data.w32->line_height);
  804.  
  805.   UNBLOCK_INPUT;
  806. }
  807.  
  808. static void
  809. w32_clear_frame ()
  810. {
  811.   struct frame *f = updating_frame;
  812.  
  813.   if (f == 0)
  814.     f = selected_frame;
  815.  
  816.   f->phys_cursor_x = -1;        /* Cursor not visible.  */
  817.   curs_x = 0;                   /* Nominal cursor position is top left.  */
  818.   curs_y = 0;
  819.  
  820.   BLOCK_INPUT;
  821.  
  822.   w32_clear_window (f);
  823.  
  824.   /* We have to clear the scroll bars, too.  If we have changed
  825.      colors or something like that, then they should be notified.  */
  826.   x_scroll_bar_clear (f);
  827.  
  828.   UNBLOCK_INPUT;
  829. }
  830.  
  831. /* Make audible bell.  */
  832.  
  833. static void
  834. w32_ring_bell (void)
  835. {
  836.   BLOCK_INPUT;
  837.  
  838.   if (visible_bell)
  839.     {
  840.       int i;
  841.       HWND hwnd = FRAME_W32_WINDOW (selected_frame);
  842.  
  843.       for (i = 0; i < 5; i++) 
  844.     {
  845.       FlashWindow (hwnd, TRUE);
  846.       Sleep (10);
  847.     }
  848.       FlashWindow (hwnd, FALSE);
  849.     }
  850.   else
  851.       w32_sys_ring_bell ();
  852.  
  853.   UNBLOCK_INPUT;
  854. }
  855.  
  856. /* Insert and delete character.
  857.    These are not supposed to be used because we are supposed to turn
  858.    off the feature of using them.  */
  859.  
  860. static void
  861. w32_insert_glyphs (start, len)
  862.      register GLYPH *start;
  863.      register int len;
  864. {
  865.   abort ();
  866. }
  867.  
  868. static void
  869. w32_delete_glyphs (n)
  870.      register int n;
  871. {
  872.   abort ();
  873. }
  874.  
  875. /* Specify how many text lines, from the top of the window,
  876.    should be affected by insert-lines and delete-lines operations.
  877.    This, and those operations, are used only within an update
  878.    that is bounded by calls to w32_update_begin and w32_update_end.  */
  879.  
  880. static void
  881. w32_set_terminal_window (n)
  882.      register int n;
  883. {
  884.   if (updating_frame == 0)
  885.     abort ();
  886.  
  887.   if ((n <= 0) || (n > updating_frame->height))
  888.     flexlines = updating_frame->height;
  889.   else
  890.     flexlines = n;
  891. }
  892.  
  893. /* These variables need not be per frame
  894.    because redisplay is done on a frame-by-frame basis
  895.    and the line dance for one frame is finished before
  896.    anything is done for another frame.  */
  897.  
  898. /* Array of line numbers from cached insert/delete operations.
  899.    line_dance[i] is the old position of the line that we want
  900.    to move to line i, or -1 if we want a blank line there.  */
  901. static int *line_dance;
  902.  
  903. /* Allocated length of that array.  */
  904. static int line_dance_len;
  905.  
  906. /* Flag indicating whether we've done any work.  */
  907. static int line_dance_in_progress;
  908.  
  909. /* Perform an insert-lines or delete-lines operation,
  910.    inserting N lines or deleting -N lines at vertical position VPOS.  */
  911.  
  912. static void
  913. w32_ins_del_lines (vpos, n)
  914.      int vpos, n;
  915. {
  916.   register int fence, i;
  917.  
  918.   if (vpos >= flexlines)
  919.     return;
  920.  
  921.   if (!line_dance_in_progress)
  922.     {
  923.       int ht = updating_frame->height;
  924.       if (ht > line_dance_len)
  925.     {
  926.       line_dance = (int *)xrealloc (line_dance, ht * sizeof (int));
  927.       line_dance_len = ht;
  928.     }
  929.       for (i = 0; i < ht; ++i) line_dance[i] = i;
  930.       line_dance_in_progress = 1;
  931.     }
  932.   if (n >= 0)
  933.     {
  934.       if (n > flexlines - vpos)
  935.     n = flexlines - vpos;
  936.       fence = vpos + n;
  937.       for (i = flexlines; --i >= fence;)
  938.     line_dance[i] = line_dance[i-n];
  939.       for (i = fence; --i >= vpos;)
  940.     line_dance[i] = -1;
  941.     }
  942.   else
  943.     {
  944.       n = -n;
  945.       if (n > flexlines - vpos)
  946.     n = flexlines - vpos;
  947.       fence = flexlines - n;
  948.       for (i = vpos; i < fence; ++i)
  949.     line_dance[i] = line_dance[i + n];
  950.       for (i = fence; i < flexlines; ++i)
  951.     line_dance[i] = -1;
  952.     }
  953. }
  954.  
  955. /* Here's where we actually move the pixels around.
  956.    Must be called with input blocked.  */
  957. static void
  958. do_line_dance ()
  959. {
  960.   register int i, j, distance;
  961.   register struct frame *f;
  962.   int ht;
  963.   int intborder;
  964.   HDC hdc;
  965.  
  966.   /* Must check this flag first.  If it's not set, then not only is the
  967.      array uninitialized, but we might not even have a frame.  */
  968.   if (!line_dance_in_progress)
  969.     return;
  970.  
  971.   f = updating_frame;
  972.   if (f == 0)
  973.     abort ();
  974.  
  975.   ht = f->height;
  976.   intborder = f->output_data.w32->internal_border_width;
  977.  
  978.   x_display_cursor (updating_frame, 0);
  979.  
  980.   hdc = get_frame_dc (f);
  981.  
  982.   for (i = 0; i < ht; ++i)
  983.     if (line_dance[i] != -1 && (distance = line_dance[i]-i) > 0)
  984.       {
  985.     for (j = i; (j < ht && line_dance[j] != -1
  986.              && line_dance[j]-j == distance); ++j);
  987.     /* Copy [i,j) upward from [i+distance, j+distance) */
  988.     BitBlt (hdc, 
  989.         intborder, CHAR_TO_PIXEL_ROW (f, i+distance),
  990.         f->width * FONT_WIDTH (f->output_data.w32->font),
  991.         (j-i) * f->output_data.w32->line_height, 
  992.         hdc,
  993.         intborder, CHAR_TO_PIXEL_ROW (f, i),
  994.         SRCCOPY);
  995.     i = j-1;
  996.       }
  997.  
  998.   for (i = ht; --i >=0; )
  999.     if (line_dance[i] != -1 && (distance = line_dance[i]-i) < 0)
  1000.       {
  1001.     for (j = i; (--j >= 0 && line_dance[j] != -1
  1002.              && line_dance[j]-j == distance););
  1003.     /* Copy (j, i] downward from (j+distance, i+distance] */
  1004.     BitBlt (hdc,
  1005.         intborder, CHAR_TO_PIXEL_ROW (f, j+1+distance),
  1006.         f->width * FONT_WIDTH (f->output_data.w32->font),
  1007.         (i-j) * f->output_data.w32->line_height, 
  1008.         hdc,
  1009.         intborder, CHAR_TO_PIXEL_ROW (f, j+1),
  1010.         SRCCOPY);
  1011.     i = j+1;
  1012.       }
  1013.  
  1014.   for (i = 0; i < ht; ++i)
  1015.     if (line_dance[i] == -1)
  1016.       {
  1017.     for (j = i; j < ht && line_dance[j] == -1; ++j);
  1018.     /* Clear [i,j) */
  1019.     w32_clear_area (f, hdc,
  1020.               intborder, 
  1021.               CHAR_TO_PIXEL_ROW (f, i),
  1022.               f->width * FONT_WIDTH (f->output_data.w32->font),
  1023.               (j-i) * f->output_data.w32->line_height);
  1024.     i = j-1;
  1025.       }
  1026.   line_dance_in_progress = 0;
  1027.  
  1028.   release_frame_dc (f, hdc);
  1029. }
  1030.  
  1031. /* Support routines for exposure events.  */
  1032. static void clear_cursor ();
  1033.  
  1034. /* Output into a rectangle of a window (for frame F)
  1035.    the characters in f->phys_lines that overlap that rectangle.
  1036.    TOP and LEFT are the position of the upper left corner of the rectangle.
  1037.    ROWS and COLS are the size of the rectangle.
  1038.    Call this function with input blocked.  */
  1039.  
  1040. void
  1041. dumprectangle (f, left, top, cols, rows)
  1042.      struct frame *f;
  1043.      register int left, top, cols, rows;
  1044. {
  1045.   register struct frame_glyphs *active_frame = FRAME_CURRENT_GLYPHS (f);
  1046.   int cursor_cleared = 0;
  1047.   int bottom, right;
  1048.   register int y;
  1049.  
  1050.   if (FRAME_GARBAGED_P (f))
  1051.     return;
  1052.  
  1053.   /* Express rectangle as four edges, instead of position-and-size.  */
  1054.   bottom = top + rows;
  1055.   right = left + cols;
  1056.  
  1057.   /* Convert rectangle edges in pixels to edges in chars.
  1058.      Round down for left and top, up for right and bottom.  */
  1059.   top  = PIXEL_TO_CHAR_ROW (f, top);
  1060.   left = PIXEL_TO_CHAR_COL (f, left);
  1061.   bottom += (f->output_data.w32->line_height - 1);
  1062.   right += (FONT_WIDTH (f->output_data.w32->font) - 1);
  1063.   bottom = PIXEL_TO_CHAR_ROW (f, bottom);
  1064.   right = PIXEL_TO_CHAR_COL (f, right);
  1065.  
  1066.   /* Clip the rectangle to what can be visible.  */
  1067.   if (left < 0)
  1068.     left = 0;
  1069.   if (top < 0)
  1070.     top = 0;
  1071.   if (right > f->width)
  1072.     right = f->width;
  1073.   if (bottom > f->height)
  1074.     bottom = f->height;
  1075.  
  1076.   /* Get size in chars of the rectangle.  */
  1077.   cols = right - left;
  1078.   rows = bottom - top;
  1079.  
  1080.   /* If rectangle has zero area, return.  */
  1081.   if (rows <= 0) return;
  1082.   if (cols <= 0) return;
  1083.  
  1084.   /* Turn off the cursor if it is in the rectangle.
  1085.      We will turn it back on afterward.  */
  1086.   if ((f->phys_cursor_x >= left) && (f->phys_cursor_x < right)
  1087.       && (f->phys_cursor_y >= top) && (f->phys_cursor_y < bottom))
  1088.     {
  1089.       clear_cursor (f);
  1090.       cursor_cleared = 1;
  1091.     }
  1092.  
  1093.   /* Display the text in the rectangle, one text line at a time.  */
  1094.  
  1095.   for (y = top; y < bottom; y++)
  1096.     {
  1097.       GLYPH *line = &active_frame->glyphs[y][left];
  1098.  
  1099.       if (! active_frame->enable[y] || left > active_frame->used[y])
  1100.     continue;
  1101.  
  1102.       dumpglyphs (f,
  1103.           CHAR_TO_PIXEL_COL (f, left),
  1104.           CHAR_TO_PIXEL_ROW (f, y),
  1105.           line, min (cols, active_frame->used[y] - left),
  1106.           active_frame->highlight[y], 0, NULL);
  1107.     }
  1108.  
  1109.   /* Turn the cursor on if we turned it off.  */
  1110.  
  1111.   if (cursor_cleared)
  1112.     x_display_cursor (f, 1);
  1113. }
  1114.  
  1115. static void
  1116. frame_highlight (f)
  1117.      struct frame *f;
  1118. {
  1119.   x_display_cursor (f, 1);
  1120. }
  1121.  
  1122. static void
  1123. frame_unhighlight (f)
  1124.      struct frame *f;
  1125. {
  1126.   x_display_cursor (f, 1);
  1127. }
  1128.  
  1129. static void x_frame_rehighlight ();
  1130.  
  1131. /* The focus has changed.  Update the frames as necessary to reflect
  1132.    the new situation.  Note that we can't change the selected frame
  1133.    here, because the Lisp code we are interrupting might become confused.
  1134.    Each event gets marked with the frame in which it occurred, so the
  1135.    Lisp code can tell when the switch took place by examining the events.  */
  1136.  
  1137. void
  1138. x_new_focus_frame (dpyinfo, frame)
  1139.      struct w32_display_info *dpyinfo;
  1140.      struct frame *frame;
  1141. {
  1142.   struct frame *old_focus = dpyinfo->w32_focus_frame;
  1143.   int events_enqueued = 0;
  1144.  
  1145.   if (frame != dpyinfo->w32_focus_frame)
  1146.     {
  1147.       /* Set this before calling other routines, so that they see
  1148.      the correct value of w32_focus_frame.  */
  1149.       dpyinfo->w32_focus_frame = frame;
  1150.  
  1151.       if (old_focus && old_focus->auto_lower)
  1152.     x_lower_frame (old_focus);
  1153.  
  1154.       if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
  1155.     pending_autoraise_frame = dpyinfo->w32_focus_frame;
  1156.       else
  1157.     pending_autoraise_frame = 0;
  1158.     }
  1159.  
  1160.   x_frame_rehighlight (dpyinfo);
  1161. }
  1162.  
  1163. /* Handle an event saying the mouse has moved out of an Emacs frame.  */
  1164.  
  1165. void
  1166. x_mouse_leave (dpyinfo)
  1167.      struct w32_display_info *dpyinfo;
  1168. {
  1169.   x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
  1170. }
  1171.  
  1172. /* The focus has changed, or we have redirected a frame's focus to
  1173.    another frame (this happens when a frame uses a surrogate
  1174.    minibuffer frame).  Shift the highlight as appropriate.
  1175.  
  1176.    The FRAME argument doesn't necessarily have anything to do with which
  1177.    frame is being highlighted or unhighlighted; we only use it to find
  1178.    the appropriate display info.  */
  1179. static void
  1180. w32_frame_rehighlight (frame)
  1181.      struct frame *frame;
  1182. {
  1183.   x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
  1184. }
  1185.  
  1186. static void
  1187. x_frame_rehighlight (dpyinfo)
  1188.      struct w32_display_info *dpyinfo;
  1189. {
  1190.   struct frame *old_highlight = dpyinfo->w32_highlight_frame;
  1191.  
  1192.   if (dpyinfo->w32_focus_frame)
  1193.     {
  1194.       dpyinfo->w32_highlight_frame
  1195.     = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
  1196.        ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
  1197.        : dpyinfo->w32_focus_frame);
  1198.       if (! FRAME_LIVE_P (dpyinfo->w32_highlight_frame))
  1199.     {
  1200.       FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
  1201.       dpyinfo->w32_highlight_frame = dpyinfo->w32_focus_frame;
  1202.     }
  1203.     }
  1204.   else
  1205.     dpyinfo->w32_highlight_frame = 0;
  1206.  
  1207.   if (dpyinfo->w32_highlight_frame != old_highlight)
  1208.     {
  1209.       if (old_highlight)
  1210.     frame_unhighlight (old_highlight);
  1211.       if (dpyinfo->w32_highlight_frame)
  1212.     frame_highlight (dpyinfo->w32_highlight_frame);
  1213.     }
  1214. }
  1215.  
  1216. /* Keyboard processing - modifier keys, etc. */
  1217.  
  1218. /* Convert a keysym to its name.  */
  1219.  
  1220. char *
  1221. x_get_keysym_name (keysym)
  1222.     int keysym;
  1223. {
  1224.   /* Make static so we can always return it */
  1225.   static char value[100];
  1226.  
  1227.   BLOCK_INPUT;
  1228.   GetKeyNameText(keysym, value, 100);
  1229.   UNBLOCK_INPUT;
  1230.  
  1231.   return value;
  1232. }
  1233.  
  1234. /* Mouse clicks and mouse movement.  Rah.  */
  1235.  
  1236. /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
  1237.    glyph co-ordinates in (*X, *Y).  Set *BOUNDS to the rectangle
  1238.    that the glyph at X, Y occupies, if BOUNDS != 0.
  1239.    If NOCLIP is nonzero, do not force the value into range.  */
  1240.  
  1241. void
  1242. pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
  1243.      FRAME_PTR f;
  1244.      register int pix_x, pix_y;
  1245.      register int *x, *y;
  1246.      RECT *bounds;
  1247.      int noclip;
  1248. {
  1249.   /* Support tty mode: if Vwindow_system is nil, behave correctly. */
  1250.   if (NILP (Vwindow_system))
  1251.     {
  1252.       *x = pix_x;
  1253.       *y = pix_y;
  1254.       return;
  1255.     }
  1256.  
  1257.   /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
  1258.      even for negative values.  */
  1259.   if (pix_x < 0)
  1260.     pix_x -= FONT_WIDTH ((f)->output_data.w32->font) - 1;
  1261.   if (pix_y < 0)
  1262.     pix_y -= (f)->output_data.w32->line_height - 1;
  1263.  
  1264.   pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
  1265.   pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
  1266.  
  1267.   if (bounds)
  1268.     {
  1269.       bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
  1270.       bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
  1271.       bounds->right  = bounds->left + FONT_WIDTH  (f->output_data.w32->font) - 1;
  1272.       bounds->bottom = bounds->top + f->output_data.w32->line_height - 1;
  1273.     }
  1274.  
  1275.   if (!noclip)
  1276.     {
  1277.       if (pix_x < 0)
  1278.     pix_x = 0;
  1279.       else if (pix_x > f->width)
  1280.     pix_x = f->width;
  1281.  
  1282.       if (pix_y < 0)
  1283.     pix_y = 0;
  1284.       else if (pix_y > f->height)
  1285.     pix_y = f->height;
  1286.     }
  1287.  
  1288.   *x = pix_x;
  1289.   *y = pix_y;
  1290. }
  1291.  
  1292. void
  1293. glyph_to_pixel_coords (f, x, y, pix_x, pix_y)
  1294.      FRAME_PTR f;
  1295.      register int x, y;
  1296.      register int *pix_x, *pix_y;
  1297. {
  1298.   /* Support tty mode: if Vwindow_system is nil, behave correctly. */
  1299.   if (NILP (Vwindow_system))
  1300.     {
  1301.       *pix_x = x;
  1302.       *pix_y = y;
  1303.       return;
  1304.     }
  1305.  
  1306.   *pix_x = CHAR_TO_PIXEL_COL (f, x);
  1307.   *pix_y = CHAR_TO_PIXEL_ROW (f, y);
  1308. }
  1309.  
  1310. BOOL 
  1311. parse_button (message, pbutton, pup)
  1312.      int message;
  1313.      int * pbutton;
  1314.      int * pup;
  1315. {
  1316.   int button = 0;
  1317.   int up = 0;
  1318.   
  1319.   switch (message)
  1320.     {
  1321.     case WM_LBUTTONDOWN:
  1322.       button = 0;
  1323.       up = 0;
  1324.       break;
  1325.     case WM_LBUTTONUP:
  1326.       button = 0;
  1327.       up = 1;
  1328.       break;
  1329.     case WM_MBUTTONDOWN:
  1330.       if (NILP (Vw32_swap_mouse_buttons))
  1331.     button = 1;
  1332.       else
  1333.     button = 2;
  1334.       up = 0;
  1335.       break;
  1336.     case WM_MBUTTONUP:
  1337.       if (NILP (Vw32_swap_mouse_buttons))
  1338.     button = 1;
  1339.       else
  1340.     button = 2;
  1341.       up = 1;
  1342.       break;
  1343.     case WM_RBUTTONDOWN:
  1344.       if (NILP (Vw32_swap_mouse_buttons))
  1345.     button = 2;
  1346.       else
  1347.     button = 1;
  1348.       up = 0;
  1349.       break;
  1350.     case WM_RBUTTONUP:
  1351.       if (NILP (Vw32_swap_mouse_buttons))
  1352.     button = 2;
  1353.       else
  1354.     button = 1;
  1355.       up = 1;
  1356.       break;
  1357.     default:
  1358.       return (FALSE);
  1359.     }
  1360.   
  1361.   if (pup) *pup = up;
  1362.   if (pbutton) *pbutton = button;
  1363.   
  1364.   return (TRUE);
  1365. }
  1366.  
  1367.  
  1368. /* Prepare a mouse-event in *RESULT for placement in the input queue.
  1369.  
  1370.    If the event is a button press, then note that we have grabbed
  1371.    the mouse.  */
  1372.  
  1373. static void
  1374. construct_mouse_click (result, msg, f)
  1375.      struct input_event *result;
  1376.      W32Msg *msg;
  1377.      struct frame *f;
  1378. {
  1379.   int button;
  1380.   int up;
  1381.  
  1382.   parse_button (msg->msg.message, &button, &up);
  1383.  
  1384.   /* Make the event type no_event; we'll change that when we decide
  1385.      otherwise.  */
  1386.   result->kind = mouse_click;
  1387.   result->code = button;
  1388.   result->timestamp = msg->msg.time;
  1389.   result->modifiers = (msg->dwModifiers
  1390.                | (up
  1391.               ? up_modifier
  1392.               : down_modifier));
  1393.  
  1394.   {
  1395.     int row, column;
  1396.  
  1397.     XSETINT (result->x, LOWORD (msg->msg.lParam));
  1398.     XSETINT (result->y, HIWORD (msg->msg.lParam));
  1399.     XSETFRAME (result->frame_or_window, f);
  1400.   }
  1401. }
  1402.  
  1403. static void
  1404. construct_mouse_wheel (result, msg, f)
  1405.      struct input_event *result;
  1406.      W32Msg *msg;
  1407.      struct frame *f;
  1408. {
  1409.   POINT p;
  1410.   result->kind = mouse_wheel;
  1411.   result->code = (short) HIWORD (msg->msg.wParam);
  1412.   result->timestamp = msg->msg.time;
  1413.   result->modifiers = msg->dwModifiers;
  1414.   p.x = LOWORD (msg->msg.lParam);
  1415.   p.y = HIWORD (msg->msg.lParam);
  1416.   ScreenToClient(msg->msg.hwnd, &p);
  1417.   XSETINT (result->x, p.x);
  1418.   XSETINT (result->y, p.y);
  1419.   XSETFRAME (result->frame_or_window, f);
  1420. }
  1421.  
  1422. static void
  1423. construct_drag_n_drop (result, msg, f)
  1424.      struct input_event *result;
  1425.      W32Msg *msg;
  1426.      struct frame *f;
  1427. {
  1428.   Lisp_Object files;
  1429.   Lisp_Object frame;
  1430.   HDROP hdrop;
  1431.   POINT p;
  1432.   WORD num_files;
  1433.   char *name;
  1434.   int i, len;
  1435.  
  1436.   result->kind = drag_n_drop;
  1437.   result->code = 0;
  1438.   result->timestamp = msg->msg.time;
  1439.   result->modifiers = msg->dwModifiers;
  1440.  
  1441.   p.x = LOWORD (msg->msg.lParam);
  1442.   p.y = HIWORD (msg->msg.lParam);
  1443.   ScreenToClient (msg->msg.hwnd, &p);
  1444.   XSETINT (result->x, p.x);
  1445.   XSETINT (result->y, p.y);
  1446.  
  1447.   hdrop = (HDROP) msg->msg.wParam;
  1448.   DragQueryPoint (hdrop, &p);
  1449.   num_files = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
  1450.   files = Qnil;
  1451.  
  1452.   for (i = 0; i < num_files; i++)
  1453.     {
  1454.       len = DragQueryFile (hdrop, i, NULL, 0);
  1455.       if (len <= 0)
  1456.     continue;
  1457.       name = alloca (len + 1);
  1458.       DragQueryFile (hdrop, i, name, len + 1);
  1459.       files = Fcons (build_string (name), files);
  1460.     }
  1461.  
  1462.   DragFinish (hdrop);
  1463.  
  1464.   XSETFRAME (frame, f);
  1465.   result->frame_or_window = Fcons (frame, files);
  1466. }
  1467.  
  1468.  
  1469. /* Function to report a mouse movement to the mainstream Emacs code.
  1470.    The input handler calls this.
  1471.  
  1472.    We have received a mouse movement event, which is given in *event.
  1473.    If the mouse is over a different glyph than it was last time, tell
  1474.    the mainstream emacs code by setting mouse_moved.  If not, ask for
  1475.    another motion event, so we can check again the next time it moves.  */
  1476.  
  1477. static void
  1478. note_mouse_movement (frame, msg)
  1479.      FRAME_PTR frame;
  1480.      MSG *msg;
  1481. {
  1482.   last_mouse_movement_time = msg->time;
  1483.  
  1484.   if (msg->hwnd != FRAME_W32_WINDOW (frame))
  1485.     {
  1486.       frame->mouse_moved = 1;
  1487.       last_mouse_scroll_bar = Qnil;
  1488.  
  1489.       note_mouse_highlight (frame, -1, -1);
  1490.     }
  1491.  
  1492.   /* Has the mouse moved off the glyph it was on at the last sighting?  */
  1493.   else if (LOWORD (msg->lParam) < last_mouse_glyph.left
  1494.        || LOWORD (msg->lParam) > last_mouse_glyph.right
  1495.        || HIWORD (msg->lParam) < last_mouse_glyph.top
  1496.        || HIWORD (msg->lParam) > last_mouse_glyph.bottom)
  1497.     {
  1498.       frame->mouse_moved = 1;
  1499.       last_mouse_scroll_bar = Qnil;
  1500.  
  1501.       note_mouse_highlight (frame, LOWORD (msg->lParam), HIWORD (msg->lParam));
  1502.     }
  1503. }
  1504.  
  1505. /* This is used for debugging, to turn off note_mouse_highlight.  */
  1506. static int disable_mouse_highlight;
  1507.  
  1508. /* Take proper action when the mouse has moved to position X, Y on frame F
  1509.    as regards highlighting characters that have mouse-face properties.
  1510.    Also dehighlighting chars where the mouse was before.
  1511.    X and Y can be negative or out of range.  */
  1512.  
  1513. static void
  1514. note_mouse_highlight (f, x, y)
  1515.      FRAME_PTR f;
  1516.      int x, y;
  1517. {
  1518.   int row, column, portion;
  1519.   RECT new_glyph;
  1520.   Lisp_Object window;
  1521.   struct window *w;
  1522.  
  1523.   if (disable_mouse_highlight)
  1524.     return;
  1525.  
  1526.   FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_x = x;
  1527.   FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_y = y;
  1528.   FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame = f;
  1529.  
  1530.   if (FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer)
  1531.     return;
  1532.  
  1533.   if (gc_in_progress)
  1534.     {
  1535.       FRAME_W32_DISPLAY_INFO (f)->mouse_face_deferred_gc = 1;
  1536.       return;
  1537.     }
  1538.  
  1539.   /* Find out which glyph the mouse is on.  */
  1540.   pixel_to_glyph_coords (f, x, y, &column, &row,
  1541.              &new_glyph, FRAME_W32_DISPLAY_INFO (f)->grabbed);
  1542.  
  1543.   /* Which window is that in?  */
  1544.   window = window_from_coordinates (f, column, row, &portion);
  1545.   w = XWINDOW (window);
  1546.  
  1547.   /* If we were displaying active text in another window, clear that.  */
  1548.   if (! EQ (window, FRAME_W32_DISPLAY_INFO (f)->mouse_face_window))
  1549.     clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
  1550.  
  1551.   /* Are we in a window whose display is up to date?
  1552.      And verify the buffer's text has not changed.  */
  1553.   if (WINDOWP (window) && portion == 0 && row >= 0 && column >= 0
  1554.       && row < FRAME_HEIGHT (f) && column < FRAME_WIDTH (f)
  1555.       && EQ (w->window_end_valid, w->buffer)
  1556.       && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer))
  1557.       && w->last_overlay_modified == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer)))
  1558.     {
  1559.       int *ptr = FRAME_CURRENT_GLYPHS (f)->charstarts[row];
  1560.       int i, pos;
  1561.  
  1562.       /* Find which buffer position the mouse corresponds to.  */
  1563.       for (i = column; i >= 0; i--)
  1564.     if (ptr[i] > 0)
  1565.       break;
  1566.       pos = ptr[i];
  1567.       /* Is it outside the displayed active region (if any)?  */
  1568.       if (pos <= 0)
  1569.     clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
  1570.       else if (! (EQ (window, FRAME_W32_DISPLAY_INFO (f)->mouse_face_window)
  1571.           && row >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
  1572.           && row <= FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
  1573.           && (row > FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
  1574.               || column >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col)
  1575.           && (row < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
  1576.               || column < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col
  1577.               || FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end)))
  1578.     {
  1579.       Lisp_Object mouse_face, overlay, position;
  1580.       Lisp_Object *overlay_vec;
  1581.       int len, noverlays, ignor1;
  1582.       struct buffer *obuf;
  1583.       int obegv, ozv;
  1584.  
  1585.       /* If we get an out-of-range value, return now; avoid an error.  */
  1586.       if (pos > BUF_Z (XBUFFER (w->buffer)))
  1587.         return;
  1588.  
  1589.       /* Make the window's buffer temporarily current for
  1590.          overlays_at and compute_char_face.  */
  1591.       obuf = current_buffer;
  1592.       current_buffer = XBUFFER (w->buffer);
  1593.       obegv = BEGV;
  1594.       ozv = ZV;
  1595.       BEGV = BEG;
  1596.       ZV = Z;
  1597.  
  1598.       /* Yes.  Clear the display of the old active region, if any.  */
  1599.       clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
  1600.  
  1601.       /* Is this char mouse-active?  */
  1602.       XSETINT (position, pos);
  1603.  
  1604.       len = 10;
  1605.       overlay_vec = (Lisp_Object *) xmalloc (len * sizeof (Lisp_Object));
  1606.  
  1607.       /* Put all the overlays we want in a vector in overlay_vec.
  1608.          Store the length in len.  */
  1609.       noverlays = overlays_at (XINT (pos), 1, &overlay_vec, &len,
  1610.                    NULL, NULL);
  1611.       noverlays = sort_overlays (overlay_vec, noverlays, w);
  1612.  
  1613.       /* Find the highest priority overlay that has a mouse-face prop.  */
  1614.       overlay = Qnil;
  1615.       for (i = 0; i < noverlays; i++)
  1616.         {
  1617.           mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
  1618.           if (!NILP (mouse_face))
  1619.         {
  1620.           overlay = overlay_vec[i];
  1621.           break;
  1622.         }
  1623.         }
  1624.       free (overlay_vec);
  1625.       /* If no overlay applies, get a text property.  */
  1626.       if (NILP (overlay))
  1627.         mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
  1628.  
  1629.       /* Handle the overlay case.  */
  1630.       if (! NILP (overlay))
  1631.         {
  1632.           /* Find the range of text around this char that
  1633.          should be active.  */
  1634.           Lisp_Object before, after;
  1635.           int ignore;
  1636.  
  1637.           before = Foverlay_start (overlay);
  1638.           after = Foverlay_end (overlay);
  1639.           /* Record this as the current active region.  */
  1640.           fast_find_position (window, before,
  1641.                   &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col,
  1642.                   &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row);
  1643.           FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end
  1644.         = !fast_find_position (window, after,
  1645.                        &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col,
  1646.                        &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row);
  1647.           FRAME_W32_DISPLAY_INFO (f)->mouse_face_window = window;
  1648.           FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id
  1649.         = compute_char_face (f, w, pos, 0, 0,
  1650.                      &ignore, pos + 1, 1);
  1651.  
  1652.           /* Display it as active.  */
  1653.           show_mouse_face (FRAME_W32_DISPLAY_INFO (f), 1);
  1654.         }
  1655.       /* Handle the text property case.  */
  1656.       else if (! NILP (mouse_face))
  1657.         {
  1658.           /* Find the range of text around this char that
  1659.          should be active.  */
  1660.           Lisp_Object before, after, beginning, end;
  1661.           int ignore;
  1662.  
  1663.           beginning = Fmarker_position (w->start);
  1664.           XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
  1665.                  - XFASTINT (w->window_end_pos)));
  1666.           before
  1667.         = Fprevious_single_property_change (make_number (pos + 1),
  1668.                             Qmouse_face,
  1669.                             w->buffer, beginning);
  1670.           after
  1671.         = Fnext_single_property_change (position, Qmouse_face,
  1672.                         w->buffer, end);
  1673.           /* Record this as the current active region.  */
  1674.           fast_find_position (window, before,
  1675.                   &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col,
  1676.                   &FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row);
  1677.           FRAME_W32_DISPLAY_INFO (f)->mouse_face_past_end
  1678.         = !fast_find_position (window, after,
  1679.                        &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col,
  1680.                        &FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row);
  1681.           FRAME_W32_DISPLAY_INFO (f)->mouse_face_window = window;
  1682.           FRAME_W32_DISPLAY_INFO (f)->mouse_face_face_id
  1683.         = compute_char_face (f, w, pos, 0, 0,
  1684.                      &ignore, pos + 1, 1);
  1685.  
  1686.           /* Display it as active.  */
  1687.           show_mouse_face (FRAME_W32_DISPLAY_INFO (f), 1);
  1688.         }
  1689.       BEGV = obegv;
  1690.       ZV = ozv;
  1691.       current_buffer = obuf;
  1692.     }
  1693.     }
  1694. }
  1695.  
  1696. /* Find the row and column of position POS in window WINDOW.
  1697.    Store them in *COLUMNP and *ROWP.
  1698.    This assumes display in WINDOW is up to date.
  1699.    If POS is above start of WINDOW, return coords
  1700.    of start of first screen line.
  1701.    If POS is after end of WINDOW, return coords of end of last screen line.
  1702.  
  1703.    Value is 1 if POS is in range, 0 if it was off screen.  */
  1704.  
  1705. static int
  1706. fast_find_position (window, pos, columnp, rowp)
  1707.      Lisp_Object window;
  1708.      int pos;
  1709.      int *columnp, *rowp;
  1710. {
  1711.   struct window *w = XWINDOW (window);
  1712.   FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
  1713.   int i;
  1714.   int row = 0;
  1715.   int left = WINDOW_LEFT_MARGIN (w);
  1716.   int top = w->top;
  1717.   int height = XFASTINT (w->height) - ! MINI_WINDOW_P (w);
  1718.   int width = window_internal_width (w);
  1719.   int *charstarts;
  1720.   int lastcol;
  1721.   int maybe_next_line = 0;
  1722.  
  1723.   /* Find the right row.  */
  1724.   for (i = 0;
  1725.        i < height;
  1726.        i++)
  1727.     {
  1728.       int linestart = FRAME_CURRENT_GLYPHS (f)->charstarts[top + i][left];
  1729.       if (linestart > pos)
  1730.     break;
  1731.       /* If the position sought is the end of the buffer,
  1732.      don't include the blank lines at the bottom of the window.  */
  1733.       if (linestart == pos && pos == BUF_ZV (XBUFFER (w->buffer)))
  1734.     {
  1735.       maybe_next_line = 1;
  1736.       break;
  1737.     }
  1738.       if (linestart > 0)
  1739.     row = i;
  1740.     }
  1741.  
  1742.   /* Find the right column with in it.  */
  1743.   charstarts = FRAME_CURRENT_GLYPHS (f)->charstarts[top + row];
  1744.   lastcol = left;
  1745.   for (i = 0; i < width; i++)
  1746.     {
  1747.       if (charstarts[left + i] == pos)
  1748.     {
  1749.       *rowp = row + top;
  1750.       *columnp = i + left;
  1751.       return 1;
  1752.     }
  1753.       else if (charstarts[left + i] > pos)
  1754.     break;
  1755.       else if (charstarts[left + i] > 0)
  1756.     lastcol = left + i;
  1757.     }
  1758.  
  1759.   /* If we're looking for the end of the buffer,
  1760.      and we didn't find it in the line we scanned,
  1761.      use the start of the following line.  */
  1762.   if (maybe_next_line)
  1763.     {
  1764.       row++;
  1765.       i = 0;
  1766.     }
  1767.  
  1768.   *rowp = row + top;
  1769.   *columnp = lastcol;
  1770.   return 0;
  1771. }
  1772.  
  1773. /* Display the active region described by mouse_face_*
  1774.    in its mouse-face if HL > 0, in its normal face if HL = 0.  */
  1775.  
  1776. static void
  1777. show_mouse_face (dpyinfo, hl)
  1778.      struct w32_display_info *dpyinfo;
  1779.      int hl;
  1780. {
  1781.   struct window *w = XWINDOW (dpyinfo->mouse_face_window);
  1782.   int width = window_internal_width (w);
  1783.   FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
  1784.   int i;
  1785.   int cursor_off = 0;
  1786.   int old_curs_x = curs_x;
  1787.   int old_curs_y = curs_y;
  1788.  
  1789.   /* Set these variables temporarily
  1790.      so that if we have to turn the cursor off and on again
  1791.      we will put it back at the same place.  */
  1792.   curs_x = f->phys_cursor_x;
  1793.   curs_y = f->phys_cursor_y;
  1794.  
  1795.   for (i = FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row;
  1796.        i <= FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row; i++)
  1797.     {
  1798.       int column = (i == FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
  1799.             ? FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col
  1800.             : WINDOW_LEFT_MARGIN (w));
  1801.       int endcolumn = (i == FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
  1802.                ? FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col
  1803.                : WINDOW_LEFT_MARGIN (w) + width);
  1804.       endcolumn = min (endcolumn, FRAME_CURRENT_GLYPHS (f)->used[i]);
  1805.  
  1806.       /* If the cursor's in the text we are about to rewrite,
  1807.      turn the cursor off.  */
  1808.       if (i == curs_y
  1809.       && curs_x >= column - 1
  1810.       && curs_x <= endcolumn)
  1811.     {
  1812.       x_display_cursor (f, 0);
  1813.       cursor_off = 1;
  1814.     }
  1815.  
  1816.       dumpglyphs (f,
  1817.           CHAR_TO_PIXEL_COL (f, column),
  1818.           CHAR_TO_PIXEL_ROW (f, i),
  1819.           FRAME_CURRENT_GLYPHS (f)->glyphs[i] + column,
  1820.           endcolumn - column,
  1821.           /* Highlight with mouse face if hl > 0.  */
  1822.           hl > 0 ? 3 : 0, 0, NULL);
  1823.     }
  1824.  
  1825.   /* If we turned the cursor off, turn it back on.  */
  1826.   if (cursor_off)
  1827.     x_display_cursor (f, 1);
  1828.  
  1829.   curs_x = old_curs_x;
  1830.   curs_y = old_curs_y;
  1831.  
  1832.   /* Change the mouse cursor according to the value of HL.  */
  1833.   if (hl > 0)
  1834.     SetCursor (f->output_data.w32->cross_cursor);
  1835.   else
  1836.     SetCursor (f->output_data.w32->text_cursor);
  1837. }
  1838.  
  1839. /* Clear out the mouse-highlighted active region.
  1840.    Redraw it unhighlighted first.  */
  1841.  
  1842. static void
  1843. clear_mouse_face (dpyinfo)
  1844.      struct w32_display_info *dpyinfo;
  1845. {
  1846.   if (! NILP (dpyinfo->mouse_face_window))
  1847.     show_mouse_face (dpyinfo, 0);
  1848.  
  1849.   dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
  1850.   dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
  1851.   dpyinfo->mouse_face_window = Qnil;
  1852. }
  1853.  
  1854. struct scroll_bar *x_window_to_scroll_bar ();
  1855. static void x_scroll_bar_report_motion ();
  1856.  
  1857. /* Return the current position of the mouse.
  1858.    *fp should be a frame which indicates which display to ask about.
  1859.  
  1860.    If the mouse movement started in a scroll bar, set *fp, *bar_window,
  1861.    and *part to the frame, window, and scroll bar part that the mouse
  1862.    is over.  Set *x and *y to the portion and whole of the mouse's
  1863.    position on the scroll bar.
  1864.  
  1865.    If the mouse movement started elsewhere, set *fp to the frame the
  1866.    mouse is on, *bar_window to nil, and *x and *y to the character cell
  1867.    the mouse is over.
  1868.  
  1869.    Set *time to the server timestamp for the time at which the mouse
  1870.    was at this position.
  1871.  
  1872.    Don't store anything if we don't have a valid set of values to report.
  1873.  
  1874.    This clears the mouse_moved flag, so we can wait for the next mouse
  1875.    movement.  This also calls XQueryPointer, which will cause the
  1876.    server to give us another MotionNotify when the mouse moves
  1877.    again. */
  1878.  
  1879. static void
  1880. w32_mouse_position (fp, insist, bar_window, part, x, y, time)
  1881.      FRAME_PTR *fp;
  1882.      int insist;
  1883.      Lisp_Object *bar_window;
  1884.      enum scroll_bar_part *part;
  1885.      Lisp_Object *x, *y;
  1886.      unsigned long *time;
  1887. {
  1888.   FRAME_PTR f1;
  1889.  
  1890.   BLOCK_INPUT;
  1891.  
  1892.   if (! NILP (last_mouse_scroll_bar) && insist == 0)
  1893.     /* This is never called at the moment.  */
  1894.     x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
  1895.   else
  1896.     {
  1897.       POINT pt;
  1898.  
  1899.       Lisp_Object frame, tail;
  1900.  
  1901.       /* Clear the mouse-moved flag for every frame on this display.  */
  1902.       FOR_EACH_FRAME (tail, frame)
  1903.     XFRAME (frame)->mouse_moved = 0;
  1904.  
  1905.       last_mouse_scroll_bar = Qnil;
  1906.       
  1907.       GetCursorPos (&pt);
  1908.  
  1909.       /* Now we have a position on the root; find the innermost window
  1910.      containing the pointer.  */
  1911.       {
  1912.     if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
  1913.         && FRAME_LIVE_P (last_mouse_frame))
  1914.       {
  1915.         f1 = last_mouse_frame;
  1916.       }
  1917.     else
  1918.       {
  1919.         /* Is win one of our frames?  */
  1920.         f1 = x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp), WindowFromPoint(pt));
  1921.       }
  1922.  
  1923.     /* If not, is it one of our scroll bars?  */
  1924.     if (! f1)
  1925.       {
  1926.         struct scroll_bar *bar = x_window_to_scroll_bar (WindowFromPoint(pt));
  1927.  
  1928.         if (bar)
  1929.           {
  1930.         f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
  1931.           }
  1932.       }
  1933.  
  1934.     if (f1 == 0 && insist > 0)
  1935.       f1 = selected_frame;
  1936.  
  1937.     if (f1)
  1938.       {
  1939.         int ignore1, ignore2;
  1940.  
  1941.         ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
  1942.  
  1943.         /* Ok, we found a frame.  Store all the values.  */
  1944.  
  1945.         pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
  1946.                    &last_mouse_glyph,
  1947.                    FRAME_W32_DISPLAY_INFO (f1)->grabbed
  1948.                    || insist);
  1949.  
  1950.         *bar_window = Qnil;
  1951.         *part = 0;
  1952.         *fp = f1;
  1953.         XSETINT (*x, pt.x);
  1954.         XSETINT (*y, pt.y);
  1955.         *time = last_mouse_movement_time;
  1956.       }
  1957.       }
  1958.     }
  1959.  
  1960.   UNBLOCK_INPUT;
  1961. }
  1962.  
  1963. /* Scroll bar support.  */
  1964.  
  1965. /* Given an window ID, find the struct scroll_bar which manages it.
  1966.    This can be called in GC, so we have to make sure to strip off mark
  1967.    bits.  */
  1968. struct scroll_bar *
  1969. x_window_to_scroll_bar (window_id)
  1970.      Window window_id;
  1971. {
  1972.   Lisp_Object tail, frame;
  1973.  
  1974.   for (tail = Vframe_list;
  1975.        XGCTYPE (tail) == Lisp_Cons;
  1976.        tail = XCONS (tail)->cdr)
  1977.     {
  1978.       Lisp_Object frame, bar, condemned;
  1979.  
  1980.       frame = XCONS (tail)->car;
  1981.       /* All elements of Vframe_list should be frames.  */
  1982.       if (! GC_FRAMEP (frame))
  1983.     abort ();
  1984.  
  1985.       /* Scan this frame's scroll bar list for a scroll bar with the
  1986.      right window ID.  */
  1987.       condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
  1988.       for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
  1989.        /* This trick allows us to search both the ordinary and
  1990.           condemned scroll bar lists with one loop.  */
  1991.        ! GC_NILP (bar) || (bar = condemned,
  1992.                    condemned = Qnil,
  1993.                    ! GC_NILP (bar));
  1994.        bar = XSCROLL_BAR (bar)->next)
  1995.     if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
  1996.       return XSCROLL_BAR (bar);
  1997.     }
  1998.  
  1999.   return 0;
  2000. }
  2001.  
  2002. HWND 
  2003. my_create_scrollbar (f, bar)
  2004.      struct frame * f;
  2005.      struct scroll_bar * bar;
  2006. {
  2007.   return (HWND) SendMessage (FRAME_W32_WINDOW (f),
  2008.                  WM_EMACS_CREATESCROLLBAR, (WPARAM) f, 
  2009.                  (LPARAM) bar);
  2010. }
  2011.  
  2012. //#define ATTACH_THREADS
  2013.  
  2014. BOOL
  2015. my_show_window (FRAME_PTR f, HWND hwnd, int how)
  2016. {
  2017. #ifndef ATTACH_THREADS
  2018.   return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
  2019.               (WPARAM) hwnd, (LPARAM) how);
  2020. #else
  2021.   return ShowWindow (hwnd, how);
  2022. #endif
  2023. }
  2024.  
  2025. void
  2026. my_set_window_pos (HWND hwnd, HWND hwndAfter,
  2027.            int x, int y, int cx, int cy, UINT flags)
  2028. {
  2029. #ifndef ATTACH_THREADS
  2030.   WINDOWPOS pos;
  2031.   pos.hwndInsertAfter = hwndAfter;
  2032.   pos.x = x;
  2033.   pos.y = y;
  2034.   pos.cx = cx;
  2035.   pos.cy = cy;
  2036.   pos.flags = flags;
  2037.   SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
  2038. #else
  2039.   SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
  2040. #endif
  2041. }
  2042.  
  2043. BOOL
  2044. my_set_focus (f, hwnd)
  2045.      struct frame * f;
  2046.      HWND hwnd;
  2047. {
  2048.   SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS, 
  2049.            (WPARAM) hwnd, 0);
  2050. }
  2051.  
  2052. BOOL
  2053. my_set_foreground_window (hwnd)
  2054.      HWND hwnd;
  2055. {
  2056.   SendMessage (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0);
  2057. }
  2058.  
  2059. void
  2060. my_destroy_window (f, hwnd)
  2061.      struct frame * f;
  2062.      HWND hwnd;
  2063. {
  2064.   SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW, 
  2065.            (WPARAM) hwnd, 0);
  2066. }
  2067.  
  2068. /* Open a new window to serve as a scroll bar, and return the
  2069.    scroll bar vector for it.  */
  2070. static struct scroll_bar *
  2071. x_scroll_bar_create (window, top, left, width, height)
  2072.      struct window *window;
  2073.      int top, left, width, height;
  2074. {
  2075.   FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
  2076.   struct scroll_bar *bar
  2077.     = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
  2078.   HWND hwnd;
  2079.  
  2080.   BLOCK_INPUT;
  2081.  
  2082.   XSETWINDOW (bar->window, window);
  2083.   XSETINT (bar->top, top);
  2084.   XSETINT (bar->left, left);
  2085.   XSETINT (bar->width, width);
  2086.   XSETINT (bar->height, height);
  2087.   XSETINT (bar->start, 0);
  2088.   XSETINT (bar->end, 0);
  2089.   bar->dragging = Qnil;
  2090.  
  2091.   /* Requires geometry to be set before call to create the real window */
  2092.  
  2093.   hwnd = my_create_scrollbar (f, bar);
  2094.  
  2095.   if (pfnSetScrollInfo)
  2096.     {
  2097.       SCROLLINFO si;
  2098.  
  2099.       si.cbSize = sizeof (si);
  2100.       si.fMask = SIF_ALL;
  2101.       si.nMin = 0;
  2102.       si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (height)
  2103.     + VERTICAL_SCROLL_BAR_MIN_HANDLE;
  2104.       si.nPage = si.nMax;
  2105.       si.nPos = 0;
  2106.  
  2107.       pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
  2108.     }
  2109.   else
  2110.     {
  2111.       SetScrollRange (hwnd, SB_CTL, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height), FALSE);
  2112.       SetScrollPos (hwnd, SB_CTL, 0, FALSE);
  2113.     }
  2114.  
  2115.   SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
  2116.  
  2117.   /* Add bar to its frame's list of scroll bars.  */
  2118.   bar->next = FRAME_SCROLL_BARS (f);
  2119.   bar->prev = Qnil;
  2120.   XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
  2121.   if (! NILP (bar->next))
  2122.     XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
  2123.  
  2124.   UNBLOCK_INPUT;
  2125.  
  2126.   return bar;
  2127. }
  2128.  
  2129. /* Draw BAR's handle in the proper position.
  2130.    If the handle is already drawn from START to END, don't bother
  2131.    redrawing it, unless REBUILD is non-zero; in that case, always
  2132.    redraw it.  (REBUILD is handy for drawing the handle after expose
  2133.    events.)
  2134.  
  2135.    Normally, we want to constrain the start and end of the handle to
  2136.    fit inside its rectangle, but if the user is dragging the scroll bar
  2137.    handle, we want to let them drag it down all the way, so that the
  2138.    bar's top is as far down as it goes; otherwise, there's no way to
  2139.    move to the very end of the buffer.  */
  2140. static void
  2141. x_scroll_bar_set_handle (bar, start, end, rebuild)
  2142.      struct scroll_bar *bar;
  2143.      int start, end;
  2144.      int rebuild;
  2145. {
  2146.   int dragging = ! NILP (bar->dragging);
  2147.   Window w = SCROLL_BAR_W32_WINDOW (bar);
  2148.   FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
  2149.  
  2150.   /* If the display is already accurate, do nothing.  */
  2151.   if (! rebuild
  2152.       && start == XINT (bar->start)
  2153.       && end == XINT (bar->end))
  2154.     return;
  2155.  
  2156.   BLOCK_INPUT;
  2157.  
  2158.   {
  2159.     int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
  2160.  
  2161.     /* Make sure the values are reasonable, and try to preserve
  2162.        the distance between start and end.  */
  2163.     {
  2164.       int length = end - start;
  2165.  
  2166.       if (start < 0)
  2167.     start = 0;
  2168.       else if (start > top_range)
  2169.     start = top_range;
  2170.       end = start + length;
  2171.  
  2172.       if (end < start)
  2173.     end = start;
  2174.       else if (end > top_range && ! dragging)
  2175.     end = top_range;
  2176.     }
  2177.   }
  2178.  
  2179.   /* Store the adjusted setting in the scroll bar.  */
  2180.   XSETINT (bar->start, start);
  2181.   XSETINT (bar->end, end);
  2182.  
  2183.   /* If being dragged, let scroll bar update itself.  */
  2184.   if (!dragging)
  2185.     {
  2186.       if (pfnSetScrollInfo)
  2187.     {
  2188.       SCROLLINFO si;
  2189.  
  2190.       si.cbSize = sizeof (si);
  2191.       si.fMask = SIF_PAGE | SIF_POS;
  2192.       si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
  2193.       si.nPos = start;
  2194.  
  2195.       pfnSetScrollInfo (w, SB_CTL, &si, TRUE);
  2196.     }
  2197.       else
  2198.     SetScrollPos (w, SB_CTL, start, TRUE);
  2199.     }
  2200.  
  2201.   UNBLOCK_INPUT;
  2202. }
  2203.  
  2204. /* Move a scroll bar around on the screen, to accommodate changing
  2205.    window configurations.  */
  2206. static void
  2207. x_scroll_bar_move (bar, top, left, width, height)
  2208.      struct scroll_bar *bar;
  2209.      int top, left, width, height;
  2210. {
  2211.   Window w = SCROLL_BAR_W32_WINDOW (bar);
  2212.   FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
  2213.  
  2214.   /* If already correctly positioned, do nothing.  */
  2215.   if ( XINT (bar->left) == left
  2216.        && XINT (bar->top) == top
  2217.        && XINT (bar->width) ==  width
  2218.        && XINT (bar->height) == height )
  2219.     {
  2220.       /* Redraw after clear_frame. */
  2221.       if (!my_show_window (f, w, SW_NORMAL))
  2222.     InvalidateRect (w, NULL, FALSE);
  2223.       return;
  2224.     }
  2225.  
  2226.   BLOCK_INPUT;
  2227.  
  2228.   /* Make sure scroll bar is "visible" before moving, to ensure the
  2229.      area of the parent window now exposed will be refreshed.  */
  2230.   my_show_window (f, w, SW_HIDE);
  2231.   MoveWindow (w, left, top, width, height, TRUE);
  2232.   if (pfnSetScrollInfo)
  2233.     {
  2234.       SCROLLINFO si;
  2235.  
  2236.       si.cbSize = sizeof (si);
  2237.       si.fMask = SIF_RANGE;
  2238.       si.nMin = 0;
  2239.       si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (height)
  2240.     + VERTICAL_SCROLL_BAR_MIN_HANDLE;
  2241.  
  2242.       pfnSetScrollInfo (w, SB_CTL, &si, FALSE);
  2243.     }
  2244.   else
  2245.     SetScrollRange (w, SB_CTL, 0, VERTICAL_SCROLL_BAR_TOP_RANGE (height), FALSE);
  2246.   my_show_window (f, w, SW_NORMAL);
  2247. //  InvalidateRect (w, NULL, FALSE);
  2248.  
  2249.   XSETINT (bar->left, left);
  2250.   XSETINT (bar->top, top);
  2251.   XSETINT (bar->width, width);
  2252.   XSETINT (bar->height, height);
  2253.  
  2254.   UNBLOCK_INPUT;
  2255. }
  2256.  
  2257. /* Destroy the window for BAR, and set its Emacs window's scroll bar
  2258.    to nil.  */
  2259. static void
  2260. x_scroll_bar_remove (bar)
  2261.      struct scroll_bar *bar;
  2262. {
  2263.   FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
  2264.  
  2265.   BLOCK_INPUT;
  2266.  
  2267.   /* Destroy the window.  */
  2268.   my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
  2269.  
  2270.   /* Disassociate this scroll bar from its window.  */
  2271.   XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
  2272.  
  2273.   UNBLOCK_INPUT;
  2274. }
  2275.  
  2276. /* Set the handle of the vertical scroll bar for WINDOW to indicate
  2277.    that we are displaying PORTION characters out of a total of WHOLE
  2278.    characters, starting at POSITION.  If WINDOW has no scroll bar,
  2279.    create one.  */
  2280. static void
  2281. w32_set_vertical_scroll_bar (window, portion, whole, position)
  2282.      struct window *window;
  2283.      int portion, whole, position;
  2284. {
  2285.   FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
  2286.   int top = XINT (window->top);
  2287.   int left = WINDOW_VERTICAL_SCROLL_BAR_COLUMN (window);
  2288.   int height = WINDOW_VERTICAL_SCROLL_BAR_HEIGHT (window);
  2289.  
  2290.   /* Where should this scroll bar be, pixelwise?  */
  2291.   int pixel_top  = CHAR_TO_PIXEL_ROW (f, top);
  2292.   int pixel_left = CHAR_TO_PIXEL_COL (f, left);
  2293.   int pixel_width
  2294.     = (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
  2295.        ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
  2296.        : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
  2297.   int pixel_height = VERTICAL_SCROLL_BAR_PIXEL_HEIGHT (f, height);
  2298.  
  2299.   struct scroll_bar *bar;
  2300.  
  2301.   /* Does the scroll bar exist yet?  */
  2302.   if (NILP (window->vertical_scroll_bar))
  2303.     bar = x_scroll_bar_create (window,
  2304.                   pixel_top, pixel_left,
  2305.                   pixel_width, pixel_height);
  2306.   else
  2307.     {
  2308.       /* It may just need to be moved and resized.  */
  2309.       bar = XSCROLL_BAR (window->vertical_scroll_bar);
  2310.       x_scroll_bar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height);
  2311.     }
  2312.  
  2313.   /* Set the scroll bar's current state.  */
  2314.   {
  2315.     int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (pixel_height);
  2316.  
  2317.     if (whole == 0)
  2318.       x_scroll_bar_set_handle (bar, 0, top_range, 0);
  2319.     else
  2320.       {
  2321.     int start = (int) (((double) position * top_range) / whole);
  2322.     int end = (int) (((double) (position + portion) * top_range) / whole);
  2323.  
  2324.     x_scroll_bar_set_handle (bar, start, end, 0);
  2325.       }
  2326.   }
  2327.  
  2328.   XSETVECTOR (window->vertical_scroll_bar, bar);
  2329. }
  2330.  
  2331.  
  2332. /* The following three hooks are used when we're doing a thorough
  2333.    redisplay of the frame.  We don't explicitly know which scroll bars
  2334.    are going to be deleted, because keeping track of when windows go
  2335.    away is a real pain - "Can you say set-window-configuration, boys
  2336.    and girls?"  Instead, we just assert at the beginning of redisplay
  2337.    that *all* scroll bars are to be removed, and then save a scroll bar
  2338.    from the fiery pit when we actually redisplay its window.  */
  2339.  
  2340. /* Arrange for all scroll bars on FRAME to be removed at the next call
  2341.    to `*judge_scroll_bars_hook'.  A scroll bar may be spared if
  2342.    `*redeem_scroll_bar_hook' is applied to its window before the judgement.  */
  2343. static void
  2344. w32_condemn_scroll_bars (frame)
  2345.      FRAME_PTR frame;
  2346. {
  2347.   /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS.  */
  2348.   while (! NILP (FRAME_SCROLL_BARS (frame)))
  2349.     {
  2350.       Lisp_Object bar;
  2351.       bar = FRAME_SCROLL_BARS (frame);
  2352.       FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
  2353.       XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
  2354.       XSCROLL_BAR (bar)->prev = Qnil;
  2355.       if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
  2356.     XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
  2357.       FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
  2358.     }
  2359. #ifdef PIGSFLY
  2360.   /* The condemned list should be empty at this point; if it's not,
  2361.      then the rest of Emacs isn't using the condemn/redeem/judge
  2362.      protocol correctly.  */
  2363.   if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
  2364.     abort ();
  2365.  
  2366.   /* Move them all to the "condemned" list.  */
  2367.   FRAME_CONDEMNED_SCROLL_BARS (frame) = FRAME_SCROLL_BARS (frame);
  2368.   FRAME_SCROLL_BARS (frame) = Qnil;
  2369. #endif
  2370. }
  2371.  
  2372. /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
  2373.    Note that WINDOW isn't necessarily condemned at all.  */
  2374. static void
  2375. w32_redeem_scroll_bar (window)
  2376.      struct window *window;
  2377. {
  2378.   struct scroll_bar *bar;
  2379.  
  2380.   /* We can't redeem this window's scroll bar if it doesn't have one.  */
  2381.   if (NILP (window->vertical_scroll_bar))
  2382.     abort ();
  2383.  
  2384.   bar = XSCROLL_BAR (window->vertical_scroll_bar);
  2385.  
  2386.   /* Unlink it from the condemned list.  */
  2387.   {
  2388.     FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
  2389.  
  2390.     if (NILP (bar->prev))
  2391.       {
  2392.     /* If the prev pointer is nil, it must be the first in one of
  2393.            the lists.  */
  2394.     if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
  2395.       /* It's not condemned.  Everything's fine.  */
  2396.       return;
  2397.     else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
  2398.              window->vertical_scroll_bar))
  2399.       FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
  2400.     else
  2401.       /* If its prev pointer is nil, it must be at the front of
  2402.              one or the other!  */
  2403.       abort ();
  2404.       }
  2405.     else
  2406.       XSCROLL_BAR (bar->prev)->next = bar->next;
  2407.  
  2408.     if (! NILP (bar->next))
  2409.       XSCROLL_BAR (bar->next)->prev = bar->prev;
  2410.  
  2411.     bar->next = FRAME_SCROLL_BARS (f);
  2412.     bar->prev = Qnil;
  2413.     XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
  2414.     if (! NILP (bar->next))
  2415.       XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
  2416.   }
  2417. #ifdef PIGSFLY
  2418.   struct scroll_bar *bar;
  2419.  
  2420.   /* We can't redeem this window's scroll bar if it doesn't have one.  */
  2421.   if (NILP (window->vertical_scroll_bar))
  2422.     abort ();
  2423.  
  2424.   bar = XSCROLL_BAR (window->vertical_scroll_bar);
  2425.  
  2426.   /* Unlink it from the condemned list.  */
  2427.   {
  2428.     FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
  2429.  
  2430.     if (NILP (bar->prev))
  2431.       {
  2432.     /* If the prev pointer is nil, it must be the first in one of
  2433.        the lists.  */
  2434.     if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
  2435.       /* It's not condemned.  Everything's fine.  */
  2436.       return;
  2437.     else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
  2438.              window->vertical_scroll_bar))
  2439.       FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
  2440.     else
  2441.       /* If its prev pointer is nil, it must be at the front of
  2442.          one or the other!  */
  2443.       abort ();
  2444.       }
  2445.     else
  2446.       XSCROLL_BAR (bar->prev)->next = bar->next;
  2447.  
  2448.     if (! NILP (bar->next))
  2449.       XSCROLL_BAR (bar->next)->prev = bar->prev;
  2450.  
  2451.     bar->next = FRAME_SCROLL_BARS (f);
  2452.     bar->prev = Qnil;
  2453.     XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
  2454.     if (! NILP (bar->next))
  2455.       XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
  2456.   }
  2457. #endif
  2458. }
  2459.  
  2460. /* Remove all scroll bars on FRAME that haven't been saved since the
  2461.    last call to `*condemn_scroll_bars_hook'.  */
  2462. static void
  2463. w32_judge_scroll_bars (f)
  2464.      FRAME_PTR f;
  2465. {
  2466.   Lisp_Object bar, next;
  2467.  
  2468.   bar = FRAME_CONDEMNED_SCROLL_BARS (f);
  2469.  
  2470.   /* Clear out the condemned list now so we won't try to process any
  2471.      more events on the hapless scroll bars.  */
  2472.   FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
  2473.  
  2474.   for (; ! NILP (bar); bar = next)
  2475.     {
  2476.       struct scroll_bar *b = XSCROLL_BAR (bar);
  2477.  
  2478.       x_scroll_bar_remove (b);
  2479.  
  2480.       next = b->next;
  2481.       b->next = b->prev = Qnil;
  2482.     }
  2483.  
  2484.   /* Now there should be no references to the condemned scroll bars,
  2485.      and they should get garbage-collected.  */
  2486. #ifdef PIGSFLY
  2487.   Lisp_Object bar, next;
  2488.  
  2489.   bar = FRAME_CONDEMNED_SCROLL_BARS (f);
  2490.  
  2491.   /* Clear out the condemned list now so we won't try to process any
  2492.      more events on the hapless scroll bars.  */
  2493.   FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
  2494.  
  2495.   for (; ! NILP (bar); bar = next)
  2496.     {
  2497.       struct scroll_bar *b = XSCROLL_BAR (bar);
  2498.  
  2499.       x_scroll_bar_remove (b);
  2500.  
  2501.       next = b->next;
  2502.       b->next = b->prev = Qnil;
  2503.     }
  2504.  
  2505.   /* Now there should be no references to the condemned scroll bars,
  2506.      and they should get garbage-collected.  */
  2507. #endif
  2508. }
  2509.  
  2510. /* Handle a mouse click on the scroll bar BAR.  If *EMACS_EVENT's kind
  2511.    is set to something other than no_event, it is enqueued.
  2512.  
  2513.    This may be called from a signal handler, so we have to ignore GC
  2514.    mark bits.  */
  2515.  
  2516. static int
  2517. x_scroll_bar_handle_click (bar, msg, emacs_event)
  2518.      struct scroll_bar *bar;
  2519.      W32Msg *msg;
  2520.      struct input_event *emacs_event;
  2521. {
  2522.   if (! GC_WINDOWP (bar->window))
  2523.     abort ();
  2524.  
  2525.   emacs_event->kind = w32_scroll_bar_click;
  2526.   emacs_event->code = 0;
  2527.   /* not really meaningful to distinguish up/down */
  2528.   emacs_event->modifiers = msg->dwModifiers;
  2529.   emacs_event->frame_or_window = bar->window;
  2530.   emacs_event->timestamp = msg->msg.time;
  2531.  
  2532.   {
  2533.     int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
  2534.     int y;
  2535.     int dragging = !NILP (bar->dragging);
  2536.  
  2537.     if (pfnGetScrollInfo)
  2538.       {
  2539.     SCROLLINFO si;
  2540.  
  2541.     si.cbSize = sizeof (si);
  2542.     si.fMask = SIF_POS;
  2543.  
  2544.     pfnGetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
  2545.     y = si.nPos;
  2546.       }
  2547.     else
  2548.       y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
  2549.  
  2550.     bar->dragging = Qnil;
  2551.  
  2552.     switch (LOWORD (msg->msg.wParam))
  2553.       {
  2554.       case SB_LINEDOWN:
  2555.     emacs_event->part = scroll_bar_down_arrow;
  2556.     break;
  2557.       case SB_LINEUP:
  2558.     emacs_event->part = scroll_bar_up_arrow;
  2559.     break;
  2560.       case SB_PAGEUP:
  2561.     emacs_event->part = scroll_bar_above_handle;
  2562.     break;
  2563.       case SB_PAGEDOWN:
  2564.     emacs_event->part = scroll_bar_below_handle;
  2565.     break;
  2566.       case SB_TOP:
  2567.     emacs_event->part = scroll_bar_handle;
  2568.     y = 0;
  2569.     break;
  2570.       case SB_BOTTOM:
  2571.     emacs_event->part = scroll_bar_handle;
  2572.     y = top_range;
  2573.     break;
  2574.       case SB_THUMBTRACK:
  2575.       case SB_THUMBPOSITION:
  2576.     if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff)
  2577.         y = HIWORD (msg->msg.wParam);
  2578.     bar->dragging = Qt;
  2579.     emacs_event->part = scroll_bar_handle;
  2580.  
  2581.     /* "Silently" update current position.  */
  2582.     if (pfnSetScrollInfo)
  2583.       {
  2584.         SCROLLINFO si;
  2585.  
  2586.         si.cbSize = sizeof (si);
  2587.         si.fMask = SIF_POS;
  2588.  
  2589. #if 0
  2590.         /* Shrink handle if necessary to allow full range for position.  */
  2591.         {
  2592.           int start = XINT (bar->start);
  2593.           int end = XINT (bar->end);
  2594.           int len = end - start;
  2595.  
  2596.           /* If new end is nearly hitting bottom, we must shrink
  2597.              handle.  How much we shrink it depends on the relative
  2598.              sizes of len and top_range.  */
  2599.           if (y + len > top_range - 2)
  2600.         {
  2601.           len -= min (top_range / 10, (len / 3) + 2);
  2602.           if (len < 0)
  2603.             len = 0;
  2604.         }
  2605.           si.nPage = len + VERTICAL_SCROLL_BAR_MIN_HANDLE;
  2606.           si.fMask |= SIF_PAGE;
  2607.         }
  2608. #endif
  2609.         si.nPos = y;
  2610.         /* Remember apparent position (we actually lag behind the real
  2611.            position, so don't set that directly.  */
  2612.         last_scroll_bar_drag_pos = y;
  2613.  
  2614.         pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
  2615.       }
  2616.     else
  2617.       SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, FALSE);
  2618.     break;
  2619.       case SB_ENDSCROLL:
  2620.     /* If this is the end of a drag sequence, then reset the scroll
  2621.        handle size to normal and do a final redraw.  Otherwise do
  2622.        nothing.  */
  2623.     if (dragging)
  2624.       {
  2625.         if (pfnSetScrollInfo)
  2626.           {
  2627.         SCROLLINFO si;
  2628.         int start = XINT (bar->start);
  2629.         int end = XINT (bar->end);
  2630.  
  2631.         si.cbSize = sizeof (si);
  2632.         si.fMask = SIF_PAGE | SIF_POS;
  2633.         si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
  2634.         si.nPos = last_scroll_bar_drag_pos;
  2635.  
  2636.         pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
  2637.           }
  2638.         else
  2639.           SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE);
  2640.       }
  2641.     /* fall through */
  2642.       default:
  2643.     emacs_event->kind = no_event;
  2644.     return FALSE;
  2645.       }
  2646.  
  2647.     XSETINT (emacs_event->x, y);
  2648.     XSETINT (emacs_event->y, top_range);
  2649.  
  2650.     return TRUE;
  2651.   }
  2652. }
  2653.  
  2654. /* Return information to the user about the current position of the mouse
  2655.    on the scroll bar.  */
  2656. static void
  2657. x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
  2658.      FRAME_PTR *fp;
  2659.      Lisp_Object *bar_window;
  2660.      enum scroll_bar_part *part;
  2661.      Lisp_Object *x, *y;
  2662.      unsigned long *time;
  2663. {
  2664.   struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
  2665.   Window w = SCROLL_BAR_W32_WINDOW (bar);
  2666.   FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
  2667.   int pos;
  2668.   int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height));
  2669.  
  2670.   BLOCK_INPUT;
  2671.  
  2672.   *fp = f;
  2673.   *bar_window = bar->window;
  2674.  
  2675.   if (pfnGetScrollInfo)
  2676.     {
  2677.       SCROLLINFO si;
  2678.  
  2679.       si.cbSize = sizeof (si);
  2680.       si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
  2681.  
  2682.       pfnGetScrollInfo (w, SB_CTL, &si);
  2683.       pos = si.nPos;
  2684.       top_range = si.nMax - si.nPage + 1;
  2685.     }
  2686.   else
  2687.     pos = GetScrollPos (w, SB_CTL);
  2688.  
  2689.   switch (LOWORD (last_mouse_scroll_bar_pos))
  2690.   {
  2691.   case SB_THUMBPOSITION:
  2692.   case SB_THUMBTRACK:
  2693.       *part = scroll_bar_handle;
  2694.       if (VERTICAL_SCROLL_BAR_TOP_RANGE (XINT (bar->height)) <= 0xffff)
  2695.       pos = HIWORD (last_mouse_scroll_bar_pos);
  2696.       break;
  2697.   case SB_LINEDOWN:
  2698.       *part = scroll_bar_handle;
  2699.       pos++;
  2700.       break;
  2701.   default:
  2702.       *part = scroll_bar_handle;
  2703.       break;
  2704.   }
  2705.  
  2706.   XSETINT(*x, pos);
  2707.   XSETINT(*y, top_range);
  2708.  
  2709.   f->mouse_moved = 0;
  2710.   last_mouse_scroll_bar = Qnil;
  2711.  
  2712.   *time = last_mouse_movement_time;
  2713.  
  2714.   UNBLOCK_INPUT;
  2715. }
  2716.  
  2717. /* The screen has been cleared so we may have changed foreground or
  2718.    background colors, and the scroll bars may need to be redrawn.
  2719.    Clear out the scroll bars, and ask for expose events, so we can
  2720.    redraw them.  */
  2721.  
  2722. x_scroll_bar_clear (f)
  2723.      FRAME_PTR f;
  2724. {
  2725.   Lisp_Object bar;
  2726.  
  2727.   for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
  2728.        bar = XSCROLL_BAR (bar)->next)
  2729.     {
  2730.       HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
  2731.       HDC hdc = GetDC (window);
  2732.       RECT rect;
  2733.  
  2734.       /* Hide scroll bar until ready to repaint.  x_scroll_bar_move
  2735.          arranges to refresh the scroll bar if hidden.  */
  2736.       my_show_window (f, window, SW_HIDE);
  2737.  
  2738.       GetClientRect (window, &rect);
  2739.       select_palette (f, hdc);
  2740.       w32_clear_rect (f, hdc, &rect);
  2741.       deselect_palette (f, hdc);
  2742.  
  2743.       ReleaseDC (window, hdc);
  2744.     }
  2745. }
  2746.  
  2747. show_scroll_bars (f, how)
  2748.      FRAME_PTR f;
  2749.      int how;
  2750. {
  2751.   Lisp_Object bar;
  2752.  
  2753.   for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
  2754.        bar = XSCROLL_BAR (bar)->next)
  2755.     {
  2756.       HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
  2757.       my_show_window (f, window, how);
  2758.     }
  2759. }
  2760.  
  2761.  
  2762. /* The main W32 event-reading loop - w32_read_socket.  */
  2763.  
  2764. /* Timestamp of enter window event.  This is only used by w32_read_socket,
  2765.    but we have to put it out here, since static variables within functions
  2766.    sometimes don't work.  */
  2767. static Time enter_timestamp;
  2768.  
  2769. /* Record the last 100 characters stored
  2770.    to help debug the loss-of-chars-during-GC problem.  */
  2771. int temp_index;
  2772. short temp_buffer[100];
  2773.  
  2774. extern int key_event (KEY_EVENT_RECORD *, struct input_event *, int *isdead);
  2775.  
  2776. /* Map a W32 WM_CHAR message into a KEY_EVENT_RECORD so that
  2777.    we can use the same routines to handle input in both console
  2778.    and window modes.  */
  2779.  
  2780. static void
  2781. convert_to_key_event (W32Msg *msgp, KEY_EVENT_RECORD *eventp)
  2782. {
  2783.   eventp->bKeyDown = TRUE;
  2784.   eventp->wRepeatCount = 1;
  2785.   eventp->wVirtualKeyCode = msgp->msg.wParam;
  2786.   eventp->wVirtualScanCode = (msgp->msg.lParam & 0xFF0000) >> 16;
  2787.   eventp->uChar.AsciiChar = 0;
  2788.   eventp->dwControlKeyState = msgp->dwModifiers;
  2789. }
  2790.  
  2791. /* Return nonzero if the virtual key is a dead key.  */
  2792.  
  2793. static int
  2794. is_dead_key (int wparam)
  2795. {
  2796.   unsigned int code = MapVirtualKey (wparam, 2);
  2797.  
  2798.   /* Windows 95 returns 0x8000, NT returns 0x80000000.  */
  2799.   if ((code & 0x8000) || (code & 0x80000000))
  2800.     return 1;
  2801.   else
  2802.     return 0;
  2803. }
  2804.  
  2805. /* Read events coming from the W32 shell.
  2806.    This routine is called by the SIGIO handler.
  2807.    We return as soon as there are no more events to be read.
  2808.  
  2809.    Events representing keys are stored in buffer BUFP,
  2810.    which can hold up to NUMCHARS characters.
  2811.    We return the number of characters stored into the buffer,
  2812.    thus pretending to be `read'.
  2813.  
  2814.    EXPECTED is nonzero if the caller knows input is available.  
  2815.  
  2816.    Some of these messages are reposted back to the message queue since the
  2817.    system calls the windows proc directly in a context where we cannot return 
  2818.    the data nor can we guarantee the state we are in.  So if we dispatch  them
  2819.    we will get into an infinite loop.  To prevent this from ever happening we
  2820.    will set a variable to indicate we are in the read_socket call and indicate
  2821.    which message we are processing since the windows proc gets called 
  2822.    recursively with different messages by the system.
  2823. */
  2824.  
  2825. int
  2826. w32_read_socket (sd, bufp, numchars, expected)
  2827.      register int sd;
  2828.      register struct input_event *bufp;
  2829.      register int numchars;
  2830.      int expected;
  2831. {
  2832.   int count = 0;
  2833.   int check_visibility = 0;
  2834.   W32Msg msg;
  2835.   struct frame *f;
  2836.   Lisp_Object part;
  2837.   struct w32_display_info *dpyinfo = &one_w32_display_info;
  2838.  
  2839.   if (interrupt_input_blocked)
  2840.     {
  2841.       interrupt_input_pending = 1;
  2842.       return -1;
  2843.     }
  2844.  
  2845.   interrupt_input_pending = 0;
  2846.   BLOCK_INPUT;
  2847.  
  2848.   /* So people can tell when we have read the available input.  */
  2849.   input_signal_count++;
  2850.  
  2851.   if (numchars <= 0)
  2852.     abort ();                   /* Don't think this happens. */
  2853.  
  2854.   while (get_next_msg (&msg, FALSE))
  2855.     {
  2856.       switch (msg.msg.message)
  2857.     {
  2858.     case WM_PAINT:
  2859.         f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
  2860.  
  2861.         if (f) 
  2862.           {
  2863.         if (msg.rect.right == msg.rect.left ||
  2864.             msg.rect.bottom == msg.rect.top)
  2865.           {
  2866.             /* We may get paint messages even though the client
  2867.                area is clipped - these are not expose events. */
  2868.             DebPrint (("clipped frame %04x (%s) got WM_PAINT\n", f,
  2869.                    XSTRING (f->name)->data));
  2870.           }
  2871.         else if (f->async_visible != 1)
  2872.           {
  2873.             /* Definitely not obscured, so mark as visible.  */
  2874.             f->async_visible = 1;
  2875.             f->async_iconified = 0;
  2876.             SET_FRAME_GARBAGED (f);
  2877.             DebPrint (("frame %04x (%s) reexposed\n", f,
  2878.                    XSTRING (f->name)->data));
  2879.  
  2880.             /* WM_PAINT serves as MapNotify as well, so report
  2881.                        visibility changes properly.  */
  2882.             if (f->iconified)
  2883.               {
  2884.             bufp->kind = deiconify_event;
  2885.             XSETFRAME (bufp->frame_or_window, f);
  2886.             bufp++;
  2887.             count++;
  2888.             numchars--;
  2889.               }
  2890.             else if (! NILP(Vframe_list)
  2891.                  && ! NILP (XCONS (Vframe_list)->cdr))
  2892.               /* Force a redisplay sooner or later to update the
  2893.              frame titles in case this is the second frame.  */
  2894.               record_asynch_buffer_change ();
  2895.           }
  2896.         else
  2897.           {
  2898.             /* Erase background again for safety.  */
  2899.             w32_clear_rect (f, NULL, &msg.rect);
  2900.             dumprectangle (f,
  2901.                    msg.rect.left,
  2902.                    msg.rect.top,
  2903.                    msg.rect.right - msg.rect.left,
  2904.                    msg.rect.bottom - msg.rect.top);
  2905.           }
  2906.           }
  2907.       break;
  2908.  
  2909.     case WM_KEYDOWN:
  2910.     case WM_SYSKEYDOWN:
  2911.       f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
  2912.       
  2913.       if (f && !f->iconified)
  2914.         {
  2915.           if (temp_index == sizeof temp_buffer / sizeof (short))
  2916.         temp_index = 0;
  2917.           temp_buffer[temp_index++] = msg.msg.wParam;
  2918.           bufp->kind = non_ascii_keystroke;
  2919.           bufp->code = msg.msg.wParam;
  2920.           bufp->modifiers = w32_kbd_mods_to_emacs (msg.dwModifiers,
  2921.                                                          msg.msg.wParam);
  2922.           XSETFRAME (bufp->frame_or_window, f);
  2923.           bufp->timestamp = msg.msg.time;
  2924.           bufp++;
  2925.           numchars--;
  2926.           count++;
  2927.         }
  2928.       break;
  2929.  
  2930.     case WM_SYSCHAR:
  2931.     case WM_CHAR:
  2932.       f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
  2933.       
  2934.       if (f && !f->iconified)
  2935.         {
  2936.           if (numchars > 1) 
  2937.         {
  2938.           int add;
  2939.           int isdead = 0;
  2940.           KEY_EVENT_RECORD key, *keyp = &key;
  2941.  
  2942.           if (temp_index == sizeof temp_buffer / sizeof (short))
  2943.             temp_index = 0;
  2944.           
  2945.           convert_to_key_event (&msg, keyp);
  2946.           add = key_event (keyp, bufp, &isdead);
  2947.           XSETFRAME (bufp->frame_or_window, f);
  2948.           if (add == -1)
  2949.             {
  2950.               /* The key pressed generated two characters, most likely
  2951.              an accent character and a key that could not be
  2952.              combined with it.  Prepend the message on the queue
  2953.              again to process the second character (which is
  2954.              being held internally in key_event), and process
  2955.              the first character now.  */
  2956.               prepend_msg (&msg);
  2957.               add = 1;
  2958.             }
  2959.  
  2960.           if (isdead)
  2961.             break;
  2962.  
  2963.           bufp += add;
  2964.           numchars -= add;
  2965.           count += add;
  2966.         } 
  2967.           else 
  2968.         {
  2969.           abort ();
  2970.         }
  2971.         }
  2972.       break;
  2973.  
  2974.     case WM_MOUSEMOVE:
  2975.       if (dpyinfo->grabbed && last_mouse_frame
  2976.           && FRAME_LIVE_P (last_mouse_frame))
  2977.         f = last_mouse_frame;
  2978.       else
  2979.         f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
  2980.       
  2981.       if (f)
  2982.         note_mouse_movement (f, &msg.msg);
  2983.       else
  2984.         clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
  2985.       
  2986.       break;
  2987.  
  2988.     case WM_LBUTTONDOWN:
  2989.     case WM_LBUTTONUP:
  2990.     case WM_MBUTTONDOWN:
  2991.     case WM_MBUTTONUP:
  2992.     case WM_RBUTTONDOWN:
  2993.     case WM_RBUTTONUP:
  2994.       {
  2995.         int button;
  2996.         int up;
  2997.         
  2998.         if (dpyinfo->grabbed && last_mouse_frame
  2999.         && FRAME_LIVE_P (last_mouse_frame))
  3000.           f = last_mouse_frame;
  3001.         else
  3002.           f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
  3003.         
  3004.         if (f)
  3005.           {
  3006.         if ((!dpyinfo->w32_focus_frame || f == dpyinfo->w32_focus_frame) 
  3007.             && (numchars >= 1))
  3008.           {
  3009.             construct_mouse_click (bufp, &msg, f);
  3010.             bufp++;
  3011.             count++;
  3012.             numchars--;
  3013.           }
  3014.           }
  3015.         
  3016.         parse_button (msg.msg.message, &button, &up);
  3017.         
  3018.         if (up)
  3019.           {
  3020.         dpyinfo->grabbed &= ~ (1 << button);
  3021.           }
  3022.         else
  3023.           {
  3024.         dpyinfo->grabbed |= (1 << button);
  3025.         last_mouse_frame = f;
  3026.           }
  3027.         break;
  3028.       }
  3029.       
  3030.       case WM_MOUSEWHEEL:
  3031.           if (dpyinfo->grabbed && last_mouse_frame
  3032.               && FRAME_LIVE_P (last_mouse_frame))
  3033.             f = last_mouse_frame;
  3034.           else
  3035.             f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
  3036.  
  3037.           if (f)
  3038.             {
  3039.               if ((!dpyinfo->w32_focus_frame 
  3040.                    || f == dpyinfo->w32_focus_frame)
  3041.                   && (numchars >= 1))
  3042.                 {
  3043.                   construct_mouse_wheel (bufp, &msg, f);
  3044.                   bufp++;
  3045.                   count++;
  3046.                   numchars--;
  3047.                 }
  3048.             }
  3049.       break;
  3050.  
  3051.     case WM_DROPFILES:
  3052.       f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
  3053.  
  3054.       if (f)
  3055.         {
  3056.           construct_drag_n_drop (bufp, &msg, f);
  3057.           bufp++;
  3058.           count++;
  3059.           numchars--;
  3060.         }
  3061.       break;
  3062.  
  3063.     case WM_VSCROLL:
  3064.       {
  3065.         struct scroll_bar *bar =
  3066.           x_window_to_scroll_bar ((HWND)msg.msg.lParam);
  3067.           
  3068.         if (bar && numchars >= 1)
  3069.           {
  3070.         if (x_scroll_bar_handle_click (bar, &msg, bufp))
  3071.           {
  3072.             bufp++;
  3073.             count++;
  3074.             numchars--;
  3075.           }
  3076.           }
  3077.         break;
  3078.       }
  3079.       
  3080.     case WM_WINDOWPOSCHANGED:
  3081.     case WM_ACTIVATE:
  3082.     case WM_ACTIVATEAPP:
  3083.       check_visibility = 1;
  3084.       break;
  3085.  
  3086.     case WM_MOVE:
  3087.       f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
  3088.       
  3089.       if (f && !f->async_iconified)
  3090.         {
  3091.           int x, y;
  3092.  
  3093.           x_real_positions (f, &x, &y);
  3094.           f->output_data.w32->left_pos = x;
  3095.           f->output_data.w32->top_pos = y;
  3096.         }
  3097.  
  3098.       check_visibility = 1;
  3099.       break;
  3100.  
  3101.     case WM_SHOWWINDOW:
  3102.       /* If window has been obscured or exposed by another window
  3103.          being maximised or minimised/restored, then recheck
  3104.          visibility of all frames.  Direct changes to our own
  3105.          windows get handled by WM_SIZE.  */
  3106. #if 0
  3107.       if (msg.msg.lParam != 0)
  3108.         check_visibility = 1;
  3109.       else
  3110.         {
  3111.           f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
  3112.           f->async_visible = msg.msg.wParam;
  3113.         }
  3114. #endif
  3115.  
  3116.       check_visibility = 1;
  3117.       break;
  3118.  
  3119.     case WM_SIZE:
  3120.       f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
  3121.       
  3122.       /* Inform lisp of whether frame has been iconified etc. */
  3123.       if (f)
  3124.         {
  3125.           switch (msg.msg.wParam)
  3126.         {
  3127.         case SIZE_MINIMIZED:
  3128.           f->async_visible = 0;
  3129.           f->async_iconified = 1;
  3130.           
  3131.           bufp->kind = iconify_event;
  3132.           XSETFRAME (bufp->frame_or_window, f);
  3133.           bufp++;
  3134.           count++;
  3135.           numchars--;
  3136.           break;
  3137.  
  3138.         case SIZE_MAXIMIZED:
  3139.         case SIZE_RESTORED:
  3140.           f->async_visible = 1;
  3141.           f->async_iconified = 0;
  3142.           
  3143.           /* wait_reading_process_input will notice this and update
  3144.              the frame's display structures.  */
  3145.           SET_FRAME_GARBAGED (f);
  3146.           
  3147.           if (f->iconified)
  3148.             {
  3149.               bufp->kind = deiconify_event;
  3150.               XSETFRAME (bufp->frame_or_window, f);
  3151.               bufp++;
  3152.               count++;
  3153.               numchars--;
  3154.             }
  3155.           else
  3156.             /* Force a redisplay sooner or later
  3157.                to update the frame titles
  3158.                in case this is the second frame.  */
  3159.             record_asynch_buffer_change ();
  3160.           break;
  3161.         }
  3162.         }
  3163.  
  3164.       if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
  3165.         {
  3166.           RECT rect;
  3167.           int rows;
  3168.           int columns;
  3169.           int width;
  3170.           int height;
  3171.           
  3172.           GetClientRect(msg.msg.hwnd, &rect);
  3173.           
  3174.           height = rect.bottom - rect.top;
  3175.           width = rect.right - rect.left;
  3176.           
  3177.           rows = PIXEL_TO_CHAR_HEIGHT (f, height);
  3178.           columns = PIXEL_TO_CHAR_WIDTH (f, width);
  3179.           
  3180.           /* TODO: Clip size to the screen dimensions.  */
  3181.           
  3182.           /* Even if the number of character rows and columns has
  3183.          not changed, the font size may have changed, so we need
  3184.          to check the pixel dimensions as well.  */
  3185.           
  3186.           if (columns != f->width
  3187.           || rows != f->height
  3188.           || width != f->output_data.w32->pixel_width
  3189.           || height != f->output_data.w32->pixel_height)
  3190.         {
  3191.           /* I had set this to 0, 0 - I am not sure why?? */
  3192.           
  3193.           change_frame_size (f, rows, columns, 0, 1);
  3194.           SET_FRAME_GARBAGED (f);
  3195.           
  3196.           f->output_data.w32->pixel_width = width;
  3197.           f->output_data.w32->pixel_height = height;
  3198.           f->output_data.w32->win_gravity = NorthWestGravity;
  3199.         }
  3200.         }
  3201.  
  3202.       check_visibility = 1;
  3203.       break;
  3204.  
  3205.     case WM_SETFOCUS:
  3206.     case WM_KILLFOCUS:
  3207.       f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
  3208.       
  3209.       if (msg.msg.message == WM_SETFOCUS)
  3210.         {
  3211.           x_new_focus_frame (dpyinfo, f);
  3212.         }
  3213.       else if (f == dpyinfo->w32_focus_frame)
  3214.         {
  3215.           x_new_focus_frame (dpyinfo, 0);
  3216.         }
  3217.  
  3218.       check_visibility = 1;
  3219.       break;
  3220.  
  3221.     case WM_CLOSE:
  3222.       f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
  3223.       
  3224.       if (f)
  3225.         {
  3226.           if (numchars == 0)
  3227.         abort ();
  3228.           
  3229.           bufp->kind = delete_window_event;
  3230.           XSETFRAME (bufp->frame_or_window, f);
  3231.           bufp++;
  3232.           count++;
  3233.           numchars--;
  3234.         }
  3235.       break;
  3236.  
  3237.     case WM_INITMENU:
  3238.       f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
  3239.       
  3240.       if (f)
  3241.         {
  3242.           if (numchars == 0)
  3243.         abort ();
  3244.       
  3245.           bufp->kind = menu_bar_activate_event;
  3246.           XSETFRAME (bufp->frame_or_window, f);
  3247.           bufp++;
  3248.           count++;
  3249.           numchars--;
  3250.         }
  3251.       break;
  3252.  
  3253.     case WM_COMMAND:
  3254.       f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
  3255.  
  3256.       if (f)
  3257.         {
  3258.           extern void menubar_selection_callback (FRAME_PTR f, void * client_data);
  3259.           menubar_selection_callback (f, (void *)msg.msg.wParam);
  3260.         }
  3261.  
  3262.       check_visibility = 1;
  3263.       break;
  3264.  
  3265.     case WM_DISPLAYCHANGE:
  3266.       f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
  3267.  
  3268.       if (f) 
  3269.         {
  3270.           dpyinfo->width = (short) LOWORD (msg.msg.lParam);
  3271.           dpyinfo->height = (short) HIWORD (msg.msg.lParam);
  3272.           dpyinfo->n_cbits = msg.msg.wParam;
  3273.           DebPrint (("display change: %d %d\n", dpyinfo->width,
  3274.              dpyinfo->height));
  3275.         }
  3276.       
  3277.       check_visibility = 1;
  3278.       break;
  3279.  
  3280.     default:
  3281.       /* Check for messages registered at runtime. */
  3282.       if (msg.msg.message == msh_mousewheel)
  3283.         {
  3284.           if (dpyinfo->grabbed && last_mouse_frame 
  3285.           && FRAME_LIVE_P (last_mouse_frame))
  3286.         f = last_mouse_frame;
  3287.           else
  3288.         f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
  3289.           
  3290.           if (f)
  3291.         {
  3292.           if ((!dpyinfo->w32_focus_frame 
  3293.                || f == dpyinfo->w32_focus_frame)
  3294.               && (numchars >= 1))
  3295.             {
  3296.               construct_mouse_wheel (bufp, &msg, f);
  3297.               bufp++;
  3298.               count++;
  3299.               numchars--;
  3300.             }
  3301.         }
  3302.         }
  3303.       break;
  3304.     }
  3305.     }
  3306.  
  3307.   /* If the focus was just given to an autoraising frame,
  3308.      raise it now.  */
  3309.   /* ??? This ought to be able to handle more than one such frame.  */
  3310.   if (pending_autoraise_frame)
  3311.     {
  3312.       x_raise_frame (pending_autoraise_frame);
  3313.       pending_autoraise_frame = 0;
  3314.     }
  3315.  
  3316.   /* Check which frames are still visisble, if we have enqueued any user
  3317.      events or been notified of events that may affect visibility.  We
  3318.      do this here because there doesn't seem to be any direct
  3319.      notification from Windows that the visibility of a window has
  3320.      changed (at least, not in all cases).  */
  3321.   if (count > 0 || check_visibility)
  3322.     {
  3323.       Lisp_Object tail, frame;
  3324.  
  3325.       FOR_EACH_FRAME (tail, frame)
  3326.     {
  3327.       FRAME_PTR f = XFRAME (frame);
  3328.       /* Check "visible" frames and mark each as obscured or not.
  3329.          Note that async_visible is nonzero for unobscured and
  3330.          obscured frames, but zero for hidden and iconified frames.  */
  3331.       if (FRAME_W32_P (f) && f->async_visible)
  3332.         {
  3333.           RECT clipbox;
  3334.           HDC  hdc = get_frame_dc (f);
  3335.           GetClipBox (hdc, &clipbox);
  3336.           release_frame_dc (f, hdc);
  3337.  
  3338.           if (clipbox.right == clipbox.left
  3339.           || clipbox.bottom == clipbox.top)
  3340.         {
  3341.           /* Frame has become completely obscured so mark as
  3342.              such (we do this by setting async_visible to 2 so
  3343.              that FRAME_VISIBLE_P is still true, but redisplay
  3344.              will skip it).  */
  3345.           f->async_visible = 2;
  3346.  
  3347.           if (!FRAME_OBSCURED_P (f))
  3348.             {
  3349.               DebPrint (("frame %04x (%s) obscured\n", f,
  3350.                  XSTRING (f->name)->data));
  3351.             }
  3352.         }
  3353.           else
  3354.         {
  3355.           /* Frame is not obscured, so mark it as such.  */
  3356.           f->async_visible = 1;
  3357.  
  3358.           if (FRAME_OBSCURED_P (f))
  3359.             {
  3360.               SET_FRAME_GARBAGED (f);
  3361.               DebPrint (("frame %04x (%s) reexposed\n", f,
  3362.                  XSTRING (f->name)->data));
  3363.  
  3364.               /* Force a redisplay sooner or later.  */
  3365.               record_asynch_buffer_change ();
  3366.             }
  3367.         }
  3368.         }
  3369.     }
  3370.     }
  3371.  
  3372.   UNBLOCK_INPUT;
  3373.   return count;
  3374. }
  3375.  
  3376. /* Drawing the cursor.  */
  3377.  
  3378.  
  3379. /* Draw a hollow box cursor.  Don't change the inside of the box.  */
  3380.  
  3381. static void
  3382. x_draw_box (f)
  3383.      struct frame *f;
  3384. {
  3385.   RECT rect;
  3386.   HBRUSH hb;
  3387.   HDC hdc;
  3388.   
  3389.   hdc = get_frame_dc (f);
  3390.   
  3391.   hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
  3392.   
  3393.   rect.left = CHAR_TO_PIXEL_COL (f, curs_x);
  3394.   rect.top  = CHAR_TO_PIXEL_ROW (f, curs_y);
  3395.   rect.right = rect.left + FONT_WIDTH (f->output_data.w32->font);
  3396.   rect.bottom = rect.top + f->output_data.w32->line_height;
  3397.  
  3398.   FrameRect (hdc, &rect, hb);
  3399.   DeleteObject (hb);
  3400.  
  3401.   release_frame_dc (f, hdc);
  3402. }
  3403.  
  3404. /* Clear the cursor of frame F to background color,
  3405.    and mark the cursor as not shown.
  3406.    This is used when the text where the cursor is
  3407.    is about to be rewritten.  */
  3408.  
  3409. static void
  3410. clear_cursor (f)
  3411.      struct frame *f;
  3412. {
  3413.   if (! FRAME_VISIBLE_P (f)
  3414.       || f->phys_cursor_x < 0)
  3415.     return;
  3416.  
  3417.   x_display_cursor (f, 0);
  3418.   f->phys_cursor_x = -1;
  3419. }
  3420.  
  3421. /* Redraw the glyph at ROW, COLUMN on frame F, in the style
  3422.    HIGHLIGHT.  HIGHLIGHT is as defined for dumpglyphs.  Return the
  3423.    glyph drawn.  */
  3424.  
  3425. static void
  3426. x_draw_single_glyph (f, row, column, glyph, highlight)
  3427.      struct frame *f;
  3428.      int row, column;
  3429.      GLYPH glyph;
  3430.      int highlight;
  3431. {
  3432.   dumpglyphs (f,
  3433.           CHAR_TO_PIXEL_COL (f, column),
  3434.           CHAR_TO_PIXEL_ROW (f, row),
  3435.           &glyph, 1, highlight, 0, NULL);
  3436. }
  3437.  
  3438. static void
  3439. x_display_bar_cursor (f, on)
  3440.      struct frame *f;
  3441.      int on;
  3442. {
  3443.   struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
  3444.  
  3445.   /* This is pointless on invisible frames, and dangerous on garbaged
  3446.      frames; in the latter case, the frame may be in the midst of
  3447.      changing its size, and curs_x and curs_y may be off the frame.  */
  3448.   if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
  3449.     return;
  3450.  
  3451.   if (! on && f->phys_cursor_x < 0)
  3452.     return;
  3453.  
  3454.   /* If there is anything wrong with the current cursor state, remove it.  */
  3455.   if (f->phys_cursor_x >= 0
  3456.       && (!on
  3457.       || f->phys_cursor_x != curs_x
  3458.       || f->phys_cursor_y != curs_y
  3459.       || f->output_data.w32->current_cursor != bar_cursor))
  3460.     {
  3461.       /* Erase the cursor by redrawing the character underneath it.  */
  3462.       x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
  3463.                f->phys_cursor_glyph,
  3464.                current_glyphs->highlight[f->phys_cursor_y]);
  3465.       f->phys_cursor_x = -1;
  3466.     }
  3467.  
  3468.   /* If we now need a cursor in the new place or in the new form, do it so.  */
  3469.   if (on
  3470.       && (f->phys_cursor_x < 0
  3471.       || (f->output_data.w32->current_cursor != bar_cursor)))
  3472.     {
  3473.       f->phys_cursor_glyph
  3474.     = ((current_glyphs->enable[curs_y]
  3475.         && curs_x < current_glyphs->used[curs_y])
  3476.        ? current_glyphs->glyphs[curs_y][curs_x]
  3477.        : SPACEGLYPH);
  3478.       w32_fill_area (f, NULL, f->output_data.w32->cursor_pixel,
  3479.                CHAR_TO_PIXEL_COL (f, curs_x),
  3480.                CHAR_TO_PIXEL_ROW (f, curs_y),
  3481.                max (f->output_data.w32->cursor_width, 1),
  3482.                f->output_data.w32->line_height);
  3483.  
  3484.       f->phys_cursor_x = curs_x;
  3485.       f->phys_cursor_y = curs_y;
  3486.  
  3487.       f->output_data.w32->current_cursor = bar_cursor;
  3488.     }
  3489. }
  3490.  
  3491.  
  3492. /* Turn the displayed cursor of frame F on or off according to ON.
  3493.    If ON is nonzero, where to put the cursor is specified
  3494.    by F->cursor_x and F->cursor_y.  */
  3495.  
  3496. static void
  3497. x_display_box_cursor (f, on)
  3498.      struct frame *f;
  3499.      int on;
  3500. {
  3501.   struct frame_glyphs *current_glyphs = FRAME_CURRENT_GLYPHS (f);
  3502.  
  3503.   /* This is pointless on invisible frames, and dangerous on garbaged
  3504.      frames; in the latter case, the frame may be in the midst of
  3505.      changing its size, and curs_x and curs_y may be off the frame.  */
  3506.   if (! FRAME_VISIBLE_P (f) || FRAME_GARBAGED_P (f))
  3507.     return;
  3508.  
  3509.   /* If cursor is off and we want it off, return quickly.  */
  3510.   if (!on && f->phys_cursor_x < 0)
  3511.     return;
  3512.  
  3513.   /* If cursor is currently being shown and we don't want it to be
  3514.      or it is in the wrong place,
  3515.      or we want a hollow box and it's not so, (pout!)
  3516.      erase it.  */
  3517.   if (f->phys_cursor_x >= 0
  3518.       && (!on
  3519.       || f->phys_cursor_x != curs_x
  3520.       || f->phys_cursor_y != curs_y
  3521.       || (f->output_data.w32->current_cursor != hollow_box_cursor
  3522.           && (f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame))))
  3523.     {
  3524.       int mouse_face_here = 0;
  3525.       struct frame_glyphs *active_glyphs = FRAME_CURRENT_GLYPHS (f);
  3526.  
  3527.       /* If the cursor is in the mouse face area, redisplay that when
  3528.      we clear the cursor.  */
  3529.       if (f == FRAME_W32_DISPLAY_INFO (f)->mouse_face_mouse_frame
  3530.       && (f->phys_cursor_y > FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
  3531.           || (f->phys_cursor_y == FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_row
  3532.           && f->phys_cursor_x >= FRAME_W32_DISPLAY_INFO (f)->mouse_face_beg_col))
  3533.       && (f->phys_cursor_y < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
  3534.           || (f->phys_cursor_y == FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_row
  3535.           && f->phys_cursor_x < FRAME_W32_DISPLAY_INFO (f)->mouse_face_end_col))
  3536.       /* Don't redraw the cursor's spot in mouse face
  3537.          if it is at the end of a line (on a newline).
  3538.          The cursor appears there, but mouse highlighting does not.  */
  3539.       && active_glyphs->used[f->phys_cursor_y] > f->phys_cursor_x)
  3540.     mouse_face_here = 1;
  3541.  
  3542.       /* If the font is not as tall as a whole line,
  3543.      we must explicitly clear the line's whole height.  */
  3544.       if (FONT_HEIGHT (f->output_data.w32->font) != f->output_data.w32->line_height)
  3545.     w32_clear_area (f, NULL,
  3546.               CHAR_TO_PIXEL_COL (f, f->phys_cursor_x),
  3547.               CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y),
  3548.               FONT_WIDTH (f->output_data.w32->font),
  3549.               f->output_data.w32->line_height);
  3550.       /* Erase the cursor by redrawing the character underneath it.  */
  3551.       x_draw_single_glyph (f, f->phys_cursor_y, f->phys_cursor_x,
  3552.                f->phys_cursor_glyph,
  3553.                (mouse_face_here
  3554.                 ? 3
  3555.                 : current_glyphs->highlight[f->phys_cursor_y]));
  3556.       f->phys_cursor_x = -1;
  3557.     }
  3558.  
  3559.   /* If we want to show a cursor,
  3560.      or we want a box cursor and it's not so,
  3561.      write it in the right place.  */
  3562.   if (on
  3563.       && (f->phys_cursor_x < 0
  3564.       || (f->output_data.w32->current_cursor != filled_box_cursor
  3565.           && f == FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)))
  3566.     {
  3567.       f->phys_cursor_glyph
  3568.     = ((current_glyphs->enable[curs_y]
  3569.         && curs_x < current_glyphs->used[curs_y])
  3570.        ? current_glyphs->glyphs[curs_y][curs_x]
  3571.        : SPACEGLYPH);
  3572.       if (f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)
  3573.     {
  3574.       x_draw_box (f);
  3575.       f->output_data.w32->current_cursor = hollow_box_cursor;
  3576.     }
  3577.       else
  3578.     {
  3579.       x_draw_single_glyph (f, curs_y, curs_x,
  3580.                    f->phys_cursor_glyph, 2);
  3581.       f->output_data.w32->current_cursor = filled_box_cursor;
  3582.     }
  3583.  
  3584.       f->phys_cursor_x = curs_x;
  3585.       f->phys_cursor_y = curs_y;
  3586.     }
  3587. }
  3588.  
  3589. /* Display the cursor on frame F, or clear it, according to ON.
  3590.    Use the position specified by curs_x and curs_y
  3591.    if we are doing an update of frame F now.
  3592.    Otherwise use the position in the FRAME_CURSOR_X and FRAME_CURSOR_Y fields
  3593.    of F.  */
  3594.  
  3595. x_display_cursor (f, on)
  3596.      struct frame *f;
  3597.      int on;
  3598. {
  3599.   BLOCK_INPUT;
  3600.  
  3601.   /* If we're not updating, then we want to use the current frame's
  3602.      cursor position, not our local idea of where the cursor ought to be.  */
  3603.   if (f != updating_frame)
  3604.     {
  3605.       curs_x = FRAME_CURSOR_X (f);
  3606.       curs_y = FRAME_CURSOR_Y (f);
  3607.     }
  3608.  
  3609.   if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
  3610.     x_display_box_cursor (f, on);
  3611.   else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
  3612.     x_display_bar_cursor (f, on);
  3613.   else
  3614.     /* Those are the only two we have implemented!  */
  3615.     abort ();
  3616.  
  3617.   UNBLOCK_INPUT;
  3618. }
  3619.  
  3620. /* Changing the font of the frame.  */
  3621.  
  3622. /* Give frame F the font named FONTNAME as its default font, and
  3623.    return the full name of that font.  FONTNAME may be a wildcard
  3624.    pattern; in that case, we choose some font that fits the pattern.
  3625.    The return value shows which font we chose.  */
  3626.  
  3627. Lisp_Object
  3628. x_new_font (f, fontname)
  3629.      struct frame *f;
  3630.      register char *fontname;
  3631. {
  3632.   int already_loaded;
  3633.   int n_matching_fonts;
  3634.   XFontStruct *font_info;
  3635.   char new_font_name[101];
  3636.  
  3637.   /* Get a font which matches this name */
  3638.   {
  3639.       LOGFONT lf;
  3640.  
  3641.       if (!x_to_w32_font(fontname, &lf)
  3642.       || !w32_to_x_font(&lf, new_font_name, 100))
  3643.       {
  3644.       return Qnil;
  3645.       }
  3646.   }
  3647.  
  3648.   /* See if we've already loaded a matching font. */
  3649.   already_loaded = -1;
  3650.  
  3651.   {
  3652.       int i;
  3653.  
  3654.       for (i = 0; i < FRAME_W32_DISPLAY_INFO (f)->n_fonts; i++)
  3655.       if (!strcmp (FRAME_W32_DISPLAY_INFO (f)->font_table[i].name, new_font_name))
  3656.       {
  3657.           already_loaded = i;
  3658.           fontname = FRAME_W32_DISPLAY_INFO (f)->font_table[i].name;
  3659.           break;
  3660.       }
  3661.   }
  3662.  
  3663.   /* If we have, just return it from the table.  */
  3664.   if (already_loaded >= 0)
  3665.     f->output_data.w32->font = FRAME_W32_DISPLAY_INFO (f)->font_table[already_loaded].font;
  3666.   /* Otherwise, load the font and add it to the table.  */
  3667.   else
  3668.     {
  3669.       XFontStruct *font;
  3670.       int n_fonts;
  3671.  
  3672.       font = w32_load_font(FRAME_W32_DISPLAY_INFO (f), fontname);
  3673.  
  3674.       if (! font)
  3675.     {
  3676.       return Qnil;
  3677.     }
  3678.  
  3679.       /* Do we need to create the table?  */
  3680.       if (FRAME_W32_DISPLAY_INFO (f)->font_table_size == 0)
  3681.     {
  3682.       FRAME_W32_DISPLAY_INFO (f)->font_table_size = 16;
  3683.       FRAME_W32_DISPLAY_INFO (f)->font_table
  3684.         = (struct font_info *) xmalloc (FRAME_W32_DISPLAY_INFO (f)->font_table_size
  3685.                         * sizeof (struct font_info));
  3686.     }
  3687.       /* Do we need to grow the table?  */
  3688.       else if (FRAME_W32_DISPLAY_INFO (f)->n_fonts
  3689.            >= FRAME_W32_DISPLAY_INFO (f)->font_table_size)
  3690.     {
  3691.       FRAME_W32_DISPLAY_INFO (f)->font_table_size *= 2;
  3692.       FRAME_W32_DISPLAY_INFO (f)->font_table
  3693.         = (struct font_info *) xrealloc (FRAME_W32_DISPLAY_INFO (f)->font_table,
  3694.                          (FRAME_W32_DISPLAY_INFO (f)->font_table_size
  3695.                           * sizeof (struct font_info)));
  3696.     }
  3697.  
  3698.       n_fonts = FRAME_W32_DISPLAY_INFO (f)->n_fonts;
  3699.       FRAME_W32_DISPLAY_INFO (f)->font_table[n_fonts].name = (char *) xmalloc (strlen (fontname) + 1);
  3700.       bcopy (fontname, FRAME_W32_DISPLAY_INFO (f)->font_table[n_fonts].name, strlen (fontname) + 1);
  3701.       f->output_data.w32->font = FRAME_W32_DISPLAY_INFO (f)->font_table[n_fonts].font = font;
  3702.       FRAME_W32_DISPLAY_INFO (f)->n_fonts++;
  3703.     }
  3704.  
  3705.   /* Compute the scroll bar width in character columns.  */
  3706.   if (f->scroll_bar_pixel_width > 0)
  3707.     {
  3708.       int wid = FONT_WIDTH (f->output_data.w32->font);
  3709.       f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
  3710.     }
  3711.   else
  3712.     f->scroll_bar_cols = 2;
  3713.  
  3714.   /* Now make the frame display the given font.  */
  3715.   if (FRAME_W32_WINDOW (f) != 0)
  3716.     {
  3717.       frame_update_line_height (f);
  3718.       x_set_window_size (f, 0, f->width, f->height);
  3719.     }
  3720.   else
  3721.     /* If we are setting a new frame's font for the first time,
  3722.        there are no faces yet, so this font's height is the line height.  */
  3723.     f->output_data.w32->line_height = FONT_HEIGHT (f->output_data.w32->font);
  3724.  
  3725.   {
  3726.     Lisp_Object lispy_name;
  3727.  
  3728.     lispy_name = build_string (fontname);
  3729.  
  3730.     return lispy_name;
  3731.   }
  3732. }
  3733.  
  3734. /* Calculate the absolute position in frame F
  3735.    from its current recorded position values and gravity.  */
  3736.  
  3737. x_calc_absolute_position (f)
  3738.      struct frame *f;
  3739. {
  3740.   Window win, child;
  3741.   POINT pt;
  3742.   int flags = f->output_data.w32->size_hint_flags;
  3743.  
  3744.   pt.x = pt.y = 0;
  3745.  
  3746.   /* Find the position of the outside upper-left corner of
  3747.      the inner window, with respect to the outer window.  */
  3748.   if (f->output_data.w32->parent_desc != FRAME_W32_DISPLAY_INFO (f)->root_window)
  3749.     {
  3750.       BLOCK_INPUT;
  3751.       MapWindowPoints (FRAME_W32_WINDOW (f),
  3752.                f->output_data.w32->parent_desc,
  3753.                &pt, 1);
  3754.       UNBLOCK_INPUT;
  3755.     }
  3756.  
  3757.   {
  3758.       RECT rt;
  3759.       rt.left = rt.right = rt.top = rt.bottom = 0;
  3760.       
  3761.       BLOCK_INPUT;
  3762.       AdjustWindowRect(&rt, f->output_data.w32->dwStyle,
  3763.                FRAME_EXTERNAL_MENU_BAR (f));
  3764.       UNBLOCK_INPUT;
  3765.  
  3766.       pt.x += (rt.right - rt.left);
  3767.       pt.y += (rt.bottom - rt.top);
  3768.   }
  3769.  
  3770.   /* Treat negative positions as relative to the leftmost bottommost
  3771.      position that fits on the screen.  */
  3772.   if (flags & XNegative)
  3773.     f->output_data.w32->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
  3774.                   - 2 * f->output_data.w32->border_width - pt.x
  3775.                   - PIXEL_WIDTH (f)
  3776.                   + f->output_data.w32->left_pos);
  3777.  
  3778.   if (flags & YNegative)
  3779.     f->output_data.w32->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
  3780.                  - 2 * f->output_data.w32->border_width - pt.y
  3781.                  - PIXEL_HEIGHT (f)
  3782.                  + f->output_data.w32->top_pos);
  3783.   /* The left_pos and top_pos
  3784.      are now relative to the top and left screen edges,
  3785.      so the flags should correspond.  */
  3786.   f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
  3787. }
  3788.  
  3789. /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
  3790.    to really change the position, and 0 when calling from
  3791.    x_make_frame_visible (in that case, XOFF and YOFF are the current
  3792.    position values).  It is -1 when calling from x_set_frame_parameters,
  3793.    which means, do adjust for borders but don't change the gravity.  */
  3794.  
  3795. x_set_offset (f, xoff, yoff, change_gravity)
  3796.      struct frame *f;
  3797.      register int xoff, yoff;
  3798.      int change_gravity;
  3799. {
  3800.   int modified_top, modified_left;
  3801.  
  3802.   if (change_gravity > 0)
  3803.     {
  3804.       f->output_data.w32->top_pos = yoff;
  3805.       f->output_data.w32->left_pos = xoff;
  3806.       f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
  3807.       if (xoff < 0)
  3808.     f->output_data.w32->size_hint_flags |= XNegative;
  3809.       if (yoff < 0)
  3810.     f->output_data.w32->size_hint_flags |= YNegative;
  3811.       f->output_data.w32->win_gravity = NorthWestGravity;
  3812.     }
  3813.   x_calc_absolute_position (f);
  3814.  
  3815.   BLOCK_INPUT;
  3816.   x_wm_set_size_hint (f, (long) 0, 0);
  3817.  
  3818.   /* It is a mystery why we need to add the border_width here
  3819.      when the frame is already visible, but experiment says we do.  */
  3820.   modified_left = f->output_data.w32->left_pos;
  3821.   modified_top = f->output_data.w32->top_pos;
  3822. #ifndef HAVE_NTGUI
  3823.   /* Do not add in border widths under W32.  */
  3824.   if (change_gravity != 0)
  3825.     {
  3826.       modified_left += f->output_data.w32->border_width;
  3827.       modified_top += f->output_data.w32->border_width;
  3828.     }
  3829. #endif
  3830.  
  3831.   my_set_window_pos (FRAME_W32_WINDOW (f),
  3832.              NULL,
  3833.              modified_left, modified_top,
  3834.              0,0,
  3835.              SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
  3836.   UNBLOCK_INPUT;
  3837. }
  3838.  
  3839. /* Call this to change the size of frame F's x-window.
  3840.    If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
  3841.    for this size change and subsequent size changes.
  3842.    Otherwise we leave the window gravity unchanged.  */
  3843.  
  3844. x_set_window_size (f, change_gravity, cols, rows)
  3845.      struct frame *f;
  3846.      int change_gravity;
  3847.      int cols, rows;
  3848. {
  3849.   int pixelwidth, pixelheight;
  3850.   Lisp_Object window;
  3851.   struct w32_display_info *dpyinfo = &one_w32_display_info;
  3852.   
  3853.   BLOCK_INPUT;
  3854.   
  3855.   check_frame_size (f, &rows, &cols);
  3856.   f->output_data.w32->vertical_scroll_bar_extra
  3857.     = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
  3858.        ? 0
  3859.        : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
  3860.        ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
  3861.        : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
  3862.   pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
  3863.   pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
  3864.   
  3865.   f->output_data.w32->win_gravity = NorthWestGravity;
  3866.   x_wm_set_size_hint (f, (long) 0, 0);
  3867.   
  3868.   {
  3869.     RECT rect;
  3870.  
  3871.     rect.left = rect.top = 0;
  3872.     rect.right = pixelwidth;
  3873.     rect.bottom = pixelheight;
  3874.       
  3875.     AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
  3876.              FRAME_EXTERNAL_MENU_BAR (f));
  3877.       
  3878.     my_set_window_pos (FRAME_W32_WINDOW (f),
  3879.                NULL, 
  3880.                0, 0,
  3881.                rect.right - rect.left,
  3882.                rect.bottom - rect.top,
  3883.                SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
  3884.   }
  3885.   
  3886.   /* Now, strictly speaking, we can't be sure that this is accurate,
  3887.      but the window manager will get around to dealing with the size
  3888.      change request eventually, and we'll hear how it went when the
  3889.      ConfigureNotify event gets here.
  3890.      
  3891.      We could just not bother storing any of this information here,
  3892.      and let the ConfigureNotify event set everything up, but that
  3893.      might be kind of confusing to the lisp code, since size changes
  3894.      wouldn't be reported in the frame parameters until some random
  3895.      point in the future when the ConfigureNotify event arrives.  */
  3896.   change_frame_size (f, rows, cols, 0, 0);
  3897.   PIXEL_WIDTH (f) = pixelwidth;
  3898.   PIXEL_HEIGHT (f) = pixelheight;
  3899.  
  3900.   /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
  3901.      receive in the ConfigureNotify event; if we get what we asked
  3902.      for, then the event won't cause the screen to become garbaged, so
  3903.      we have to make sure to do it here.  */
  3904.   SET_FRAME_GARBAGED (f);
  3905.  
  3906.   /* If cursor was outside the new size, mark it as off.  */
  3907.   if (f->phys_cursor_y >= rows
  3908.       || f->phys_cursor_x >= cols)
  3909.     {
  3910.       f->phys_cursor_x = -1;
  3911.       f->phys_cursor_y = -1;
  3912.     }
  3913.  
  3914.   /* Clear out any recollection of where the mouse highlighting was,
  3915.      since it might be in a place that's outside the new frame size. 
  3916.      Actually checking whether it is outside is a pain in the neck,
  3917.      so don't try--just let the highlighting be done afresh with new size.  */
  3918.   window = dpyinfo->mouse_face_window;
  3919.   if (! NILP (window) && XFRAME (window) == f)
  3920.     {
  3921.       dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
  3922.       dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
  3923.       dpyinfo->mouse_face_window = Qnil;
  3924.     }
  3925.   
  3926.   UNBLOCK_INPUT;
  3927. }
  3928.  
  3929. /* Mouse warping.  */
  3930.  
  3931. void
  3932. x_set_mouse_pixel_position (f, pix_x, pix_y)
  3933.      struct frame *f;
  3934.      int pix_x, pix_y;
  3935. {
  3936.   RECT rect;
  3937.   POINT pt;
  3938.  
  3939.   BLOCK_INPUT;
  3940.  
  3941.   GetClientRect (FRAME_W32_WINDOW (f), &rect);
  3942.   pt.x = rect.left + pix_x;
  3943.   pt.y = rect.top + pix_y;
  3944.   ClientToScreen (FRAME_W32_WINDOW (f), &pt);
  3945.  
  3946.   SetCursorPos (pt.x, pt.y);
  3947.  
  3948.   UNBLOCK_INPUT;
  3949. }
  3950.  
  3951. void
  3952. x_set_mouse_position (f, x, y)
  3953.      struct frame *f;
  3954.      int x, y;
  3955. {
  3956.   int pix_x, pix_y;
  3957.  
  3958.   pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH  (f->output_data.w32->font) / 2;
  3959.   pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.w32->line_height / 2;
  3960.  
  3961.   if (pix_x < 0) pix_x = 0;
  3962.   if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
  3963.  
  3964.   if (pix_y < 0) pix_y = 0;
  3965.   if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
  3966.  
  3967.   x_set_mouse_pixel_position (f, pix_x, pix_y);
  3968. }
  3969.  
  3970. /* focus shifting, raising and lowering.  */
  3971.  
  3972. x_focus_on_frame (f)
  3973.      struct frame *f;
  3974. {
  3975.   struct w32_display_info *dpyinfo = &one_w32_display_info;
  3976.  
  3977.   /* Give input focus to frame.  */
  3978.   BLOCK_INPUT;
  3979. #if 0
  3980.   /* Try not to change its Z-order if possible.  */
  3981.   if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
  3982.     my_set_focus (f, FRAME_W32_WINDOW (f));
  3983.   else
  3984. #endif
  3985.     my_set_foreground_window (FRAME_W32_WINDOW (f));
  3986.   UNBLOCK_INPUT;
  3987. }
  3988.  
  3989. x_unfocus_frame (f)
  3990.      struct frame *f;
  3991. {
  3992. }
  3993.  
  3994. /* Raise frame F.  */
  3995.  
  3996. x_raise_frame (f)
  3997.      struct frame *f;
  3998. {
  3999.   BLOCK_INPUT;
  4000.  
  4001.   /* Strictly speaking, raise-frame should only change the frame's Z
  4002.      order, leaving input focus unchanged.  This is reasonable behaviour
  4003.      on X where the usual policy is point-to-focus.  However, this
  4004.      behaviour would be very odd on Windows where the usual policy is
  4005.      click-to-focus.
  4006.  
  4007.      On X, if the mouse happens to be over the raised frame, it gets
  4008.      input focus anyway (so the window with focus will never be
  4009.      completely obscured) - if not, then just moving the mouse over it
  4010.      is sufficient to give it focus.  On Windows, the user must actually
  4011.      click on the frame (preferrably the title bar so as not to move
  4012.      point), which is more awkward.  Also, no other Windows program
  4013.      raises a window to the top but leaves another window (possibly now
  4014.      completely obscured) with input focus.
  4015.  
  4016.      Because there is a system setting on Windows that allows the user
  4017.      to choose the point to focus policy, we make the strict semantics
  4018.      optional, but by default we grab focus when raising.  */
  4019.  
  4020.   if (NILP (Vw32_grab_focus_on_raise))
  4021.     {
  4022.       /* The obvious call to my_set_window_pos doesn't work if Emacs is
  4023.      not already the foreground application: the frame is raised
  4024.      above all other frames belonging to us, but not above the
  4025.      current top window.  To achieve that, we have to resort to this
  4026.      more cumbersome method.  */
  4027.  
  4028.       HDWP handle = BeginDeferWindowPos (2);
  4029.       if (handle)
  4030.     {
  4031.       DeferWindowPos (handle,
  4032.               FRAME_W32_WINDOW (f),
  4033.                 HWND_TOP,
  4034.                 0, 0, 0, 0,
  4035.                 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  4036.  
  4037.       DeferWindowPos (handle,
  4038.               GetForegroundWindow (),
  4039.               FRAME_W32_WINDOW (f),
  4040.               0, 0, 0, 0,
  4041.               SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  4042.  
  4043.       EndDeferWindowPos (handle);
  4044.     }
  4045.     }
  4046.   else
  4047.     {
  4048.       my_set_foreground_window (FRAME_W32_WINDOW (f));
  4049.     }
  4050.  
  4051.   UNBLOCK_INPUT;
  4052. }
  4053.  
  4054. /* Lower frame F.  */
  4055.  
  4056. x_lower_frame (f)
  4057.      struct frame *f;
  4058. {
  4059.   BLOCK_INPUT;
  4060.   my_set_window_pos (FRAME_W32_WINDOW (f),
  4061.              HWND_BOTTOM,
  4062.              0, 0, 0, 0,
  4063.              SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
  4064.   UNBLOCK_INPUT;
  4065. }
  4066.  
  4067. static void
  4068. w32_frame_raise_lower (f, raise)
  4069.      FRAME_PTR f;
  4070.      int raise;
  4071. {
  4072.   if (raise)
  4073.     x_raise_frame (f);
  4074.   else
  4075.     x_lower_frame (f);
  4076. }
  4077.  
  4078. /* Change of visibility.  */
  4079.  
  4080. /* This tries to wait until the frame is really visible.
  4081.    However, if the window manager asks the user where to position
  4082.    the frame, this will return before the user finishes doing that.
  4083.    The frame will not actually be visible at that time,
  4084.    but it will become visible later when the window manager
  4085.    finishes with it.  */
  4086.  
  4087. x_make_frame_visible (f)
  4088.      struct frame *f;
  4089. {
  4090.   BLOCK_INPUT;
  4091.  
  4092.   if (! FRAME_VISIBLE_P (f))
  4093.     {
  4094.       /* We test FRAME_GARBAGED_P here to make sure we don't
  4095.      call x_set_offset a second time
  4096.      if we get to x_make_frame_visible a second time
  4097.      before the window gets really visible.  */
  4098.       if (! FRAME_ICONIFIED_P (f)
  4099.       && ! f->output_data.w32->asked_for_visible)
  4100.     x_set_offset (f, f->output_data.w32->left_pos, f->output_data.w32->top_pos, 0);
  4101.  
  4102.       f->output_data.w32->asked_for_visible = 1;
  4103.  
  4104. //      my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);
  4105.       my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
  4106.     }
  4107.  
  4108.   /* Synchronize to ensure Emacs knows the frame is visible
  4109.      before we do anything else.  We do this loop with input not blocked
  4110.      so that incoming events are handled.  */
  4111.   {
  4112.     Lisp_Object frame;
  4113.     int count = input_signal_count;
  4114.  
  4115.     /* This must come after we set COUNT.  */
  4116.     UNBLOCK_INPUT;
  4117.  
  4118.     XSETFRAME (frame, f);
  4119.  
  4120.     while (1)
  4121.       {
  4122.     /* Once we have handled input events,
  4123.        we should have received the MapNotify if one is coming.
  4124.        So if we have not got it yet, stop looping.
  4125.        Some window managers make their own decisions
  4126.        about visibility.  */
  4127.     if (input_signal_count != count)
  4128.       break;
  4129.     /* Machines that do polling rather than SIGIO have been observed
  4130.        to go into a busy-wait here.  So we'll fake an alarm signal
  4131.        to let the handler know that there's something to be read.
  4132.        We used to raise a real alarm, but it seems that the handler
  4133.        isn't always enabled here.  This is probably a bug.  */
  4134.     if (input_polling_used ())
  4135.       {
  4136.         /* It could be confusing if a real alarm arrives while processing
  4137.            the fake one.  Turn it off and let the handler reset it.  */
  4138.         alarm (0);
  4139.         input_poll_signal (0);
  4140.       }
  4141.     /* Once we have handled input events,
  4142.        we should have received the MapNotify if one is coming.
  4143.        So if we have not got it yet, stop looping.
  4144.        Some window managers make their own decisions
  4145.        about visibility.  */
  4146.     if (input_signal_count != count)
  4147.       break;
  4148.       }
  4149.     FRAME_SAMPLE_VISIBILITY (f);
  4150.   }
  4151. }
  4152.  
  4153. /* Change from mapped state to withdrawn state. */
  4154.  
  4155. /* Make the frame visible (mapped and not iconified).  */
  4156.  
  4157. x_make_frame_invisible (f)
  4158.      struct frame *f;
  4159. {
  4160.   Window window;
  4161.   
  4162.   /* Don't keep the highlight on an invisible frame.  */
  4163.   if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
  4164.     FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
  4165.   
  4166.   BLOCK_INPUT;
  4167.   
  4168.   my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
  4169.   
  4170.   /* We can't distinguish this from iconification
  4171.      just by the event that we get from the server.
  4172.      So we can't win using the usual strategy of letting
  4173.      FRAME_SAMPLE_VISIBILITY set this.  So do it by hand,
  4174.      and synchronize with the server to make sure we agree.  */
  4175.   f->visible = 0;
  4176.   FRAME_ICONIFIED_P (f) = 0;
  4177.   f->async_visible = 0;
  4178.   f->async_iconified = 0;
  4179.   
  4180.   UNBLOCK_INPUT;
  4181. }
  4182.  
  4183. /* Change window state from mapped to iconified. */
  4184.  
  4185. void
  4186. x_iconify_frame (f)
  4187.      struct frame *f;
  4188. {
  4189.   int result;
  4190.  
  4191.   /* Don't keep the highlight on an invisible frame.  */
  4192.   if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
  4193.     FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
  4194.  
  4195.   if (f->async_iconified)
  4196.     return;
  4197.  
  4198.   BLOCK_INPUT;
  4199.  
  4200.   /* Simulate the user minimizing the frame.  */
  4201.   PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
  4202.  
  4203.   f->async_iconified = 1;
  4204.  
  4205.   UNBLOCK_INPUT;
  4206. }
  4207.  
  4208. /* Destroy the window of frame F.  */
  4209.  
  4210. x_destroy_window (f)
  4211.      struct frame *f;
  4212. {
  4213.   struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
  4214.  
  4215.   BLOCK_INPUT;
  4216.  
  4217.   my_destroy_window (f, FRAME_W32_WINDOW (f));
  4218.   free_frame_menubar (f);
  4219.   free_frame_faces (f);
  4220.  
  4221.   xfree (f->output_data.w32);
  4222.   f->output_data.w32 = 0;
  4223.   if (f == dpyinfo->w32_focus_frame)
  4224.     dpyinfo->w32_focus_frame = 0;
  4225.   if (f == dpyinfo->w32_focus_event_frame)
  4226.     dpyinfo->w32_focus_event_frame = 0;
  4227.   if (f == dpyinfo->w32_highlight_frame)
  4228.     dpyinfo->w32_highlight_frame = 0;
  4229.  
  4230.   dpyinfo->reference_count--;
  4231.  
  4232.   if (f == dpyinfo->mouse_face_mouse_frame)
  4233.     {
  4234.       dpyinfo->mouse_face_beg_row
  4235.     = dpyinfo->mouse_face_beg_col = -1;
  4236.       dpyinfo->mouse_face_end_row
  4237.     = dpyinfo->mouse_face_end_col = -1;
  4238.       dpyinfo->mouse_face_window = Qnil;
  4239.     }
  4240.  
  4241.   UNBLOCK_INPUT;
  4242. }
  4243.  
  4244. /* Setting window manager hints.  */
  4245.  
  4246. /* Set the normal size hints for the window manager, for frame F.
  4247.    FLAGS is the flags word to use--or 0 meaning preserve the flags
  4248.    that the window now has.
  4249.    If USER_POSITION is nonzero, we set the USPosition
  4250.    flag (this is useful when FLAGS is 0).  */
  4251.  
  4252. x_wm_set_size_hint (f, flags, user_position)
  4253.      struct frame *f;
  4254.      long flags;
  4255.      int user_position;
  4256. {
  4257.   Window window = FRAME_W32_WINDOW (f);
  4258.  
  4259.   flexlines = f->height;
  4260.  
  4261.   enter_crit ();
  4262.  
  4263.   SetWindowLong (window, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font));
  4264.   SetWindowLong (window, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height);
  4265.   SetWindowLong (window, WND_BORDER_INDEX, f->output_data.w32->internal_border_width);
  4266.   SetWindowLong (window, WND_SCROLLBAR_INDEX, f->output_data.w32->vertical_scroll_bar_extra);
  4267.  
  4268.   leave_crit ();
  4269. }
  4270.  
  4271. /* Window manager things */
  4272. x_wm_set_icon_position (f, icon_x, icon_y)
  4273.      struct frame *f;
  4274.      int icon_x, icon_y;
  4275. {
  4276. #if 0
  4277.   Window window = FRAME_W32_WINDOW (f);
  4278.  
  4279.   f->display.x->wm_hints.flags |= IconPositionHint;
  4280.   f->display.x->wm_hints.icon_x = icon_x;
  4281.   f->display.x->wm_hints.icon_y = icon_y;
  4282.  
  4283.   XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
  4284. #endif
  4285. }
  4286.  
  4287.  
  4288. /* Initialization.  */
  4289.  
  4290. #ifdef USE_X_TOOLKIT
  4291. static XrmOptionDescRec emacs_options[] = {
  4292.   {"-geometry", ".geometry", XrmoptionSepArg, NULL},
  4293.   {"-iconic",   ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
  4294.  
  4295.   {"-internal-border-width", "*EmacsScreen.internalBorderWidth",
  4296.      XrmoptionSepArg, NULL},
  4297.   {"-ib",       "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
  4298.  
  4299.   {"-T",        "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
  4300.   {"-wn",       "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
  4301.   {"-title",    "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
  4302.   {"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
  4303.   {"-in",       "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
  4304.   {"-mc",       "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
  4305.   {"-cr",       "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
  4306. };
  4307. #endif /* USE_X_TOOLKIT */
  4308.  
  4309. static int w32_initialized = 0;
  4310.  
  4311. struct w32_display_info *
  4312. w32_term_init (display_name, xrm_option, resource_name)
  4313.      Lisp_Object display_name;
  4314.      char *xrm_option;
  4315.      char *resource_name;
  4316. {
  4317.   Lisp_Object frame;
  4318.   char *defaultvalue;
  4319.   struct w32_display_info *dpyinfo;
  4320.   HDC hdc;
  4321.   
  4322.   BLOCK_INPUT;
  4323.   
  4324.   if (!w32_initialized)
  4325.     {
  4326.       w32_initialize ();
  4327.       w32_initialized = 1;
  4328.     }
  4329.   
  4330.   {
  4331.     int argc = 0;
  4332.     char *argv[3];
  4333.  
  4334.     argv[0] = "";
  4335.     argc = 1;
  4336.     if (xrm_option)
  4337.       {
  4338.     argv[argc++] = "-xrm";
  4339.     argv[argc++] = xrm_option;
  4340.       }
  4341.   }
  4342.   
  4343.   dpyinfo = &one_w32_display_info;
  4344.   
  4345.   /* Put this display on the chain.  */
  4346.   dpyinfo->next = NULL;
  4347.   
  4348.   /* Put it on w32_display_name_list as well, to keep them parallel.  */ 
  4349.   w32_display_name_list = Fcons (Fcons (display_name, Qnil),
  4350.                    w32_display_name_list);
  4351.   dpyinfo->name_list_element = XCONS (w32_display_name_list)->car;
  4352.   
  4353.   dpyinfo->w32_id_name
  4354.     = (char *) xmalloc (XSTRING (Vinvocation_name)->size
  4355.             + XSTRING (Vsystem_name)->size
  4356.             + 2);
  4357.   sprintf (dpyinfo->w32_id_name, "%s@%s",
  4358.        XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
  4359.  
  4360. #if 0
  4361.   xrdb = x_load_resources (dpyinfo->display, xrm_option,
  4362.                resource_name, EMACS_CLASS);
  4363.   
  4364.   /* Put the rdb where we can find it in a way that works on
  4365.      all versions.  */
  4366.   dpyinfo->xrdb = xrdb;
  4367. #endif
  4368.   hdc = GetDC (GetDesktopWindow ());
  4369.   
  4370.   dpyinfo->height = GetDeviceCaps (hdc, VERTRES);
  4371.   dpyinfo->width = GetDeviceCaps (hdc, HORZRES);
  4372.   dpyinfo->root_window = GetDesktopWindow ();
  4373.   dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
  4374.   dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
  4375.   dpyinfo->height_in = GetDeviceCaps (hdc, LOGPIXELSX);
  4376.   dpyinfo->width_in = GetDeviceCaps (hdc, LOGPIXELSY);
  4377.   dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
  4378.   dpyinfo->grabbed = 0;
  4379.   dpyinfo->reference_count = 0;
  4380.   dpyinfo->n_fonts = 0;
  4381.   dpyinfo->font_table_size = 0;
  4382.   dpyinfo->bitmaps = 0;
  4383.   dpyinfo->bitmaps_size = 0;
  4384.   dpyinfo->bitmaps_last = 0;
  4385.   dpyinfo->mouse_face_mouse_frame = 0;
  4386.   dpyinfo->mouse_face_deferred_gc = 0;
  4387.   dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
  4388.   dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
  4389.   dpyinfo->mouse_face_face_id = 0;
  4390.   dpyinfo->mouse_face_window = Qnil;
  4391.   dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
  4392.   dpyinfo->mouse_face_defer = 0;
  4393.   dpyinfo->w32_focus_frame = 0;
  4394.   dpyinfo->w32_focus_event_frame = 0;
  4395.   dpyinfo->w32_highlight_frame = 0;
  4396.   
  4397.   ReleaseDC (GetDesktopWindow (), hdc);
  4398.  
  4399.   /* Determine if there is a middle mouse button, to allow parse_button
  4400.      to decide whether right mouse events should be mouse-2 or
  4401.      mouse-3. */
  4402.   XSETINT (Vw32_num_mouse_buttons, GetSystemMetrics (SM_CMOUSEBUTTONS));
  4403.  
  4404.   /* initialise palette with white and black */
  4405.   {
  4406.     COLORREF color;
  4407.     defined_color (0, "white", &color, 1);
  4408.     defined_color (0, "black", &color, 1);
  4409.   }
  4410.  
  4411. #ifndef F_SETOWN_BUG
  4412. #ifdef F_SETOWN
  4413. #ifdef F_SETOWN_SOCK_NEG
  4414.   /* stdin is a socket here */
  4415.   fcntl (connection, F_SETOWN, -getpid ());
  4416. #else /* ! defined (F_SETOWN_SOCK_NEG) */
  4417.   fcntl (connection, F_SETOWN, getpid ());
  4418. #endif /* ! defined (F_SETOWN_SOCK_NEG) */
  4419. #endif /* ! defined (F_SETOWN) */
  4420. #endif /* F_SETOWN_BUG */
  4421.  
  4422. #ifdef SIGIO
  4423.   if (interrupt_input)
  4424.     init_sigio (connection);
  4425. #endif /* ! defined (SIGIO) */
  4426.  
  4427.   UNBLOCK_INPUT;
  4428.  
  4429.   return dpyinfo;
  4430. }
  4431.  
  4432. /* Get rid of display DPYINFO, assuming all frames are already gone.  */
  4433.  
  4434. void
  4435. x_delete_display (dpyinfo)
  4436.      struct w32_display_info *dpyinfo;
  4437. {
  4438.   /* Discard this display from w32_display_name_list and w32_display_list.
  4439.      We can't use Fdelq because that can quit.  */
  4440.   if (! NILP (w32_display_name_list)
  4441.       && EQ (XCONS (w32_display_name_list)->car, dpyinfo->name_list_element))
  4442.     w32_display_name_list = XCONS (w32_display_name_list)->cdr;
  4443.   else
  4444.     {
  4445.       Lisp_Object tail;
  4446.  
  4447.       tail = w32_display_name_list;
  4448.       while (CONSP (tail) && CONSP (XCONS (tail)->cdr))
  4449.     {
  4450.       if (EQ (XCONS (XCONS (tail)->cdr)->car,
  4451.           dpyinfo->name_list_element))
  4452.         {
  4453.           XCONS (tail)->cdr = XCONS (XCONS (tail)->cdr)->cdr;
  4454.           break;
  4455.         }
  4456.       tail = XCONS (tail)->cdr;
  4457.     }
  4458.     }
  4459.  
  4460.   /* free palette table */
  4461.   {
  4462.     struct w32_palette_entry * plist;
  4463.  
  4464.     plist = dpyinfo->color_list;
  4465.     while (plist)
  4466.     {
  4467.       struct w32_palette_entry * pentry = plist;
  4468.       plist = plist->next;
  4469.       xfree(pentry);
  4470.     }
  4471.     dpyinfo->color_list = NULL;
  4472.     if (dpyinfo->palette)
  4473.       DeleteObject(dpyinfo->palette);
  4474.   }
  4475.   xfree (dpyinfo->font_table);
  4476.   xfree (dpyinfo->w32_id_name);
  4477. }
  4478.  
  4479. /* Set up use of W32.  */
  4480.  
  4481. DWORD w32_msg_worker ();
  4482.  
  4483. w32_initialize ()
  4484. {
  4485.   /* MSVC does not type K&R functions with no arguments correctly, and
  4486.      so we must explicitly cast them.  */
  4487.   clear_frame_hook = (void (*)(void)) w32_clear_frame;
  4488.   clear_end_of_line_hook = w32_clear_end_of_line;
  4489.   ins_del_lines_hook = w32_ins_del_lines;
  4490.   change_line_highlight_hook = w32_change_line_highlight;
  4491.   insert_glyphs_hook = w32_insert_glyphs;
  4492.   write_glyphs_hook = w32_write_glyphs;
  4493.   delete_glyphs_hook = w32_delete_glyphs;
  4494.   ring_bell_hook = (void (*)(void)) w32_ring_bell;
  4495.   reset_terminal_modes_hook = (void (*)(void)) w32_reset_terminal_modes;
  4496.   set_terminal_modes_hook = (void (*)(void)) w32_set_terminal_modes;
  4497.   update_begin_hook = w32_update_begin;
  4498.   update_end_hook = w32_update_end;
  4499.   set_terminal_window_hook = w32_set_terminal_window;
  4500.   read_socket_hook = w32_read_socket;
  4501.   frame_up_to_date_hook = w32_frame_up_to_date;
  4502.   cursor_to_hook = w32_cursor_to;
  4503.   reassert_line_highlight_hook = w32_reassert_line_highlight;
  4504.   mouse_position_hook = w32_mouse_position;
  4505.   frame_rehighlight_hook = w32_frame_rehighlight;
  4506.   frame_raise_lower_hook = w32_frame_raise_lower;
  4507.   set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
  4508.   condemn_scroll_bars_hook = w32_condemn_scroll_bars;
  4509.   redeem_scroll_bar_hook = w32_redeem_scroll_bar;
  4510.   judge_scroll_bars_hook = w32_judge_scroll_bars;
  4511.  
  4512.   scroll_region_ok = 1;         /* we'll scroll partial frames */
  4513.   char_ins_del_ok = 0;          /* just as fast to write the line */
  4514.   line_ins_del_ok = 1;          /* we'll just blt 'em */
  4515.   fast_clear_end_of_line = 1;   /* X does this well */
  4516.   memory_below_frame = 0;       /* we don't remember what scrolls
  4517.                    off the bottom */
  4518.   baud_rate = 19200;
  4519.  
  4520.   /* Initialize input mode: interrupt_input off, no flow control, allow
  4521.      8 bit character input, standard quit char.  */
  4522.   Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
  4523.  
  4524.   /* Create the window thread - it will terminate itself or when the app terminates */
  4525.  
  4526.   init_crit ();
  4527.  
  4528.   dwMainThreadId = GetCurrentThreadId ();
  4529.   DuplicateHandle (GetCurrentProcess (), GetCurrentThread (), 
  4530.            GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
  4531.  
  4532.   /* Wait for thread to start */
  4533.  
  4534.   {
  4535.     MSG msg;
  4536.  
  4537.     PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
  4538.  
  4539.     hWindowsThread = CreateThread (NULL, 0, 
  4540.                    (LPTHREAD_START_ROUTINE) w32_msg_worker, 
  4541.                    0, 0, &dwWindowsThreadId);
  4542.  
  4543.     GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
  4544.   }
  4545.   
  4546.   /* It is desirable that mainThread should have the same notion of
  4547.      focus window and active window as windowsThread.  Unfortunately, the
  4548.      following call to AttachThreadInput, which should do precisely what
  4549.      we need, causes major problems when Emacs is linked as a console
  4550.      program.  Unfortunately, we have good reasons for doing that, so
  4551.      instead we need to send messages to windowsThread to make some API
  4552.      calls for us (ones that affect, or depend on, the active/focus
  4553.      window state.  */
  4554. #ifdef ATTACH_THREADS
  4555.   AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
  4556. #endif
  4557.  
  4558.   /* Dynamically link to optional system components. */
  4559.   {
  4560.     HANDLE user_lib = LoadLibrary ("user32.dll");
  4561.  
  4562. #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
  4563.  
  4564.     /* New proportional scroll bar functions. */
  4565.     LOAD_PROC( SetScrollInfo );
  4566.     LOAD_PROC( GetScrollInfo );
  4567.  
  4568. #undef LOAD_PROC
  4569.  
  4570.     FreeLibrary (user_lib);
  4571.  
  4572.     /* If using proportional scroll bars, ensure handle is at least 5 pixels;
  4573.        otherwise use the fixed height.  */
  4574.     vertical_scroll_bar_min_handle = (pfnSetScrollInfo != NULL) ? 5 :
  4575.       GetSystemMetrics (SM_CYVTHUMB);
  4576.  
  4577.     /* For either kind of scroll bar, take account of the arrows; these
  4578.        effectively form the border of the main scroll bar range.  */
  4579.     vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
  4580.       = GetSystemMetrics (SM_CYVSCROLL);
  4581.   }
  4582. }
  4583.  
  4584. void
  4585. syms_of_w32term ()
  4586. {
  4587.   staticpro (&w32_display_name_list);
  4588.   w32_display_name_list = Qnil;
  4589.  
  4590.   staticpro (&last_mouse_scroll_bar);
  4591.   last_mouse_scroll_bar = Qnil;
  4592.  
  4593.   staticpro (&Qvendor_specific_keysyms);
  4594.   Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
  4595.  
  4596.   DEFVAR_INT ("w32-num-mouse-buttons",
  4597.           &Vw32_num_mouse_buttons,
  4598.           "Number of physical mouse buttons.");
  4599.   Vw32_num_mouse_buttons = Qnil;
  4600.  
  4601.   DEFVAR_LISP ("w32-swap-mouse-buttons",
  4602.           &Vw32_swap_mouse_buttons,
  4603.           "Swap the mapping of middle and right mouse buttons.\n\
  4604. When nil, middle button is mouse-2 and right button is mouse-3.");
  4605.   Vw32_swap_mouse_buttons = Qnil;
  4606.  
  4607.   DEFVAR_LISP ("w32-grab-focus-on-raise",
  4608.            &Vw32_grab_focus_on_raise,
  4609.            "Raised frame grabs input focus.\n\
  4610. When t, `raise-frame' grabs input focus as well.  This fits well\n\
  4611. with the normal Windows click-to-focus policy, but might not be\n\
  4612. desirable when using a point-to-focus policy.");
  4613.   Vw32_grab_focus_on_raise = Qt;
  4614.  
  4615.   DEFVAR_LISP ("w32-capslock-is-shiftlock",
  4616.            &Vw32_capslock_is_shiftlock,
  4617.            "Apply CapsLock state to non character input keys.\n\
  4618. When nil, CapsLock only affects normal character input keys.");
  4619.   Vw32_capslock_is_shiftlock = Qnil;
  4620.  
  4621.   DEFVAR_LISP ("w32-recognize-altgr",
  4622.            &Vw32_recognize_altgr,
  4623.            "Recognize right-alt and left-ctrl as AltGr.\n\
  4624. When nil, the right-alt and left-ctrl key combination is\n\
  4625. interpreted normally."); 
  4626.   Vw32_recognize_altgr = Qt;
  4627. }
  4628.