#include <config.h>
#include <signal.h>
#include <stdio.h>
#include "lisp.h"
#include "blockinput.h"
#include "syssignal.h"
#include "macterm.h"
#include <stdlib.h>
#include <string.h>
#include <alloca.h>
#include <Quickdraw.h>
#include <ToolUtils.h>
#include <Sound.h>
#include <Events.h>
#include <Script.h>
#include <Resources.h>
#include <Fonts.h>
#include <TextUtils.h>
#include <LowMem.h>
#include <Controls.h>
#if defined (__MRC__) || defined (CODEWARRIOR_VERSION_6)
#include <ControlDefinitions.h>
#endif
#if __profile__
#include <profiler.h>
#endif
#include <sys/types.h>
#include "systty.h"
#include "systime.h"
#ifndef INCLUDED_FCNTL
#include <fcntl.h>
#endif
#include <ctype.h>
#include <errno.h>
#include <setjmp.h>
#include <sys/stat.h>
#include "charset.h"
#include "ccl.h"
#include "frame.h"
#include "dispextern.h"
#include "fontset.h"
#include "termhooks.h"
#include "termopts.h"
#include "termchar.h"
#include "gnu.h"
#include "disptab.h"
#include "buffer.h"
#include "window.h"
#include "keyboard.h"
#include "intervals.h"
#include "process.h"
#include "atimer.h"
#include "coding.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifndef USE_X_TOOLKIT
#define x_any_window_to_frame x_window_to_frame
#define x_top_window_to_frame x_window_to_frame
#endif
#ifndef min
#define min(a,b) ((a) < (b) ? (a) : (b))
#endif
#ifndef max
#define max(a,b) ((a) > (b) ? (a) : (b))
#endif
#define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
enum bitmap_type
{
NO_BITMAP,
LEFT_TRUNCATION_BITMAP,
RIGHT_TRUNCATION_BITMAP,
OVERLAY_ARROW_BITMAP,
CONTINUED_LINE_BITMAP,
CONTINUATION_LINE_BITMAP,
ZV_LINE_BITMAP
};
#define zv_width 8
#define zv_height 8
static unsigned char zv_bits[] = {
0x00, 0x00, 0x78, 0x78, 0x78, 0x78, 0x00, 0x00};
#define left_width 8
#define left_height 8
static unsigned char left_bits[] = {
0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
#define right_width 8
#define right_height 8
static unsigned char right_bits[] = {
0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
#define continued_width 8
#define continued_height 8
static unsigned char continued_bits[] = {
0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
#define continuation_width 8
#define continuation_height 8
static unsigned char continuation_bits[] = {
0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
#if 0
#define ov_width 8
#define ov_height 8
static unsigned char ov_bits[] = {
0x0c, 0x10, 0x3c, 0x7e, 0x5e, 0x5e, 0x46, 0x3c};
#else
#define ov_width 8
#define ov_height 8
static unsigned char ov_bits[] = {
0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
#endif
extern Lisp_Object Qhelp_echo;
int x_toolkit_scroll_bars_p;
static Lisp_Object help_echo;
static Lisp_Object help_echo_window;
static Lisp_Object help_echo_object;
static int help_echo_pos;
static Lisp_Object previous_help_echo;
static int any_help_event_p;
int x_stretch_cursor_p;
struct x_display_info *x_display_list;
Lisp_Object x_display_name_list;
struct mac_display_info one_mac_display_info;
extern struct frame *updating_frame;
extern int waiting_for_input;
struct frame *pending_autoraise_frame;
struct cursor_pos output_cursor;
static int toolkit_scroll_bar_interaction;
FRAME_PTR last_mouse_frame;
static Rect last_mouse_glyph;
static Lisp_Object last_mouse_press_frame;
static Lisp_Object last_mouse_scroll_bar;
static Time last_mouse_movement_time;
enum mouse_tracking_type {
mouse_tracking_none,
mouse_tracking_mouse_movement,
mouse_tracking_scroll_bar
};
enum mouse_tracking_type mouse_tracking_in_progress = mouse_tracking_none;
struct scroll_bar *tracked_scroll_bar = NULL;
#ifdef __STDC__
static int volatile input_signal_count;
#else
static int input_signal_count;
#endif
static int x_noop_count;
extern char **initial_argv;
extern int initial_argc;
extern Lisp_Object Vcommand_line_args, Vsystem_name;
extern Lisp_Object Vx_no_window_manager;
extern Lisp_Object Qface, Qmouse_face;
extern int errno;
extern int extra_keyboard_modifiers;
static Lisp_Object Qvendor_specific_keysyms;
#if 0
extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
#endif
extern Lisp_Object x_icon_type P_ ((struct frame *));
#if __MRC__
QDGlobals qd;
#endif
enum draw_glyphs_face
{
DRAW_NORMAL_TEXT,
DRAW_INVERSE_VIDEO,
DRAW_CURSOR,
DRAW_MOUSE_FACE,
DRAW_IMAGE_RAISED,
DRAW_IMAGE_SUNKEN
};
struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
struct mac_display_info *mac_display_info_for_display (Display *);
static void x_update_window_end P_ ((struct window *, int, int));
static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
void x_delete_display P_ ((struct x_display_info *));
static unsigned int x_mac_to_emacs_modifiers P_ ((struct x_display_info *,
unsigned short));
static int fast_find_position P_ ((struct window *, int, int *, int *,
int *, int *));
static void set_output_cursor P_ ((struct cursor_pos *));
static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
int *, int *, int *));
static void note_mode_line_highlight P_ ((struct window *, int, int));
static void note_mouse_highlight P_ ((struct frame *, int, int));
static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
static void x_handle_tool_bar_click P_ ((struct frame *, XButtonEvent *));
static void show_mouse_face P_ ((struct x_display_info *,
enum draw_glyphs_face));
void clear_mouse_face P_ ((struct mac_display_info *));
static int x_io_error_quitter P_ ((Display *));
int x_catch_errors P_ ((Display *));
void x_uncatch_errors P_ ((Display *, int));
void x_lower_frame P_ ((struct frame *));
void x_scroll_bar_clear P_ ((struct frame *));
int x_had_errors_p P_ ((Display *));
void x_wm_set_size_hint P_ ((struct frame *, long, int));
void x_raise_frame P_ ((struct frame *));
void x_set_window_size P_ ((struct frame *, int, int, int));
void x_wm_set_window_state P_ ((struct frame *, int));
void x_wm_set_icon_pixmap P_ ((struct frame *, int));
void x_initialize P_ ((void));
static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
static int x_compute_min_glyph_bounds P_ ((struct frame *));
enum text_cursor_kinds x_specified_cursor_type P_ ((Lisp_Object, int *));
static void x_draw_phys_cursor_glyph P_ ((struct window *,
struct glyph_row *,
enum draw_glyphs_face));
static void x_update_end P_ ((struct frame *));
static void XTframe_up_to_date P_ ((struct frame *));
static void XTreassert_line_highlight P_ ((int, int));
static void x_change_line_highlight P_ ((int, int, int, int));
static void XTset_terminal_modes P_ ((void));
static void XTreset_terminal_modes P_ ((void));
static void XTcursor_to P_ ((int, int, int, int));
static void x_write_glyphs P_ ((struct glyph *, int));
static void x_clear_end_of_line P_ ((int));
static void x_clear_frame P_ ((void));
static void x_clear_cursor P_ ((struct window *));
static void frame_highlight P_ ((struct frame *));
static void frame_unhighlight P_ ((struct frame *));
static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
static void XTframe_rehighlight P_ ((struct frame *));
static void x_frame_rehighlight P_ ((struct x_display_info *));
static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
static int x_intersect_rectangles P_ ((Rect *, Rect *, Rect *));
static void expose_frame P_ ((struct frame *, int, int, int, int));
static void expose_window_tree P_ ((struct window *, Rect *));
static void expose_window P_ ((struct window *, Rect *));
static void expose_area P_ ((struct window *, struct glyph_row *,
XRectangle *, enum glyph_row_area));
static void expose_line P_ ((struct window *, struct glyph_row *,
XRectangle *));
void x_display_cursor (struct window *, int, int, int, int, int);
void x_update_cursor P_ ((struct frame *, int));
static void x_update_cursor_in_window_tree P_ ((struct window *, int));
static void x_update_window_cursor P_ ((struct window *, int));
static void x_erase_phys_cursor P_ ((struct window *));
void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
static void x_draw_bitmap P_ ((struct window *, struct glyph_row *,
enum bitmap_type));
static void x_clip_to_row P_ ((struct window *, struct glyph_row *,
GC, int));
static int x_phys_cursor_in_rect_p P_ ((struct window *, Rect *));
static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
static void note_overwritten_text_cursor P_ ((struct window *, int, int));
static void x_flush P_ ((struct frame *f));
static void x_update_begin P_ ((struct frame *));
static void x_update_window_begin P_ ((struct window *));
static void x_draw_vertical_border P_ ((struct window *));
static void x_after_update_window_line P_ ((struct glyph_row *));
static INLINE void take_vertical_position_into_account P_ ((struct it *));
static void x_produce_stretch_glyph P_ ((struct it *));
static void activate_scroll_bars (FRAME_PTR);
static void deactivate_scroll_bars (FRAME_PTR);
extern int image_ascent (struct image *, struct face *);
void x_set_offset (struct frame *, int, int, int);
int x_bitmap_icon (struct frame *, Lisp_Object);
void x_make_frame_visible (struct frame *);
extern void window_scroll (Lisp_Object, int, int, int);
extern void menubar_selection_callback (FRAME_PTR, int);
extern void set_frame_menubar (FRAME_PTR, int, int);
typedef struct {
unsigned char byte1;
unsigned char byte2;
} XChar2b;
static void
XFreePixmap (display, pixmap)
Display *display;
Pixmap pixmap;
{
PixMap *p = (PixMap *) pixmap;
xfree (p->baseAddr);
xfree (p);
}
static void
mac_set_forecolor (unsigned long color)
{
RGBColor fg_color;
fg_color.red = RED_FROM_ULONG (color) * 256;
fg_color.green = GREEN_FROM_ULONG (color) * 256;
fg_color.blue = BLUE_FROM_ULONG (color) * 256;
RGBForeColor (&fg_color);
}
static void
mac_set_backcolor (unsigned long color)
{
RGBColor bg_color;
bg_color.red = RED_FROM_ULONG (color) * 256;
bg_color.green = GREEN_FROM_ULONG (color) * 256;
bg_color.blue = BLUE_FROM_ULONG (color) * 256;
RGBBackColor (&bg_color);
}
static void
mac_set_colors (GC gc)
{
mac_set_forecolor (gc->foreground);
mac_set_backcolor (gc->background);
}
static void
XDrawLine (display, w, gc, x1, y1, x2, y2)
Display *display;
WindowPtr w;
GC gc;
int x1, y1, x2, y2;
{
SetPort (w);
mac_set_colors (gc);
MoveTo (x1, y1);
LineTo (x2, y2);
}
void
XClearArea (display, w, x, y, width, height, exposures)
Display *display;
WindowPtr w;
int x, y;
unsigned int width, height;
int exposures;
{
struct mac_output *mwp = (mac_output *) GetWRefCon (w);
Rect r;
XGCValues xgc;
xgc.foreground = mwp->foreground_pixel;
xgc.background = mwp->background_pixel;
SetPort (w);
mac_set_colors (&xgc);
SetRect (&r, x, y, x + width, y + height);
EraseRect (&r);
}
static void
XClearWindow (display, w)
Display *display;
WindowPtr w;
{
struct mac_output *mwp = (mac_output *) GetWRefCon (w);
XGCValues xgc;
xgc.foreground = mwp->foreground_pixel;
xgc.background = mwp->background_pixel;
SetPort (w);
mac_set_colors (&xgc);
EraseRect (&(w->portRect));
}
static void
mac_draw_bitmap (display, w, gc, x, y, bitmap)
Display *display;
WindowPtr w;
GC gc;
int x, y;
BitMap *bitmap;
{
Rect r;
SetPort (w);
mac_set_colors (gc);
SetRect (&r, x, y, x + bitmap->bounds.right, y + bitmap->bounds.bottom);
CopyBits (bitmap, &(w->portBits), &(bitmap->bounds), &r, srcCopy, 0);
}
static void
mac_set_clip_rectangle (display, w, r)
Display *display;
WindowPtr w;
Rect *r;
{
SetPort (w);
ClipRect (r);
}
static void
mac_reset_clipping (display, w)
Display *display;
WindowPtr w;
{
Rect r;
SetPort (w);
SetRect (&r, -32767, -32767, 32767, 32767);
ClipRect (&r);
}
static void
mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
BitMap *bitmap;
char *bits;
int w, h;
{
int bytes_per_row, i, j;
bitmap->rowBytes = (w + 15) / 16 * 2;
bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
if (!bitmap->baseAddr)
abort ();
bzero (bitmap->baseAddr, bitmap->rowBytes * h);
for (i = 0; i < h; i++)
for (j = 0; j < w; j++)
if (BitTst (bits, i * w + j))
BitSet (bitmap->baseAddr, i * bitmap->rowBytes * 8 + j);
SetRect (&(bitmap->bounds), 0, 0, w, h);
}
static void
mac_free_bitmap (bitmap)
BitMap *bitmap;
{
xfree (bitmap->baseAddr);
}
static void
XFillRectangle (display, w, gc, x, y, width, height)
Display *display;
WindowPtr w;
GC gc;
int x, y;
unsigned int width, height;
{
Rect r;
SetPort (w);
mac_set_colors (gc);
SetRect (&r, x, y, x + width, y + height);
PaintRect (&r);
}
static void
mac_draw_rectangle (display, w, gc, x, y, width, height)
Display *display;
WindowPtr w;
GC gc;
int x, y;
unsigned int width, height;
{
Rect r;
SetPort (w);
mac_set_colors (gc);
SetRect (&r, x, y, x + width + 1, y + height + 1);
FrameRect (&r);
}
static void
mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
Display *display;
Pixmap p;
GC gc;
int x, y;
unsigned int width, height;
{
#if 0
Rect r;
SetPort (w);
mac_set_colors (gc);
SetRect (&r, x, y, x + width, y + height);
FrameRect (&r);
#endif
}
static void
mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
bytes_per_char)
Display *display;
WindowPtr w;
GC gc;
int x, y;
char *buf;
int nchars, mode, bytes_per_char;
{
SetPort (w);
mac_set_colors (gc);
TextFont (gc->font->mac_fontnum);
TextSize (gc->font->mac_fontsize);
TextFace (gc->font->mac_fontface);
TextMode (mode);
MoveTo (x, y);
DrawText (buf, 0, nchars * bytes_per_char);
}
static void
XDrawString (display, w, gc, x, y, buf, nchars)
Display *display;
WindowPtr w;
GC gc;
int x, y;
char *buf;
int nchars;
{
mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
}
static void
XDrawString16 (display, w, gc, x, y, buf, nchars)
Display *display;
WindowPtr w;
GC gc;
int x, y;
XChar2b *buf;
int nchars;
{
mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
2);
}
static void
XDrawImageString (display, w, gc, x, y, buf, nchars)
Display *display;
WindowPtr w;
GC gc;
int x, y;
char *buf;
int nchars;
{
mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
}
static void
XDrawImageString16 (display, w, gc, x, y, buf, nchars)
Display *display;
WindowPtr w;
GC gc;
int x, y;
XChar2b *buf;
int nchars;
{
mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
2);
}
static void
mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
dest_y)
Display *display;
Pixmap src;
WindowPtr dest;
GC gc;
int src_x, src_y;
unsigned int width, height;
int dest_x, dest_y;
{
Rect src_r, dest_r;
SetPort (dest);
mac_set_colors (gc);
SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
CopyBits ((BitMap *) src, &(dest->portBits), &src_r, &dest_r, srcCopy, 0);
}
#if 0
static void
local_to_global_coord (short *h, short *v)
{
Point p;
p.h = *h;
p.v = *v;
LocalToGlobal (&p);
*h = p.h;
*v = p.v;
}
#endif
static void
mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
Display *display;
WindowPtr w;
GC gc;
int src_x, src_y;
unsigned int width, height;
int dest_x, dest_y;
{
Rect src_r, dest_r;
SetPort (w);
#if 0
mac_set_colors (gc);
#endif
SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
#if 0
local_to_global_coord (&src_r.left, &src_r.top);
local_to_global_coord (&src_r.right, &src_r.bottom);
local_to_global_coord (&dest_r.left, &dest_r.top);
local_to_global_coord (&dest_r.right, &dest_r.bottom);
CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
#else
ForeColor (blackColor);
BackColor (whiteColor);
CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
mac_set_colors (gc);
#endif
}
static void
mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
dest_x, dest_y)
Display *display;
Pixmap src;
Pixmap dest;
GC gc;
int src_x, src_y;
unsigned int width, height;
int dest_x, dest_y;
{
Rect src_r, dest_r;
int src_right = ((PixMap *) src)->bounds.right;
int src_bottom = ((PixMap *) src)->bounds.bottom;
int w = src_right - src_x;
int h = src_bottom - src_y;
mac_set_colors (gc);
SetRect (&src_r, src_x, src_y, src_right, src_bottom);
SetRect (&dest_r, dest_x, dest_y, dest_x + w, dest_y + h);
CopyBits ((BitMap *) src, (BitMap *) dest, &src_r, &dest_r, srcCopy, 0);
}
static void
XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
XGCValues *xgcv)
{
if (mask & GCForeground)
gc->foreground = xgcv->foreground;
if (mask & GCBackground)
gc->background = xgcv->background;
if (mask & GCFont)
gc->font = xgcv->font;
}
XGCValues *
XCreateGC (void * ignore, Window window, unsigned long mask,
XGCValues *xgcv)
{
XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
bzero (gc, sizeof (XGCValues));
XChangeGC (ignore, gc, mask, xgcv);
return gc;
}
void
XFreeGC (display, gc)
Display *display;
GC gc;
{
xfree (gc);
}
static void
XGetGCValues (void* ignore, XGCValues *gc,
unsigned long mask, XGCValues *xgcv)
{
XChangeGC (ignore, xgcv, mask, gc);
}
static void
XSetForeground (display, gc, color)
Display *display;
GC gc;
unsigned long color;
{
gc->foreground = color;
}
static void
XSetFont (display, gc, font)
Display *display;
GC gc;
XFontStruct *font;
{
gc->font = font;
}
static void
XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
int *direction,int *font_ascent,
int *font_descent, XCharStruct *cs)
{
}
void
x_sync (f)
void *f;
{
}
void
x_flush (f)
struct frame *f;
{
#if 0
BLOCK_INPUT;
if (f == NULL)
{
Lisp_Object rest, frame;
FOR_EACH_FRAME (rest, frame)
x_flush (XFRAME (frame));
}
else if (FRAME_X_P (f))
XFlush (FRAME_MAC_DISPLAY (f));
UNBLOCK_INPUT;
#endif
}
#define XFlush(DISPLAY) (void) 0
struct mac_display_info *
mac_display_info_for_display (dpy)
Display *dpy;
{
return &one_mac_display_info;
}
void
x_update_begin (f)
struct frame *f;
{
}
void
x_update_window_begin (w)
struct window *w;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
updated_window = w;
set_output_cursor (&w->cursor);
BLOCK_INPUT;
if (f == display_info->mouse_face_mouse_frame)
{
display_info->mouse_face_defer = 1;
if (FRAME_GARBAGED_P (f))
display_info->mouse_face_window = Qnil;
#if 0
if (!NILP (display_info->mouse_face_window)
&& w == XWINDOW (display_info->mouse_face_window))
{
int i;
for (i = 0; i < w->desired_matrix->nrows; ++i)
if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
break;
if (i < w->desired_matrix->nrows)
clear_mouse_face (display_info);
}
#endif
}
UNBLOCK_INPUT;
}
static void
x_draw_vertical_border (w)
struct window *w;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
if (!WINDOW_RIGHTMOST_P (w)
&& !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
{
int x0, x1, y0, y1;
window_box_edges (w, -1, &x0, &y0, &x1, &y1);
x1 += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
y1 -= 1;
XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
f->output_data.mac->normal_gc, x1, y0, x1, y1);
}
}
void
x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
struct window *w;
int cursor_on_p, mouse_face_overwritten_p;
{
if (!w->pseudo_window_p)
{
struct mac_display_info *dpyinfo
= FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
BLOCK_INPUT;
if (mouse_face_overwritten_p)
{
dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
dpyinfo->mouse_face_window = Qnil;
}
if (cursor_on_p)
x_display_and_set_cursor (w, 1, output_cursor.hpos,
output_cursor.vpos,
output_cursor.x, output_cursor.y);
x_draw_vertical_border (w);
UNBLOCK_INPUT;
}
updated_window = NULL;
}
void
x_update_end (f)
struct frame *f;
{
SetPort (FRAME_MAC_WINDOW (f));
mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
BLOCK_INPUT;
XFlush (FRAME_MAC_DISPLAY (f));
UNBLOCK_INPUT;
}
void
XTframe_up_to_date (f)
struct frame *f;
{
if (FRAME_X_P (f))
{
struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
if (dpyinfo->mouse_face_deferred_gc
|| f == dpyinfo->mouse_face_mouse_frame)
{
BLOCK_INPUT;
if (dpyinfo->mouse_face_mouse_frame)
note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
dpyinfo->mouse_face_mouse_x,
dpyinfo->mouse_face_mouse_y);
dpyinfo->mouse_face_deferred_gc = 0;
UNBLOCK_INPUT;
}
}
}
void
x_after_update_window_line (desired_row)
struct glyph_row *desired_row;
{
struct window *w = updated_window;
xassert (w);
if (!desired_row->mode_line_p && !w->pseudo_window_p)
{
BLOCK_INPUT;
x_draw_row_bitmaps (w, desired_row);
if (windows_or_buffers_changed)
{
struct frame *f = XFRAME (w->frame);
int width = FRAME_INTERNAL_BORDER_WIDTH (f);
int height = desired_row->visible_height;
int x = (window_box_right (w, -1)
+ FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
x, y, width, height, 0);
}
UNBLOCK_INPUT;
}
}
static void
x_draw_bitmap (w, row, which)
struct window *w;
struct glyph_row *row;
enum bitmap_type which;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
Display *display = FRAME_MAC_DISPLAY (f);
WindowPtr window = FRAME_MAC_WINDOW (f);
int x, y, wd, h, dy;
unsigned char *bits;
BitMap bitmap;
XGCValues gcv;
struct face *face;
x_clip_to_row (w, row, 1);
switch (which)
{
case LEFT_TRUNCATION_BITMAP:
wd = left_width;
h = left_height;
bits = left_bits;
x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
- wd
- (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
break;
case OVERLAY_ARROW_BITMAP:
wd = left_width;
h = left_height;
bits = ov_bits;
x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
- wd
- (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
break;
case RIGHT_TRUNCATION_BITMAP:
wd = right_width;
h = right_height;
bits = right_bits;
x = window_box_right (w, -1);
x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
break;
case CONTINUED_LINE_BITMAP:
wd = right_width;
h = right_height;
bits = continued_bits;
x = window_box_right (w, -1);
x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
break;
case CONTINUATION_LINE_BITMAP:
wd = continuation_width;
h = continuation_height;
bits = continuation_bits;
x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
- wd
- (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
break;
case ZV_LINE_BITMAP:
wd = zv_width;
h = zv_height;
bits = zv_bits;
x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
- wd
- (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
break;
default:
abort ();
}
y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
dy = (row->height - h) / 2;
face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
mac_create_bitmap_from_bitmap_data (&bitmap, bits, wd, h);
gcv.foreground = face->foreground;
gcv.background = face->background;
mac_draw_bitmap (display, window, &gcv, x, y + dy, &bitmap);
mac_free_bitmap (&bitmap);
mac_reset_clipping (display, window);
}
static void
x_draw_row_bitmaps (w, row)
struct window *w;
struct glyph_row *row;
{
struct frame *f = XFRAME (w->frame);
enum bitmap_type bitmap;
struct face *face;
int header_line_height = -1;
xassert (interrupt_input_blocked);
if (row->visible_height <= 0)
return;
face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
PREPARE_FACE_FOR_DISPLAY (f, face);
if (row->overlay_arrow_p)
bitmap = OVERLAY_ARROW_BITMAP;
else if (row->truncated_on_left_p)
bitmap = LEFT_TRUNCATION_BITMAP;
else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
bitmap = CONTINUATION_LINE_BITMAP;
else if (row->indicate_empty_line_p)
bitmap = ZV_LINE_BITMAP;
else
bitmap = NO_BITMAP;
if (bitmap == NO_BITMAP
|| FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
|| row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
{
int border = ((XFASTINT (w->left) > 0
&& !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
? 1 : 0);
int left = window_box_left (w, -1);
if (header_line_height < 0)
header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
#if 0
if (face->stipple)
XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
else
XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
face->gc,
(left
- FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
+ border),
WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
row->y)),
FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
row->visible_height);
if (!face->stipple)
XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
#endif
{
XGCValues gcv;
gcv.foreground = face->background;
XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
&gcv,
(left
- FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
+ border),
WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
row->y)),
FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
row->visible_height);
}
}
if (bitmap != NO_BITMAP)
x_draw_bitmap (w, row, bitmap);
if (row->truncated_on_right_p)
bitmap = RIGHT_TRUNCATION_BITMAP;
else if (row->continued_p)
bitmap = CONTINUED_LINE_BITMAP;
else
bitmap = NO_BITMAP;
if (bitmap == NO_BITMAP
|| FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
|| row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
{
int right = window_box_right (w, -1);
if (header_line_height < 0)
header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
#if 0
if (face->stipple)
XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
else
XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
face->gc,
right,
WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
row->y)),
FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
row->visible_height);
if (!face->stipple)
XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
#endif
{
XGCValues gcv;
gcv.foreground = face->background;
XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
&gcv,
right,
WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
row->y)),
FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
row->visible_height);
}
}
if (bitmap != NO_BITMAP)
x_draw_bitmap (w, row, bitmap);
}
void
XTreassert_line_highlight (new, vpos)
int new, vpos;
{
abort ();
}
void
x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
int new_highlight, vpos, y, first_unused_hpos;
{
abort ();
}
void
XTset_terminal_modes ()
{
}
void
XTreset_terminal_modes ()
{
}
static void
set_output_cursor (cursor)
struct cursor_pos *cursor;
{
output_cursor.hpos = cursor->hpos;
output_cursor.vpos = cursor->vpos;
output_cursor.x = cursor->x;
output_cursor.y = cursor->y;
}
void
XTcursor_to (vpos, hpos, y, x)
int vpos, hpos, y, x;
{
struct window *w;
if (updated_window)
w = updated_window;
else
w = XWINDOW (selected_window);
output_cursor.hpos = hpos;
output_cursor.vpos = vpos;
output_cursor.x = x;
output_cursor.y = y;
if (updated_window == NULL)
{
BLOCK_INPUT;
x_display_cursor (w, 1, hpos, vpos, x, y);
XFlush (FRAME_X_DISPLAY (SELECTED_FRAME ()));
UNBLOCK_INPUT;
}
}
static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
struct glyph *,
XChar2b *,
int *));
static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
int, XChar2b *, int));
static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
static void x_encode_char P_ ((int, XChar2b *, struct font_info *));
static void x_append_glyph P_ ((struct it *));
static void x_append_composite_glyph P_ ((struct it *));
static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
int, int, double));
static void x_produce_glyphs P_ ((struct it *));
static void x_produce_image_glyph P_ ((struct it *it));
#define PER_CHAR_METRIC(font, b) \
((font)->per_char \
? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
+ (((font)->min_byte1 || (font)->max_byte1) \
? (((b)->byte1 - (font)->min_byte1) \
* ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
: 0)) \
: &((font)->max_bounds))
static INLINE XCharStruct *
x_per_char_metric (font, char2b)
XFontStruct *font;
XChar2b *char2b;
{
XCharStruct *pcm = NULL;
xassert (font && char2b);
if (font->per_char != NULL)
{
if (font->min_byte1 == 0 && font->max_byte1 == 0)
{
if (char2b->byte1 == 0
&& char2b->byte2 >= font->min_char_or_byte2
&& char2b->byte2 <= font->max_char_or_byte2)
pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
}
else
{
if (char2b->byte1 >= font->min_byte1
&& char2b->byte1 <= font->max_byte1
&& char2b->byte2 >= font->min_char_or_byte2
&& char2b->byte2 <= font->max_char_or_byte2)
{
pcm = (font->per_char
+ ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
* (char2b->byte1 - font->min_byte1))
+ (char2b->byte2 - font->min_char_or_byte2));
}
}
}
else
{
if (char2b->byte2 >= font->min_char_or_byte2
&& char2b->byte2 <= font->max_char_or_byte2)
pcm = &font->max_bounds;
}
return ((pcm == NULL
|| (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
? NULL : pcm);
}
static INLINE void
x_encode_char (c, char2b, font_info)
int c;
XChar2b *char2b;
struct font_info *font_info;
{
int charset = CHAR_CHARSET (c);
XFontStruct *font = font_info->font;
if (font_info->font_encoder)
{
struct ccl_program *ccl = font_info->font_encoder;
if (CHARSET_DIMENSION (charset) == 1)
{
ccl->reg[0] = charset;
ccl->reg[1] = char2b->byte2;
}
else
{
ccl->reg[0] = charset;
ccl->reg[1] = char2b->byte1;
ccl->reg[2] = char2b->byte2;
}
ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
if (font->max_byte1 == 0)
char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
else
char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
}
else if (font_info->encoding[charset])
{
int enc = font_info->encoding[charset];
if ((enc == 1 || enc == 2)
&& CHARSET_DIMENSION (charset) == 2)
char2b->byte1 |= 0x80;
if (enc == 1 || enc == 3)
char2b->byte2 |= 0x80;
if (enc == 4)
{
int sjis1, sjis2;
ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
char2b->byte1 = sjis1;
char2b->byte2 = sjis2;
}
}
}
static INLINE struct face *
x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
struct frame *f;
int c, face_id;
XChar2b *char2b;
int multibyte_p;
{
struct face *face = FACE_FROM_ID (f, face_id);
if (!multibyte_p)
{
char2b->byte1 = 0;
char2b->byte2 = c;
face_id = FACE_FOR_CHAR (f, face, c);
face = FACE_FROM_ID (f, face_id);
}
else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
{
char2b->byte1 = 0;
char2b->byte2 = c;
}
else
{
int c1, c2, charset;
SPLIT_CHAR (c, charset, c1, c2);
if (c2 > 0)
char2b->byte1 = c1, char2b->byte2 = c2;
else
char2b->byte1 = 0, char2b->byte2 = c1;
if (face->font != NULL)
{
struct font_info *font_info
= FONT_INFO_FROM_ID (f, face->font_info_id);
if (font_info)
x_encode_char (c, char2b, font_info);
}
}
xassert (face != NULL);
PREPARE_FACE_FOR_DISPLAY (f, face);
return face;
}
static INLINE struct face *
x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
struct frame *f;
struct glyph *glyph;
XChar2b *char2b;
int *two_byte_p;
{
struct face *face;
xassert (glyph->type == CHAR_GLYPH);
face = FACE_FROM_ID (f, glyph->face_id);
if (two_byte_p)
*two_byte_p = 0;
if (!glyph->multibyte_p)
{
char2b->byte1 = 0;
char2b->byte2 = glyph->u.ch;
}
else if (glyph->u.ch < 128
&& glyph->face_id < BASIC_FACE_ID_SENTINEL)
{
char2b->byte1 = 0;
char2b->byte2 = glyph->u.ch;
}
else
{
int c1, c2, charset;
SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
if (c2 > 0)
char2b->byte1 = c1, char2b->byte2 = c2;
else
char2b->byte1 = 0, char2b->byte2 = c1;
if (charset != CHARSET_ASCII)
{
struct font_info *font_info
= FONT_INFO_FROM_ID (f, face->font_info_id);
if (font_info)
{
x_encode_char (glyph->u.ch, char2b, font_info);
if (two_byte_p)
*two_byte_p
= ((XFontStruct *) (font_info->font))->max_byte1 > 0;
}
}
}
xassert (face != NULL);
PREPARE_FACE_FOR_DISPLAY (f, face);
return face;
}
static INLINE void
x_append_glyph (it)
struct it *it;
{
struct glyph *glyph;
enum glyph_row_area area = it->area;
xassert (it->glyph_row);
xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
if (glyph < it->glyph_row->glyphs[area + 1])
{
glyph->charpos = CHARPOS (it->position);
glyph->object = it->object;
glyph->pixel_width = it->pixel_width;
glyph->voffset = it->voffset;
glyph->type = CHAR_GLYPH;
glyph->multibyte_p = it->multibyte_p;
glyph->left_box_line_p = it->start_of_box_run_p;
glyph->right_box_line_p = it->end_of_box_run_p;
glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
|| it->phys_descent > it->descent);
glyph->padding_p = 0;
glyph->glyph_not_available_p = it->glyph_not_available_p;
glyph->face_id = it->face_id;
glyph->u.ch = it->char_to_display;
++it->glyph_row->used[area];
}
}
static INLINE void
x_append_composite_glyph (it)
struct it *it;
{
struct glyph *glyph;
enum glyph_row_area area = it->area;
xassert (it->glyph_row);
glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
if (glyph < it->glyph_row->glyphs[area + 1])
{
glyph->charpos = CHARPOS (it->position);
glyph->object = it->object;
glyph->pixel_width = it->pixel_width;
glyph->voffset = it->voffset;
glyph->type = COMPOSITE_GLYPH;
glyph->multibyte_p = it->multibyte_p;
glyph->left_box_line_p = it->start_of_box_run_p;
glyph->right_box_line_p = it->end_of_box_run_p;
glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
|| it->phys_descent > it->descent);
glyph->padding_p = 0;
glyph->glyph_not_available_p = 0;
glyph->face_id = it->face_id;
glyph->u.cmp_id = it->cmp_id;
++it->glyph_row->used[area];
}
}
static INLINE void
take_vertical_position_into_account (it)
struct it *it;
{
if (it->voffset)
{
if (it->voffset < 0)
it->ascent += abs (it->voffset);
else
it->descent += it->voffset;
}
}
static void
x_produce_image_glyph (it)
struct it *it;
{
struct image *img;
struct face *face;
xassert (it->what == IT_IMAGE);
face = FACE_FROM_ID (it->f, it->face_id);
img = IMAGE_FROM_ID (it->f, it->image_id);
xassert (img);
PREPARE_FACE_FOR_DISPLAY (it->f, face);
prepare_image_for_display (it->f, img);
it->ascent = it->phys_ascent = image_ascent (img, face);
it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
it->pixel_width = img->width + 2 * img->hmargin;
it->nglyphs = 1;
if (face->box != FACE_NO_BOX)
{
it->ascent += face->box_line_width;
it->descent += face->box_line_width;
if (it->start_of_box_run_p)
it->pixel_width += face->box_line_width;
if (it->end_of_box_run_p)
it->pixel_width += face->box_line_width;
}
take_vertical_position_into_account (it);
if (it->glyph_row)
{
struct glyph *glyph;
enum glyph_row_area area = it->area;
glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
if (glyph < it->glyph_row->glyphs[area + 1])
{
glyph->charpos = CHARPOS (it->position);
glyph->object = it->object;
glyph->pixel_width = it->pixel_width;
glyph->voffset = it->voffset;
glyph->type = IMAGE_GLYPH;
glyph->multibyte_p = it->multibyte_p;
glyph->left_box_line_p = it->start_of_box_run_p;
glyph->right_box_line_p = it->end_of_box_run_p;
glyph->overlaps_vertically_p = 0;
glyph->padding_p = 0;
glyph->glyph_not_available_p = 0;
glyph->face_id = it->face_id;
glyph->u.img_id = img->id;
++it->glyph_row->used[area];
}
}
}
static void
x_append_stretch_glyph (it, object, width, height, ascent)
struct it *it;
Lisp_Object object;
int width, height;
double ascent;
{
struct glyph *glyph;
enum glyph_row_area area = it->area;
xassert (ascent >= 0 && ascent <= 1);
glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
if (glyph < it->glyph_row->glyphs[area + 1])
{
glyph->charpos = CHARPOS (it->position);
glyph->object = object;
glyph->pixel_width = width;
glyph->voffset = it->voffset;
glyph->type = STRETCH_GLYPH;
glyph->multibyte_p = it->multibyte_p;
glyph->left_box_line_p = it->start_of_box_run_p;
glyph->right_box_line_p = it->end_of_box_run_p;
glyph->overlaps_vertically_p = 0;
glyph->padding_p = 0;
glyph->glyph_not_available_p = 0;
glyph->face_id = it->face_id;
glyph->u.stretch.ascent = height * ascent;
glyph->u.stretch.height = height;
++it->glyph_row->used[area];
}
}
#define NUMVAL(X) \
((INTEGERP (X) || FLOATP (X)) \
? XFLOATINT (X) \
: - 1)
static void
x_produce_stretch_glyph (it)
struct it *it;
{
#if GLYPH_DEBUG
extern Lisp_Object Qspace;
#endif
extern Lisp_Object QCwidth, QCheight, QCascent;
extern Lisp_Object QCrelative_width, QCrelative_height;
extern Lisp_Object QCalign_to;
Lisp_Object prop, plist;
double width = 0, height = 0, ascent = 0;
struct face *face = FACE_FROM_ID (it->f, it->face_id);
XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
PREPARE_FACE_FOR_DISPLAY (it->f, face);
xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
plist = XCDR (it->object);
if (prop = Fplist_get (plist, QCwidth),
NUMVAL (prop) > 0)
width = NUMVAL (prop) * CANON_X_UNIT (it->f);
else if (prop = Fplist_get (plist, QCrelative_width),
NUMVAL (prop) > 0)
{
struct it it2;
unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
it2 = *it;
if (it->multibyte_p)
{
int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
- IT_BYTEPOS (*it));
it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
}
else
it2.c = *p, it2.len = 1;
it2.glyph_row = NULL;
it2.what = IT_CHARACTER;
x_produce_glyphs (&it2);
width = NUMVAL (prop) * it2.pixel_width;
}
else if (prop = Fplist_get (plist, QCalign_to),
NUMVAL (prop) > 0)
width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
else
width = CANON_X_UNIT (it->f);
if (prop = Fplist_get (plist, QCheight),
NUMVAL (prop) > 0)
height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
else if (prop = Fplist_get (plist, QCrelative_height),
NUMVAL (prop) > 0)
height = FONT_HEIGHT (font) * NUMVAL (prop);
else
height = FONT_HEIGHT (font);
if (prop = Fplist_get (plist, QCascent),
NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
ascent = NUMVAL (prop) / 100.0;
else
ascent = (double) font->ascent / FONT_HEIGHT (font);
if (width <= 0)
width = 1;
if (height <= 0)
height = 1;
if (it->glyph_row)
{
Lisp_Object object = it->stack[it->sp - 1].string;
if (!STRINGP (object))
object = it->w->buffer;
x_append_stretch_glyph (it, object, width, height, ascent);
}
it->pixel_width = width;
it->ascent = it->phys_ascent = height * ascent;
it->descent = it->phys_descent = height - it->ascent;
it->nglyphs = 1;
if (face->box != FACE_NO_BOX)
{
it->ascent += face->box_line_width;
it->descent += face->box_line_width;
if (it->start_of_box_run_p)
it->pixel_width += face->box_line_width;
if (it->end_of_box_run_p)
it->pixel_width += face->box_line_width;
}
take_vertical_position_into_account (it);
}
#define VCENTER_BASELINE_OFFSET(FONT, F) \
((FONT)->descent \
+ (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2 \
- ((F)->output_data.mac->font->descent - (F)->output_data.mac->baseline_offset))
void
x_produce_glyphs (it)
struct it *it;
{
it->glyph_not_available_p = 0;
if (it->what == IT_CHARACTER)
{
XChar2b char2b;
XFontStruct *font;
struct face *face = FACE_FROM_ID (it->f, it->face_id);
XCharStruct *pcm;
int font_not_found_p;
struct font_info *font_info;
int boff;
it->char_to_display = it->c;
if (!ASCII_BYTE_P (it->c))
{
if (unibyte_display_via_language_environment
&& SINGLE_BYTE_CHAR_P (it->c)
&& (it->c >= 0240
|| !NILP (Vnonascii_translation_table)))
{
it->char_to_display = unibyte_char_to_multibyte (it->c);
it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
face = FACE_FROM_ID (it->f, it->face_id);
}
else if (!SINGLE_BYTE_CHAR_P (it->c)
&& !it->multibyte_p)
{
it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
face = FACE_FROM_ID (it->f, it->face_id);
}
}
x_get_char_face_and_encoding (it->f, it->char_to_display,
it->face_id, &char2b,
it->multibyte_p);
font = face->font;
font_not_found_p = font == NULL;
if (font_not_found_p)
{
font = FRAME_FONT (it->f);
boff = it->f->output_data.mac->baseline_offset;
font_info = NULL;
}
else
{
font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
boff = font_info->baseline_offset;
if (font_info->vertical_centering)
boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
}
if (it->char_to_display >= ' '
&& (!it->multibyte_p || it->char_to_display < 128))
{
int stretched_p;
it->nglyphs = 1;
pcm = x_per_char_metric (font, &char2b);
it->ascent = font->ascent + boff;
it->descent = font->descent - boff;
if (pcm)
{
it->phys_ascent = pcm->ascent + boff;
it->phys_descent = pcm->descent - boff;
it->pixel_width = pcm->width;
}
else
{
it->glyph_not_available_p = 1;
it->phys_ascent = font->ascent + boff;
it->phys_descent = font->descent - boff;
it->pixel_width = FONT_WIDTH (font);
}
stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
if (stretched_p)
it->pixel_width *= XFLOATINT (it->space_width);
if (face->box != FACE_NO_BOX)
{
int thick = face->box_line_width;
it->ascent += thick;
it->descent += thick;
if (it->start_of_box_run_p)
it->pixel_width += thick;
if (it->end_of_box_run_p)
it->pixel_width += thick;
}
if (face->overline_p)
it->ascent += 2;
take_vertical_position_into_account (it);
if (it->glyph_row)
{
if (stretched_p)
{
double ascent = (double) font->ascent / FONT_HEIGHT (font);
x_append_stretch_glyph (it, it->object, it->pixel_width,
it->ascent + it->descent, ascent);
}
else
x_append_glyph (it);
if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
it->glyph_row->contains_overlapping_glyphs_p = 1;
}
}
else if (it->char_to_display == '\n')
{
it->pixel_width = 0;
it->nglyphs = 0;
it->ascent = it->phys_ascent = font->ascent + boff;
it->descent = it->phys_descent = font->descent - boff;
if (face->box != FACE_NO_BOX)
{
int thick = face->box_line_width;
it->ascent += thick;
it->descent += thick;
}
}
else if (it->char_to_display == '\t')
{
int tab_width = it->tab_width * CANON_X_UNIT (it->f);
int x = it->current_x + it->continuation_lines_width;
int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
it->pixel_width = next_tab_x - x;
it->nglyphs = 1;
it->ascent = it->phys_ascent = font->ascent + boff;
it->descent = it->phys_descent = font->descent - boff;
if (it->glyph_row)
{
double ascent = (double) it->ascent / (it->ascent + it->descent);
x_append_stretch_glyph (it, it->object, it->pixel_width,
it->ascent + it->descent, ascent);
}
}
else
{
pcm = x_per_char_metric (font, &char2b);
if (font_not_found_p || !pcm)
{
int charset = CHAR_CHARSET (it->char_to_display);
it->glyph_not_available_p = 1;
it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
* CHARSET_WIDTH (charset));
it->phys_ascent = font->ascent + boff;
it->phys_descent = font->descent - boff;
}
else
{
it->pixel_width = pcm->width;
it->phys_ascent = pcm->ascent + boff;
it->phys_descent = pcm->descent - boff;
if (it->glyph_row
&& (pcm->lbearing < 0
|| pcm->rbearing > pcm->width))
it->glyph_row->contains_overlapping_glyphs_p = 1;
}
it->nglyphs = 1;
it->ascent = font->ascent + boff;
it->descent = font->descent - boff;
if (face->box != FACE_NO_BOX)
{
int thick = face->box_line_width;
it->ascent += thick;
it->descent += thick;
if (it->start_of_box_run_p)
it->pixel_width += thick;
if (it->end_of_box_run_p)
it->pixel_width += thick;
}
if (face->overline_p)
it->ascent += 2;
take_vertical_position_into_account (it);
if (it->glyph_row)
x_append_glyph (it);
}
}
else if (it->what == IT_COMPOSITION)
{
XChar2b char2b;
XFontStruct *font;
struct face *face = FACE_FROM_ID (it->f, it->face_id);
XCharStruct *pcm;
int font_not_found_p;
struct font_info *font_info;
int boff;
struct composition *cmp = composition_table[it->cmp_id];
it->char_to_display = it->c;
if (unibyte_display_via_language_environment
&& SINGLE_BYTE_CHAR_P (it->c)
&& (it->c >= 0240
|| (it->c >= 0200
&& !NILP (Vnonascii_translation_table))))
{
it->char_to_display = unibyte_char_to_multibyte (it->c);
}
it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
face = FACE_FROM_ID (it->f, it->face_id);
x_get_char_face_and_encoding (it->f, it->char_to_display,
it->face_id, &char2b, it->multibyte_p);
font = face->font;
font_not_found_p = font == NULL;
if (font_not_found_p)
{
font = FRAME_FONT (it->f);
boff = it->f->output_data.mac->baseline_offset;
font_info = NULL;
}
else
{
font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
boff = font_info->baseline_offset;
if (font_info->vertical_centering)
boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
}
it->nglyphs = 1;
if (cmp->font != (void *) font)
{
int font_ascent = font->ascent + boff;
int font_descent = font->descent - boff;
int leftmost, rightmost, lowest, highest;
int i, width, ascent, descent;
cmp->font = (void *) font;
pcm = x_per_char_metric (font, &char2b);
if (pcm)
{
width = pcm->width;
ascent = pcm->ascent;
descent = pcm->descent;
}
else
{
width = FONT_WIDTH (font);
ascent = font->ascent;
descent = font->descent;
}
rightmost = width;
lowest = - descent + boff;
highest = ascent + boff;
leftmost = 0;
if (font_info
&& font_info->default_ascent
&& CHAR_TABLE_P (Vuse_default_ascent)
&& !NILP (Faref (Vuse_default_ascent,
make_number (it->char_to_display))))
highest = font_info->default_ascent + boff;
cmp->offsets[0] = 0;
cmp->offsets[1] = boff;
for (i = 1; i < cmp->glyph_len; i++)
{
int left, right, btm, top;
int ch = COMPOSITION_GLYPH (cmp, i);
int face_id = FACE_FOR_CHAR (it->f, face, ch);
face = FACE_FROM_ID (it->f, face_id);
x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
it->multibyte_p);
font = face->font;
if (font == NULL)
{
font = FRAME_FONT (it->f);
boff = it->f->output_data.mac->baseline_offset;
font_info = NULL;
}
else
{
font_info
= FONT_INFO_FROM_ID (it->f, face->font_info_id);
boff = font_info->baseline_offset;
if (font_info->vertical_centering)
boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
}
pcm = x_per_char_metric (font, &char2b);
if (pcm)
{
width = pcm->width;
ascent = pcm->ascent;
descent = pcm->descent;
}
else
{
width = FONT_WIDTH (font);
ascent = font->ascent;
descent = font->descent;
}
if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
{
left = (leftmost + rightmost - width) / 2;
btm = - descent + boff;
if (font_info && font_info->relative_compose
&& (! CHAR_TABLE_P (Vignore_relative_composition)
|| NILP (Faref (Vignore_relative_composition,
make_number (ch)))))
{
if (- descent >= font_info->relative_compose)
btm = highest + 1;
else if (ascent <= 0)
btm = lowest - 1 - ascent - descent;
}
}
else
{
int rule = COMPOSITION_RULE (cmp, i);
int gref, nref, grefx, grefy, nrefx, nrefy;
COMPOSITION_DECODE_RULE (rule, gref, nref);
grefx = gref % 3, nrefx = nref % 3;
grefy = gref / 3, nrefy = nref / 3;
left = (leftmost
+ grefx * (rightmost - leftmost) / 2
- nrefx * width / 2);
btm = ((grefy == 0 ? highest
: grefy == 1 ? 0
: grefy == 2 ? lowest
: (highest + lowest) / 2)
- (nrefy == 0 ? ascent + descent
: nrefy == 1 ? descent - boff
: nrefy == 2 ? 0
: (ascent + descent) / 2));
}
cmp->offsets[i * 2] = left;
cmp->offsets[i * 2 + 1] = btm + descent;
right = left + width;
top = btm + descent + ascent;
if (left < leftmost)
leftmost = left;
if (right > rightmost)
rightmost = right;
if (top > highest)
highest = top;
if (btm < lowest)
lowest = btm;
}
if (leftmost < 0)
{
for (i = 0; i < cmp->glyph_len; i++)
cmp->offsets[i * 2] -= leftmost;
rightmost -= leftmost;
}
cmp->pixel_width = rightmost;
cmp->ascent = highest;
cmp->descent = - lowest;
if (cmp->ascent < font_ascent)
cmp->ascent = font_ascent;
if (cmp->descent < font_descent)
cmp->descent = font_descent;
}
it->pixel_width = cmp->pixel_width;
it->ascent = it->phys_ascent = cmp->ascent;
it->descent = it->phys_descent = cmp->descent;
if (face->box != FACE_NO_BOX)
{
int thick = face->box_line_width;
it->ascent += thick;
it->descent += thick;
if (it->start_of_box_run_p)
it->pixel_width += thick;
if (it->end_of_box_run_p)
it->pixel_width += thick;
}
if (face->overline_p)
it->ascent += 2;
take_vertical_position_into_account (it);
if (it->glyph_row)
x_append_composite_glyph (it);
}
else if (it->what == IT_IMAGE)
x_produce_image_glyph (it);
else if (it->what == IT_STRETCH)
x_produce_stretch_glyph (it);
xassert (it->ascent >= 0 && it->descent >= 0);
if (it->area == TEXT_AREA)
it->current_x += it->pixel_width;
it->descent += it->extra_line_spacing;
it->max_ascent = max (it->max_ascent, it->ascent);
it->max_descent = max (it->max_descent, it->descent);
it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
}
int
x_estimate_mode_line_height (f, face_id)
struct frame *f;
enum face_id face_id;
{
int height = 1;
if (FRAME_FACE_CACHE (f))
{
struct face *face = FACE_FROM_ID (f, face_id);
if (face)
height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
}
return height;
}
struct glyph_string
{
int x;
int y, ybase;
int width;
int background_width;
int height;
int left_overhang;
int right_overhang;
struct frame *f;
struct window *w;
Display *display;
Window window;
struct glyph_row *row;
enum glyph_row_area area;
XChar2b *char2b;
int nchars;
enum draw_glyphs_face hl;
struct face *face;
XFontStruct *font;
struct font_info *font_info;
struct composition *cmp;
int gidx;
unsigned extends_to_end_of_line_p : 1;
unsigned background_filled_p : 1;
unsigned two_byte_p : 1;
unsigned font_not_found_p : 1;
unsigned stippled_p : 1;
unsigned for_overlaps_p : 1;
GC gc;
struct glyph *first_glyph;
struct image *img;
struct glyph_string *next, *prev;
};
#if 0
static void
x_dump_glyph_string (s)
struct glyph_string *s;
{
fprintf (stderr, "glyph string\n");
fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
s->x, s->y, s->width, s->height);
fprintf (stderr, " ybase = %d\n", s->ybase);
fprintf (stderr, " hl = %d\n", s->hl);
fprintf (stderr, " left overhang = %d, right = %d\n",
s->left_overhang, s->right_overhang);
fprintf (stderr, " nchars = %d\n", s->nchars);
fprintf (stderr, " extends to end of line = %d\n",
s->extends_to_end_of_line_p);
fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
fprintf (stderr, " bg width = %d\n", s->background_width);
}
#endif
static void x_append_glyph_string_lists P_ ((struct glyph_string **,
struct glyph_string **,
struct glyph_string *,
struct glyph_string *));
static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
struct glyph_string **,
struct glyph_string *,
struct glyph_string *));
static void x_append_glyph_string P_ ((struct glyph_string **,
struct glyph_string **,
struct glyph_string *));
static int x_left_overwritten P_ ((struct glyph_string *));
static int x_left_overwriting P_ ((struct glyph_string *));
static int x_right_overwritten P_ ((struct glyph_string *));
static int x_right_overwriting P_ ((struct glyph_string *));
static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
int));
static void x_init_glyph_string P_ ((struct glyph_string *,
XChar2b *, struct window *,
struct glyph_row *,
enum glyph_row_area, int,
enum draw_glyphs_face));
static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
enum glyph_row_area, int, int,
enum draw_glyphs_face, int *, int *, int));
static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
static void x_set_glyph_string_gc P_ ((struct glyph_string *));
static void x_draw_glyph_string_background P_ ((struct glyph_string *,
int));
static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
static void x_draw_glyph_string_box P_ ((struct glyph_string *));
static void x_draw_glyph_string P_ ((struct glyph_string *));
static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
static void x_set_cursor_gc P_ ((struct glyph_string *));
static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
static void x_set_mouse_face_gc P_ ((struct glyph_string *));
static void x_get_glyph_overhangs P_ ((struct glyph *, struct frame *,
int *, int *));
static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
unsigned long *, double, int));
static void x_setup_relief_color P_ ((struct frame *, struct relief *,
double, int, unsigned long));
static void x_setup_relief_colors P_ ((struct glyph_string *));
static void x_draw_image_glyph_string P_ ((struct glyph_string *));
static void x_draw_image_relief P_ ((struct glyph_string *));
static void x_draw_image_foreground P_ ((struct glyph_string *));
static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
static void x_fill_image_glyph_string P_ ((struct glyph_string *));
static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
int, int, int));
static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
int, int, int, int, XRectangle *));
static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
int, int, int, XRectangle *));
static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
enum glyph_row_area));
static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
struct glyph_row *,
enum glyph_row_area, int, int));
#if GLYPH_DEBUG
static void x_check_font P_ ((struct frame *, XFontStruct *));
#endif
static INLINE void
x_append_glyph_string_lists (head, tail, h, t)
struct glyph_string **head, **tail;
struct glyph_string *h, *t;
{
if (h)
{
if (*head)
(*tail)->next = h;
else
*head = h;
h->prev = *tail;
*tail = t;
}
}
static INLINE void
x_prepend_glyph_string_lists (head, tail, h, t)
struct glyph_string **head, **tail;
struct glyph_string *h, *t;
{
if (h)
{
if (*head)
(*head)->prev = t;
else
*tail = t;
t->next = *head;
*head = h;
}
}
static INLINE void
x_append_glyph_string (head, tail, s)
struct glyph_string **head, **tail;
struct glyph_string *s;
{
s->next = s->prev = NULL;
x_append_glyph_string_lists (head, tail, s, s);
}
static void
x_set_cursor_gc (s)
struct glyph_string *s;
{
if (s->font == FRAME_FONT (s->f)
&& s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
&& s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
&& !s->cmp)
s->gc = s->f->output_data.mac->cursor_gc;
else
{
XGCValues xgcv;
unsigned long mask;
xgcv.background = s->f->output_data.mac->cursor_pixel;
xgcv.foreground = s->face->background;
if (xgcv.foreground == xgcv.background)
xgcv.foreground = s->face->foreground;
if (xgcv.foreground == xgcv.background)
xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
if (xgcv.foreground == xgcv.background)
xgcv.foreground = s->face->foreground;
if (xgcv.background == s->face->background
&& xgcv.foreground == s->face->foreground)
{
xgcv.background = s->face->foreground;
xgcv.foreground = s->face->background;
}
IF_DEBUG (x_check_font (s->f, s->font));
xgcv.font = s->font;
mask = GCForeground | GCBackground | GCFont;
if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
mask, &xgcv);
else
FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
= XCreateGC (s->display, s->window, mask, &xgcv);
s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
}
}
static void
x_set_mouse_face_gc (s)
struct glyph_string *s;
{
int face_id;
struct face *face;
face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
face = FACE_FROM_ID (s->f, face_id);
if (s->first_glyph->type == CHAR_GLYPH)
face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
else
face_id = FACE_FOR_CHAR (s->f, face, 0);
s->face = FACE_FROM_ID (s->f, face_id);
PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
if (s->font == s->face->font)
s->gc = s->face->gc;
else
{
XGCValues xgcv;
unsigned long mask;
xgcv.background = s->face->background;
xgcv.foreground = s->face->foreground;
IF_DEBUG (x_check_font (s->f, s->font));
xgcv.font = s->font;
mask = GCForeground | GCBackground | GCFont;
if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
mask, &xgcv);
else
FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
= XCreateGC (s->display, s->window, mask, &xgcv);
s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
}
xassert (s->gc != 0);
}
static INLINE void
x_set_mode_line_face_gc (s)
struct glyph_string *s;
{
s->gc = s->face->gc;
}
static INLINE void
x_set_glyph_string_gc (s)
struct glyph_string *s;
{
PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
if (s->hl == DRAW_NORMAL_TEXT)
{
s->gc = s->face->gc;
s->stippled_p = s->face->stipple != 0;
}
else if (s->hl == DRAW_INVERSE_VIDEO)
{
x_set_mode_line_face_gc (s);
s->stippled_p = s->face->stipple != 0;
}
else if (s->hl == DRAW_CURSOR)
{
x_set_cursor_gc (s);
s->stippled_p = 0;
}
else if (s->hl == DRAW_MOUSE_FACE)
{
x_set_mouse_face_gc (s);
s->stippled_p = s->face->stipple != 0;
}
else if (s->hl == DRAW_IMAGE_RAISED
|| s->hl == DRAW_IMAGE_SUNKEN)
{
s->gc = s->face->gc;
s->stippled_p = s->face->stipple != 0;
}
else
{
s->gc = s->face->gc;
s->stippled_p = s->face->stipple != 0;
}
xassert (s->gc != 0);
}
static void
x_get_glyph_string_clip_rect (s, r)
struct glyph_string *s;
Rect *r;
{
int r_height, r_width;
if (s->row->full_width_p)
{
int canon_x = CANON_X_UNIT (s->f);
r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
r_width = XFASTINT (s->w->width) * canon_x;
if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
{
int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
r->left -= width;
}
r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
if (s->w->pseudo_window_p)
r_height = s->row->visible_height;
else
r_height = s->height;
}
else
{
r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
r_width = window_box_width (s->w, s->area);
r_height = s->row->visible_height;
}
if (!s->row->full_width_p
&& MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
else
r->top = max (0, s->row->y);
if (s->w == XWINDOW (s->f->tool_bar_window))
r->top -= s->f->output_data.mac->internal_border_width;
if (s->for_overlaps_p)
{
r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
r_height = window_text_bottom_y (s->w) - r->top;
}
r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
r->bottom = r->top + r_height;
r->right = r->left + r_width;
}
static INLINE void
x_set_glyph_string_clipping (s)
struct glyph_string *s;
{
Rect r;
x_get_glyph_string_clip_rect (s, &r);
mac_set_clip_rectangle (s->display, s->window, &r);
}
static INLINE void
x_compute_glyph_string_overhangs (s)
struct glyph_string *s;
{
if (s->cmp == NULL
&& s->first_glyph->type == CHAR_GLYPH)
{
XCharStruct cs;
int direction, font_ascent, font_descent;
XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
&font_ascent, &font_descent, &cs);
s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
}
}
static void
x_compute_overhangs_and_x (s, x, backward_p)
struct glyph_string *s;
int x;
int backward_p;
{
if (backward_p)
{
while (s)
{
x_compute_glyph_string_overhangs (s);
x -= s->width;
s->x = x;
s = s->prev;
}
}
else
{
while (s)
{
x_compute_glyph_string_overhangs (s);
s->x = x;
x += s->width;
s = s->next;
}
}
}
void
x_get_glyph_overhangs (glyph, f, left, right)
struct glyph *glyph;
struct frame *f;
int *left, *right;
{
*left = *right = 0;
if (glyph->type == CHAR_GLYPH)
{
XFontStruct *font;
struct face *face;
struct font_info *font_info;
XChar2b char2b;
XCharStruct *pcm;
face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
font = face->font;
font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
if (font
&& (pcm = x_per_char_metric (font, &char2b)))
{
if (pcm->rbearing > pcm->width)
*right = pcm->rbearing - pcm->width;
if (pcm->lbearing < 0)
*left = -pcm->lbearing;
}
}
}
static int
x_left_overwritten (s)
struct glyph_string *s;
{
int k;
if (s->left_overhang)
{
int x = 0, i;
struct glyph *glyphs = s->row->glyphs[s->area];
int first = s->first_glyph - glyphs;
for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
x -= glyphs[i].pixel_width;
k = i + 1;
}
else
k = -1;
return k;
}
static int
x_left_overwriting (s)
struct glyph_string *s;
{
int i, k, x;
struct glyph *glyphs = s->row->glyphs[s->area];
int first = s->first_glyph - glyphs;
k = -1;
x = 0;
for (i = first - 1; i >= 0; --i)
{
int left, right;
x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
if (x + right > 0)
k = i;
x -= glyphs[i].pixel_width;
}
return k;
}
static int
x_right_overwritten (s)
struct glyph_string *s;
{
int k = -1;
if (s->right_overhang)
{
int x = 0, i;
struct glyph *glyphs = s->row->glyphs[s->area];
int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
int end = s->row->used[s->area];
for (i = first; i < end && s->right_overhang > x; ++i)
x += glyphs[i].pixel_width;
k = i;
}
return k;
}
static int
x_right_overwriting (s)
struct glyph_string *s;
{
int i, k, x;
int end = s->row->used[s->area];
struct glyph *glyphs = s->row->glyphs[s->area];
int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
k = -1;
x = 0;
for (i = first; i < end; ++i)
{
int left, right;
x_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
if (x - left < 0)
k = i;
x += glyphs[i].pixel_width;
}
return k;
}
static INLINE void
x_clear_glyph_string_rect (s, x, y, w, h)
struct glyph_string *s;
int x, y, w, h;
{
XGCValues xgcv;
xgcv.foreground = s->gc->background;
XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
}
static void
x_draw_glyph_string_background (s, force_p)
struct glyph_string *s;
int force_p;
{
if (!s->background_filled_p)
{
#if 0
if (s->stippled_p)
{
XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
XFillRectangle (s->display, s->window, s->gc, s->x,
s->y + s->face->box_line_width,
s->background_width,
s->height - 2 * s->face->box_line_width);
XSetFillStyle (s->display, s->gc, FillSolid);
s->background_filled_p = 1;
}
else
#endif
if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
|| s->font_not_found_p
|| s->extends_to_end_of_line_p
|| force_p)
{
x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
s->background_width,
s->height - 2 * s->face->box_line_width);
s->background_filled_p = 1;
}
}
}
static void
x_draw_glyph_string_foreground (s)
struct glyph_string *s;
{
int i, x;
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
x = s->x + s->face->box_line_width;
else
x = s->x;
if (s->font_not_found_p)
{
for (i = 0; i < s->nchars; ++i)
{
struct glyph *g = s->first_glyph + i;
mac_draw_rectangle (s->display, s->window,
s->gc, x, s->y, g->pixel_width - 1,
s->height - 1);
x += g->pixel_width;
}
}
else
{
char *char1b = (char *) s->char2b;
int boff = s->font_info->baseline_offset;
if (s->font_info->vertical_centering)
boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
if (!s->two_byte_p)
for (i = 0; i < s->nchars; ++i)
char1b[i] = s->char2b[i].byte2;
if (s->for_overlaps_p
|| (s->background_filled_p && s->hl != DRAW_CURSOR))
{
if (s->two_byte_p)
XDrawString16 (s->display, s->window, s->gc, x,
s->ybase - boff, s->char2b, s->nchars);
else
XDrawString (s->display, s->window, s->gc, x,
s->ybase - boff, char1b, s->nchars);
}
else
{
if (s->two_byte_p)
XDrawImageString16 (s->display, s->window, s->gc, x,
s->ybase - boff, s->char2b, s->nchars);
else
XDrawImageString (s->display, s->window, s->gc, x,
s->ybase - boff, char1b, s->nchars);
}
}
}
static void
x_draw_composite_glyph_string_foreground (s)
struct glyph_string *s;
{
int i, x;
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
x = s->x + s->face->box_line_width;
else
x = s->x;
if (s->font_not_found_p)
{
if (s->gidx == 0)
mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
s->width - 1, s->height - 1);
}
else
{
for (i = 0; i < s->nchars; i++, ++s->gidx)
XDrawString16 (s->display, s->window, s->gc,
x + s->cmp->offsets[s->gidx * 2],
s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
s->char2b + i, 1);
}
}
#ifdef USE_X_TOOLKIT
static struct frame *x_frame_of_widget P_ ((Widget));
static struct frame *
x_frame_of_widget (widget)
Widget widget;
{
struct x_display_info *dpyinfo;
Lisp_Object tail;
struct frame *f;
dpyinfo = x_display_info_for_display (XtDisplay (widget));
while (!XtIsTopLevelShell (widget))
widget = XtParent (widget);
for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
if (GC_FRAMEP (XCAR (tail))
&& (f = XFRAME (XCAR (tail)),
(f->output_data.nothing != 1
&& FRAME_X_DISPLAY_INFO (f) == dpyinfo))
&& f->output_data.x->widget == widget)
return f;
abort ();
}
int
x_alloc_nearest_color_for_widget (widget, cmap, color)
Widget widget;
Colormap cmap;
XColor *color;
{
struct frame *f = x_frame_of_widget (widget);
return x_alloc_nearest_color (f, cmap, color);
}
#endif
#if 0
int
x_alloc_nearest_color (f, cmap, color)
struct frame *f;
Colormap cmap;
XColor *color;
{
Display *display = FRAME_X_DISPLAY (f);
Screen *screen = FRAME_X_SCREEN (f);
int rc;
gamma_correct (f, color);
rc = XAllocColor (display, cmap, color);
if (rc == 0)
{
int nearest, i;
unsigned long nearest_delta = ~0;
int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
for (i = 0; i < ncells; ++i)
cells[i].pixel = i;
XQueryColors (display, cmap, cells, ncells);
for (nearest = i = 0; i < ncells; ++i)
{
long dred = (color->red >> 8) - (cells[i].red >> 8);
long dgreen = (color->green >> 8) - (cells[i].green >> 8);
long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
if (delta < nearest_delta)
{
nearest = i;
nearest_delta = delta;
}
}
color->red = cells[nearest].red;
color->green = cells[nearest].green;
color->blue = cells[nearest].blue;
rc = XAllocColor (display, cmap, color);
}
#ifdef DEBUG_X_COLORS
if (rc)
register_color (color->pixel);
#endif
return rc;
}
unsigned long
x_copy_color (f, pixel)
struct frame *f;
unsigned long pixel;
{
XColor color;
color.pixel = pixel;
BLOCK_INPUT;
XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
UNBLOCK_INPUT;
#ifdef DEBUG_X_COLORS
register_color (pixel);
#endif
return color.pixel;
}
unsigned long
x_copy_dpy_color (dpy, cmap, pixel)
Display *dpy;
Colormap cmap;
unsigned long pixel;
{
XColor color;
color.pixel = pixel;
BLOCK_INPUT;
XQueryColor (dpy, cmap, &color);
XAllocColor (dpy, cmap, &color);
UNBLOCK_INPUT;
#ifdef DEBUG_X_COLORS
register_color (pixel);
#endif
return color.pixel;
}
#endif
static int
mac_alloc_lighter_color (f, color, factor, delta)
struct frame *f;
unsigned long *color;
double factor;
int delta;
{
unsigned long new;
xassert (factor >= 0);
new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
if (new == *color)
new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
if (new == *color)
return 0;
*color = new;
return 1;
}
static void
x_setup_relief_color (f, relief, factor, delta, default_pixel)
struct frame *f;
struct relief *relief;
double factor;
int delta;
unsigned long default_pixel;
{
XGCValues xgcv;
struct mac_output *di = f->output_data.mac;
unsigned long mask = GCForeground;
unsigned long pixel;
unsigned long background = di->relief_background;
struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
xgcv.foreground = default_pixel;
pixel = background;
if (mac_alloc_lighter_color (f, &pixel, factor, delta))
{
relief->allocated_p = 1;
xgcv.foreground = relief->pixel = pixel;
}
if (relief->gc == 0)
{
#if 0
xgcv.stipple = dpyinfo->gray;
mask |= GCStipple;
#endif
relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
}
else
XChangeGC (NULL, relief->gc, mask, &xgcv);
}
static void
x_setup_relief_colors (s)
struct glyph_string *s;
{
struct mac_output *di = s->f->output_data.mac;
unsigned long color;
if (s->face->use_box_color_for_shadows_p)
color = s->face->box_color;
else
{
XGCValues xgcv;
XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
color = xgcv.background;
}
if (di->white_relief.gc == 0
|| color != di->relief_background)
{
di->relief_background = color;
x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
WHITE_PIX_DEFAULT (s->f));
x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
BLACK_PIX_DEFAULT (s->f));
}
}
static void
x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
raised_p, left_p, right_p, clip_rect)
struct frame *f;
int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
Rect *clip_rect;
{
int i;
GC gc;
if (raised_p)
gc = f->output_data.mac->white_relief.gc;
else
gc = f->output_data.mac->black_relief.gc;
mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
for (i = 0; i < width; ++i)
XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
left_x + i * left_p, top_y + i,
right_x + 1 - i * right_p, top_y + i);
if (left_p)
for (i = 0; i < width; ++i)
XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
left_x + i, top_y + i, left_x + i, bottom_y - i);
mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
if (raised_p)
gc = f->output_data.mac->black_relief.gc;
else
gc = f->output_data.mac->white_relief.gc;
mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), clip_rect);
for (i = 0; i < width; ++i)
XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
left_x + i * left_p, bottom_y - i,
right_x + 1 - i * right_p, bottom_y - i);
if (right_p)
for (i = 0; i < width; ++i)
XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), gc,
right_x - i, top_y + i + 1, right_x - i, bottom_y - i);
mac_reset_clipping (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
}
static void
x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
left_p, right_p, clip_rect)
struct glyph_string *s;
int left_x, top_y, right_x, bottom_y, left_p, right_p;
Rect *clip_rect;
{
XGCValues xgcv;
xgcv.foreground = s->face->box_color;
mac_set_clip_rectangle (s->display, s->window, clip_rect);
XFillRectangle (s->display, s->window, &xgcv,
left_x, top_y, right_x - left_x, width);
if (left_p)
XFillRectangle (s->display, s->window, &xgcv,
left_x, top_y, width, bottom_y - top_y);
XFillRectangle (s->display, s->window, &xgcv,
left_x, bottom_y - width, right_x - left_x, width);
if (right_p)
XFillRectangle (s->display, s->window, &xgcv,
right_x - width, top_y, width, bottom_y - top_y);
mac_reset_clipping (s->display, s->window);
}
static void
x_draw_glyph_string_box (s)
struct glyph_string *s;
{
int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
int left_p, right_p;
struct glyph *last_glyph;
Rect clip_rect;
last_x = window_box_right (s->w, s->area);
if (s->row->full_width_p
&& !s->w->pseudo_window_p)
{
last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
}
last_glyph = (s->cmp || s->img
? s->first_glyph
: s->first_glyph + s->nchars - 1);
width = s->face->box_line_width;
raised_p = s->face->box == FACE_RAISED_BOX;
left_x = s->x;
right_x = ((s->row->full_width_p
? last_x - 1
: min (last_x, s->x + s->background_width) - 1));
top_y = s->y;
bottom_y = top_y + s->height - 1;
left_p = (s->first_glyph->left_box_line_p
|| (s->hl == DRAW_MOUSE_FACE
&& (s->prev == NULL
|| s->prev->hl != s->hl)));
right_p = (last_glyph->right_box_line_p
|| (s->hl == DRAW_MOUSE_FACE
&& (s->next == NULL
|| s->next->hl != s->hl)));
x_get_glyph_string_clip_rect (s, &clip_rect);
if (s->face->box == FACE_SIMPLE_BOX)
x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
left_p, right_p, &clip_rect);
else
{
x_setup_relief_colors (s);
x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
width, raised_p, left_p, right_p, &clip_rect);
}
}
static void
x_draw_image_foreground (s)
struct glyph_string *s;
{
int x;
int y = s->ybase - image_ascent (s->img, s->face);
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
x = s->x + s->face->box_line_width;
else
x = s->x;
x += s->img->hmargin;
y += s->img->vmargin;
if (s->img->pixmap)
{
#if 0
if (s->img->mask)
{
unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
| GCFunction);
XGCValues xgcv;
XRectangle clip_rect, image_rect, r;
xgcv.clip_mask = s->img->mask;
xgcv.clip_x_origin = x;
xgcv.clip_y_origin = y;
xgcv.function = GXcopy;
XChangeGC (s->display, s->gc, mask, &xgcv);
x_get_glyph_string_clip_rect (s, &clip_rect);
image_rect.x = x;
image_rect.y = y;
image_rect.width = s->img->width;
image_rect.height = s->img->height;
if (x_intersect_rectangles (&clip_rect, &image_rect, &r))
XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
r.x - x, r.y - y, r.width, r.height, r.x, r.y);
}
else
#endif
{
mac_copy_area (s->display, s->img->pixmap, s->window, s->gc,
0, 0, s->img->width, s->img->height, x, y);
if (s->hl == DRAW_CURSOR)
mac_draw_rectangle (s->display, s->window, s->gc, x, y,
s->img->width - 1, s->img->height - 1);
}
}
else
mac_draw_rectangle (s->display, s->window, s->gc, x, y,
s->img->width - 1, s->img->height - 1);
}
static void
x_draw_image_relief (s)
struct glyph_string *s;
{
int x0, y0, x1, y1, thick, raised_p;
Rect r;
int x;
int y = s->ybase - image_ascent (s->img, s->face);
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
x = s->x + s->face->box_line_width;
else
x = s->x;
x += s->img->hmargin;
y += s->img->vmargin;
if (s->hl == DRAW_IMAGE_SUNKEN
|| s->hl == DRAW_IMAGE_RAISED)
{
thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
raised_p = s->hl == DRAW_IMAGE_RAISED;
}
else
{
thick = abs (s->img->relief);
raised_p = s->img->relief > 0;
}
x0 = x - thick;
y0 = y - thick;
x1 = x + s->img->width + thick - 1;
y1 = y + s->img->height + thick - 1;
x_setup_relief_colors (s);
x_get_glyph_string_clip_rect (s, &r);
x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
}
static void
x_draw_image_foreground_1 (s, pixmap)
struct glyph_string *s;
Pixmap pixmap;
{
int x;
int y = s->ybase - s->y - image_ascent (s->img, s->face);
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
x = s->face->box_line_width;
else
x = 0;
x += s->img->hmargin;
y += s->img->vmargin;
if (s->img->pixmap)
{
#if 0
if (s->img->mask)
{
unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
| GCFunction);
XGCValues xgcv;
xgcv.clip_mask = s->img->mask;
xgcv.clip_x_origin = x;
xgcv.clip_y_origin = y;
xgcv.function = GXcopy;
XChangeGC (s->display, s->gc, mask, &xgcv);
XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
0, 0, s->img->width, s->img->height, x, y);
XSetClipMask (s->display, s->gc, None);
}
else
#endif
{
mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
0, 0, s->img->width, s->img->height, x, y);
if (s->hl == DRAW_CURSOR)
mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
s->img->width - 1, s->img->height - 1);
}
}
else
mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
s->img->width - 1, s->img->height - 1);
}
static void
x_draw_glyph_string_bg_rect (s, x, y, w, h)
struct glyph_string *s;
int x, y, w, h;
{
#if 0
if (s->stippled_p)
{
XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
XSetFillStyle (s->display, s->gc, FillSolid);
}
else
#endif
x_clear_glyph_string_rect (s, x, y, w, h);
}
static void
x_draw_image_glyph_string (s)
struct glyph_string *s;
{
int x, y;
int box_line_width = s->face->box_line_width;
int height;
Pixmap pixmap = 0;
height = s->height - 2 * box_line_width;
s->stippled_p = s->face->stipple != 0;
if (height > s->img->height
|| s->img->vmargin
|| s->img->hmargin
#if 0
|| s->img->mask
#endif
|| s->img->pixmap == 0
|| s->width != s->background_width)
{
if (box_line_width && s->first_glyph->left_box_line_p)
x = s->x + box_line_width;
else
x = s->x;
y = s->y + box_line_width;
#if 0
if (s->img->mask)
{
Screen *screen = FRAME_X_SCREEN (s->f);
int depth = DefaultDepthOfScreen (screen);
pixmap = XCreatePixmap (s->display, s->window,
s->background_width,
s->height, depth);
XSetClipMask (s->display, s->gc, None);
if (s->stippled_p)
{
XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
XFillRectangle (s->display, pixmap, s->gc,
0, 0, s->background_width, s->height);
XSetFillStyle (s->display, s->gc, FillSolid);
}
else
{
XGCValues xgcv;
XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
&xgcv);
XSetForeground (s->display, s->gc, xgcv.background);
XFillRectangle (s->display, pixmap, s->gc,
0, 0, s->background_width, s->height);
XSetForeground (s->display, s->gc, xgcv.foreground);
}
}
else
#endif
x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
s->background_filled_p = 1;
}
if (pixmap != 0)
{
x_draw_image_foreground_1 (s, pixmap);
x_set_glyph_string_clipping (s);
mac_copy_area (s->display, pixmap, s->window, s->gc,
0, 0, s->background_width, s->height, s->x, s->y);
XFreePixmap (s->display, pixmap);
}
else
x_draw_image_foreground (s);
if (s->img->relief
|| s->hl == DRAW_IMAGE_RAISED
|| s->hl == DRAW_IMAGE_SUNKEN)
x_draw_image_relief (s);
}
static void
x_draw_stretch_glyph_string (s)
struct glyph_string *s;
{
xassert (s->first_glyph->type == STRETCH_GLYPH);
s->stippled_p = s->face->stipple != 0;
if (s->hl == DRAW_CURSOR
&& !x_stretch_cursor_p)
{
int width = min (CANON_X_UNIT (s->f), s->background_width);
x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
if (width < s->background_width)
{
GC gc = s->face->gc;
int x = s->x + width, y = s->y;
int w = s->background_width - width, h = s->height;
Rect r;
x_get_glyph_string_clip_rect (s, &r);
mac_set_clip_rectangle (s->display, s->window, &r);
#if 0
if (s->face->stipple)
{
XSetFillStyle (s->display, gc, FillOpaqueStippled);
XFillRectangle (s->display, s->window, gc, x, y, w, h);
XSetFillStyle (s->display, gc, FillSolid);
}
else
#endif
{
XGCValues xgcv;
XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
XSetForeground (s->display, gc, xgcv.background);
XFillRectangle (s->display, s->window, gc, x, y, w, h);
XSetForeground (s->display, gc, xgcv.foreground);
}
}
}
else
x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
s->height);
s->background_filled_p = 1;
}
static void
x_draw_glyph_string (s)
struct glyph_string *s;
{
if (s->next && s->right_overhang && !s->for_overlaps_p)
{
xassert (s->next->img == NULL);
x_set_glyph_string_gc (s->next);
x_set_glyph_string_clipping (s->next);
x_draw_glyph_string_background (s->next, 1);
}
x_set_glyph_string_gc (s);
x_set_glyph_string_clipping (s);
switch (s->first_glyph->type)
{
case IMAGE_GLYPH:
x_draw_image_glyph_string (s);
break;
case STRETCH_GLYPH:
x_draw_stretch_glyph_string (s);
break;
case CHAR_GLYPH:
if (s->for_overlaps_p)
s->background_filled_p = 1;
else
x_draw_glyph_string_background (s, 0);
x_draw_glyph_string_foreground (s);
break;
case COMPOSITE_GLYPH:
if (s->for_overlaps_p || s->gidx > 0)
s->background_filled_p = 1;
else
x_draw_glyph_string_background (s, 1);
x_draw_composite_glyph_string_foreground (s);
break;
default:
abort ();
}
if (!s->for_overlaps_p)
{
if (s->face->underline_p)
{
unsigned long h = 1;
unsigned long dy = s->height - h;
if (s->face->underline_defaulted_p)
XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
s->width, h);
else
{
XGCValues xgcv;
XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
XSetForeground (s->display, s->gc, s->face->underline_color);
XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
s->width, h);
XSetForeground (s->display, s->gc, xgcv.foreground);
}
}
if (s->face->overline_p)
{
unsigned long dy = 0, h = 1;
if (s->face->overline_color_defaulted_p)
XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
s->width, h);
else
{
XGCValues xgcv;
XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
XSetForeground (s->display, s->gc, s->face->overline_color);
XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
s->width, h);
XSetForeground (s->display, s->gc, xgcv.foreground);
}
}
if (s->face->strike_through_p)
{
unsigned long h = 1;
unsigned long dy = (s->height - h) / 2;
if (s->face->strike_through_color_defaulted_p)
XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
s->width, h);
else
{
XGCValues xgcv;
XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
XSetForeground (s->display, s->gc, s->face->strike_through_color);
XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
s->width, h);
XSetForeground (s->display, s->gc, xgcv.foreground);
}
}
if (s->face->box != FACE_NO_BOX)
x_draw_glyph_string_box (s);
}
mac_reset_clipping (s->display, s->window);
}
static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
struct face **, int));
static int
x_fill_composite_glyph_string (s, faces, overlaps_p)
struct glyph_string *s;
struct face **faces;
int overlaps_p;
{
int i;
xassert (s);
s->for_overlaps_p = overlaps_p;
s->face = faces[s->gidx];
s->font = s->face->font;
s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
++s->nchars;
for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
++s->nchars;
s->width = s->first_glyph->pixel_width;
if (s->font == NULL)
{
s->font_not_found_p = 1;
s->font = FRAME_FONT (s->f);
}
s->ybase += s->first_glyph->voffset;
xassert (s->face && s->face->gc);
s->two_byte_p = 1;
return s->gidx + s->nchars;
}
static int
x_fill_glyph_string (s, face_id, start, end, overlaps_p)
struct glyph_string *s;
int face_id;
int start, end, overlaps_p;
{
struct glyph *glyph, *last;
int voffset;
int glyph_not_available_p;
xassert (s->f == XFRAME (s->w->frame));
xassert (s->nchars == 0);
xassert (start >= 0 && end > start);
s->for_overlaps_p = overlaps_p,
glyph = s->row->glyphs[s->area] + start;
last = s->row->glyphs[s->area] + end;
voffset = glyph->voffset;
glyph_not_available_p = glyph->glyph_not_available_p;
while (glyph < last
&& glyph->type == CHAR_GLYPH
&& glyph->voffset == voffset
&& glyph->face_id == face_id
&& glyph->glyph_not_available_p == glyph_not_available_p)
{
int two_byte_p;
s->face = x_get_glyph_face_and_encoding (s->f, glyph,
s->char2b + s->nchars,
&two_byte_p);
s->two_byte_p = two_byte_p;
++s->nchars;
xassert (s->nchars <= end - start);
s->width += glyph->pixel_width;
++glyph;
}
s->font = s->face->font;
s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
if (s->font == NULL || glyph_not_available_p)
{
s->font_not_found_p = 1;
s->font = FRAME_FONT (s->f);
}
s->ybase += voffset;
xassert (s->face && s->face->gc);
return glyph - s->row->glyphs[s->area];
}
static void
x_fill_image_glyph_string (s)
struct glyph_string *s;
{
xassert (s->first_glyph->type == IMAGE_GLYPH);
s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
xassert (s->img);
s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
s->font = s->face->font;
s->width = s->first_glyph->pixel_width;
s->ybase += s->first_glyph->voffset;
}
static int
x_fill_stretch_glyph_string (s, row, area, start, end)
struct glyph_string *s;
struct glyph_row *row;
enum glyph_row_area area;
int start, end;
{
struct glyph *glyph, *last;
int voffset, face_id;
xassert (s->first_glyph->type == STRETCH_GLYPH);
glyph = s->row->glyphs[s->area] + start;
last = s->row->glyphs[s->area] + end;
face_id = glyph->face_id;
s->face = FACE_FROM_ID (s->f, face_id);
s->font = s->face->font;
s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
s->width = glyph->pixel_width;
voffset = glyph->voffset;
for (++glyph;
(glyph < last
&& glyph->type == STRETCH_GLYPH
&& glyph->voffset == voffset
&& glyph->face_id == face_id);
++glyph)
s->width += glyph->pixel_width;
s->ybase += voffset;
xassert (s->face && s->face->gc);
return glyph - s->row->glyphs[s->area];
}
static void
x_init_glyph_string (s, char2b, w, row, area, start, hl)
struct glyph_string *s;
XChar2b *char2b;
struct window *w;
struct glyph_row *row;
enum glyph_row_area area;
int start;
enum draw_glyphs_face hl;
{
bzero (s, sizeof *s);
s->w = w;
s->f = XFRAME (w->frame);
s->display = FRAME_MAC_DISPLAY (s->f);
s->window = FRAME_MAC_WINDOW (s->f);
s->char2b = char2b;
s->hl = hl;
s->row = row;
s->area = area;
s->first_glyph = row->glyphs[area] + start;
s->height = row->height;
s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
if (s->w == XWINDOW (s->f->tool_bar_window))
s->y -= s->f->output_data.mac->internal_border_width;
s->ybase = s->y + row->ascent;
}
static INLINE void
x_set_glyph_string_background_width (s, start, last_x)
struct glyph_string *s;
int start;
int last_x;
{
struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
if (start == s->row->used[s->area]
&& s->hl == DRAW_NORMAL_TEXT
&& ((s->area == TEXT_AREA && s->row->fill_line_p)
|| s->face->background != default_face->background
|| s->face->stipple != default_face->stipple))
s->extends_to_end_of_line_p = 1;
if (s->extends_to_end_of_line_p)
s->background_width = last_x - s->x + 1;
else
s->background_width = s->width;
}
#define BUILD_STRETCH_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
do \
{ \
s = (struct glyph_string *) alloca (sizeof *s); \
x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
x_append_glyph_string (&HEAD, &TAIL, s); \
s->x = (X); \
} \
while (0)
#define BUILD_IMAGE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
do \
{ \
s = (struct glyph_string *) alloca (sizeof *s); \
x_init_glyph_string (s, NULL, W, ROW, AREA, START, HL); \
x_fill_image_glyph_string (s); \
x_append_glyph_string (&HEAD, &TAIL, s); \
++START; \
s->x = (X); \
} \
while (0)
#define BUILD_CHAR_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
do \
{ \
int c, face_id; \
XChar2b *char2b; \
\
c = (ROW)->glyphs[AREA][START].u.ch; \
face_id = (ROW)->glyphs[AREA][START].face_id; \
\
s = (struct glyph_string *) alloca (sizeof *s); \
char2b = (XChar2b *) alloca ((END - START) * sizeof *char2b); \
x_init_glyph_string (s, char2b, W, ROW, AREA, START, HL); \
x_append_glyph_string (&HEAD, &TAIL, s); \
s->x = (X); \
START = x_fill_glyph_string (s, face_id, START, END, \
OVERLAPS_P); \
} \
while (0)
#define BUILD_COMPOSITE_GLYPH_STRING(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
do { \
int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
int face_id = (ROW)->glyphs[AREA][START].face_id; \
struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
struct composition *cmp = composition_table[cmp_id]; \
int glyph_len = cmp->glyph_len; \
XChar2b *char2b; \
struct face **faces; \
struct glyph_string *first_s = NULL; \
int n; \
\
base_face = base_face->ascii_face; \
char2b = (XChar2b *) alloca ((sizeof *char2b) * glyph_len); \
faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
\
for (n = 0; n < glyph_len; n++) \
{ \
int c = COMPOSITION_GLYPH (cmp, n); \
int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
x_get_char_face_and_encoding (XFRAME (w->frame), c, \
this_face_id, char2b + n, 1); \
} \
\
\
for (n = 0; n < cmp->glyph_len;) \
{ \
s = (struct glyph_string *) alloca (sizeof *s); \
x_init_glyph_string (s, char2b + n, W, ROW, AREA, START, HL); \
x_append_glyph_string (&(HEAD), &(TAIL), s); \
s->cmp = cmp; \
s->gidx = n; \
s->x = (X); \
\
if (n == 0) \
first_s = s; \
\
n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
} \
\
++START; \
s = first_s; \
} while (0)
#define BUILD_GLYPH_STRINGS(W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
do \
{ \
HEAD = TAIL = NULL; \
while (START < END) \
{ \
struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
switch (first_glyph->type) \
{ \
case CHAR_GLYPH: \
BUILD_CHAR_GLYPH_STRINGS (W, ROW, AREA, START, END, HEAD, \
TAIL, HL, X, LAST_X, \
OVERLAPS_P); \
break; \
\
case COMPOSITE_GLYPH: \
BUILD_COMPOSITE_GLYPH_STRING (W, ROW, AREA, START, END, \
HEAD, TAIL, HL, X, LAST_X,\
OVERLAPS_P); \
break; \
\
case STRETCH_GLYPH: \
BUILD_STRETCH_GLYPH_STRING (W, ROW, AREA, START, END, \
HEAD, TAIL, HL, X, LAST_X); \
break; \
\
case IMAGE_GLYPH: \
BUILD_IMAGE_GLYPH_STRING (W, ROW, AREA, START, END, HEAD, \
TAIL, HL, X, LAST_X); \
break; \
\
default: \
abort (); \
} \
\
x_set_glyph_string_background_width (s, START, LAST_X); \
(X) += s->width; \
} \
} \
while (0)
static int
x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
overlaps_p)
struct window *w;
int x;
struct glyph_row *row;
enum glyph_row_area area;
int start, end;
enum draw_glyphs_face hl;
int *real_start, *real_end;
int overlaps_p;
{
struct glyph_string *head, *tail;
struct glyph_string *s;
int last_x, area_width;
int x_reached;
int i, j;
start = max (0, start);
end = min (end, row->used[area]);
if (real_start)
*real_start = start;
if (real_end)
*real_end = end;
if (row->full_width_p)
{
struct frame *f = XFRAME (w->frame);
int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
x += window_left_x;
area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
last_x = window_left_x + area_width;
if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
{
int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
last_x += width;
else
x -= width;
}
x += FRAME_INTERNAL_BORDER_WIDTH (f);
last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
}
else
{
x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
area_width = window_box_width (w, area);
last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
}
i = start;
BUILD_GLYPH_STRINGS (w, row, area, i, end, head, tail, hl, x, last_x,
overlaps_p);
if (tail)
x_reached = tail->x + tail->background_width;
else
x_reached = x;
if (!overlaps_p && row->contains_overlapping_glyphs_p)
{
int dummy_x = 0;
struct glyph_string *h, *t;
for (s = head; s; s = s->next)
x_compute_glyph_string_overhangs (s);
i = x_left_overwritten (head);
if (i >= 0)
{
j = i;
BUILD_GLYPH_STRINGS (w, row, area, j, start, h, t,
DRAW_NORMAL_TEXT, dummy_x, last_x,
overlaps_p);
start = i;
if (real_start)
*real_start = start;
x_compute_overhangs_and_x (t, head->x, 1);
x_prepend_glyph_string_lists (&head, &tail, h, t);
}
i = x_left_overwriting (head);
if (i >= 0)
{
BUILD_GLYPH_STRINGS (w, row, area, i, start, h, t,
DRAW_NORMAL_TEXT, dummy_x, last_x,
overlaps_p);
for (s = h; s; s = s->next)
s->background_filled_p = 1;
if (real_start)
*real_start = i;
x_compute_overhangs_and_x (t, head->x, 1);
x_prepend_glyph_string_lists (&head, &tail, h, t);
}
i = x_right_overwritten (tail);
if (i >= 0)
{
BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
DRAW_NORMAL_TEXT, x, last_x,
overlaps_p);
x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
x_append_glyph_string_lists (&head, &tail, h, t);
if (real_end)
*real_end = i;
}
i = x_right_overwriting (tail);
if (i >= 0)
{
BUILD_GLYPH_STRINGS (w, row, area, end, i, h, t,
DRAW_NORMAL_TEXT, x, last_x,
overlaps_p);
for (s = h; s; s = s->next)
s->background_filled_p = 1;
x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
x_append_glyph_string_lists (&head, &tail, h, t);
if (real_end)
*real_end = i;
}
}
for (s = head; s; s = s->next)
x_draw_glyph_string (s);
x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
if (!row->full_width_p)
{
if (area > LEFT_MARGIN_AREA)
x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
if (area > TEXT_AREA)
x_reached -= window_box_width (w, TEXT_AREA);
}
return x_reached;
}
void
x_fix_overlapping_area (w, row, area)
struct window *w;
struct glyph_row *row;
enum glyph_row_area area;
{
int i, x;
BLOCK_INPUT;
if (area == LEFT_MARGIN_AREA)
x = 0;
else if (area == TEXT_AREA)
x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
else
x = (window_box_width (w, LEFT_MARGIN_AREA)
+ window_box_width (w, TEXT_AREA));
for (i = 0; i < row->used[area];)
{
if (row->glyphs[area][i].overlaps_vertically_p)
{
int start = i, start_x = x;
do
{
x += row->glyphs[area][i].pixel_width;
++i;
}
while (i < row->used[area]
&& row->glyphs[area][i].overlaps_vertically_p);
x_draw_glyphs (w, start_x, row, area, start, i,
(row->inverse_p
? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
NULL, NULL, 1);
}
else
{
x += row->glyphs[area][i].pixel_width;
++i;
}
}
UNBLOCK_INPUT;
}
void
x_write_glyphs (start, len)
struct glyph *start;
int len;
{
int x, hpos, real_start, real_end;
xassert (updated_window && updated_row);
BLOCK_INPUT;
hpos = start - updated_row->glyphs[updated_area];
x = x_draw_glyphs (updated_window, output_cursor.x,
updated_row, updated_area,
hpos, hpos + len,
(updated_row->inverse_p
? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
&real_start, &real_end, 0);
note_overwritten_text_cursor (updated_window, real_start,
real_end - real_start);
UNBLOCK_INPUT;
output_cursor.hpos += len;
output_cursor.x = x;
}
void
x_insert_glyphs (start, len)
struct glyph *start;
register int len;
{
struct frame *f;
struct window *w;
int line_height, shift_by_width, shifted_region_width;
struct glyph_row *row;
struct glyph *glyph;
int frame_x, frame_y, hpos, real_start, real_end;
xassert (updated_window && updated_row);
BLOCK_INPUT;
w = updated_window;
f = XFRAME (WINDOW_FRAME (w));
row = updated_row;
line_height = row->height;
shift_by_width = 0;
for (glyph = start; glyph < start + len; ++glyph)
shift_by_width += glyph->pixel_width;
shifted_region_width = (window_box_width (w, updated_area)
- output_cursor.x
- shift_by_width);
frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
f->output_data.mac->normal_gc,
frame_x, frame_y,
shifted_region_width, line_height,
frame_x + shift_by_width, frame_y);
hpos = start - row->glyphs[updated_area];
x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
note_overwritten_text_cursor (w, real_start, real_end - real_start);
output_cursor.hpos += len;
output_cursor.x += shift_by_width;
UNBLOCK_INPUT;
}
void
x_delete_glyphs (n)
register int n;
{
abort ();
}
void
x_clear_end_of_line (to_x)
int to_x;
{
struct frame *f;
struct window *w = updated_window;
int max_x, min_y, max_y;
int from_x, from_y, to_y;
xassert (updated_window && updated_row);
f = XFRAME (w->frame);
if (updated_row->full_width_p)
{
max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
&& !w->pseudo_window_p)
max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
}
else
max_x = window_box_width (w, updated_area);
max_y = window_text_bottom_y (w);
if (to_x == 0)
return;
else if (to_x < 0)
to_x = max_x;
else
to_x = min (to_x, max_x);
to_y = min (max_y, output_cursor.y + updated_row->height);
if (!updated_row->full_width_p)
note_overwritten_text_cursor (w, output_cursor.hpos, -1);
from_x = output_cursor.x;
if (updated_row->full_width_p)
{
from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
}
else
{
from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
}
min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
if (to_x > from_x && to_y > from_y)
{
BLOCK_INPUT;
XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
from_x, from_y, to_x - from_x, to_y - from_y,
0);
UNBLOCK_INPUT;
}
}
void
x_clear_frame ()
{
struct frame *f;
if (updating_frame)
f = updating_frame;
else
f = SELECTED_FRAME ();
mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
output_cursor.hpos = output_cursor.vpos = 0;
output_cursor.x = -1;
BLOCK_INPUT;
XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
#if 0
x_scroll_bar_clear (f);
#endif
XFlush (FRAME_MAC_DISPLAY (f));
UNBLOCK_INPUT;
}
#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
static int
timeval_subtract (result, x, y)
struct timeval *result, x, y;
{
if (x.tv_usec < y.tv_usec)
{
int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
y.tv_usec -= 1000000 * nsec;
y.tv_sec += nsec;
}
if (x.tv_usec - y.tv_usec > 1000000)
{
int nsec = (y.tv_usec - x.tv_usec) / 1000000;
y.tv_usec += 1000000 * nsec;
y.tv_sec -= nsec;
}
result->tv_sec = x.tv_sec - y.tv_sec;
result->tv_usec = x.tv_usec - y.tv_usec;
return x.tv_sec < y.tv_sec;
}
void
XTflash (f)
struct frame *f;
{
BLOCK_INPUT;
FlashMenuBar (0);
{
struct timeval wakeup;
EMACS_GET_TIME (wakeup);
wakeup.tv_usec += 150000;
wakeup.tv_sec += (wakeup.tv_usec / 1000000);
wakeup.tv_usec %= 1000000;
while (1)
{
struct timeval timeout;
EMACS_GET_TIME (timeout);
if (timeval_subtract (&timeout, wakeup, timeout))
break;
select (0, NULL, NULL, NULL, &timeout);
}
}
FlashMenuBar (0);
UNBLOCK_INPUT;
}
#endif
void
XTring_bell ()
{
struct frame *f = SELECTED_FRAME ();
#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
if (visible_bell)
XTflash (f);
else
#endif
{
BLOCK_INPUT;
SysBeep (1);
XFlush (FRAME_MAC_DISPLAY (f));
UNBLOCK_INPUT;
}
}
void
XTset_terminal_window (n)
register int n;
{
}
void
x_ins_del_lines (vpos, n)
int vpos, n;
{
abort ();
}
void
x_scroll_run (w, run)
struct window *w;
struct run *run;
{
struct frame *f = XFRAME (w->frame);
int x, y, width, height, from_y, to_y, bottom_y;
window_box (w, -1, &x, &y, &width, &height);
width += FRAME_X_FLAGS_AREA_WIDTH (f);
x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
bottom_y = y + height;
if (to_y < from_y)
{
if (from_y + run->height > bottom_y)
height = bottom_y - from_y;
else
height = run->height;
}
else
{
if (to_y + run->height > bottom_y)
height = bottom_y - to_y;
else
height = run->height;
}
BLOCK_INPUT;
updated_window = w;
x_clear_cursor (w);
mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
f->output_data.mac->normal_gc,
x, from_y,
width, height,
x, to_y);
UNBLOCK_INPUT;
}
static void
expose_frame (f, x, y, w, h)
struct frame *f;
int x, y, w, h;
{
Rect r;
TRACE ((stderr, "expose_frame "));
if (FRAME_GARBAGED_P (f))
{
TRACE ((stderr, " garbaged\n"));
return;
}
if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
activate_scroll_bars (f);
else
deactivate_scroll_bars (f);
if (FRAME_FACE_CACHE (f) == NULL
|| FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
{
TRACE ((stderr, " no faces\n"));
return;
}
if (w == 0 || h == 0)
{
r.left = r.top = 0;
r.right = CANON_X_UNIT (f) * f->width;
r.bottom = CANON_Y_UNIT (f) * f->height;
}
else
{
r.left = x;
r.top = y;
r.right = x + w;
r.bottom = y + h;
}
TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
expose_window_tree (XWINDOW (f->root_window), &r);
if (WINDOWP (f->tool_bar_window))
{
struct window *w = XWINDOW (f->tool_bar_window);
Rect window_rect;
Rect intersection_rect;
int window_x, window_y, window_width, window_height;
window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
window_rect.left = window_x;
window_rect.top = window_y;
window_rect.right = window_x + window_width;
window_rect.bottom = window_y + window_height;
if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
expose_window (w, &intersection_rect);
}
#ifndef USE_X_TOOLKIT
if (WINDOWP (f->menu_bar_window))
{
struct window *w = XWINDOW (f->menu_bar_window);
Rect window_rect;
Rect intersection_rect;
int window_x, window_y, window_width, window_height;
window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
window_rect.left = window_x;
window_rect.top = window_y;
window_rect.right = window_x + window_width;
window_rect.bottom = window_y + window_height;
if (x_intersect_rectangles (&r, &window_rect, &intersection_rect))
expose_window (w, &intersection_rect);
}
#endif
}
static void
expose_window_tree (w, r)
struct window *w;
Rect *r;
{
while (w)
{
if (!NILP (w->hchild))
expose_window_tree (XWINDOW (w->hchild), r);
else if (!NILP (w->vchild))
expose_window_tree (XWINDOW (w->vchild), r);
else
{
Rect window_rect;
Rect intersection_rect;
struct frame *f = XFRAME (w->frame);
int window_x, window_y, window_width, window_height;
window_box (w, -1, &window_x, &window_y, &window_width,
&window_height);
window_rect.left
= (window_x
- FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
- FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_Y_UNIT (f));
window_rect.top = window_y;
window_rect.right = window_rect.left
+ (window_width
+ FRAME_X_FLAGS_AREA_WIDTH (f)
+ FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
window_rect.bottom = window_rect.top
+ window_height + CURRENT_MODE_LINE_HEIGHT (w);
if (x_intersect_rectangles (r, &window_rect, &intersection_rect))
expose_window (w, &intersection_rect);
}
w = NILP (w->next) ? 0 : XWINDOW (w->next);
}
}
static void
expose_area (w, row, r, area)
struct window *w;
struct glyph_row *row;
Rect *r;
enum glyph_row_area area;
{
int x;
struct glyph *first = row->glyphs[area];
struct glyph *end = row->glyphs[area] + row->used[area];
struct glyph *last;
int first_x;
if (area == LEFT_MARGIN_AREA)
x = 0;
else if (area == TEXT_AREA)
x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
else
x = (window_box_width (w, LEFT_MARGIN_AREA)
+ window_box_width (w, TEXT_AREA));
if (area == TEXT_AREA && row->fill_line_p)
x_draw_glyphs (w, x, row, area,
0, row->used[area],
row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
NULL, NULL, 0);
else
{
while (first < end
&& x + first->pixel_width < r->left)
{
x += first->pixel_width;
++first;
}
last = first;
first_x = x;
while (last < end
&& x < r->right)
{
x += last->pixel_width;
++last;
}
if (last > first)
x_draw_glyphs (w, first_x, row, area,
first - row->glyphs[area],
last - row->glyphs[area],
row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
NULL, NULL, 0);
}
}
static void
expose_line (w, row, r)
struct window *w;
struct glyph_row *row;
Rect *r;
{
xassert (row->enabled_p);
if (row->mode_line_p || w->pseudo_window_p)
x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
NULL, NULL, 0);
else
{
if (row->used[LEFT_MARGIN_AREA])
expose_area (w, row, r, LEFT_MARGIN_AREA);
if (row->used[TEXT_AREA])
expose_area (w, row, r, TEXT_AREA);
if (row->used[RIGHT_MARGIN_AREA])
expose_area (w, row, r, RIGHT_MARGIN_AREA);
x_draw_row_bitmaps (w, row);
}
}
static int
x_phys_cursor_in_rect_p (w, r)
struct window *w;
Rect *r;
{
Rect cr, result;
struct glyph *cursor_glyph;
cursor_glyph = get_phys_cursor_glyph (w);
if (cursor_glyph)
{
cr.left = w->phys_cursor.x;
cr.top = w->phys_cursor.y;
cr.right = cr.left + cursor_glyph->pixel_width;
cr.bottom = cr.top + w->phys_cursor_height;
return x_intersect_rectangles (&cr, r, &result);
}
else
return 0;
}
static void
expose_window (w, r)
struct window *w;
Rect *r;
{
struct glyph_row *row;
int y;
int yb = window_text_bottom_y (w);
int cursor_cleared_p;
if (w->current_matrix == NULL)
return;
TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
r->left, r->top, r->right, r->bottom));
r->left = FRAME_TO_WINDOW_PIXEL_X (w, r->left);
r->top = FRAME_TO_WINDOW_PIXEL_Y (w, r->top);
r->right = FRAME_TO_WINDOW_PIXEL_X (w, r->right);
r->bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r->bottom);
if (!w->pseudo_window_p
&& x_phys_cursor_in_rect_p (w, r))
{
x_clear_cursor (w);
cursor_cleared_p = 1;
}
else
cursor_cleared_p = 0;
row = w->current_matrix->rows;
y = 0;
while (row->enabled_p
&& y < yb
&& y + row->height < r->top)
{
y += row->height;
++row;
}
while (row->enabled_p
&& y < yb
&& y < r->bottom)
{
expose_line (w, row, r);
y += row->height;
++row;
}
if (WINDOW_WANTS_MODELINE_P (w)
&& (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
row->enabled_p)
&& row->y < r->bottom)
expose_line (w, row, r);
if (!w->pseudo_window_p)
{
x_draw_vertical_border (w);
if (cursor_cleared_p)
x_update_window_cursor (w, 1);
}
if (!NILP (w->vertical_scroll_bar))
{
ControlHandle ch
= SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (w->vertical_scroll_bar));
Draw1Control (ch);
}
}
static int
x_intersect_rectangles (r1, r2, result)
Rect *r1, *r2, *result;
{
Rect *left, *right;
Rect *upper, *lower;
int intersection_p = 0;
if (r1->left < r2->left)
left = r1, right = r2;
else
left = r2, right = r1;
if (right->left <= left->right)
{
result->left = right->left;
result->right = min (left->right, right->right);
if (r1->top < r2->top)
upper = r1, lower = r2;
else
upper = r2, lower = r1;
if (lower->top <= upper->bottom)
{
result->top = lower->top;
result->bottom = min (lower->bottom, upper->bottom);
intersection_p = 1;
}
}
return intersection_p;
}
static void
frame_highlight (f)
struct frame *f;
{
x_update_cursor (f, 1);
}
static void
frame_unhighlight (f)
struct frame *f;
{
x_update_cursor (f, 1);
}
static void
x_new_focus_frame (dpyinfo, frame)
struct x_display_info *dpyinfo;
struct frame *frame;
{
struct frame *old_focus = dpyinfo->x_focus_frame;
if (frame != dpyinfo->x_focus_frame)
{
dpyinfo->x_focus_frame = frame;
if (old_focus && old_focus->auto_lower)
x_lower_frame (old_focus);
#if 0
selected_frame = frame;
XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
selected_frame);
Fselect_window (selected_frame->selected_window);
choose_minibuf_frame ();
#endif
if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
pending_autoraise_frame = dpyinfo->x_focus_frame;
else
pending_autoraise_frame = 0;
}
x_frame_rehighlight (dpyinfo);
}
static void
x_mouse_leave (dpyinfo)
struct x_display_info *dpyinfo;
{
x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
}
void
XTframe_rehighlight (frame)
struct frame *frame;
{
x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
}
static void
x_frame_rehighlight (dpyinfo)
struct x_display_info *dpyinfo;
{
struct frame *old_highlight = dpyinfo->x_highlight_frame;
if (dpyinfo->x_focus_frame)
{
dpyinfo->x_highlight_frame
= ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
: dpyinfo->x_focus_frame);
if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
{
FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
}
}
else
dpyinfo->x_highlight_frame = 0;
if (dpyinfo->x_highlight_frame != old_highlight)
{
if (old_highlight)
frame_unhighlight (old_highlight);
if (dpyinfo->x_highlight_frame)
frame_highlight (dpyinfo->x_highlight_frame);
}
}
#if 0
static void
x_find_modifier_meanings (dpyinfo)
struct x_display_info *dpyinfo;
{
int min_code, max_code;
KeySym *syms;
int syms_per_code;
XModifierKeymap *mods;
dpyinfo->meta_mod_mask = 0;
dpyinfo->shift_lock_mask = 0;
dpyinfo->alt_mod_mask = 0;
dpyinfo->super_mod_mask = 0;
dpyinfo->hyper_mod_mask = 0;
#ifdef HAVE_X11R4
XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
#else
min_code = dpyinfo->display->min_keycode;
max_code = dpyinfo->display->max_keycode;
#endif
syms = XGetKeyboardMapping (dpyinfo->display,
min_code, max_code - min_code + 1,
&syms_per_code);
mods = XGetModifierMapping (dpyinfo->display);
{
int row, col;
for (row = 3; row < 8; row++)
for (col = 0; col < mods->max_keypermod; col++)
{
KeyCode code
= mods->modifiermap[(row * mods->max_keypermod) + col];
if (code == 0)
continue;
{
int code_col;
for (code_col = 0; code_col < syms_per_code; code_col++)
{
int sym = syms[((code - min_code) * syms_per_code) + code_col];
switch (sym)
{
case XK_Meta_L:
case XK_Meta_R:
dpyinfo->meta_mod_mask |= (1 << row);
break;
case XK_Alt_L:
case XK_Alt_R:
dpyinfo->alt_mod_mask |= (1 << row);
break;
case XK_Hyper_L:
case XK_Hyper_R:
dpyinfo->hyper_mod_mask |= (1 << row);
break;
case XK_Super_L:
case XK_Super_R:
dpyinfo->super_mod_mask |= (1 << row);
break;
case XK_Shift_Lock:
if ((1 << row) == LockMask)
dpyinfo->shift_lock_mask = LockMask;
break;
}
}
}
}
}
if (! dpyinfo->meta_mod_mask)
{
dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
dpyinfo->alt_mod_mask = 0;
}
if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
{
dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
}
XFree ((char *) syms);
XFreeModifiermap (mods);
}
#endif
static unsigned int
x_mac_to_emacs_modifiers (dpyinfo, state)
struct x_display_info *dpyinfo;
unsigned short state;
{
return (((state & shiftKey) ? shift_modifier : 0)
| ((state & controlKey) ? ctrl_modifier : 0)
| ((state & cmdKey) ? meta_modifier : 0)
| ((state & optionKey) ? alt_modifier : 0));
}
#if 0
static unsigned short
x_emacs_to_x_modifiers (dpyinfo, state)
struct x_display_info *dpyinfo;
unsigned int state;
{
return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
| ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
| ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
| ((state & shift_modifier) ? ShiftMask : 0)
| ((state & ctrl_modifier) ? ControlMask : 0)
| ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
}
#endif
char *
x_get_keysym_name (keysym)
int keysym;
{
char *value;
BLOCK_INPUT;
#if 0
value = XKeysymToString (keysym);
#else
value = 0;
#endif
UNBLOCK_INPUT;
return value;
}
void
pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
FRAME_PTR f;
register int pix_x, pix_y;
register int *x, *y;
Rect *bounds;
int noclip;
{
if (pix_x < 0)
pix_x -= FONT_WIDTH ((f)->output_data.mac->font) - 1;
if (pix_y < 0)
pix_y -= (f)->output_data.mac->line_height - 1;
pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
if (bounds)
{
bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
bounds->right = bounds->left + FONT_WIDTH (f->output_data.mac->font);
bounds->bottom = bounds->top + f->output_data.mac->line_height;
}
if (!noclip)
{
if (pix_x < 0)
pix_x = 0;
else if (pix_x > FRAME_WINDOW_WIDTH (f))
pix_x = FRAME_WINDOW_WIDTH (f);
if (pix_y < 0)
pix_y = 0;
else if (pix_y > f->height)
pix_y = f->height;
}
*x = pix_x;
*y = pix_y;
}
static int
glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
struct window *w;
int hpos, vpos;
int *frame_x, *frame_y;
{
int success_p;
xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
if (display_completed)
{
struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
struct glyph *glyph = row->glyphs[TEXT_AREA];
struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
*frame_y = row->y;
*frame_x = row->x;
while (glyph < end)
{
*frame_x += glyph->pixel_width;
++glyph;
}
success_p = 1;
}
else
{
*frame_y = *frame_x = 0;
success_p = 0;
}
*frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
*frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
return success_p;
}
static Lisp_Object
construct_mouse_click (result, event, f)
struct input_event *result;
EventRecord *event;
struct frame *f;
{
Point mouseLoc;
result->kind = mouse_click;
result->code = 0;
result->timestamp = event->when;
result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
mouseLoc = event->where;
SetPort (FRAME_MAC_WINDOW (f));
GlobalToLocal (&mouseLoc);
XSETINT (result->x, mouseLoc.h);
XSETINT (result->y, mouseLoc.v);
XSETFRAME (result->frame_or_window, f);
result->arg = Qnil;
return Qnil;
}
static Point last_mouse_motion_position;
static Lisp_Object last_mouse_motion_frame;
static void
note_mouse_movement (frame, pos)
FRAME_PTR frame;
Point *pos;
{
last_mouse_movement_time = TickCount () * (1000 / 60);
last_mouse_motion_position = *pos;
XSETFRAME (last_mouse_motion_frame, frame);
if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
{
frame->mouse_moved = 1;
last_mouse_scroll_bar = Qnil;
note_mouse_highlight (frame, -1, -1);
}
else if (pos->h < last_mouse_glyph.left
|| pos->h >= last_mouse_glyph.right
|| pos->v < last_mouse_glyph.top
|| pos->v >= last_mouse_glyph.bottom)
{
frame->mouse_moved = 1;
last_mouse_scroll_bar = Qnil;
note_mouse_highlight (frame, pos->h, pos->v);
}
}
int disable_mouse_highlight;
static struct glyph *
x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
struct window *w;
int x, y;
int *hpos, *vpos, *area;
{
struct glyph *glyph, *end;
struct glyph_row *row = NULL;
int x0, i, left_area_width;
for (i = 0; i < w->current_matrix->nrows; ++i)
{
row = MATRIX_ROW (w->current_matrix, i);
if (!row->enabled_p)
return NULL;
if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
break;
}
*vpos = i;
*hpos = 0;
if (i == w->current_matrix->nrows)
return NULL;
if (w->pseudo_window_p)
{
*area = TEXT_AREA;
x0 = 0;
}
else
{
left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
if (x < left_area_width)
{
*area = LEFT_MARGIN_AREA;
x0 = 0;
}
else if (x < left_area_width + window_box_width (w, TEXT_AREA))
{
*area = TEXT_AREA;
x0 = row->x + left_area_width;
}
else
{
*area = RIGHT_MARGIN_AREA;
x0 = left_area_width + window_box_width (w, TEXT_AREA);
}
}
glyph = row->glyphs[*area];
end = glyph + row->used[*area];
while (glyph < end)
{
if (x < x0 + glyph->pixel_width)
{
if (w->pseudo_window_p)
break;
else if (BUFFERP (glyph->object))
break;
}
x0 += glyph->pixel_width;
++glyph;
}
if (glyph == end)
return NULL;
*hpos = glyph - row->glyphs[*area];
return glyph;
}
static void
frame_to_window_pixel_xy (w, x, y)
struct window *w;
int *x, *y;
{
if (w->pseudo_window_p)
{
struct frame *f = XFRAME (w->frame);
*x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
*y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
}
else
{
*x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
*y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
}
}
static void
note_mode_line_highlight (w, x, mode_line_p)
struct window *w;
int x, mode_line_p;
{
struct frame *f = XFRAME (w->frame);
struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
struct glyph_row *row;
if (mode_line_p)
row = MATRIX_MODE_LINE_ROW (w->current_matrix);
else
row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
if (row->enabled_p)
{
struct glyph *glyph, *end;
Lisp_Object help, map;
int x0;
glyph = row->glyphs[TEXT_AREA];
end = glyph + row->used[TEXT_AREA];
x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
+ FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
while (glyph < end
&& x >= x0 + glyph->pixel_width)
{
x0 += glyph->pixel_width;
++glyph;
}
if (glyph < end
&& STRINGP (glyph->object)
&& XSTRING (glyph->object)->intervals
&& glyph->charpos >= 0
&& glyph->charpos < XSTRING (glyph->object)->size)
{
help = Fget_text_property (make_number (glyph->charpos),
Qhelp_echo, glyph->object);
if (!NILP (help))
{
help_echo = help;
XSETWINDOW (help_echo_window, w);
help_echo_object = glyph->object;
help_echo_pos = glyph->charpos;
}
map = Fget_text_property (make_number (glyph->charpos),
Qlocal_map, glyph->object);
if (!NILP (Fkeymapp (map)))
cursor = f->output_data.mac->nontext_cursor;
else
{
map = Fget_text_property (make_number (glyph->charpos),
Qkeymap, glyph->object);
if (!NILP (Fkeymapp (map)))
cursor = f->output_data.mac->nontext_cursor;
}
}
}
#if 0
XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
#endif
}
static void
note_mouse_highlight (f, x, y)
struct frame *f;
int x, y;
{
struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
int portion;
Lisp_Object window;
struct window *w;
#ifdef USE_X_TOOLKIT
if (popup_activated ())
return;
#endif
if (disable_mouse_highlight
|| !f->glyphs_initialized_p)
return;
dpyinfo->mouse_face_mouse_x = x;
dpyinfo->mouse_face_mouse_y = y;
dpyinfo->mouse_face_mouse_frame = f;
if (dpyinfo->mouse_face_defer)
return;
if (gc_in_progress)
{
dpyinfo->mouse_face_deferred_gc = 1;
return;
}
window = window_from_coordinates (f, x, y, &portion, 1);
if (! EQ (window, dpyinfo->mouse_face_window))
clear_mouse_face (dpyinfo);
if (!WINDOWP (window))
return;
w = XWINDOW (window);
frame_to_window_pixel_xy (w, &x, &y);
if (EQ (window, f->tool_bar_window))
{
note_tool_bar_highlight (f, x, y);
return;
}
if (portion == 1 || portion == 3)
{
note_mode_line_highlight (w, x, portion == 1);
return;
}
#if 0
else
XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f->output_data.x->text_cursor);
#endif
if (
portion == 0
&& EQ (w->window_end_valid, w->buffer)
&& XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
&& (XFASTINT (w->last_overlay_modified)
== BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
{
int hpos, vpos, pos, i, area;
struct glyph *glyph;
glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
if (glyph == NULL
|| area != TEXT_AREA
|| !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
{
clear_mouse_face (dpyinfo);
return;
}
pos = glyph->charpos;
xassert (w->pseudo_window_p || BUFFERP (glyph->object));
{
Lisp_Object mouse_face, overlay, position;
Lisp_Object *overlay_vec;
int len, noverlays;
struct buffer *obuf;
int obegv, ozv;
if (pos > BUF_Z (XBUFFER (w->buffer)))
return;
obuf = current_buffer;
current_buffer = XBUFFER (w->buffer);
obegv = BEGV;
ozv = ZV;
BEGV = BEG;
ZV = Z;
XSETINT (position, pos);
len = 10;
overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
if (noverlays > len)
{
len = noverlays;
overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
}
noverlays = sort_overlays (overlay_vec, noverlays, w);
if (! (EQ (window, dpyinfo->mouse_face_window)
&& vpos >= dpyinfo->mouse_face_beg_row
&& vpos <= dpyinfo->mouse_face_end_row
&& (vpos > dpyinfo->mouse_face_beg_row
|| hpos >= dpyinfo->mouse_face_beg_col)
&& (vpos < dpyinfo->mouse_face_end_row
|| hpos < dpyinfo->mouse_face_end_col
|| dpyinfo->mouse_face_past_end)))
{
clear_mouse_face (dpyinfo);
overlay = Qnil;
for (i = noverlays - 1; i >= 0; --i)
{
mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
if (!NILP (mouse_face))
{
overlay = overlay_vec[i];
break;
}
}
if (NILP (overlay))
mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
if (! NILP (overlay))
{
Lisp_Object before, after;
int ignore;
before = Foverlay_start (overlay);
after = Foverlay_end (overlay);
fast_find_position (w, XFASTINT (before),
&dpyinfo->mouse_face_beg_col,
&dpyinfo->mouse_face_beg_row,
&dpyinfo->mouse_face_beg_x,
&dpyinfo->mouse_face_beg_y);
dpyinfo->mouse_face_past_end
= !fast_find_position (w, XFASTINT (after),
&dpyinfo->mouse_face_end_col,
&dpyinfo->mouse_face_end_row,
&dpyinfo->mouse_face_end_x,
&dpyinfo->mouse_face_end_y);
dpyinfo->mouse_face_window = window;
dpyinfo->mouse_face_face_id
= face_at_buffer_position (w, pos, 0, 0,
&ignore, pos + 1, 1);
show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
}
else if (! NILP (mouse_face))
{
Lisp_Object before, after, beginning, end;
int ignore;
beginning = Fmarker_position (w->start);
XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
- XFASTINT (w->window_end_pos)));
before
= Fprevious_single_property_change (make_number (pos + 1),
Qmouse_face,
w->buffer, beginning);
after
= Fnext_single_property_change (position, Qmouse_face,
w->buffer, end);
fast_find_position (w, XFASTINT (before),
&dpyinfo->mouse_face_beg_col,
&dpyinfo->mouse_face_beg_row,
&dpyinfo->mouse_face_beg_x,
&dpyinfo->mouse_face_beg_y);
dpyinfo->mouse_face_past_end
= !fast_find_position (w, XFASTINT (after),
&dpyinfo->mouse_face_end_col,
&dpyinfo->mouse_face_end_row,
&dpyinfo->mouse_face_end_x,
&dpyinfo->mouse_face_end_y);
dpyinfo->mouse_face_window = window;
dpyinfo->mouse_face_face_id
= face_at_buffer_position (w, pos, 0, 0,
&ignore, pos + 1, 1);
show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
}
}
{
Lisp_Object help, overlay;
help = Qnil;
for (i = noverlays - 1; i >= 0 && NILP (help); --i)
{
overlay = overlay_vec[i];
help = Foverlay_get (overlay, Qhelp_echo);
}
if (!NILP (help))
{
help_echo = help;
help_echo_window = window;
help_echo_object = overlay;
help_echo_pos = pos;
}
else
{
if ((STRINGP (glyph->object)
&& glyph->charpos >= 0
&& glyph->charpos < XSTRING (glyph->object)->size)
|| (BUFFERP (glyph->object)
&& glyph->charpos >= BEGV
&& glyph->charpos < ZV))
help = Fget_text_property (make_number (glyph->charpos),
Qhelp_echo, glyph->object);
if (!NILP (help))
{
help_echo = help;
help_echo_window = window;
help_echo_object = glyph->object;
help_echo_pos = glyph->charpos;
}
}
}
BEGV = obegv;
ZV = ozv;
current_buffer = obuf;
}
}
}
static void
redo_mouse_highlight ()
{
if (!NILP (last_mouse_motion_frame)
&& FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
note_mouse_highlight (XFRAME (last_mouse_motion_frame),
last_mouse_motion_position.h,
last_mouse_motion_position.v);
}
static int x_tool_bar_item P_ ((struct frame *, int, int,
struct glyph **, int *, int *, int *));
static int last_tool_bar_item;
static int
x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
struct frame *f;
int x, y;
struct glyph **glyph;
int *hpos, *vpos, *prop_idx;
{
struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
struct window *w = XWINDOW (f->tool_bar_window);
int area;
*glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
if (*glyph == NULL)
return -1;
if (!tool_bar_item_info (f, *glyph, prop_idx))
return -1;
if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
&& *vpos >= dpyinfo->mouse_face_beg_row
&& *vpos <= dpyinfo->mouse_face_end_row
&& (*vpos > dpyinfo->mouse_face_beg_row
|| *hpos >= dpyinfo->mouse_face_beg_col)
&& (*vpos < dpyinfo->mouse_face_end_row
|| *hpos < dpyinfo->mouse_face_end_col
|| dpyinfo->mouse_face_past_end))
return 0;
return 1;
}
static void
x_handle_tool_bar_click (f, button_event)
struct frame *f;
EventRecord *button_event;
{
struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
struct window *w = XWINDOW (f->tool_bar_window);
int hpos, vpos, prop_idx;
struct glyph *glyph;
Lisp_Object enabled_p;
int x = button_event->where.h;
int y = button_event->where.v;
frame_to_window_pixel_xy (w, &x, &y);
if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
return;
enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
if (NILP (enabled_p))
return;
if (button_event->what == mouseDown)
{
show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
last_tool_bar_item = prop_idx;
}
else
{
Lisp_Object key, frame;
struct input_event event;
show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
XSETFRAME (frame, f);
event.kind = TOOL_BAR_EVENT;
event.frame_or_window = frame;
event.arg = frame;
kbd_buffer_store_event (&event);
event.kind = TOOL_BAR_EVENT;
event.frame_or_window = frame;
event.arg = key;
event.modifiers = x_mac_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
button_event->modifiers);
kbd_buffer_store_event (&event);
last_tool_bar_item = -1;
}
}
static void
note_tool_bar_highlight (f, x, y)
struct frame *f;
int x, y;
{
Lisp_Object window = f->tool_bar_window;
struct window *w = XWINDOW (window);
struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
int hpos, vpos;
struct glyph *glyph;
struct glyph_row *row;
int i;
Lisp_Object enabled_p;
int prop_idx;
enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
int mouse_down_p, rc;
if (x <= 0 || y <= 0)
{
clear_mouse_face (dpyinfo);
return;
}
rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
if (rc < 0)
{
clear_mouse_face (dpyinfo);
return;
}
else if (rc == 0)
goto set_help_echo;
clear_mouse_face (dpyinfo);
mouse_down_p = (dpyinfo->grabbed
&& f == last_mouse_frame
&& FRAME_LIVE_P (f));
if (mouse_down_p
&& last_tool_bar_item != prop_idx)
return;
dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
if (!NILP (enabled_p))
{
row = MATRIX_ROW (w->current_matrix, vpos);
for (i = x = 0; i < hpos; ++i)
x += row->glyphs[TEXT_AREA][i].pixel_width;
dpyinfo->mouse_face_beg_col = hpos;
dpyinfo->mouse_face_beg_row = vpos;
dpyinfo->mouse_face_beg_x = x;
dpyinfo->mouse_face_beg_y = row->y;
dpyinfo->mouse_face_past_end = 0;
dpyinfo->mouse_face_end_col = hpos + 1;
dpyinfo->mouse_face_end_row = vpos;
dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
dpyinfo->mouse_face_end_y = row->y;
dpyinfo->mouse_face_window = window;
dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
show_mouse_face (dpyinfo, draw);
dpyinfo->mouse_face_image_state = draw;
}
set_help_echo:
help_echo_object = help_echo_window = Qnil;
help_echo_pos = -1;
help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
if (NILP (help_echo))
help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
}
static int
fast_find_position (w, pos, hpos, vpos, x, y)
struct window *w;
int pos;
int *hpos, *vpos, *x, *y;
{
int i;
int lastcol;
int maybe_next_line_p = 0;
int line_start_position;
int yb = window_text_bottom_y (w);
struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
struct glyph_row *best_row = row;
int row_vpos = 0, best_row_vpos = 0;
int current_x;
while (row->y < yb)
{
if (row->used[TEXT_AREA])
line_start_position = row->glyphs[TEXT_AREA]->charpos;
else
line_start_position = 0;
if (line_start_position > pos)
break;
else if (line_start_position == pos
&& pos == BUF_ZV (XBUFFER (w->buffer)))
{
maybe_next_line_p = 1;
break;
}
else if (line_start_position > 0)
{
best_row = row;
best_row_vpos = row_vpos;
}
if (row->y + row->height >= yb)
break;
++row;
++row_vpos;
}
lastcol = 0;
current_x = best_row->x;
for (i = 0; i < best_row->used[TEXT_AREA]; i++)
{
struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
int charpos;
charpos = glyph->charpos;
if (charpos == pos)
{
*hpos = i;
*vpos = best_row_vpos;
*x = current_x;
*y = best_row->y;
return 1;
}
else if (charpos > pos)
break;
else if (charpos > 0)
lastcol = i;
current_x += glyph->pixel_width;
}
if (maybe_next_line_p)
{
++best_row;
++best_row_vpos;
lastcol = 0;
current_x = best_row->x;
}
*vpos = best_row_vpos;
*hpos = lastcol + 1;
*x = current_x;
*y = best_row->y;
return 0;
}
static void
show_mouse_face (dpyinfo, draw)
struct mac_display_info *dpyinfo;
enum draw_glyphs_face draw;
{
struct window *w = XWINDOW (dpyinfo->mouse_face_window);
struct frame *f = XFRAME (WINDOW_FRAME (w));
int i;
int cursor_off_p = 0;
struct cursor_pos saved_cursor;
saved_cursor = output_cursor;
if (w->current_matrix == NULL)
goto set_x_cursor;
if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
goto set_x_cursor;
set_output_cursor (&w->phys_cursor);
for (i = dpyinfo->mouse_face_beg_row;
i <= dpyinfo->mouse_face_end_row;
i++)
{
int start_hpos, end_hpos, start_x;
struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
if (!row->enabled_p)
continue;
if (i == dpyinfo->mouse_face_beg_row)
{
start_hpos = dpyinfo->mouse_face_beg_col;
start_x = dpyinfo->mouse_face_beg_x;
}
else
{
start_hpos = 0;
start_x = 0;
}
if (i == dpyinfo->mouse_face_end_row)
end_hpos = dpyinfo->mouse_face_end_col;
else
end_hpos = row->used[TEXT_AREA];
if (!w->pseudo_window_p
&& i == output_cursor.vpos
&& output_cursor.hpos >= start_hpos - 1
&& output_cursor.hpos <= end_hpos)
{
x_update_window_cursor (w, 0);
cursor_off_p = 1;
}
if (end_hpos > start_hpos)
{
row->mouse_face_p = draw == DRAW_MOUSE_FACE;
x_draw_glyphs (w, start_x, row, TEXT_AREA,
start_hpos, end_hpos, draw, NULL, NULL, 0);
}
}
if (cursor_off_p)
x_display_cursor (w, 1,
output_cursor.hpos, output_cursor.vpos,
output_cursor.x, output_cursor.y);
output_cursor = saved_cursor;
set_x_cursor:
#if 0
if (draw == DRAW_NORMAL_TEXT)
XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f->output_data.x->text_cursor);
else if (draw == DRAW_MOUSE_FACE)
XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f->output_data.x->cross_cursor);
else
XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f->output_data.x->nontext_cursor);
#endif
;
}
void
clear_mouse_face (dpyinfo)
struct mac_display_info *dpyinfo;
{
if (!NILP (tip_frame))
return;
if (! NILP (dpyinfo->mouse_face_window))
show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
dpyinfo->mouse_face_window = Qnil;
}
void
x_clear_mouse_face (w)
struct window *w;
{
struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
Lisp_Object window;
XSETWINDOW (window, w);
if (EQ (window, dpyinfo->mouse_face_window))
clear_mouse_face (dpyinfo);
}
static void
cancel_mouse_face (f)
FRAME_PTR f;
{
Lisp_Object window;
struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
window = dpyinfo->mouse_face_window;
if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
{
dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
dpyinfo->mouse_face_window = Qnil;
}
}
static struct scroll_bar *x_window_to_scroll_bar ();
static void x_scroll_bar_report_motion ();
void
XTmouse_position (fp, insist, bar_window, part, x, y, time)
FRAME_PTR *fp;
int insist;
Lisp_Object *bar_window;
enum scroll_bar_part *part;
Lisp_Object *x, *y;
unsigned long *time;
{
Point mouse_pos;
int ignore1, ignore2;
WindowPtr wp = FrontWindow ();
struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
Lisp_Object frame, tail;
BLOCK_INPUT;
if (! NILP (last_mouse_scroll_bar) && insist == 0)
x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
else
{
FOR_EACH_FRAME (tail, frame)
XFRAME (frame)->mouse_moved = 0;
last_mouse_scroll_bar = Qnil;
SetPort (wp);
GetMouse (&mouse_pos);
pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
&last_mouse_glyph, insist);
*bar_window = Qnil;
*part = scroll_bar_handle;
*fp = f;
XSETINT (*x, mouse_pos.h);
XSETINT (*y, mouse_pos.v);
*time = last_mouse_movement_time;
}
UNBLOCK_INPUT;
}
static struct scroll_bar *
x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
struct window *w;
int top, left, width, height, disp_top, disp_height;
{
struct frame *f = XFRAME (w->frame);
struct scroll_bar *bar
= XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
Rect r;
ControlHandle ch;
BLOCK_INPUT;
r.left = left;
r.top = disp_top;
r.right = left + width;
r.bottom = disp_top + disp_height;
ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
0L);
SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
SetControlReference (ch, (long) bar);
XSETWINDOW (bar->window, w);
XSETINT (bar->top, top);
XSETINT (bar->left, left);
XSETINT (bar->width, width);
XSETINT (bar->height, height);
XSETINT (bar->start, 0);
XSETINT (bar->end, 0);
bar->dragging = Qnil;
bar->next = FRAME_SCROLL_BARS (f);
bar->prev = Qnil;
XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
if (!NILP (bar->next))
XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
UNBLOCK_INPUT;
return bar;
}
static void
x_scroll_bar_set_handle (bar, start, end, rebuild)
struct scroll_bar *bar;
int start, end;
int rebuild;
{
int dragging = ! NILP (bar->dragging);
ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
if (! rebuild
&& start == XINT (bar->start)
&& end == XINT (bar->end))
return;
BLOCK_INPUT;
{
int inside_width = VERTICAL_SCROLL_BAR_INSIDE_WIDTH (f, XINT (bar->width));
int inside_height = VERTICAL_SCROLL_BAR_INSIDE_HEIGHT (f, XINT (bar->height));
int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
{
int length = end - start;
if (start < 0)
start = 0;
else if (start > top_range)
start = top_range;
end = start + length;
if (end < start)
end = start;
else if (end > top_range && ! dragging)
end = top_range;
}
XSETINT (bar->start, start);
XSETINT (bar->end, end);
if (end > top_range)
end = top_range;
end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
SetControlMinimum (ch, 0);
if (GetControlMaximum (ch) != -1)
SetControlMaximum (ch,
VERTICAL_SCROLL_BAR_TOP_RANGE (f,
XINT (bar->height))
- 1);
SetControlValue (ch, start);
#if 0
SetControlViewSize (ch, end);
#endif
}
UNBLOCK_INPUT;
}
static void
x_scroll_bar_remove (bar)
struct scroll_bar *bar;
{
FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
BLOCK_INPUT;
DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
UNBLOCK_INPUT;
}
static void
XTset_vertical_scroll_bar (w, portion, whole, position)
struct window *w;
int portion, whole, position;
{
struct frame *f = XFRAME (w->frame);
struct scroll_bar *bar;
int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
int window_x, window_y, window_width, window_height;
window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
top = window_y;
width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
height = window_height;
if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
else
left = XFASTINT (w->left);
left *= CANON_X_UNIT (f);
left += FRAME_INTERNAL_BORDER_WIDTH (f);
if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
else
sb_width = width;
if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
sb_left = left + width - sb_width - (width - sb_width) / 2;
else
sb_left = left + (width - sb_width) / 2;
disp_top = top;
disp_height = height;
if (disp_top == 0)
{
disp_top = -1;
disp_height++;
}
else if (disp_top == PIXEL_HEIGHT (f) - 16)
{
disp_top++;
disp_height--;
}
if (sb_left + sb_width == PIXEL_WIDTH (f))
sb_left++;
if (NILP (w->vertical_scroll_bar))
{
BLOCK_INPUT;
XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
left, top, width, height, 0);
UNBLOCK_INPUT;
bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
disp_height);
XSETVECTOR (w->vertical_scroll_bar, bar);
}
else
{
ControlHandle ch;
bar = XSCROLL_BAR (w->vertical_scroll_bar);
ch = SCROLL_BAR_CONTROL_HANDLE (bar);
BLOCK_INPUT;
if (XINT (bar->left) == sb_left
&& XINT (bar->top) == top
&& XINT (bar->width) == sb_width
&& XINT (bar->height) == height)
Draw1Control (ch);
else
{
if (sb_left + sb_width >= PIXEL_WIDTH (f))
XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
sb_left - 1, top, 1, height, 0);
HideControl (ch);
MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
disp_height);
ShowControl (ch);
XSETINT (bar->left, sb_left);
XSETINT (bar->top, top);
XSETINT (bar->width, sb_width);
XSETINT (bar->height, height);
}
UNBLOCK_INPUT;
}
if (NILP (bar->dragging))
{
int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
if (whole == 0)
x_scroll_bar_set_handle (bar, 0, top_range, 0);
else
{
int start = ((double) position * top_range) / whole;
int end = ((double) (position + portion) * top_range) / whole;
x_scroll_bar_set_handle (bar, start, end, 0);
}
}
}
static void
XTcondemn_scroll_bars (frame)
FRAME_PTR frame;
{
while (! NILP (FRAME_SCROLL_BARS (frame)))
{
Lisp_Object bar;
bar = FRAME_SCROLL_BARS (frame);
FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
XSCROLL_BAR (bar)->prev = Qnil;
if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
}
}
static void
XTredeem_scroll_bar (window)
struct window *window;
{
struct scroll_bar *bar;
if (NILP (window->vertical_scroll_bar))
abort ();
bar = XSCROLL_BAR (window->vertical_scroll_bar);
{
FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
if (NILP (bar->prev))
{
if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
return;
else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
window->vertical_scroll_bar))
FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
else
abort ();
}
else
XSCROLL_BAR (bar->prev)->next = bar->next;
if (! NILP (bar->next))
XSCROLL_BAR (bar->next)->prev = bar->prev;
bar->next = FRAME_SCROLL_BARS (f);
bar->prev = Qnil;
XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
if (! NILP (bar->next))
XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
}
}
static void
XTjudge_scroll_bars (f)
FRAME_PTR f;
{
Lisp_Object bar, next;
bar = FRAME_CONDEMNED_SCROLL_BARS (f);
FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
for (; ! NILP (bar); bar = next)
{
struct scroll_bar *b = XSCROLL_BAR (bar);
x_scroll_bar_remove (b);
next = b->next;
b->next = b->prev = Qnil;
}
}
static void
activate_scroll_bars (frame)
FRAME_PTR frame;
{
Lisp_Object bar;
ControlHandle ch;
bar = FRAME_SCROLL_BARS (frame);
while (! NILP (bar))
{
ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
SetControlMaximum (ch,
VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
XINT (XSCROLL_BAR (bar)
->height)) - 1);
bar = XSCROLL_BAR (bar)->next;
}
}
static void
deactivate_scroll_bars (frame)
FRAME_PTR frame;
{
Lisp_Object bar;
ControlHandle ch;
bar = FRAME_SCROLL_BARS (frame);
while (! NILP (bar))
{
ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
SetControlMaximum (ch, XINT (-1));
bar = XSCROLL_BAR (bar)->next;
}
}
static void
x_scroll_bar_handle_click (bar, part_code, er, bufp)
struct scroll_bar *bar;
int part_code;
EventRecord *er;
struct input_event *bufp;
{
if (! GC_WINDOWP (bar->window))
abort ();
bufp->kind = scroll_bar_click;
bufp->frame_or_window = bar->window;
bufp->arg = Qnil;
bar->dragging = Qnil;
switch (part_code)
{
case kControlUpButtonPart:
bufp->part = scroll_bar_up_arrow;
break;
case kControlDownButtonPart:
bufp->part = scroll_bar_down_arrow;
break;
case kControlPageUpPart:
bufp->part = scroll_bar_above_handle;
break;
case kControlPageDownPart:
bufp->part = scroll_bar_below_handle;
break;
case kControlIndicatorPart:
if (er->what == mouseDown)
bar->dragging = make_number (0);
XSETVECTOR (last_mouse_scroll_bar, bar);
bufp->part = scroll_bar_handle;
break;
}
}
static void
x_scroll_bar_note_movement (bar, y_pos, t)
struct scroll_bar *bar;
int y_pos;
Time t;
{
FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
last_mouse_movement_time = t;
f->mouse_moved = 1;
XSETVECTOR (last_mouse_scroll_bar, bar);
if (! GC_NILP (bar->dragging))
{
int new_start = y_pos - 24;
if (new_start != XINT (bar->start))
{
int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
x_scroll_bar_set_handle (bar, new_start, new_end, 0);
}
}
}
static void
x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
FRAME_PTR *fp;
Lisp_Object *bar_window;
enum scroll_bar_part *part;
Lisp_Object *x, *y;
unsigned long *time;
{
struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
WindowPtr wp = FrontWindow ();
Point mouse_pos;
struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
int win_y, top_range;
SetPort (wp);
GetMouse (&mouse_pos);
win_y = mouse_pos.v - XINT (bar->top);
top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
win_y -= 24;
if (! NILP (bar->dragging))
win_y -= XINT (bar->dragging);
if (win_y < 0)
win_y = 0;
if (win_y > top_range)
win_y = top_range;
*fp = f;
*bar_window = bar->window;
if (! NILP (bar->dragging))
*part = scroll_bar_handle;
else if (win_y < XINT (bar->start))
*part = scroll_bar_above_handle;
else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
*part = scroll_bar_handle;
else
*part = scroll_bar_below_handle;
XSETINT (*x, win_y);
XSETINT (*y, top_range);
f->mouse_moved = 0;
last_mouse_scroll_bar = Qnil;
*time = last_mouse_movement_time;
}
static void
note_overwritten_text_cursor (w, hpos, n)
struct window *w;
int hpos, n;
{
if (updated_area == TEXT_AREA
&& output_cursor.vpos == w->phys_cursor.vpos
&& hpos <= w->phys_cursor.hpos
&& (n < 0
|| hpos + n > w->phys_cursor.hpos))
w->phys_cursor_on_p = 0;
}
static void
x_clip_to_row (w, row, gc, whole_line_p)
struct window *w;
struct glyph_row *row;
GC gc;
int whole_line_p;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
Rect clip_rect;
int window_x, window_y, window_width, window_height;
window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
clip_rect.top = max (clip_rect.top, window_y);
clip_rect.right = clip_rect.left + window_width;
clip_rect.bottom = clip_rect.top + row->visible_height;
if (whole_line_p)
{
clip_rect.left -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
clip_rect.right += FRAME_X_FLAGS_AREA_WIDTH (f);
}
mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
}
static void
x_draw_hollow_cursor (w, row)
struct window *w;
struct glyph_row *row;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
Display *dpy = FRAME_MAC_DISPLAY (f);
int x, y, wd, h;
XGCValues xgcv;
struct glyph *cursor_glyph;
GC gc;
x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
+ row->ascent - w->phys_cursor_ascent);
h = row->height - 1;
cursor_glyph = get_phys_cursor_glyph (w);
if (cursor_glyph == NULL)
return;
wd = cursor_glyph->pixel_width - 1;
if (cursor_glyph->type == STRETCH_GLYPH
&& !x_stretch_cursor_p)
wd = min (CANON_X_UNIT (f), wd);
xgcv.foreground = f->output_data.mac->cursor_pixel;
if (dpyinfo->scratch_cursor_gc)
XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
else
dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
GCForeground, &xgcv);
gc = dpyinfo->scratch_cursor_gc;
x_clip_to_row (w, row, gc, 0);
mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
}
static void
x_draw_bar_cursor (w, row, width)
struct window *w;
struct glyph_row *row;
int width;
{
if (w->phys_cursor.hpos < row->used[TEXT_AREA])
{
struct frame *f = XFRAME (w->frame);
struct glyph *cursor_glyph;
GC gc;
int x;
unsigned long mask;
XGCValues xgcv;
Display *dpy;
Window window;
cursor_glyph = get_phys_cursor_glyph (w);
if (cursor_glyph == NULL)
return;
xgcv.background = f->output_data.mac->cursor_pixel;
xgcv.foreground = f->output_data.mac->cursor_pixel;
mask = GCForeground | GCBackground;
dpy = FRAME_MAC_DISPLAY (f);
window = FRAME_MAC_WINDOW (f);
gc = FRAME_X_DISPLAY_INFO (f)->scratch_cursor_gc;
if (gc)
XChangeGC (dpy, gc, mask, &xgcv);
else
{
gc = XCreateGC (dpy, window, mask, &xgcv);
FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
}
if (width < 0)
width = f->output_data.mac->cursor_width;
x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
x_clip_to_row (w, row, gc, 0);
XFillRectangle (dpy, window, gc,
x,
WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
min (cursor_glyph->pixel_width, width),
row->height);
mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
}
}
static void
x_clear_cursor (w)
struct window *w;
{
if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
x_update_window_cursor (w, 0);
}
static void
x_draw_phys_cursor_glyph (w, row, hl)
struct window *w;
struct glyph_row *row;
enum draw_glyphs_face hl;
{
if (w->phys_cursor.hpos < row->used[TEXT_AREA])
{
x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
hl, 0, 0, 0);
if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
{
if (row > w->current_matrix->rows
&& MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
x_fix_overlapping_area (w, row - 1, TEXT_AREA);
if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
&& MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
x_fix_overlapping_area (w, row + 1, TEXT_AREA);
}
}
}
static void
x_erase_phys_cursor (w)
struct window *w;
{
struct frame *f = XFRAME (w->frame);
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
int hpos = w->phys_cursor.hpos;
int vpos = w->phys_cursor.vpos;
int mouse_face_here_p = 0;
struct glyph_matrix *active_glyphs = w->current_matrix;
struct glyph_row *cursor_row;
struct glyph *cursor_glyph;
enum draw_glyphs_face hl;
if (w->phys_cursor_type == NO_CURSOR)
goto mark_cursor_off;
if (vpos >= active_glyphs->nrows)
goto mark_cursor_off;
cursor_row = MATRIX_ROW (active_glyphs, vpos);
if (!cursor_row->enabled_p)
goto mark_cursor_off;
if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
goto mark_cursor_off;
if (! NILP (dpyinfo->mouse_face_window)
&& w == XWINDOW (dpyinfo->mouse_face_window)
&& (vpos > dpyinfo->mouse_face_beg_row
|| (vpos == dpyinfo->mouse_face_beg_row
&& hpos >= dpyinfo->mouse_face_beg_col))
&& (vpos < dpyinfo->mouse_face_end_row
|| (vpos == dpyinfo->mouse_face_end_row
&& hpos < dpyinfo->mouse_face_end_col))
&& cursor_row->used[TEXT_AREA] > hpos)
mouse_face_here_p = 1;
if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
{
int x;
int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
cursor_glyph = get_phys_cursor_glyph (w);
if (cursor_glyph == NULL)
goto mark_cursor_off;
x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
x,
WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
cursor_row->y)),
cursor_glyph->pixel_width,
cursor_row->visible_height,
0);
}
if (mouse_face_here_p)
hl = DRAW_MOUSE_FACE;
else if (cursor_row->inverse_p)
hl = DRAW_INVERSE_VIDEO;
else
hl = DRAW_NORMAL_TEXT;
x_draw_phys_cursor_glyph (w, cursor_row, hl);
mark_cursor_off:
w->phys_cursor_on_p = 0;
w->phys_cursor_type = NO_CURSOR;
}
void
x_display_and_set_cursor (w, on, hpos, vpos, x, y)
struct window *w;
int on, hpos, vpos, x, y;
{
struct frame *f = XFRAME (w->frame);
int new_cursor_type;
int new_cursor_width;
struct glyph_matrix *current_glyphs;
struct glyph_row *glyph_row;
struct glyph *glyph;
if (! FRAME_VISIBLE_P (f)
|| FRAME_GARBAGED_P (f)
|| vpos >= w->current_matrix->nrows
|| hpos >= w->current_matrix->matrix_w)
return;
if (!on && !w->phys_cursor_on_p)
return;
current_glyphs = w->current_matrix;
glyph_row = MATRIX_ROW (current_glyphs, vpos);
glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
if (!glyph_row->enabled_p)
{
w->phys_cursor_on_p = 0;
return;
}
xassert (interrupt_input_blocked);
new_cursor_width = -1;
if (cursor_in_echo_area
&& FRAME_HAS_MINIBUF_P (f)
&& EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
{
if (w == XWINDOW (echo_area_window))
new_cursor_type = FRAME_DESIRED_CURSOR (f);
else
new_cursor_type = HOLLOW_BOX_CURSOR;
}
else
{
if (w != XWINDOW (selected_window)
|| f != FRAME_X_DISPLAY_INFO (f)->x_highlight_frame)
{
extern int cursor_in_non_selected_windows;
if (MINI_WINDOW_P (w) || !cursor_in_non_selected_windows)
new_cursor_type = NO_CURSOR;
else
new_cursor_type = HOLLOW_BOX_CURSOR;
}
else if (w->cursor_off_p)
new_cursor_type = NO_CURSOR;
else
{
struct buffer *b = XBUFFER (w->buffer);
if (EQ (b->cursor_type, Qt))
new_cursor_type = FRAME_DESIRED_CURSOR (f);
else
new_cursor_type = x_specified_cursor_type (b->cursor_type,
&new_cursor_width);
}
}
if (w->phys_cursor_on_p
&& (!on
|| w->phys_cursor.x != x
|| w->phys_cursor.y != y
|| new_cursor_type != w->phys_cursor_type))
x_erase_phys_cursor (w);
if (on && !w->phys_cursor_on_p)
{
w->phys_cursor_ascent = glyph_row->ascent;
w->phys_cursor_height = glyph_row->height;
w->phys_cursor.x = x;
w->phys_cursor.y = glyph_row->y;
w->phys_cursor.hpos = hpos;
w->phys_cursor.vpos = vpos;
w->phys_cursor_type = new_cursor_type;
w->phys_cursor_on_p = 1;
switch (new_cursor_type)
{
case HOLLOW_BOX_CURSOR:
x_draw_hollow_cursor (w, glyph_row);
break;
case FILLED_BOX_CURSOR:
x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
break;
case BAR_CURSOR:
x_draw_bar_cursor (w, glyph_row, new_cursor_width);
break;
case NO_CURSOR:
break;
default:
abort ();
}
#ifdef HAVE_X_I18N
if (w == XWINDOW (f->selected_window))
if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMPreeditPosition))
xic_set_preeditarea (w, x, y);
#endif
}
#ifndef XFlush
if (updating_frame != f)
XFlush (FRAME_X_DISPLAY (f));
#endif
}
void
x_display_cursor (w, on, hpos, vpos, x, y)
struct window *w;
int on, hpos, vpos, x, y;
{
BLOCK_INPUT;
x_display_and_set_cursor (w, on, hpos, vpos, x, y);
UNBLOCK_INPUT;
}
void
x_update_cursor (f, on_p)
struct frame *f;
{
x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
}
static void
x_update_cursor_in_window_tree (w, on_p)
struct window *w;
int on_p;
{
while (w)
{
if (!NILP (w->hchild))
x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
else if (!NILP (w->vchild))
x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
else
x_update_window_cursor (w, on_p);
w = NILP (w->next) ? 0 : XWINDOW (w->next);
}
}
static void
x_update_window_cursor (w, on)
struct window *w;
int on;
{
if (w->current_matrix)
{
BLOCK_INPUT;
x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
w->phys_cursor.x, w->phys_cursor.y);
UNBLOCK_INPUT;
}
}
#if 0
void
refreshicon (f)
struct frame *f;
{
}
int
x_bitmap_icon (f, file)
struct frame *f;
Lisp_Object file;
{
int bitmap_id;
if (FRAME_X_WINDOW (f) == 0)
return 1;
if (f->output_data.x->icon_bitmap > 0)
x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
f->output_data.x->icon_bitmap = 0;
if (STRINGP (file))
bitmap_id = x_create_bitmap_from_file (f, file);
else
{
if (FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id < 0)
FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
= x_create_bitmap_from_data (f, gnu_bits,
gnu_width, gnu_height);
x_reference_bitmap (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
bitmap_id = FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id;
}
x_wm_set_icon_pixmap (f, bitmap_id);
f->output_data.x->icon_bitmap = bitmap_id;
return 0;
}
int
x_text_icon (f, icon_name)
struct frame *f;
char *icon_name;
{
if (FRAME_X_WINDOW (f) == 0)
return 1;
#ifdef HAVE_X11R4
{
XTextProperty text;
text.value = (unsigned char *) icon_name;
text.encoding = XA_STRING;
text.format = 8;
text.nitems = strlen (icon_name);
#ifdef USE_X_TOOLKIT
XSetWMIconName (FRAME_X_DISPLAY (f), XtWindow (f->output_data.x->widget),
&text);
#else
XSetWMIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), &text);
#endif
}
#else
XSetIconName (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), icon_name);
#endif
if (f->output_data.x->icon_bitmap > 0)
x_destroy_bitmap (f, f->output_data.x->icon_bitmap);
f->output_data.x->icon_bitmap = 0;
x_wm_set_icon_pixmap (f, 0);
return 0;
}
#define X_ERROR_MESSAGE_SIZE 200
static Lisp_Object x_error_message_string;
static void
x_error_catcher (display, error)
Display *display;
XErrorEvent *error;
{
XGetErrorText (display, error->error_code,
XSTRING (x_error_message_string)->data,
X_ERROR_MESSAGE_SIZE);
}
void x_check_errors ();
static Lisp_Object x_catch_errors_unwind ();
int
x_catch_errors (dpy)
Display *dpy;
{
int count = specpdl_ptr - specpdl;
XSync (dpy, False);
record_unwind_protect (x_catch_errors_unwind, x_error_message_string);
x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE);
XSTRING (x_error_message_string)->data[0] = 0;
return count;
}
static Lisp_Object
x_catch_errors_unwind (old_val)
Lisp_Object old_val;
{
x_error_message_string = old_val;
return Qnil;
}
void
x_check_errors (dpy, format)
Display *dpy;
char *format;
{
XSync (dpy, False);
if (XSTRING (x_error_message_string)->data[0])
error (format, XSTRING (x_error_message_string)->data);
}
int
x_had_errors_p (dpy)
Display *dpy;
{
XSync (dpy, False);
return XSTRING (x_error_message_string)->data[0] != 0;
}
void
x_clear_errors (dpy)
Display *dpy;
{
XSTRING (x_error_message_string)->data[0] = 0;
}
void
x_uncatch_errors (dpy, count)
Display *dpy;
int count;
{
unbind_to (count, Qnil);
}
#if 0
static unsigned int x_wire_count;
x_trace_wire ()
{
fprintf (stderr, "Lib call: %d\n", ++x_wire_count);
}
#endif
static SIGTYPE
x_connection_signal (signalnum)
int signalnum;
{
#ifdef USG
signal (signalnum, x_connection_signal);
#endif
}
static SIGTYPE
x_connection_closed (display, error_message)
Display *display;
char *error_message;
{
struct x_display_info *dpyinfo = x_display_info_for_display (display);
Lisp_Object frame, tail;
#if 0
#ifdef USE_X_TOOLKIT
XtCloseDisplay (display);
#endif
#endif
if (dpyinfo)
dpyinfo->display = 0;
FOR_EACH_FRAME (tail, frame)
{
Lisp_Object minibuf_frame;
minibuf_frame
= WINDOW_FRAME (XWINDOW (FRAME_MINIBUF_WINDOW (XFRAME (frame))));
if (FRAME_X_P (XFRAME (frame))
&& FRAME_X_P (XFRAME (minibuf_frame))
&& ! EQ (frame, minibuf_frame)
&& FRAME_X_DISPLAY_INFO (XFRAME (minibuf_frame)) == dpyinfo)
Fdelete_frame (frame, Qt);
}
FOR_EACH_FRAME (tail, frame)
if (FRAME_X_P (XFRAME (frame))
&& FRAME_X_DISPLAY_INFO (XFRAME (frame)) == dpyinfo)
{
FRAME_KBOARD (XFRAME (frame))->Vdefault_minibuffer_frame = Qt;
Fdelete_frame (frame, Qt);
}
if (dpyinfo)
x_delete_display (dpyinfo);
if (x_display_list == 0)
{
fprintf (stderr, "%s\n", error_message);
shut_down_emacs (0, 0, Qnil);
exit (70);
}
#ifdef SIGIO
sigunblock (sigmask (SIGIO));
#endif
sigunblock (sigmask (SIGALRM));
TOTALLY_UNBLOCK_INPUT;
clear_waiting_for_input ();
error ("%s", error_message);
}
static void
x_error_quitter (display, error)
Display *display;
XErrorEvent *error;
{
char buf[256], buf1[356];
XGetErrorText (display, error->error_code, buf, sizeof (buf));
sprintf (buf1, "X protocol error: %s on protocol request %d",
buf, error->request_code);
x_connection_closed (display, buf1);
}
static int
x_error_handler (display, error)
Display *display;
XErrorEvent *error;
{
if (! NILP (x_error_message_string))
x_error_catcher (display, error);
else
x_error_quitter (display, error);
return 0;
}
static int
x_io_error_quitter (display)
Display *display;
{
char buf[256];
sprintf (buf, "Connection lost to X server `%s'", DisplayString (display));
x_connection_closed (display, buf);
return 0;
}
#endif
Lisp_Object
x_new_font (f, fontname)
struct frame *f;
register char *fontname;
{
struct font_info *fontp
= FS_LOAD_FONT (f, 0, fontname, -1);
if (!fontp)
return Qnil;
f->output_data.mac->font = (XFontStruct *) (fontp->font);
f->output_data.mac->baseline_offset = fontp->baseline_offset;
f->output_data.mac->fontset = -1;
if (f->scroll_bar_pixel_width > 0)
{
int wid = FONT_WIDTH (f->output_data.mac->font);
f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
}
else
{
int wid = FONT_WIDTH (f->output_data.mac->font);
f->scroll_bar_cols = (14 + wid - 1) / wid;
}
if (FRAME_MAC_WINDOW (f) != 0)
{
XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
f->output_data.mac->font);
XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
f->output_data.mac->font);
XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
f->output_data.mac->font);
frame_update_line_height (f);
x_set_window_size (f, 0, f->width, f->height);
}
else
f->output_data.mac->line_height = FONT_HEIGHT (f->output_data.mac->font);
return build_string (fontp->full_name);
}
Lisp_Object
x_new_fontset (f, fontsetname)
struct frame *f;
char *fontsetname;
{
int fontset = fs_query_fontset (build_string (fontsetname), 0);
Lisp_Object result;
if (fontset < 0)
return Qnil;
if (f->output_data.mac->fontset == fontset)
return fontset_name (fontset);
result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
if (!STRINGP (result))
return Qnil;
f->output_data.mac->fontset = fontset;
#ifdef HAVE_X_I18N
if (FRAME_XIC (f)
&& (FRAME_XIC_STYLE (f) & (XIMPreeditPosition | XIMStatusArea)))
xic_set_xfontset (f, XSTRING (fontset_ascii (fontset))->data);
#endif
return build_string (fontsetname);
}
#if 0
#ifdef HAVE_X_I18N
#ifdef HAVE_X11R6
static void
xim_destroy_callback (xim, client_data, call_data)
XIM xim;
XPointer client_data;
XPointer call_data;
{
struct x_display_info *dpyinfo = (struct x_display_info *) client_data;
Lisp_Object frame, tail;
BLOCK_INPUT;
FOR_EACH_FRAME (tail, frame)
{
struct frame *f = XFRAME (frame);
if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
{
FRAME_XIC (f) = NULL;
if (FRAME_XIC_FONTSET (f))
{
XFreeFontSet (FRAME_X_DISPLAY (f), FRAME_XIC_FONTSET (f));
FRAME_XIC_FONTSET (f) = NULL;
}
}
}
dpyinfo->xim = NULL;
XFree (dpyinfo->xim_styles);
UNBLOCK_INPUT;
}
#endif
static void
xim_open_dpy (dpyinfo, resource_name)
struct x_display_info *dpyinfo;
char *resource_name;
{
#ifdef USE_XIM
XIM xim;
xim = XOpenIM (dpyinfo->display, dpyinfo->xrdb, resource_name, EMACS_CLASS);
dpyinfo->xim = xim;
if (xim)
{
#ifdef HAVE_X11R6
XIMCallback destroy;
#endif
XGetIMValues (xim, XNQueryInputStyle, &dpyinfo->xim_styles, NULL);
#ifdef HAVE_X11R6
destroy.callback = xim_destroy_callback;
destroy.client_data = (XPointer)dpyinfo;
XSetIMValues (xim, XNDestroyCallback, &destroy, NULL);
#endif
}
#else
dpyinfo->xim = NULL;
#endif
}
#ifdef HAVE_X11R6_XIM
struct xim_inst_t
{
struct x_display_info *dpyinfo;
char *resource_name;
};
static void
xim_instantiate_callback (display, client_data, call_data)
Display *display;
XPointer client_data;
XPointer call_data;
{
struct xim_inst_t *xim_inst = (struct xim_inst_t *) client_data;
struct x_display_info *dpyinfo = xim_inst->dpyinfo;
if (dpyinfo->xim)
return;
xim_open_dpy (dpyinfo, xim_inst->resource_name);
if (dpyinfo->xim && dpyinfo->reference_count > 0)
{
Lisp_Object tail, frame;
BLOCK_INPUT;
FOR_EACH_FRAME (tail, frame)
{
struct frame *f = XFRAME (frame);
if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
if (FRAME_XIC (f) == NULL)
{
create_frame_xic (f);
if (FRAME_XIC_STYLE (f) & XIMStatusArea)
xic_set_statusarea (f);
if (FRAME_XIC_STYLE (f) & XIMPreeditPosition)
{
struct window *w = XWINDOW (f->selected_window);
xic_set_preeditarea (w, w->cursor.x, w->cursor.y);
}
}
}
UNBLOCK_INPUT;
}
}
#endif
static void
xim_initialize (dpyinfo, resource_name)
struct x_display_info *dpyinfo;
char *resource_name;
{
#ifdef USE_XIM
#ifdef HAVE_X11R6_XIM
struct xim_inst_t *xim_inst;
int len;
dpyinfo->xim = NULL;
xim_inst = (struct xim_inst_t *) xmalloc (sizeof (struct xim_inst_t));
xim_inst->dpyinfo = dpyinfo;
len = strlen (resource_name);
xim_inst->resource_name = (char *) xmalloc (len + 1);
bcopy (resource_name, xim_inst->resource_name, len + 1);
XRegisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
resource_name, EMACS_CLASS,
xim_instantiate_callback,
(XPointer) xim_inst);
#else
dpyinfo->xim = NULL;
xim_open_dpy (dpyinfo, resource_name);
#endif
#else
dpyinfo->xim = NULL;
#endif
}
static void
xim_close_dpy (dpyinfo)
struct x_display_info *dpyinfo;
{
#ifdef USE_XIM
#ifdef HAVE_X11R6_XIM
XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
NULL, EMACS_CLASS,
xim_instantiate_callback, NULL);
#endif
XCloseIM (dpyinfo->xim);
dpyinfo->xim = NULL;
XFree (dpyinfo->xim_styles);
#endif
}
#endif
#endif
static void
x_calc_absolute_position (f)
struct frame *f;
{
Point pt;
int flags = f->output_data.mac->size_hint_flags;
pt.h = pt.v = 0;
if (f->output_data.mac->parent_desc != FRAME_MAC_DISPLAY_INFO (f)->root_window)
{
GrafPtr savePort;
GetPort (&savePort);
SetPort (FRAME_MAC_WINDOW (f));
SetPt(&pt, FRAME_MAC_WINDOW (f)->portRect.left, FRAME_MAC_WINDOW (f)->portRect.top);
LocalToGlobal (&pt);
SetPort (savePort);
}
if (flags & XNegative)
f->output_data.mac->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
- 2 * f->output_data.mac->border_width - pt.h
- PIXEL_WIDTH (f)
+ f->output_data.mac->left_pos);
if (flags & YNegative)
f->output_data.mac->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
- 2 * f->output_data.mac->border_width - pt.v
- PIXEL_HEIGHT (f)
+ f->output_data.mac->top_pos);
f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
}
void
x_set_offset (f, xoff, yoff, change_gravity)
struct frame *f;
register int xoff, yoff;
int change_gravity;
{
if (change_gravity > 0)
{
f->output_data.mac->top_pos = yoff;
f->output_data.mac->left_pos = xoff;
f->output_data.mac->size_hint_flags &= ~ (XNegative | YNegative);
if (xoff < 0)
f->output_data.mac->size_hint_flags |= XNegative;
if (yoff < 0)
f->output_data.mac->size_hint_flags |= YNegative;
f->output_data.mac->win_gravity = NorthWestGravity;
}
x_calc_absolute_position (f);
BLOCK_INPUT;
x_wm_set_size_hint (f, (long) 0, 0);
MoveWindow (f->output_data.mac->mWP, xoff + 6, yoff + 42, false);
UNBLOCK_INPUT;
}
void
x_set_window_size (f, change_gravity, cols, rows)
struct frame *f;
int change_gravity;
int cols, rows;
{
int pixelwidth, pixelheight;
check_frame_size (f, &rows, &cols);
f->output_data.mac->vertical_scroll_bar_extra
= (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
? 0
: FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
: (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.mac->font)));
f->output_data.mac->flags_areas_extra
= FRAME_FLAGS_AREA_WIDTH (f);
pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
f->output_data.mac->win_gravity = NorthWestGravity;
x_wm_set_size_hint (f, (long) 0, 0);
SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
change_frame_size (f, rows, cols, 0, 1, 0);
PIXEL_WIDTH (f) = pixelwidth;
PIXEL_HEIGHT (f) = pixelheight;
SET_FRAME_GARBAGED (f);
XFlush (FRAME_X_DISPLAY (f));
mark_window_cursors_off (XWINDOW (f->root_window));
cancel_mouse_face (f);
}
void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
void
x_set_mouse_position (f, x, y)
struct frame *f;
int x, y;
{
int pix_x, pix_y;
pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.mac->font) / 2;
pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.mac->line_height / 2;
if (pix_x < 0) pix_x = 0;
if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
if (pix_y < 0) pix_y = 0;
if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
x_set_mouse_pixel_position (f, pix_x, pix_y);
}
void
x_set_mouse_pixel_position (f, pix_x, pix_y)
struct frame *f;
int pix_x, pix_y;
{
#if 0
BLOCK_INPUT;
XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
0, 0, 0, 0, pix_x, pix_y);
UNBLOCK_INPUT;
#endif
}
static void
x_focus_on_frame (f)
struct frame *f;
{
#if 0
x_raise_frame (f);
#endif
#if 0
XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
RevertToPointerRoot, CurrentTime);
#endif
}
static void
x_unfocus_frame (f)
struct frame *f;
{
#if 0
if (FRAME_X_DISPLAY_INFO (f)->x_focus_frame == f)
XSetInputFocus (FRAME_X_DISPLAY (f), PointerRoot,
RevertToPointerRoot, CurrentTime);
#endif
}
void
x_raise_frame (f)
struct frame *f;
{
if (f->async_visible)
SelectWindow (FRAME_MAC_WINDOW (f));
}
void
x_lower_frame (f)
struct frame *f;
{
if (f->async_visible)
SendBehind (FRAME_MAC_WINDOW (f), nil);
}
void
XTframe_raise_lower (f, raise_flag)
FRAME_PTR f;
int raise_flag;
{
if (raise_flag)
x_raise_frame (f);
else
x_lower_frame (f);
}
void
x_make_frame_visible (f)
struct frame *f;
{
Lisp_Object type;
int original_top, original_left;
BLOCK_INPUT;
if (! FRAME_VISIBLE_P (f))
{
if (! FRAME_ICONIFIED_P (f)
&& ! f->output_data.mac->asked_for_visible)
x_set_offset (f, f->output_data.mac->left_pos,
f->output_data.mac->top_pos, 0);
f->output_data.mac->asked_for_visible = 1;
ShowWindow (FRAME_MAC_WINDOW (f));
}
XFlush (FRAME_MAC_DISPLAY (f));
{
Lisp_Object frame;
int count;
UNBLOCK_INPUT;
XSETFRAME (frame, f);
for (count = input_signal_count + 10;
input_signal_count < count && !FRAME_VISIBLE_P (f);)
{
x_sync (f);
if (input_polling_used ())
{
extern void poll_for_input_1 P_ ((void));
int old_poll_suppress_count = poll_suppress_count;
poll_suppress_count = 1;
poll_for_input_1 ();
poll_suppress_count = old_poll_suppress_count;
}
FRAME_SAMPLE_VISIBILITY (f);
}
}
}
void
x_make_frame_invisible (f)
struct frame *f;
{
if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
BLOCK_INPUT;
HideWindow (FRAME_MAC_WINDOW (f));
f->visible = 0;
FRAME_ICONIFIED_P (f) = 0;
f->async_visible = 0;
f->async_iconified = 0;
UNBLOCK_INPUT;
}
void
x_iconify_frame (f)
struct frame *f;
{
#if 0
int result;
Lisp_Object type;
if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
if (f->async_iconified)
return;
BLOCK_INPUT;
FRAME_SAMPLE_VISIBILITY (f);
type = x_icon_type (f);
if (!NILP (type))
x_bitmap_icon (f, type);
#ifdef USE_X_TOOLKIT
if (! FRAME_VISIBLE_P (f))
{
if (! EQ (Vx_no_window_manager, Qt))
x_wm_set_window_state (f, IconicState);
XtMapWidget (f->output_data.x->widget);
f->iconified = 1;
f->visible = 1;
f->async_iconified = 1;
f->async_visible = 0;
UNBLOCK_INPUT;
return;
}
result = XIconifyWindow (FRAME_X_DISPLAY (f),
XtWindow (f->output_data.x->widget),
DefaultScreen (FRAME_X_DISPLAY (f)));
UNBLOCK_INPUT;
if (!result)
error ("Can't notify window manager of iconification");
f->async_iconified = 1;
f->async_visible = 0;
BLOCK_INPUT;
XFlush (FRAME_X_DISPLAY (f));
UNBLOCK_INPUT;
#else
if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
{
XEvent message;
message.xclient.window = FRAME_X_WINDOW (f);
message.xclient.type = ClientMessage;
message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
message.xclient.format = 32;
message.xclient.data.l[0] = IconicState;
if (! XSendEvent (FRAME_X_DISPLAY (f),
DefaultRootWindow (FRAME_X_DISPLAY (f)),
False,
SubstructureRedirectMask | SubstructureNotifyMask,
&message))
{
UNBLOCK_INPUT_RESIGNAL;
error ("Can't notify window manager of iconification");
}
}
x_wm_set_window_state (f, IconicState);
if (!FRAME_VISIBLE_P (f))
{
XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
}
f->async_iconified = 1;
f->async_visible = 0;
XFlush (FRAME_X_DISPLAY (f));
UNBLOCK_INPUT;
#endif
#endif
}
void
x_destroy_window (f)
struct frame *f;
{
struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
BLOCK_INPUT;
DisposeWindow (FRAME_MAC_WINDOW (f));
free_frame_menubar (f);
free_frame_faces (f);
xfree (f->output_data.mac);
f->output_data.mac = 0;
if (f == dpyinfo->x_focus_frame)
dpyinfo->x_focus_frame = 0;
if (f == dpyinfo->x_focus_event_frame)
dpyinfo->x_focus_event_frame = 0;
if (f == dpyinfo->x_highlight_frame)
dpyinfo->x_highlight_frame = 0;
dpyinfo->reference_count--;
if (f == dpyinfo->mouse_face_mouse_frame)
{
dpyinfo->mouse_face_beg_row
= dpyinfo->mouse_face_beg_col = -1;
dpyinfo->mouse_face_end_row
= dpyinfo->mouse_face_end_col = -1;
dpyinfo->mouse_face_window = Qnil;
dpyinfo->mouse_face_deferred_gc = 0;
dpyinfo->mouse_face_mouse_frame = 0;
}
UNBLOCK_INPUT;
}
void
x_wm_set_size_hint (f, flags, user_position)
struct frame *f;
long flags;
int user_position;
{
#if 0
XSizeHints size_hints;
#ifdef USE_X_TOOLKIT
Arg al[2];
int ac = 0;
Dimension widget_width, widget_height;
Window window = XtWindow (f->output_data.x->widget);
#else
Window window = FRAME_X_WINDOW (f);
#endif
size_hints.flags = PResizeInc | PMinSize ;
size_hints.x = f->output_data.x->left_pos;
size_hints.y = f->output_data.x->top_pos;
#ifdef USE_X_TOOLKIT
XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
XtSetArg (al[ac], XtNheight, &widget_height); ac++;
XtGetValues (f->output_data.x->widget, al, ac);
size_hints.height = widget_height;
size_hints.width = widget_width;
#else
size_hints.height = PIXEL_HEIGHT (f);
size_hints.width = PIXEL_WIDTH (f);
#endif
size_hints.width_inc = FONT_WIDTH (f->output_data.x->font);
size_hints.height_inc = f->output_data.x->line_height;
size_hints.max_width
= FRAME_X_DISPLAY_INFO (f)->width - CHAR_TO_PIXEL_WIDTH (f, 0);
size_hints.max_height
= FRAME_X_DISPLAY_INFO (f)->height - CHAR_TO_PIXEL_HEIGHT (f, 0);
#ifndef USE_X_TOOLKIT
{
int base_width, base_height;
int min_rows = 0, min_cols = 0;
base_width = CHAR_TO_PIXEL_WIDTH (f, 0);
base_height = CHAR_TO_PIXEL_HEIGHT (f, 0);
check_frame_size (f, &min_rows, &min_cols);
#ifdef HAVE_X11R4
size_hints.flags |= PBaseSize;
size_hints.base_width = base_width;
size_hints.base_height = base_height;
size_hints.min_width = base_width + min_cols * size_hints.width_inc;
size_hints.min_height = base_height + min_rows * size_hints.height_inc;
#else
size_hints.min_width = base_width;
size_hints.min_height = base_height;
#endif
}
if (flags)
{
size_hints.flags |= flags;
goto no_read;
}
#endif
{
XSizeHints hints;
long supplied_return;
int value;
#ifdef HAVE_X11R4
value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
&supplied_return);
#else
value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
#endif
#ifdef USE_X_TOOLKIT
size_hints.base_height = hints.base_height;
size_hints.base_width = hints.base_width;
size_hints.min_height = hints.min_height;
size_hints.min_width = hints.min_width;
#endif
if (flags)
size_hints.flags |= flags;
else
{
if (value == 0)
hints.flags = 0;
if (hints.flags & PSize)
size_hints.flags |= PSize;
if (hints.flags & PPosition)
size_hints.flags |= PPosition;
if (hints.flags & USPosition)
size_hints.flags |= USPosition;
if (hints.flags & USSize)
size_hints.flags |= USSize;
}
}
#ifndef USE_X_TOOLKIT
no_read:
#endif
#ifdef PWinGravity
size_hints.win_gravity = f->output_data.x->win_gravity;
size_hints.flags |= PWinGravity;
if (user_position)
{
size_hints.flags &= ~ PPosition;
size_hints.flags |= USPosition;
}
#endif
#ifdef HAVE_X11R4
XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
#else
XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
#endif
#endif
}
#if 0
void
x_wm_set_window_state (f, state)
struct frame *f;
int state;
{
#ifdef USE_X_TOOLKIT
Arg al[1];
XtSetArg (al[0], XtNinitialState, state);
XtSetValues (f->output_data.x->widget, al, 1);
#else
Window window = FRAME_X_WINDOW (f);
f->output_data.x->wm_hints.flags |= StateHint;
f->output_data.x->wm_hints.initial_state = state;
XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
#endif
}
void
x_wm_set_icon_pixmap (f, pixmap_id)
struct frame *f;
int pixmap_id;
{
Pixmap icon_pixmap;
#ifndef USE_X_TOOLKIT
Window window = FRAME_X_WINDOW (f);
#endif
if (pixmap_id > 0)
{
icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
}
else
{
#if 0
f->output_data.x->wm_hints.icon_pixmap = None;
#else
return;
#endif
}
#ifdef USE_X_TOOLKIT
{
Arg al[1];
XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
XtSetValues (f->output_data.x->widget, al, 1);
}
#else
f->output_data.x->wm_hints.flags |= IconPixmapHint;
XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
#endif
}
#endif
void
x_wm_set_icon_position (f, icon_x, icon_y)
struct frame *f;
int icon_x, icon_y;
{
#if 0
#ifdef USE_X_TOOLKIT
Window window = XtWindow (f->output_data.x->widget);
#else
Window window = FRAME_X_WINDOW (f);
#endif
f->output_data.x->wm_hints.flags |= IconPositionHint;
f->output_data.x->wm_hints.icon_x = icon_x;
f->output_data.x->wm_hints.icon_y = icon_y;
XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
#endif
}
struct font_info *
x_get_font_info (f, font_idx)
FRAME_PTR f;
int font_idx;
{
return (FRAME_MAC_FONT_TABLE (f) + font_idx);
}
char **font_name_table = NULL;
int font_name_table_size = 0;
int font_name_count = 0;
static int
stricmp (const char *s, const char *t)
{
for ( ; tolower (*s) == tolower (*t); s++, t++)
if (*s == '\0')
return 0;
return tolower (*s) - tolower (*t);
}
static int
wildstrieq (char *s1, char *s2)
{
if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
return true;
return stricmp (s1, s2) == 0;
}
static int
mac_font_pattern_match (fontname, pattern)
char * fontname;
char * pattern;
{
char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
char *ptr;
strcpy (font_name_copy, fontname);
ptr = regex;
*ptr++ = '^';
for (; *pattern; pattern++)
{
if (*pattern == '?')
*ptr++ = '.';
else if (*pattern == '*')
{
*ptr++ = '.';
*ptr++ = '*';
}
else
*ptr++ = *pattern;
}
*ptr = '$';
*(ptr + 1) = '\0';
return (fast_c_string_match_ignore_case (build_string (regex),
font_name_copy) >= 0);
}
static int
mac_font_match (char *mf, char *xf)
{
char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
return mac_font_pattern_match (mf, xf);
if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
return mac_font_pattern_match (mf, xf);
return (wildstrieq (m_foundry, x_foundry)
&& wildstrieq (m_family, x_family)
&& wildstrieq (m_weight, x_weight)
&& wildstrieq (m_slant, x_slant)
&& wildstrieq (m_charset, x_charset))
|| mac_font_pattern_match (mf, xf);
}
static char *
mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
{
char foundry[32], family[32], cs[32];
char xf[255], *result, *p;
if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
{
strcpy(foundry, "Apple");
strcpy(family, name);
switch (scriptcode)
{
case smTradChinese:
strcpy(cs, "big5-0");
break;
case smSimpChinese:
strcpy(cs, "gb2312.1980-0");
break;
case smJapanese:
strcpy(cs, "jisx0208.1983-sjis");
break;
case -smJapanese:
strcpy(cs, "jisx0201.1976-0");
break;
case smKorean:
strcpy(cs, "ksc5601.1989-0");
break;
default:
strcpy(cs, "mac-roman");
break;
}
}
sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
foundry, family, style & bold ? "bold" : "medium",
style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
result = (char *) xmalloc (strlen (xf) + 1);
strcpy (result, xf);
for (p = result; *p; p++)
*p = tolower(*p);
return result;
}
static void
x_font_name_to_mac_font_name (char *xf, char *mf)
{
char foundry[32], family[32], weight[20], slant[2], cs[32];
strcpy (mf, "");
if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
foundry, family, weight, slant, cs) != 5 &&
sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
foundry, family, weight, slant, cs) != 5)
return;
if (strcmp (cs, "big5-0") == 0 || strcmp (cs, "gb2312.1980-0") == 0
|| strcmp (cs, "jisx0208.1983-sjis") == 0
|| strcmp (cs, "jisx0201.1976-0") == 0
|| strcmp (cs, "ksc5601.1989-0") == 0 || strcmp (cs, "mac-roman") == 0)
strcpy(mf, family);
else
sprintf(mf, "%s-%s-%s", foundry, family, cs);
}
static void
init_font_name_table ()
{
GrafPtr port;
SInt16 fontnum, old_fontnum;
int num_mac_fonts = CountResources('FOND');
int i, j;
Handle font_handle, font_handle_2;
short id, scriptcode;
ResType type;
Str32 name;
struct FontAssoc *fat;
struct AsscEntry *assc_entry;
GetPort (&port);
old_fontnum = port->txFont;
for (i = 1; i <= num_mac_fonts; i++)
{
font_handle = GetIndResource ('FOND', i);
if (!font_handle)
continue;
GetResInfo (font_handle, &id, &type, name);
GetFNum (name, &fontnum);
p2cstr (name);
if (fontnum == 0)
continue;
TextFont (fontnum);
scriptcode = FontToScript (fontnum);
do
{
HLock (font_handle);
if (GetResourceSizeOnDisk (font_handle) >= sizeof (struct FamRec))
{
fat = (struct FontAssoc *) (*font_handle
+ sizeof (struct FamRec));
assc_entry = (struct AsscEntry *) (*font_handle
+ sizeof (struct FamRec)
+ sizeof (struct FontAssoc));
for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
{
if (font_name_table_size == 0)
{
font_name_table_size = 16;
font_name_table = (char **)
xmalloc (font_name_table_size * sizeof (char *));
}
else if (font_name_count >= font_name_table_size ||
scriptcode == smJapanese &&
font_name_count + 1 >= font_name_table_size)
{
font_name_table_size += 16;
font_name_table = (char **)
xrealloc (font_name_table,
font_name_table_size * sizeof (char *));
}
font_name_table[font_name_count++]
= mac_to_x_fontname (name,
assc_entry->fontSize,
assc_entry->fontStyle,
scriptcode);
if (smJapanese == scriptcode)
{
font_name_table[font_name_count++]
= mac_to_x_fontname (name,
assc_entry->fontSize,
assc_entry->fontStyle,
-smJapanese);
}
}
}
HUnlock (font_handle);
font_handle_2 = GetNextFOND (font_handle);
ReleaseResource (font_handle);
font_handle = font_handle_2;
}
while (ResError () == noErr && font_handle);
}
TextFont (old_fontnum);
}
Lisp_Object
x_list_fonts (struct frame *f,
Lisp_Object pattern,
int size,
int maxnames)
{
char *ptnstr;
Lisp_Object newlist = Qnil;
int n_fonts = 0;
int i;
struct gcpro gcpro1, gcpro2;
if (font_name_table == NULL)
init_font_name_table ();
ptnstr = XSTRING (pattern)->data;
GCPRO2 (pattern, newlist);
for (i = 0; i < font_name_count; i++)
{
if (mac_font_pattern_match (font_name_table[i], ptnstr))
{
newlist = Fcons (build_string (font_name_table[i]), newlist);
n_fonts++;
if (n_fonts >= maxnames)
break;
}
}
UNGCPRO;
return newlist;
}
#if GLYPH_DEBUG
static void
x_check_font (f, font)
struct frame *f;
XFontStruct *font;
{
int i;
struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
xassert (font != NULL);
for (i = 0; i < dpyinfo->n_fonts; i++)
if (dpyinfo->font_table[i].name
&& font == dpyinfo->font_table[i].font)
break;
xassert (i < dpyinfo->n_fonts);
}
#endif
static INLINE void
x_font_min_bounds (font, w, h)
MacFontStruct *font;
int *w, *h;
{
*h = FONT_HEIGHT (font);
*w = font->min_bounds.width;
if (*w <= 0)
*w = font->max_bounds.width;
}
static int
x_compute_min_glyph_bounds (f)
struct frame *f;
{
int i;
struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
MacFontStruct *font;
int old_width = dpyinfo->smallest_char_width;
int old_height = dpyinfo->smallest_font_height;
dpyinfo->smallest_font_height = 100000;
dpyinfo->smallest_char_width = 100000;
for (i = 0; i < dpyinfo->n_fonts; ++i)
if (dpyinfo->font_table[i].name)
{
struct font_info *fontp = dpyinfo->font_table + i;
int w, h;
font = (MacFontStruct *) fontp->font;
xassert (font != (MacFontStruct *) ~0);
x_font_min_bounds (font, &w, &h);
dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
}
xassert (dpyinfo->smallest_char_width > 0
&& dpyinfo->smallest_font_height > 0);
return (dpyinfo->n_fonts == 1
|| dpyinfo->smallest_char_width < old_width
|| dpyinfo->smallest_font_height < old_height);
}
static int
is_fully_specified_xlfd (char *p)
{
int i;
char *q;
if (*p != '-')
return 0;
for (i = 0; i < 13; i++)
{
q = strchr (p + 1, '-');
if (q == NULL)
return 0;
if (q - p == 2 && *(p + 1) == '*')
return 0;
p = q;
}
if (strchr (p + 1, '-') != NULL)
return 0;
if (*(p + 1) == '*' && *(p + 2) == '\0')
return 0;
return 1;
}
const int kDefaultFontSize = 9;
static MacFontStruct *
XLoadQueryFont (Display *dpy, char *fontname)
{
int i, size, is_two_byte_font, char_width;
char *name;
GrafPtr port;
SInt16 old_fontnum, old_fontsize;
Style old_fontface;
Str32 mfontname;
SInt16 fontnum;
Style fontface = normal;
MacFontStruct *font;
FontInfo the_fontinfo;
char s_weight[7], c_slant;
if (is_fully_specified_xlfd (fontname))
name = fontname;
else
{
for (i = 0; i < font_name_count; i++)
if (mac_font_pattern_match (font_name_table[i], fontname))
break;
if (i >= font_name_count)
return NULL;
name = font_name_table[i];
}
GetPort (&port);
old_fontnum = port->txFont;
old_fontsize = port->txSize;
old_fontface = port->txFace;
if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
size = kDefaultFontSize;
if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
if (strcmp (s_weight, "bold") == 0)
fontface |= bold;
if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
if (c_slant == 'i')
fontface |= italic;
x_font_name_to_mac_font_name (name, mfontname);
c2pstr (mfontname);
GetFNum (mfontname, &fontnum);
if (fontnum == 0)
return NULL;
font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
font->fontname = (char *) xmalloc (strlen (name) + 1);
bcopy (name, font->fontname, strlen (name) + 1);
font->mac_fontnum = fontnum;
font->mac_fontsize = size;
font->mac_fontface = fontface;
font->mac_scriptcode = FontToScript (fontnum);
{
char cs[32];
if (sscanf (name,
"-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
cs) == 1
&& 0 == strcmp (cs, "jisx0201.1976-0"))
font->mac_scriptcode = smRoman;
}
is_two_byte_font = font->mac_scriptcode == smJapanese ||
font->mac_scriptcode == smTradChinese ||
font->mac_scriptcode == smSimpChinese ||
font->mac_scriptcode == smKorean;
TextFont (fontnum);
TextSize (size);
TextFace (fontface);
GetFontInfo (&the_fontinfo);
font->ascent = the_fontinfo.ascent;
font->descent = the_fontinfo.descent;
font->min_byte1 = 0;
if (is_two_byte_font)
font->max_byte1 = 1;
else
font->max_byte1 = 0;
font->min_char_or_byte2 = 0x20;
font->max_char_or_byte2 = 0xff;
if (is_two_byte_font)
{
switch (font->mac_scriptcode)
{
case smJapanese:
char_width = StringWidth("\p\x81\x40");
break;
case smTradChinese:
char_width = StringWidth("\p\xa1\x40");
break;
case smSimpChinese:
char_width = StringWidth("\p\xa1\xa1");
break;
case smKorean:
char_width = StringWidth("\p\xa1\xa1");
break;
}
}
else
char_width = CharWidth ('m');
font->max_bounds.rbearing = char_width;
font->max_bounds.lbearing = 0;
font->max_bounds.width = char_width;
font->max_bounds.ascent = the_fontinfo.ascent;
font->max_bounds.descent = the_fontinfo.descent;
font->min_bounds = font->max_bounds;
if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
font->per_char = NULL;
else
{
font->per_char = (XCharStruct *)
xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
{
int c;
for (c = 0x20; c <= 0xff; c++)
{
font->per_char[c - 0x20] = font->max_bounds;
font->per_char[c - 0x20].width = CharWidth (c);
}
}
}
TextFont (old_fontnum);
TextSize (old_fontsize);
TextFace (old_fontface);
return font;
}
struct font_info *
x_load_font (f, fontname, size)
struct frame *f;
register char *fontname;
int size;
{
struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
Lisp_Object font_names;
font_names = x_list_fonts (f, build_string (fontname), size, 1);
if (!NILP (font_names))
{
Lisp_Object tail;
int i;
for (i = 0; i < dpyinfo->n_fonts; i++)
for (tail = font_names; CONSP (tail); tail = XCDR (tail))
if (dpyinfo->font_table[i].name
&& (!strcmp (dpyinfo->font_table[i].name,
XSTRING (XCAR (tail))->data)
|| !strcmp (dpyinfo->font_table[i].full_name,
XSTRING (XCAR (tail))->data)))
return (dpyinfo->font_table + i);
}
{
char *full_name;
struct MacFontStruct *font;
struct font_info *fontp;
unsigned long value;
int i;
if (size > 0 && !NILP (font_names))
fontname = (char *) XSTRING (XCAR (font_names))->data;
font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
if (!font)
return NULL;
for (i = 0; i < dpyinfo->n_fonts; ++i)
if (dpyinfo->font_table[i].name == NULL)
break;
if (i == dpyinfo->n_fonts
&& dpyinfo->n_fonts == dpyinfo->font_table_size)
{
int sz;
dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
dpyinfo->font_table
= (struct font_info *) xrealloc (dpyinfo->font_table, sz);
}
fontp = dpyinfo->font_table + i;
if (i == dpyinfo->n_fonts)
++dpyinfo->n_fonts;
BLOCK_INPUT;
fontp->font = font;
fontp->font_idx = i;
fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
fontp->full_name = fontp->name;
fontp->size = font->max_bounds.width;
fontp->height = FONT_HEIGHT (font);
{
int max_height = font->max_bounds.ascent + font->max_bounds.descent;
if (max_height > fontp->height)
fontp->height = max_height;
}
if (font->mac_scriptcode == smJapanese)
fontp->encoding[1] = 4;
else
{
fontp->encoding[1]
= (font->max_byte1 == 0
? (font->min_char_or_byte2 < 0x80
? (font->max_char_or_byte2 < 0x80
? 0
: FONT_ENCODING_NOT_DECIDED)
: 1)
: (font->min_byte1 < 0x80
? (font->max_byte1 < 0x80
? (font->min_char_or_byte2 < 0x80
? (font->max_char_or_byte2 < 0x80
? 0
: FONT_ENCODING_NOT_DECIDED)
: 3)
: FONT_ENCODING_NOT_DECIDED)
: (font->min_char_or_byte2 < 0x80
? (font->max_char_or_byte2 < 0x80
? 2
: FONT_ENCODING_NOT_DECIDED)
: 1)));
}
#if 0
fontp->baseline_offset
= (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
? (long) value : 0);
fontp->relative_compose
= (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
? (long) value : 0);
fontp->default_ascent
= (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
? (long) value : 0);
#else
fontp->baseline_offset = 0;
fontp->relative_compose = 0;
fontp->default_ascent = 0;
#endif
fonts_changed_p = x_compute_min_glyph_bounds (f);
UNBLOCK_INPUT;
return fontp;
}
}
struct font_info *
x_query_font (f, fontname)
struct frame *f;
register char *fontname;
{
struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
int i;
for (i = 0; i < dpyinfo->n_fonts; i++)
if (dpyinfo->font_table[i].name
&& (!strcmp (dpyinfo->font_table[i].name, fontname)
|| !strcmp (dpyinfo->font_table[i].full_name, fontname)))
return (dpyinfo->font_table + i);
return NULL;
}
void
x_find_ccl_program (fontp)
struct font_info *fontp;
{
Lisp_Object list, elt;
for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
{
elt = XCAR (list);
if (CONSP (elt)
&& STRINGP (XCAR (elt))
&& (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
>= 0))
break;
}
if (! NILP (list))
{
struct ccl_program *ccl
= (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
if (setup_ccl_program (ccl, XCDR (elt)) < 0)
xfree (ccl);
else
fontp->font_encoder = ccl;
}
}
#ifdef USE_X_TOOLKIT
static XrmOptionDescRec emacs_options[] = {
{"-geometry", ".geometry", XrmoptionSepArg, NULL},
{"-iconic", ".iconic", XrmoptionNoArg, (XtPointer) "yes"},
{"-internal-border-width", "*EmacsScreen.internalBorderWidth",
XrmoptionSepArg, NULL},
{"-ib", "*EmacsScreen.internalBorderWidth", XrmoptionSepArg, NULL},
{"-T", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
{"-wn", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
{"-title", "*EmacsShell.title", XrmoptionSepArg, (XtPointer) NULL},
{"-iconname", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
{"-in", "*EmacsShell.iconName", XrmoptionSepArg, (XtPointer) NULL},
{"-mc", "*pointerColor", XrmoptionSepArg, (XtPointer) NULL},
{"-cr", "*cursorColor", XrmoptionSepArg, (XtPointer) NULL}
};
#endif
static int x_initialized;
#ifdef MULTI_KBOARD
static int
same_x_server (name1, name2)
char *name1, *name2;
{
int seen_colon = 0;
unsigned char *system_name = XSTRING (Vsystem_name)->data;
int system_name_length = strlen (system_name);
int length_until_period = 0;
while (system_name[length_until_period] != 0
&& system_name[length_until_period] != '.')
length_until_period++;
if (! strncmp (name1, "unix:", 5))
name1 += 4;
if (! strncmp (name2, "unix:", 5))
name2 += 4;
if (! strncmp (name1, system_name, system_name_length)
&& name1[system_name_length] == ':')
name1 += system_name_length;
if (! strncmp (name2, system_name, system_name_length)
&& name2[system_name_length] == ':')
name2 += system_name_length;
if (! strncmp (name1, system_name, length_until_period)
&& name1[length_until_period] == ':')
name1 += length_until_period;
if (! strncmp (name2, system_name, length_until_period)
&& name2[length_until_period] == ':')
name2 += length_until_period;
for (; *name1 != '\0' && *name1 == *name2; name1++, name2++)
{
if (*name1 == ':')
seen_colon++;
if (seen_colon && *name1 == '.')
return 1;
}
return (seen_colon
&& (*name1 == '.' || *name1 == '\0')
&& (*name2 == '.' || *name2 == '\0'));
}
#endif
struct mac_display_info *
x_term_init (display_name, xrm_option, resource_name)
Lisp_Object display_name;
char *xrm_option;
char *resource_name;
{
if (!x_initialized)
{
x_initialize ();
x_initialized = 1;
}
return &one_mac_display_info;
}
static struct redisplay_interface x_redisplay_interface =
{
x_produce_glyphs,
x_write_glyphs,
x_insert_glyphs,
x_clear_end_of_line,
x_scroll_run,
x_after_update_window_line,
x_update_window_begin,
x_update_window_end,
XTcursor_to,
x_flush,
x_clear_mouse_face,
x_get_glyph_overhangs,
x_fix_overlapping_area
};
#include <Events.h>
#include <Quickdraw.h>
#include <Balloons.h>
#include <Devices.h>
#include <Fonts.h>
#include <Gestalt.h>
#include <Menus.h>
#include <Processes.h>
#include <Sound.h>
#include <ToolUtils.h>
#include <TextUtils.h>
#include <Dialogs.h>
#include <Script.h>
#include <Scrap.h>
#include <Types.h>
#include <TextEncodingConverter.h>
#include <Resources.h>
#if __MWERKS__
#include <unix.h>
#endif
#define M_APPLE 128
#define I_ABOUT 1
#define WINDOW_RESOURCE 128
#define TERM_WINDOW_RESOURCE 129
#define DEFAULT_NUM_COLS 80
#define MIN_DOC_SIZE 64
#define MAX_DOC_SIZE 32767
#define WNE_SLEEP_AT_SUSPEND 10
#define WNE_SLEEP_AT_RESUME 1
static int handling_window_update = 0;
static Boolean app_is_suspended = false;
static long app_sleep_time = WNE_SLEEP_AT_RESUME;
#define EXTRA_STACK_ALLOC (256 * 1024)
#define ARGV_STRING_LIST_ID 129
#define ABOUT_ALERT_ID 128
#define RAM_TOO_LARGE_ALERT_ID 129
Boolean terminate_flag = false;
Lisp_Object Vmac_command_key_is_meta;
int mac_keyboard_text_encoding;
int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
Lisp_Object Qmac_ready_for_drag_n_drop;
Lisp_Object drag_and_drop_file_list;
Point saved_menu_event_location;
static void init_required_apple_events(void);
static pascal OSErr do_ae_open_application(const AppleEvent *, AppleEvent *, long);
static pascal OSErr do_ae_print_documents(const AppleEvent *, AppleEvent *, long);
static pascal OSErr do_ae_open_documents(AppleEvent *, AppleEvent *, long);
static pascal OSErr do_ae_quit_application(AppleEvent *, AppleEvent *, long);
extern void init_emacs_passwd_dir ();
extern int emacs_main (int, char **, char **);
extern void check_alarm ();
extern void initialize_applescript();
extern void terminate_applescript();
static void
do_get_menus (void)
{
Handle menubar_handle;
MenuHandle menu_handle;
menubar_handle = GetNewMBar (128);
if(menubar_handle == NULL)
abort ();
SetMenuBar (menubar_handle);
DrawMenuBar ();
menu_handle = GetMenuHandle (M_APPLE);
if(menu_handle != NULL)
AppendResMenu (menu_handle,'DRVR');
else
abort ();
}
static void
do_init_managers (void)
{
InitGraf (&qd.thePort);
InitFonts ();
FlushEvents (everyEvent, 0);
InitWindows ();
InitMenus ();
TEInit ();
InitDialogs (NULL);
InitCursor ();
SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
MaxApplZone ();
MoreMasters ();
}
static void
do_check_ram_size (void)
{
SInt32 physical_ram_size, logical_ram_size;
if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
|| Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
|| physical_ram_size > 256 * 1024 * 1024
|| logical_ram_size > 256 * 1024 * 1024)
{
StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
exit (1);
}
}
static void
do_window_update (WindowPtr win)
{
struct mac_output *mwp = (mac_output *) GetWRefCon (win);
struct frame *f = mwp->mFP;
if (f)
{
if (f->async_visible == 0)
{
f->async_visible = 1;
f->async_iconified = 0;
SET_FRAME_GARBAGED (f);
if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
record_asynch_buffer_change ();
}
else
{
BeginUpdate (win);
handling_window_update = 1;
expose_frame (f, 0, 0, 0, 0);
handling_window_update = 0;
EndUpdate (win);
}
}
}
static void
do_window_activate (WindowPtr win)
{
mac_output *mwp = (mac_output *) GetWRefCon (win);
struct frame *f = mwp->mFP;
if (f)
{
x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
activate_scroll_bars (f);
}
}
static void
do_window_deactivate (WindowPtr win)
{
mac_output *mwp = (mac_output *) GetWRefCon (win);
struct frame *f = mwp->mFP;
if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
{
x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
deactivate_scroll_bars (f);
}
}
static void
do_app_resume ()
{
mac_output *mwp = (mac_output *) GetWRefCon (FrontWindow ());
struct frame *f = mwp->mFP;
SetCursor (&qd.arrow);
if (f)
{
x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
activate_scroll_bars (f);
}
app_is_suspended = false;
app_sleep_time = WNE_SLEEP_AT_RESUME;
}
static void
do_app_suspend ()
{
mac_output *mwp = (mac_output *) GetWRefCon (FrontWindow ());
struct frame *f = mwp->mFP;
if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
{
x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
deactivate_scroll_bars (f);
}
app_is_suspended = true;
app_sleep_time = WNE_SLEEP_AT_SUSPEND;
}
static void
do_mouse_moved (Point mouse_pos)
{
WindowPtr wp = FrontWindow ();
struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
SetPort (wp);
GlobalToLocal (&mouse_pos);
note_mouse_movement (f, &mouse_pos);
}
static void
do_os_event (EventRecord *erp)
{
switch((erp->message >> 24) & 0x000000FF)
{
case suspendResumeMessage:
if((erp->message & resumeFlag) == 1)
do_app_resume ();
else
do_app_suspend ();
break;
case mouseMovedMessage:
do_mouse_moved (erp->where);
break;
}
}
static void
do_events (EventRecord *erp)
{
switch (erp->what)
{
case updateEvt:
do_window_update ((WindowPtr) erp->message);
break;
case osEvt:
do_os_event (erp);
break;
case activateEvt:
if ((erp->modifiers & activeFlag) != 0)
do_window_activate ((WindowPtr) erp->message);
else
do_window_deactivate ((WindowPtr) erp->message);
break;
}
}
static void
do_apple_menu (SInt16 menu_item)
{
Str255 item_name;
SInt16 da_driver_refnum;
if (menu_item == I_ABOUT)
NoteAlert (ABOUT_ALERT_ID, NULL);
else
{
GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
da_driver_refnum = OpenDeskAcc (item_name);
}
}
void
do_menu_choice (SInt32 menu_choice)
{
SInt16 menu_id, menu_item;
menu_id = HiWord (menu_choice);
menu_item = LoWord (menu_choice);
if (menu_id == 0)
return;
switch (menu_id)
{
case M_APPLE:
do_apple_menu (menu_item);
break;
default:
{
WindowPtr wp = FrontWindow ();
struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
MenuHandle menu = GetMenuHandle (menu_id);
if (menu)
{
UInt32 refcon;
GetMenuItemRefCon (menu, menu_item, &refcon);
menubar_selection_callback (f, refcon);
}
}
}
HiliteMenu (0);
}
static void
do_grow_window (WindowPtr w, EventRecord *e)
{
long grow_size;
Rect limit_rect;
int rows, columns;
mac_output *mwp = (mac_output *) GetWRefCon (w);
struct frame *f = mwp->mFP;
SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
grow_size = GrowWindow (w, e->where, &limit_rect);
if (grow_size != 0)
{
rows = PIXEL_TO_CHAR_HEIGHT (f, HiWord (grow_size));
columns = PIXEL_TO_CHAR_WIDTH (f, LoWord (grow_size));
x_set_window_size (f, 0, columns, rows);
}
}
static void
do_zoom_window (WindowPtr w, int zoom_in_or_out)
{
GrafPtr save_port;
Rect zoom_rect, port_rect;
Point top_left;
int w_title_height, columns, rows, width, height, dummy, x, y;
mac_output *mwp = (mac_output *) GetWRefCon (w);
struct frame *f = mwp->mFP;
GetPort (&save_port);
SetPort (w);
EraseRect (&(w->portRect));
if (zoom_in_or_out == inZoomOut)
{
SetPt(&top_left, w->portRect.left, w->portRect.top);
LocalToGlobal (&top_left);
w_title_height = top_left.v - 1
- (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight();
zoom_rect = qd.screenBits.bounds;
zoom_rect.top += w_title_height;
InsetRect (&zoom_rect, 8, 4);
zoom_rect.right = zoom_rect.left
+ CHAR_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
(**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState = zoom_rect;
}
ZoomWindow (w, zoom_in_or_out, w == FrontWindow());
port_rect = w->portRect;
rows = PIXEL_TO_CHAR_HEIGHT (f, port_rect.bottom - port_rect.top);
columns = PIXEL_TO_CHAR_WIDTH (f, port_rect.right - port_rect.left);
x_set_window_size (mwp->mFP, 0, columns, rows);
SetPort (save_port);
}
void
init_required_apple_events ()
{
OSErr err;
long result;
err = Gestalt (gestaltAppleEventsAttr, &result);
if (err != noErr)
abort ();
if (!(result & (1 << gestaltAppleEventsPresent)))
abort ();
err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
NewAEEventHandlerProc ((AEEventHandlerProcPtr) do_ae_open_application),
0L, false);
if (err != noErr)
abort ();
err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
NewAEEventHandlerProc ((AEEventHandlerProcPtr) do_ae_open_documents),
0L, false);
if (err != noErr)
abort ();
err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
NewAEEventHandlerProc ((AEEventHandlerProcPtr) do_ae_print_documents),
0L, false);
if (err != noErr)
abort ();
err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
NewAEEventHandlerProc ((AEEventHandlerProcPtr) do_ae_quit_application),
0L, false);
if (err != noErr)
abort ();
}
static pascal OSErr
do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
{
return noErr;
}
extern int
path_from_vol_dir_name (char *, int, short, long, char *);
static pascal OSErr
do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
{
OSErr err, err2;
AEDesc the_desc;
AEKeyword keyword;
DescType actual_type;
Size actual_size;
err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
if (err != noErr)
goto descriptor_error_exit;
err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
&actual_type, (Ptr) &keyword,
sizeof (keyword), &actual_size);
if ((err == noErr) || (err != errAEDescNotFound))
{
err = errAEEventNotHandled;
goto error_exit;
}
err = noErr;
{
long num_files_to_open;
err = AECountItems (&the_desc, &num_files_to_open);
if (err == noErr)
{
int i;
for (i = 1; (err == noErr) && (i <= num_files_to_open); i++) {
FSSpec fs;
Str255 path_name, unix_path_name;
err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
(Ptr) &fs, sizeof (fs), &actual_size);
if (err != noErr) break;
if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
fs.name) &&
mac_to_posix_pathname (path_name, unix_path_name, 255))
drag_and_drop_file_list = Fcons (build_string (unix_path_name),
drag_and_drop_file_list);
}
}
}
error_exit:
err2 = AEDisposeDesc(&the_desc);
descriptor_error_exit:
return err;
}
static pascal OSErr
do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
{
return errAEEventNotHandled;
}
static pascal OSErr
do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
{
terminate_flag = true;
return noErr;
}
#if __profile__
void
profiler_exit_proc ()
{
ProfilerDump ("\pEmacs.prof");
ProfilerTerm ();
}
#endif
#undef main
int
main (void)
{
#if __profile__
if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
exit(1);
#endif
#if __MWERKS__
_fcreator = 'EMAx';
_ftype = 'TEXT';
#endif
do_init_managers ();
do_get_menus ();
do_check_ram_size ();
init_emacs_passwd_dir ();
init_environ ();
initialize_applescript ();
init_required_apple_events ();
{
char **argv;
int argc = 0;
get_string_list (&argv, ARGV_STRING_LIST_ID);
while (argv[argc])
argc++;
atexit (terminate_applescript);
#if __profile__
atexit (profiler_exit_proc);
#endif
(void) emacs_main (argc, argv, 0);
}
return 0;
}
static unsigned char keycode_to_xkeysym_table[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, '\xae' , 0, '\xaa' ,
0, '\xab' , 0, '\x7f' ,
0, 0, 0, '\xaf' ,
'\x8d' , 0, '\xad' , 0,
0, '\xbd' , '\xb0' , '\xb1' ,
'\xb2' , '\xb3' , '\xb4' , '\xb5' ,
'\xb6' , '\xb7' , 0, '\xb8' ,
'\xb9' , 0, 0, 0,
'\xc2' , '\xc3' , '\xc4' , '\xc0' ,
'\xc5' , '\xc6' , 0, '\xc8' ,
0, '\xca' , 0, '\xcb' ,
0, '\xc7' , 0, '\xc9' ,
0, '\xcc' , '\x9e' , '\x95' ,
'\x9a' , '\x9f' , '\xc1' , '\x9c' ,
'\xbf' , '\x9b' , '\xbe' , '\x51' ,
'\x53' , '\x54' , '\x52' , 0
};
static int
keycode_to_xkeysym (int keyCode, int *xKeySym)
{
*xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
return *xKeySym != 0;
}
int
XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
{
int count = 0;
EventRecord er;
int the_modifiers;
EventMask event_mask;
if (interrupt_input_blocked)
{
interrupt_input_pending = 1;
return -1;
}
interrupt_input_pending = 0;
BLOCK_INPUT;
input_signal_count++;
if (numchars <= 0)
abort ();
if (handling_window_update)
{
UNBLOCK_INPUT;
return 0;
}
if (terminate_flag)
Fkill_emacs (make_number (1));
bufp->arg = Qnil;
event_mask = everyEvent;
if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
event_mask -= highLevelEventMask;
while (WaitNextEvent (event_mask, &er, 0L, NULL) && numchars > 0)
switch (er.what)
{
case mouseDown:
case mouseUp:
{
WindowPtr window_ptr = FrontWindow ();
SInt16 part_code;
if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
&& er.what == mouseUp)
{
struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
Point mouse_loc = er.where;
SetPort (window_ptr);
GlobalToLocal (&mouse_loc);
bufp->code = 0;
bufp->kind = scroll_bar_click;
bufp->frame_or_window = tracked_scroll_bar->window;
bufp->part = scroll_bar_handle;
bufp->modifiers = up_modifier;
bufp->timestamp = er.when * (1000 / 60);
XSETINT (bufp->x, tracked_scroll_bar->left + 2);
XSETINT (bufp->y, mouse_loc.v - 24);
tracked_scroll_bar->dragging = Qnil;
mouse_tracking_in_progress = mouse_tracking_none;
tracked_scroll_bar = NULL;
count++;
bufp++;
numchars--;
break;
}
part_code = FindWindow (er.where, &window_ptr);
switch (part_code)
{
case inMenuBar:
{
struct frame *f = ((mac_output *)
GetWRefCon (FrontWindow ()))->mFP;
saved_menu_event_location = er.where;
bufp->kind = menu_bar_activate_event;
XSETFRAME (bufp->frame_or_window, f);
count++;
bufp++;
numchars--;
}
break;
case inContent:
if (window_ptr != FrontWindow ())
SelectWindow (window_ptr);
else
{
int control_part_code;
ControlHandle ch;
struct mac_output *mwp = (mac_output *)
GetWRefCon (window_ptr);
Point mouse_loc = er.where;
SetPort (window_ptr);
GlobalToLocal (&mouse_loc);
control_part_code = FindControl (mouse_loc, window_ptr, &ch);
bufp->code = 0;
XSETINT (bufp->x, mouse_loc.h);
XSETINT (bufp->y, mouse_loc.v);
bufp->timestamp = er.when * (1000 / 60);
if (control_part_code != 0)
{
struct scroll_bar *bar = (struct scroll_bar *)
GetControlReference (ch);
x_scroll_bar_handle_click (bar, control_part_code, &er,
bufp);
if (er.what == mouseDown
&& control_part_code == kControlIndicatorPart)
{
mouse_tracking_in_progress = mouse_tracking_scroll_bar;
tracked_scroll_bar = bar;
}
else
{
mouse_tracking_in_progress = mouse_tracking_none;
tracked_scroll_bar = NULL;
}
}
else
{
bufp->kind = mouse_click;
XSETFRAME (bufp->frame_or_window, mwp->mFP);
if (er.what == mouseDown)
mouse_tracking_in_progress = mouse_tracking_mouse_movement;
else
mouse_tracking_in_progress = mouse_tracking_none;
}
switch (er.what)
{
case mouseDown:
bufp->modifiers = down_modifier;
break;
case mouseUp:
bufp->modifiers = up_modifier;
break;
}
count++;
bufp++;
numchars--;
}
break;
case inDrag:
DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
break;
case inGoAway:
if (TrackGoAway (window_ptr, er.where))
{
bufp->kind = delete_window_event;
XSETFRAME (bufp->frame_or_window,
((mac_output *) GetWRefCon (window_ptr))->mFP);
count++;
bufp++;
numchars--;
}
break;
case inGrow:
do_grow_window(window_ptr, &er);
break;
case inZoomIn:
case inZoomOut:
if (TrackBox (window_ptr, er.where, part_code))
do_zoom_window (window_ptr, part_code);
break;
default:
break;
}
}
break;
case updateEvt:
case osEvt:
case activateEvt:
do_events (&er);
break;
case keyDown:
case autoKey:
{
int keycode = (er.message & keyCodeMask) >> 8;
int xkeysym;
ObscureCursor ();
if (keycode == 0x33)
{
bufp->code = 0x7f;
bufp->kind = ascii_keystroke;
}
else if (keycode_to_xkeysym (keycode, &xkeysym))
{
bufp->code = 0xff00 | xkeysym;
bufp->kind = non_ascii_keystroke;
}
else
{
if (er.modifiers
& (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
{
int new_modifiers = er.modifiers & 0xf600;
int new_keycode = keycode | new_modifiers;
Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
unsigned long some_state = 0;
bufp->code = KeyTranslate (kchr_ptr, new_keycode,
&some_state) & 0xff;
}
else
bufp->code = er.message & charCodeMask;
bufp->kind = ascii_keystroke;
}
}
if (mac_keyboard_text_encoding != kTextEncodingMacRoman
&& bufp->kind == ascii_keystroke && bufp->code >= 128)
{
static TECObjectRef converter = NULL;
OSStatus the_err = noErr;
OSStatus convert_status = noErr;
if (converter == NULL)
{
the_err = TECCreateConverter (&converter,
kTextEncodingMacRoman,
mac_keyboard_text_encoding);
current_mac_keyboard_text_encoding = mac_keyboard_text_encoding;
}
else if (mac_keyboard_text_encoding != current_mac_keyboard_text_encoding)
{
TECDisposeConverter (converter);
the_err = TECCreateConverter (&converter,
kTextEncodingMacRoman,
mac_keyboard_text_encoding);
current_mac_keyboard_text_encoding = mac_keyboard_text_encoding;
}
if (the_err == noErr)
{
unsigned char ch = bufp->code;
ByteCount actual_input_length, actual_output_length;
unsigned char outch;
convert_status = TECConvertText (converter, &ch, 1,
&actual_input_length,
&outch, 1,
&actual_output_length);
if (convert_status == noErr
&& actual_input_length == 1
&& actual_output_length == 1)
bufp->code = outch;
}
}
the_modifiers = 0;
if (er.modifiers & shiftKey)
the_modifiers |= shift_modifier;
if (er.modifiers & controlKey)
the_modifiers |= ctrl_modifier;
if (er.modifiers
& (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
the_modifiers |= meta_modifier;
bufp->modifiers = the_modifiers;
{
mac_output *mwp = (mac_output *) GetWRefCon (FrontWindow ());
XSETFRAME (bufp->frame_or_window, mwp->mFP);
}
bufp->timestamp = er.when * (1000 / 60);
count++;
bufp++;
numchars--;
break;
case kHighLevelEvent:
drag_and_drop_file_list = Qnil;
AEProcessAppleEvent(&er);
if (!NILP (drag_and_drop_file_list))
{
struct frame *f;
WindowPtr wp;
Lisp_Object frame;
wp = FrontWindow ();
if (!wp)
f = NULL;
else
f = ((mac_output *) GetWRefCon (wp))->mFP;
bufp->kind = drag_n_drop;
bufp->code = 0;
bufp->timestamp = er.when * (1000 / 60);
bufp->modifiers = 0;
XSETINT (bufp->x, 0);
XSETINT (bufp->y, 0);
XSETFRAME (frame, f);
bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
if (wp)
InvalRect (&(wp->portRect));
count++;
bufp++;
numchars--;
}
default:
break;
}
if (pending_autoraise_frame)
{
x_raise_frame (pending_autoraise_frame);
pending_autoraise_frame = 0;
}
check_alarm ();
{
static Point old_mouse_pos = { -1, -1 };
if (app_is_suspended)
{
old_mouse_pos.h = -1;
old_mouse_pos.v = -1;
}
else
{
Point mouse_pos;
WindowPtr wp = FrontWindow ();
struct frame *f = ((mac_output *) GetWRefCon (wp))->mFP;
Lisp_Object bar;
struct scroll_bar *sb;
SetPort (wp);
GetMouse (&mouse_pos);
if (!EqualPt (mouse_pos, old_mouse_pos))
{
if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
&& tracked_scroll_bar)
x_scroll_bar_note_movement (tracked_scroll_bar,
mouse_pos.v
- XINT (tracked_scroll_bar->top),
TickCount() * (1000 / 60));
else
note_mouse_movement (f, &mouse_pos);
old_mouse_pos = mouse_pos;
}
}
}
UNBLOCK_INPUT;
return count;
}
#ifdef __MWERKS__
void
__convert_to_newlines (unsigned char * p, size_t * n)
{
#pragma unused(p,n)
}
void
__convert_from_newlines (unsigned char * p, size_t * n)
{
#pragma unused(p,n)
}
#endif
void
NewMacWindow (FRAME_PTR fp)
{
mac_output *mwp;
static int making_terminal_window = 1;
mwp = fp->output_data.mac;
if (making_terminal_window)
{
if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
(WindowPtr) -1)))
abort ();
making_terminal_window = 0;
}
else
if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
abort ();
SetWRefCon (mwp->mWP, (long) mwp);
mwp->mFP = fp;
SetPort (mwp->mWP);
mwp->fontset = -1;
SizeWindow (mwp->mWP, mwp->pixel_width, mwp->pixel_height, false);
ShowWindow (mwp->mWP);
}
void make_mac_frame (struct frame *f)
{
FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
NewMacWindow(f);
f->output_data.mac->background_pixel = 0xffffff;
f->output_data.mac->foreground_pixel = 0;
f->output_data.mac->cursor_pixel = 0;
f->output_data.mac->border_pixel = 0x00ff00;
f->output_data.mac->mouse_pixel = 0xff00ff;
f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
f->output_data.mac->desired_cursor = FILLED_BOX_CURSOR;
f->output_data.mac->fontset = -1;
f->output_data.mac->scroll_bar_foreground_pixel = -1;
f->output_data.mac->scroll_bar_background_pixel = -1;
f->output_data.mac->left_pos = 4;
f->output_data.mac->top_pos = 4;
f->output_data.mac->border_width = 0;
f->output_data.mac->explicit_parent = 0;
f->output_data.mac->internal_border_width = 0;
f->output_method = output_mac;
f->auto_raise = 1;
f->auto_lower = 1;
f->new_width = 0;
f->new_height = 0;
}
void make_mac_terminal_frame (struct frame *f)
{
Lisp_Object frame;
XSETFRAME (frame, f);
f->output_method = output_mac;
f->output_data.mac = (struct mac_output *)
xmalloc (sizeof (struct mac_output));
bzero (f->output_data.mac, sizeof (struct mac_output));
f->output_data.mac->fontset = -1;
f->output_data.mac->scroll_bar_foreground_pixel = -1;
f->output_data.mac->scroll_bar_background_pixel = -1;
XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
f->width = 96;
f->height = 4;
make_mac_frame (f);
Fmodify_frame_parameters (frame,
Fcons (Fcons (Qfont,
build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
Fmodify_frame_parameters (frame,
Fcons (Fcons (Qforeground_color,
build_string ("black")), Qnil));
Fmodify_frame_parameters (frame,
Fcons (Fcons (Qbackground_color,
build_string ("white")), Qnil));
}
void
mac_initialize_display_info ()
{
struct mac_display_info *dpyinfo = &one_mac_display_info;
GDHandle main_device_handle;
bzero (dpyinfo, sizeof (*dpyinfo));
x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
x_display_name_list);
dpyinfo->name_list_element = XCAR (x_display_name_list);
main_device_handle = LMGetMainDevice();
dpyinfo->reference_count = 0;
dpyinfo->resx = 75.0;
dpyinfo->resy = 75.0;
dpyinfo->n_planes = 1;
dpyinfo->n_cbits = 16;
dpyinfo->height = (**main_device_handle).gdRect.bottom;
dpyinfo->width = (**main_device_handle).gdRect.right;
dpyinfo->grabbed = 0;
dpyinfo->root_window = NULL;
dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
dpyinfo->mouse_face_window = Qnil;
}
void
x_initialize ()
{
rif = &x_redisplay_interface;
clear_frame_hook = x_clear_frame;
ins_del_lines_hook = x_ins_del_lines;
change_line_highlight_hook = x_change_line_highlight;
delete_glyphs_hook = x_delete_glyphs;
ring_bell_hook = XTring_bell;
reset_terminal_modes_hook = XTreset_terminal_modes;
set_terminal_modes_hook = XTset_terminal_modes;
update_begin_hook = x_update_begin;
update_end_hook = x_update_end;
set_terminal_window_hook = XTset_terminal_window;
read_socket_hook = XTread_socket;
frame_up_to_date_hook = XTframe_up_to_date;
reassert_line_highlight_hook = XTreassert_line_highlight;
mouse_position_hook = XTmouse_position;
frame_rehighlight_hook = XTframe_rehighlight;
frame_raise_lower_hook = XTframe_raise_lower;
set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
condemn_scroll_bars_hook = XTcondemn_scroll_bars;
redeem_scroll_bar_hook = XTredeem_scroll_bar;
judge_scroll_bars_hook = XTjudge_scroll_bars;
estimate_mode_line_height_hook = x_estimate_mode_line_height;
scroll_region_ok = 1;
char_ins_del_ok = 0;
line_ins_del_ok = 1;
fast_clear_end_of_line = 1;
memory_below_frame = 0;
baud_rate = 19200;
x_noop_count = 0;
last_tool_bar_item = -1;
any_help_event_p = 0;
Fset_input_mode (Qt, Qnil, Qt, Qnil);
#ifdef USE_X_TOOLKIT
XtToolkitInitialize ();
Xt_app_con = XtCreateApplicationContext ();
XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
{
EMACS_TIME interval;
EMACS_SET_SECS_USECS (interval, 0, 100000);
start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
}
#endif
#if USE_TOOLKIT_SCROLL_BARS
xaw3d_arrow_scroll = False;
xaw3d_pick_top = True;
#endif
#if 0
XSetErrorHandler (x_error_handler);
XSetIOErrorHandler (x_io_error_quitter);
#ifdef SIGWINCH
signal (SIGWINCH, SIG_DFL);
#endif
signal (SIGPIPE, x_connection_signal);
#endif
mac_initialize_display_info ();
}
void
syms_of_macterm ()
{
#if 0
staticpro (&x_error_message_string);
x_error_message_string = Qnil;
#endif
staticpro (&x_display_name_list);
x_display_name_list = Qnil;
staticpro (&last_mouse_scroll_bar);
last_mouse_scroll_bar = Qnil;
staticpro (&Qvendor_specific_keysyms);
Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
staticpro (&last_mouse_press_frame);
last_mouse_press_frame = Qnil;
Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
staticpro (&Qmac_ready_for_drag_n_drop);
help_echo = Qnil;
staticpro (&help_echo);
help_echo_object = Qnil;
staticpro (&help_echo_object);
help_echo_window = Qnil;
staticpro (&help_echo_window);
previous_help_echo = Qnil;
staticpro (&previous_help_echo);
help_echo_pos = -1;
DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
"*Non-nil means draw block cursor as wide as the glyph under it.\n\
For example, if a block cursor is over a tab, it will be drawn as\n\
wide as that tab on the display.");
x_stretch_cursor_p = 0;
DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
"If not nil, Emacs uses toolkit scroll bars.");
#if USE_TOOLKIT_SCROLL_BARS
x_toolkit_scroll_bars_p = 1;
#else
x_toolkit_scroll_bars_p = 0;
#endif
staticpro (&last_mouse_motion_frame);
last_mouse_motion_frame = Qnil;
DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
"Non-nil means that the command key is used as the Emacs meta key.\n\
Otherwise the option key is used.");
Vmac_command_key_is_meta = Qt;
DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
"One of the Text Encoding Base constant values defined in the\n\
Basic Text Constants section of Inside Macintosh - Text Encoding\n\
Conversion Manager. Its value determines the encoding characters\n\
typed at the Mac keyboard (presumed to be in the MacRoman encoding)\n\
will convert into. E.g., if it is set to kTextEncodingMacRoman (0),\n\
its default value, no conversion takes place. If it is set to\n\
kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),\n\
characters typed on Mac keyboard are first converted into the\n\
ISO Latin-1 or ISO Latin-2 encoding, respectively before being\n\
passed to Emacs. Together with Emacs's set-keyboard-coding-system\n\
command, this enables the Mac keyboard to be used to enter non-ASCII\n\
characters directly.");
mac_keyboard_text_encoding = kTextEncodingMacRoman;
}