(x_draw_composite_glyph_string_foreground): Adjusted
[bpt/emacs.git] / src / frame.c
index 84a4e54..f762149 100644 (file)
@@ -20,6 +20,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <config.h>
 
 #include <stdio.h>
+#include <ctype.h>
 #include "lisp.h"
 #include "character.h"
 #ifdef HAVE_X_WINDOWS
@@ -28,8 +29,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #ifdef WINDOWSNT
 #include "w32term.h"
 #endif
-#ifdef MAC_OS
-#include "macterm.h"
+#ifdef HAVE_NS
+#include "nsterm.h"
 #endif
 #include "buffer.h"
 /* These help us bind and responding to switch-frame events.  */
@@ -68,10 +69,14 @@ Lisp_Object Vframe_alpha_lower_limit;
 
 #endif
 
+#ifdef HAVE_NS
+Lisp_Object Qns_parse_geometry;
+#endif
+
 Lisp_Object Qframep, Qframe_live_p;
 Lisp_Object Qicon, Qmodeline;
 Lisp_Object Qonly;
-Lisp_Object Qx, Qw32, Qmac, Qpc;
+Lisp_Object Qx, Qw32, Qmac, Qpc, Qns;
 Lisp_Object Qvisible;
 Lisp_Object Qdisplay_type;
 Lisp_Object Qbackground_mode;
@@ -119,7 +124,6 @@ Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth;
 Lisp_Object Qfont_backend;
 Lisp_Object Qalpha;
 
-Lisp_Object Qinhibit_face_set_after_frame_default;
 Lisp_Object Qface_set_after_frame_default;
 
 Lisp_Object Vterminal_frame;
@@ -203,7 +207,7 @@ DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
 Value is t for a termcap frame (a character-only terminal),
 `x' for an Emacs frame that is really an X window,
 `w32' for an Emacs frame that is a window on MS-Windows display,
-`mac' for an Emacs frame on a Macintosh display,
+`ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
 `pc' for a direct-write MS-DOS frame.
 See also `frame-live-p'.  */)
      (object)
@@ -224,6 +228,8 @@ See also `frame-live-p'.  */)
       return Qpc;
     case output_mac:
       return Qmac;
+    case output_ns:
+      return Qns;
     default:
       abort ();
     }
@@ -431,11 +437,9 @@ make_frame_without_minibuffer (mini_window, kb, display)
   if (!NILP (mini_window))
     CHECK_LIVE_WINDOW (mini_window);
 
-#ifdef MULTI_KBOARD
   if (!NILP (mini_window)
       && FRAME_KBOARD (XFRAME (XWINDOW (mini_window)->frame)) != kb)
     error ("Frame and minibuffer must be on the same terminal");
-#endif
 
   /* Make a frame containing just a root window.  */
   f = make_frame (0);
@@ -551,6 +555,11 @@ make_initial_frame (void)
   FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
   FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
 
+#ifdef CANNOT_DUMP
+  if (!noninteractive)
+    init_frame_faces (f);
+#endif
+
   return f;
 }
 
@@ -576,20 +585,23 @@ make_terminal_frame (struct terminal *terminal)
 
   f->visible = 1;              /* FRAME_SET_VISIBLE wd set frame_garbaged. */
   f->async_visible = 1;                /* Don't let visible be cleared later. */
+  f->terminal = terminal;
+  f->terminal->reference_count++;
 #ifdef MSDOS
-  f->output_data.x = &the_only_x_display;
+  f->output_data.tty->display_info = &the_only_display_info;
   if (!inhibit_window_system
       && (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))
          || XFRAME (selected_frame)->output_method == output_msdos_raw))
     {
       f->output_method = output_msdos_raw;
+#if 0
       /* This initialization of foreground and background pixels is
         only important for the initial frame created in temacs.  If
         we don't do that, we get black background and foreground in
-        the dumped Emacs because the_only_x_display is a static
+        the dumped Emacs because the_only_display_info is a static
         variable, hence it is born all-zeroes, and zero is the code
         for the black color.  Other frames all inherit their pixels
-        from what's already in the_only_x_display.  */
+        from what's already in the_only_display_info.  */
       if ((!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame)))
          && FRAME_BACKGROUND_PIXEL (f) == 0
          && FRAME_FOREGROUND_PIXEL (f) == 0)
@@ -597,28 +609,17 @@ make_terminal_frame (struct terminal *terminal)
          FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
          FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
        }
+#endif
     }
   else
     f->output_method = output_termcap;
 #else
   {
     f->output_method = output_termcap;
-    f->terminal = terminal;
-    f->terminal->reference_count++;
     create_tty_output (f);
 
     FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
     FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
-
-    FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
-    FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
-
-    /* Set the top frame to the newly created frame. */
-    if (FRAMEP (FRAME_TTY (f)->top_frame)
-        && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
-      XFRAME (FRAME_TTY (f)->top_frame)->async_visible = 2; /* obscured */
-
-    FRAME_TTY (f)->top_frame = frame;
   }
 
 #ifdef CANNOT_DUMP
@@ -627,6 +628,16 @@ make_terminal_frame (struct terminal *terminal)
 #endif
 #endif /* MSDOS */
 
+  FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
+  FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
+
+  /* Set the top frame to the newly created frame. */
+  if (FRAMEP (FRAME_TTY (f)->top_frame)
+      && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
+    XFRAME (FRAME_TTY (f)->top_frame)->async_visible = 2; /* obscured */
+
+  FRAME_TTY (f)->top_frame = frame;
+
   if (!noninteractive)
     init_frame_faces (f);
 
@@ -691,17 +702,10 @@ affects all frames on the same terminal device.  */)
     abort ();
 #else /* not MSDOS */
 
-#if 0
-  /* This can happen for multi-tty when using both terminal frames and
-     Carbon frames. */
-  if (sf->output_method != output_mac)
-    error ("Not running on a Macintosh screen; cannot make a new Macintosh frame");
-#else
 #if 0                           /* This should work now! */
   if (sf->output_method != output_termcap)
     error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
 #endif
-#endif
 #endif /* not MSDOS */
 
   {
@@ -713,6 +717,13 @@ affects all frames on the same terminal device.  */)
         terminal = XCDR (terminal);
         t = get_terminal (terminal, 1);
       }
+#ifdef MSDOS
+    if (t && t != the_only_display_info.terminal)
+      /* msdos.c assumes a single tty_display_info object.  */
+      error ("Multiple terminals are not supported on this platform");
+    if (!t)
+      t = the_only_display_info.terminal;
+#endif
   }
 
   if (!t)
@@ -865,7 +876,7 @@ do_switch_frame (frame, track, for_deletion)
   if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
     resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
 
-  if (FRAME_TERMCAP_P (XFRAME (frame)))
+  if (FRAME_TERMCAP_P (XFRAME (frame)) || FRAME_MSDOS_P (XFRAME (frame)))
     {
       if (FRAMEP (FRAME_TTY (XFRAME (frame))->top_frame))
        /* Mark previously displayed frame as now obscured.  */
@@ -880,6 +891,12 @@ do_switch_frame (frame, track, for_deletion)
 
   Fselect_window (XFRAME (frame)->selected_window, Qnil);
 
+#ifdef NS_IMPL_COCOA
+  /* term gets no other notification of this */
+  if (for_deletion)
+    Fraise_frame(Qnil);
+#endif
+
   /* We want to make sure that the next event generates a frame-switch
      event to the appropriate frame.  This seems kludgy to me, but
      before you take it out, make sure that evaluating something like
@@ -1453,10 +1470,6 @@ But FORCE inhibits this too.  */)
   if (FRAME_X_P (f))
     x_clear_frame_selections (f);
 #endif
-#ifdef MAC_OS
-  if (FRAME_MAC_P (f))
-    x_clear_frame_selections (f);
-#endif
 
   /* Free glyphs.
      This function must be called before the window tree of the
@@ -1511,10 +1524,8 @@ But FORCE inhibits this too.  */)
         kb = NULL;
        Fdelete_terminal (tmp, NILP (force) ? Qt : force);
       }
-#ifdef MULTI_KBOARD
     else
       kb = terminal->kboard;
-#endif
   }
 
   /* If we've deleted the last_nonminibuf_frame, then try to find
@@ -2966,20 +2977,11 @@ x_set_frame_parameters (f, alist)
           || EQ (prop, Qfullscreen))
        {
          register Lisp_Object param_index, old_value;
-         int count = SPECPDL_INDEX ();
 
          old_value = get_frame_param (f, prop);
          fullscreen_is_being_set |= EQ (prop, Qfullscreen);
-
          if (NILP (Fequal (val, old_value)))
            {
-             /* For :font attributes, the frame_parm_handler
-                x_set_font calls `face-set-after-frame-default'.
-                Unless we bind inhibit-face-set-after-frame-default
-                here, this would reset the :font attribute that we
-                just applied to the default value for new faces.  */
-             specbind (Qinhibit_face_set_after_frame_default, Qt);
-
              store_frame_param (f, prop, val);
 
              param_index = Fget (prop, Qx_frame_parameter);
@@ -2988,7 +2990,6 @@ x_set_frame_parameters (f, alist)
                      < sizeof (frame_parms)/sizeof (frame_parms[0]))
                   && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
                 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
-             unbind_to (count, Qnil);
            }
        }
     }
@@ -3339,7 +3340,7 @@ x_set_font (f, arg, oldval)
   int fontset = -1;
   Lisp_Object font_object;
 
-  /* Set the frame parameter back to the old value because we mail
+  /* Set the frame parameter back to the old value because we may
      fail to use ARG as the new parameter value.  */
   store_frame_param (f, Qfont, oldval);
 
@@ -3391,16 +3392,12 @@ x_set_font (f, arg, oldval)
 
   do_pending_window_change (0);
 
-  /* Don't call `face-set-after-frame-default' when faces haven't been
-     initialized yet.  This is the case when called from
-     Fx_create_frame.  In that case, the X widget or window doesn't
-     exist either, and we can end up in x_report_frame_params with a
-     null widget which gives a segfault.  */
-  if (FRAME_FACE_CACHE (f))
-    {
-      XSETFRAME (frame, f);
-      call1 (Qface_set_after_frame_default, frame);
-    }
+  /* We used to call face-set-after-frame-default here, but it leads to
+     recursive calls (since that function can set the `default' face's
+     font which in turns changes the frame's `font' parameter).
+     Also I don't know what this call is meant to do, but it seems the
+     wrong way to do it anyway (it does a lot more work than what seems
+     reasonable in response to a change to `font').  */
 }
 
 
@@ -3419,12 +3416,16 @@ x_set_font_backend (f, new_value, old_value)
       new_value = Qnil;
       while (*p0)
        {
-         while (*p1 && *p1 != ',') p1++;
+         while (*p1 && ! isspace (*p1) && *p1 != ',') p1++;
          if (p0 < p1)
            new_value = Fcons (Fintern (make_string (p0, p1 - p0), Qnil),
                               new_value);
          if (*p1)
-           p1++;
+           {
+             int c;
+
+             while ((c = *++p1) && isspace (c));
+           }
          p0 = p1;
        }
       new_value = Fnreverse (new_value);
@@ -3654,7 +3655,7 @@ x_set_alpha (f, arg, oldval)
           arg  = CDR (arg);
         }
       else
-        item=arg;
+        item = arg;
 
       if (! NILP (item))
         {
@@ -3681,7 +3682,7 @@ x_set_alpha (f, arg, oldval)
   for (i = 0; i < 2; i++)
     f->alpha[i] = newval[i];
 
-#ifdef HAVE_X_WINDOWS
+#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
   BLOCK_INPUT;
   x_set_frame_alpha (f);
   UNBLOCK_INPUT;
@@ -3958,6 +3959,9 @@ x_get_arg (dpyinfo, alist, param, attribute, class, type)
            case RES_TYPE_BOOLEAN:
              tem = Fdowncase (tem);
              if (!strcmp (SDATA (tem), "on")
+#ifdef HAVE_NS
+                  || !strcmp(SDATA(tem), "yes")
+#endif
                  || !strcmp (SDATA (tem), "true"))
                return Qt;
              else
@@ -3973,9 +3977,15 @@ x_get_arg (dpyinfo, alist, param, attribute, class, type)
                Lisp_Object lower;
                lower = Fdowncase (tem);
                if (!strcmp (SDATA (lower), "on")
+#ifdef HAVE_NS
+                    || !strcmp(SDATA(lower), "yes")
+#endif
                    || !strcmp (SDATA (lower), "true"))
                  return Qt;
                else if (!strcmp (SDATA (lower), "off")
+#ifdef HAVE_NS
+                      || !strcmp(SDATA(lower), "no")
+#endif
                      || !strcmp (SDATA (lower), "false"))
                  return Qnil;
                else
@@ -4053,6 +4063,25 @@ x_default_parameter (f, alist, prop, deflt, xprop, xclass, type)
 
 
 \f
+#ifdef HAVE_NS
+
+/* We used to define x-parse-geometry directly in ns-win.el, but that
+   confused make-docfile: the documentation string in ns-win.el was
+   used for x-parse-geometry even in non-NS builds..  */
+
+DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
+       doc: /* Parse a Nextstep-style geometry string STRING.
+Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
+The properties returned may include `top', `left', `height', and `width'.
+This works by calling `ns-parse-geometry'.  */)
+     (string)
+     Lisp_Object string;
+{
+  call1 (Qns_parse_geometry, string);
+}
+
+#else /* !HAVE_NS */
+
 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
        doc: /* Parse an X-style geometry string STRING.
 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
@@ -4071,12 +4100,6 @@ or a list (- N) meaning -N pixels relative to bottom/right corner.  */)
 
   geometry = XParseGeometry ((char *) SDATA (string),
                             &x, &y, &width, &height);
-
-#if 0
-  if (!!(geometry & XValue) != !!(geometry & YValue))
-    error ("Must specify both x and y position, or neither");
-#endif
-
   result = Qnil;
   if (geometry & XValue)
     {
@@ -4111,6 +4134,8 @@ or a list (- N) meaning -N pixels relative to bottom/right corner.  */)
 
   return result;
 }
+#endif /* HAVE_NS */
+
 
 /* Calculate the desired size and position of frame F.
    Return the flags saying which aspects were specified.
@@ -4375,6 +4400,8 @@ syms_of_frame ()
   staticpro (&Qpc);
   Qmac = intern ("mac");
   staticpro (&Qmac);
+  Qns = intern ("ns");
+  staticpro (&Qns);
   Qvisible = intern ("visible");
   staticpro (&Qvisible);
   Qbuffer_predicate = intern ("buffer-predicate");
@@ -4399,10 +4426,6 @@ syms_of_frame ()
   Qface_set_after_frame_default = intern ("face-set-after-frame-default");
   staticpro (&Qface_set_after_frame_default);
 
-  Qinhibit_face_set_after_frame_default
-    = intern ("inhibit-face-set-after-frame-default");
-  staticpro (&Qinhibit_face_set_after_frame_default);
-
   Qfullwidth = intern ("fullwidth");
   staticpro (&Qfullwidth);
   Qfullheight = intern ("fullheight");
@@ -4420,6 +4443,11 @@ syms_of_frame ()
   Qterminal_live_p = intern ("terminal-live-p");
   staticpro (&Qterminal_live_p);
 
+#ifdef HAVE_NS
+  Qns_parse_geometry = intern ("ns-parse-geometry");
+  staticpro (&Qns_parse_geometry);
+#endif
+
   {
     int i;
 
@@ -4486,8 +4514,8 @@ Setting this variable does not affect existing frames, only new ones.  */);
   DEFVAR_LISP ("default-frame-scroll-bars", &Vdefault_frame_scroll_bars,
               doc: /* Default position of scroll bars on this window-system.  */);
 #ifdef HAVE_WINDOW_SYSTEM
-#if defined(HAVE_NTGUI) || defined(MAC_OS)
-  /* MS-Windows has scroll bars on the right by default.  */
+#if defined(HAVE_NTGUI) || defined(NS_IMPL_COCOA)
+  /* MS-Windows and Mac OS X have scroll bars on the right by default.  */
   Vdefault_frame_scroll_bars = Qright;
 #else
   Vdefault_frame_scroll_bars = Qleft;
@@ -4553,7 +4581,7 @@ You should set this variable to tell Emacs how your window manager
 handles focus, since there is no way in general for Emacs to find out
 automatically.  */);
 #ifdef HAVE_WINDOW_SYSTEM
-#if defined(HAVE_NTGUI) || defined(MAC_OS)
+#if defined(HAVE_NTGUI) || defined(HAVE_NS)
   focus_follows_mouse = 0;
 #else
   focus_follows_mouse = 1;