2 Copyright (C) 1992, 1993 Free Software Foundation.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20 /* This is derived from work by Lucid (some parts very loosely so). */
22 #include <sys/types.h>
32 #include "dispextern.h"
34 #include "blockinput.h"
35 /* #include "window.h" */
37 /* Display Context for the icons */
38 #include <X11/Intrinsic.h>
39 #include <X11/StringDefs.h>
40 /* #include <X11/Xmu/Drawing.h> */ /* Appears not to be used */
44 /* An explanation of the face data structures. */
46 /* ========================= Face Data Structures =========================
48 All lisp code uses symbols as face names.
50 Each frame has a face_alist member (with the frame-face-alist and
51 set-frame-face-alist accessors), associating the face names with
53 [face NAME ID FONT FOREGROUND BACKGROUND BACKGROUND-PIXMAP UNDERLINE-P]
55 face is the symbol `face',
56 NAME is the symbol with which this vector is associated (a backpointer),
57 ID is the face ID, an integer used internally by the C code to identify
59 FONT, FOREGROUND, and BACKGROUND are strings naming the fonts and colors
61 BACKGROUND-PIXMAP is the name of an x bitmap filename, which we don't
63 UNDERLINE-P is non-nil if the face should be underlined.
64 (lisp/faces.el maintains these association lists.)
66 The frames' private alists hold the frame-local definitions for the
67 faces. The lisp variable global-face-data contains the global
68 defaults for faces. (See lisp/faces.el for this too.)
70 In the C code, we also have a `struct face' with the elements
71 `foreground', `background', `font', and `underline',
72 which specify its visual appearance, and elements
73 `gc' and `cached_index';
74 `gc' may be an X GC which has been built for the given display
75 parameters. Faces with GC's are called `display faces'. Whether
76 or not a face has a GC depends on what data structure the face is
77 in; we explain these more below. (See src/dispextern.h.)
79 Each frame also has members called `faces' and `n_faces' (with the
80 accessors FRAME_FACES and FRAME_N_FACES), which define an array of
81 struct face pointers, indexed by face ID (element 2 of the
82 vector). These are called "frame faces".
83 Element 0 is the default face --- the one used for normal text.
84 Element 1 is the modeline face.
85 These faces have their GC's set; the rest do not. (See src/xterm.h.)
87 The global variables `face_vector' and `nfaces' define another
88 array of struct face pointers, with their GC's set. This array
89 acts as a cache of GC's to be used by all frames. The function
90 `intern_face', passed a struct face *, searches face_vector for a
91 struct face with the same parameters, adds a new one with a GC if
92 it doesn't find one, and returns it. If you have a `struct face',
93 and you want a GC for it, call intern_face on that struct, and it
94 will return a `struct face *' with its GC set. The faces in
95 face_vector are called `cached faces.' (See src/xfaces.c.)
97 The `GLYPH' data type is an unsigned integer type; the bottom byte
98 is a character code, and the byte above that is a face id. The
99 `struct frame_glyphs' structure, used to describe frames' current
100 or desired contents, is essentially a matrix of GLYPHs; the face
101 ID's in a struct frame_glyphs are indices into FRAME_FACES. (See
106 Since face_vector is just a cache --- there are no pointers into it
107 from the rest of the code, and everyone accesses it through
108 intern_face --- we could just free its GC's and throw the whole
109 thing away without breaking anything. This gives us a simple way
110 to garbage-collect old GC's nobody's using any more - we can just
111 purge face_vector, and then let subsequent calls to intern_face
112 refill it as needed. The function clear_face_vector performs this
115 We're often applying intern_face to faces in frames' local arrays -
116 for example, we do this while sending GLYPHs from a struct
117 frame_glyphs to X during redisplay. It would be nice to avoid
118 searching all of face_vector every time we intern a frame's face.
119 So, when intern_face finds a match for FACE in face_vector, it
120 stores the index of the match in FACE's cached_index member, and
121 checks there first next time. */
124 /* Definitions and declarations. */
126 /* A table of display faces. */
127 struct face
**face_vector
;
128 /* The length in use of the table. */
130 /* The allocated length of the table. */
131 int nfaces_allocated
;
133 /* The number of face-id's in use (same for all frames). */
136 #define FACE_DEFAULT (~0)
138 Lisp_Object Qface
, Qwindow
, Qpriority
;
140 static void build_face ();
141 static Lisp_Object
face_name_id_number ();
143 struct face
*intern_face ();
144 static void ensure_face_ready ();
146 /* Allocating, copying, and comparing struct faces. */
148 /* Allocate a new face */
152 struct face
*result
= (struct face
*) xmalloc (sizeof (struct face
));
153 bzero (result
, sizeof (struct face
));
154 result
->font
= (XFontStruct
*) FACE_DEFAULT
;
155 result
->foreground
= FACE_DEFAULT
;
156 result
->background
= FACE_DEFAULT
;
157 result
->stipple
= FACE_DEFAULT
;
161 /* Make a new face that's a copy of an existing one. */
166 struct face
*result
= allocate_face ();
168 result
->font
= face
->font
;
169 result
->foreground
= face
->foreground
;
170 result
->background
= face
->background
;
171 result
->stipple
= face
->stipple
;
172 result
->underline
= face
->underline
;
178 face_eql (face1
, face2
)
179 struct face
*face1
, *face2
;
181 return ( face1
->font
== face2
->font
182 && face1
->foreground
== face2
->foreground
183 && face1
->background
== face2
->background
184 && face1
->stipple
== face2
->stipple
185 && face1
->underline
== face2
->underline
);
188 /* Interning faces in the `face_vector' cache, and clearing that cache. */
190 /* Return the unique display face corresponding to the user-level face FACE.
191 If there isn't one, make one, and find a slot in the face_vector to
194 get_cached_face (f
, face
)
201 /* Perhaps FACE->cached_index is valid; this could happen if FACE is
202 in a frame's face list. */
203 if (face
->cached_index
>= 0
204 && face
->cached_index
< nfaces
205 && face_eql (face_vector
[face
->cached_index
], face
))
206 return face_vector
[face
->cached_index
];
208 /* Look for an existing display face that does the job.
209 Also find an empty slot if any. */
210 for (i
= 0; i
< nfaces
; i
++)
212 if (face_eql (face_vector
[i
], face
))
213 return face_vector
[i
];
214 if (face_vector
[i
] == 0)
218 /* If no empty slots, make one. */
219 if (empty
< 0 && nfaces
== nfaces_allocated
)
221 int newsize
= nfaces
+ 20;
223 = (struct face
**) xrealloc (face_vector
,
224 newsize
* sizeof (struct face
*));
225 nfaces_allocated
= newsize
;
231 /* Put a new display face in the empty slot. */
232 result
= copy_face (face
);
233 face_vector
[empty
] = result
;
235 /* Make a graphics context for it. */
236 build_face (f
, result
);
241 /* Given a frame face, return an equivalent display face
242 (one which has a graphics context). */
245 intern_face (f
, face
)
251 /* Does the face have a GC already? */
255 /* If it's equivalent to the default face, use that. */
256 if (face_eql (face
, FRAME_DEFAULT_FACE (f
)))
258 if (!FRAME_DEFAULT_FACE (f
)->gc
)
259 build_face (f
, FRAME_DEFAULT_FACE (f
));
260 return FRAME_DEFAULT_FACE (f
);
263 /* If it's equivalent to the mode line face, use that. */
264 if (face_eql (face
, FRAME_MODE_LINE_FACE (f
)))
266 if (!FRAME_MODE_LINE_FACE (f
)->gc
)
267 build_face (f
, FRAME_MODE_LINE_FACE (f
));
268 return FRAME_MODE_LINE_FACE (f
);
271 /* Get a specialized display face. */
272 return get_cached_face (f
, face
);
275 /* Clear out face_vector and start anew.
276 This should be done from time to time just to avoid
277 keeping too many graphics contexts in face_vector
278 that are no longer needed. */
284 Display
*dpy
= x_current_display
;
288 /* Free the display faces in the face_vector. */
289 for (i
= 0; i
< nfaces
; i
++)
291 struct face
*face
= face_vector
[i
];
293 XFreeGC (dpy
, face
->gc
);
301 /* Allocating and freeing X resources for display faces. */
303 /* Make a graphics context for face FACE, which is on frame F,
304 if that can be done. */
314 if (face
->foreground
!= FACE_DEFAULT
)
315 xgcv
.foreground
= face
->foreground
;
317 xgcv
. foreground
= f
->display
.x
->foreground_pixel
;
318 if (face
->background
!= FACE_DEFAULT
)
319 xgcv
.background
= face
->background
;
321 xgcv
. background
= f
->display
.x
->background_pixel
;
322 if (face
->font
&& (int) face
->font
!= FACE_DEFAULT
)
323 xgcv
.font
= face
->font
->fid
;
325 xgcv
.font
= f
->display
.x
->font
->fid
;
326 xgcv
.graphics_exposures
= 0;
327 mask
= GCForeground
| GCBackground
| GCFont
| GCGraphicsExposures
;
328 gc
= XCreateGC (x_current_display
, FRAME_X_WINDOW (f
),
331 if (face
->stipple
&& face
->stipple
!= FACE_DEFAULT
)
332 XSetStipple (x_current_display
, gc
, face
->stipple
);
337 /* Allocating, freeing, and duplicating fonts, colors, and pixmaps. */
347 return (XFontStruct
*) FACE_DEFAULT
;
349 CHECK_STRING (name
, 0);
351 font
= XLoadQueryFont (x_current_display
, (char *) XSTRING (name
)->data
);
355 Fsignal (Qerror
, Fcons (build_string ("undefined font"),
356 Fcons (name
, Qnil
)));
361 unload_font (f
, font
)
365 if (!font
|| font
== ((XFontStruct
*) FACE_DEFAULT
))
367 XFreeFont (x_current_display
, font
);
375 Display
*dpy
= x_current_display
;
383 cmap
= DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display
));
385 CHECK_STRING (name
, 0);
387 result
= XParseColor (dpy
, cmap
, (char *) XSTRING (name
)->data
, &color
);
390 Fsignal (Qerror
, Fcons (build_string ("undefined color"),
391 Fcons (name
, Qnil
)));
393 result
= XAllocColor (dpy
, cmap
, &color
);
396 Fsignal (Qerror
, Fcons (build_string ("X server cannot allocate color"),
397 Fcons (name
, Qnil
)));
398 return (unsigned long) color
.pixel
;
402 unload_color (f
, pixel
)
407 Display
*dpy
= x_current_display
;
408 if (pixel
== FACE_DEFAULT
)
410 cmap
= DefaultColormapOfScreen (DefaultScreenOfDisplay (x_current_display
));
412 XFreeColors (dpy
, cmap
, &pixel
, 1, 0);
416 /* Initializing face arrays for frames. */
418 /* Set up faces 0 and 1 based on the normal text and modeline GC's. */
423 ensure_face_ready (f
, 0);
426 struct face
*face
= FRAME_FACES (f
) [0];
428 XGetGCValues (x_current_display
, f
->display
.x
->normal_gc
,
429 GCForeground
| GCBackground
| GCFont
, &gcv
);
430 face
->gc
= f
->display
.x
->normal_gc
;
431 face
->foreground
= gcv
.foreground
;
432 face
->background
= gcv
.background
;
433 face
->font
= XQueryFont (x_current_display
, gcv
.font
);
438 ensure_face_ready (f
, 1);
441 struct face
*face
= FRAME_FACES (f
) [1];
443 XGetGCValues (x_current_display
, f
->display
.x
->reverse_gc
,
444 GCForeground
| GCBackground
| GCFont
, &gcv
);
445 face
->gc
= f
->display
.x
->reverse_gc
;
446 face
->foreground
= gcv
.foreground
;
447 face
->background
= gcv
.background
;
448 face
->font
= XQueryFont (x_current_display
, gcv
.font
);
459 struct frame
*other_frame
= 0;
462 for (rest
= Vframe_list
; !NILP (rest
); rest
= Fcdr (rest
))
464 struct frame
*f2
= XFRAME (Fcar (rest
));
465 if (f2
!= f
&& FRAME_X_P (f2
))
474 /* Make sure this frame's face vector is as big as the others. */
475 FRAME_N_FACES (f
) = FRAME_N_FACES (other_frame
);
477 = (struct face
**) xmalloc (FRAME_N_FACES (f
) * sizeof (struct face
*));
479 /* Make sure the frame has the two basic faces. */
480 FRAME_DEFAULT_FACE (f
)
481 = copy_face (FRAME_DEFAULT_FACE (other_frame
));
482 FRAME_MODE_LINE_FACE (f
)
483 = copy_face (FRAME_MODE_LINE_FACE (other_frame
));
489 /* Called from Fdelete_frame. */
494 Display
*dpy
= x_current_display
;
497 for (i
= 0; i
< FRAME_N_FACES (f
); i
++)
499 struct face
*face
= FRAME_FACES (f
) [i
];
503 XFreeGC (dpy
, face
->gc
);
504 unload_font (f
, face
->font
);
505 unload_color (f
, face
->foreground
);
506 unload_color (f
, face
->background
);
508 unload_pixmap (f
, face
->stipple
);
512 xfree (FRAME_FACES (f
));
514 FRAME_N_FACES (f
) = 0;
517 /* Interning faces in a frame's face array. */
519 /* Find a match for NEW_FACE in a FRAME's face array, and add it if we don't
522 intern_frame_face (new_face
, frame
)
523 struct face
*new_face
;
526 int len
= FRAME_N_FACES (frame
);
529 /* Search for a face already on FRAME equivalent to FACE. */
530 for (i
= 0; i
< len
; i
++)
532 struct face
*frame_face
= FRAME_FACES (frame
)[i
];
534 if (frame_face
&& face_eql (new_face
, frame_face
))
538 /* We didn't find one; add a new one. */
541 ensure_face_ready (frame
, i
);
542 bcopy (new_face
, FRAME_FACES (frame
)[i
], sizeof (new_face
));
547 /* Make face id ID valid on frame F. */
550 ensure_face_ready (f
, id
)
554 if (FRAME_N_FACES (f
) <= id
)
558 if (!FRAME_N_FACES (f
))
560 = (struct face
**) xmalloc (sizeof (struct face
*) * n
);
563 = (struct face
**) xrealloc (FRAME_FACES (f
),
564 sizeof (struct face
*) * n
);
566 bzero (FRAME_FACES (f
) + FRAME_N_FACES (f
),
567 (n
- FRAME_N_FACES (f
)) * sizeof (struct face
*));
568 FRAME_N_FACES (f
) = n
;
571 if (FRAME_FACES (f
) [id
] == 0)
572 FRAME_FACES (f
) [id
] = allocate_face ();
575 /* Computing faces appropriate for a given piece of text in a buffer. */
577 /* Modify face TO by copying from FROM all properties which have
578 nondefault settings. */
580 merge_faces (from
, to
)
581 struct face
*from
, *to
;
583 if (from
->font
!= (XFontStruct
*)FACE_DEFAULT
)
585 to
->font
= from
->font
;
587 if (from
->foreground
!= FACE_DEFAULT
)
588 to
->foreground
= from
->foreground
;
589 if (from
->background
!= FACE_DEFAULT
)
590 to
->background
= from
->background
;
591 if (from
->stipple
!= FACE_DEFAULT
)
592 to
->stipple
= from
->stipple
;
594 to
->underline
= from
->underline
;
605 sort_overlays (s1
, s2
)
606 struct sortvec
*s1
, *s2
;
608 if (s1
->priority
!= s2
->priority
)
609 return s1
->priority
- s2
->priority
;
610 if (s1
->beg
!= s2
->beg
)
611 return s1
->beg
- s2
->beg
;
612 if (s1
->end
!= s2
->end
)
613 return s2
->end
- s1
->end
;
617 /* Return the face ID associated with a buffer position POS.
618 Store into *ENDPTR the position at which a different face is needed.
619 This does not take account of glyphs that specify their own face codes.
620 F is the frame in use for display, and W is the window. */
622 compute_char_face (f
, w
, pos
, endptr
)
629 Lisp_Object prop
, position
, length
;
630 Lisp_Object overlay
, start
, end
;
634 Lisp_Object
*overlay_vec
;
636 struct sortvec
*sortvec
;
639 XSET (frame
, Lisp_Frame
, f
);
641 XFASTINT (position
) = pos
;
642 prop
= Fget_text_property (position
, Qface
);
645 overlay_vec
= (Lisp_Object
*) xmalloc (len
* sizeof (Lisp_Object
));
646 noverlays
= overlays_at (pos
, &overlay_vec
, &len
, &endpos
);
648 /* Optimize the default case. */
649 if (noverlays
== 0 && NILP (prop
))
652 bcopy (FRAME_DEFAULT_FACE (f
), &face
, sizeof (struct face
));
656 facecode
= face_name_id_number (frame
, prop
);
657 if (facecode
>= 0 && facecode
< FRAME_N_FACES (f
)
658 && FRAME_FACES (f
) [facecode
] != 0)
659 merge_faces (FRAME_FACES (f
) [facecode
], &face
);
662 /* Put the valid and relevant overlays into sortvec. */
663 sortvec
= (struct sortvec
*) alloca (noverlays
* sizeof (struct sortvec
));
665 for (i
= 0, j
= 0; i
< noverlays
; i
++)
667 overlay
= overlay_vec
[i
];
669 if (OVERLAY_VALID (overlay
)
670 && OVERLAY_POSITION (OVERLAY_START (overlay
)) > 0
671 && OVERLAY_POSITION (OVERLAY_END (overlay
)) > 0)
674 window
= Foverlay_get (overlay
, Qwindow
);
676 /* Also ignore overlays limited to one window
677 if it's not the window we are using. */
678 if (NILP (window
) || XWINDOW (window
) == w
)
682 /* This overlay is good and counts:
683 put it in sortvec. */
684 sortvec
[j
].overlay
= overlay
;
685 sortvec
[j
].beg
= OVERLAY_POSITION (OVERLAY_START (overlay
));
686 sortvec
[j
].end
= OVERLAY_POSITION (OVERLAY_END (overlay
));
687 tem
= Foverlay_get (overlay
, Qpriority
);
689 sortvec
[j
].priority
= XINT (tem
);
691 sortvec
[j
].priority
= 0;
698 /* Sort the overlays into the proper order: increasing priority. */
700 qsort (sortvec
, noverlays
, sizeof (struct sortvec
), sort_overlays
);
702 /* Now merge the overlay data in that order. */
704 for (i
= 0; i
< noverlays
; i
++)
706 prop
= Foverlay_get (overlay_vec
[i
], Qface
);
712 facecode
= face_name_id_number (frame
, prop
);
713 if (facecode
>= 0 && facecode
< FRAME_N_FACES (f
)
714 && FRAME_FACES (f
) [facecode
] != 0)
715 merge_faces (FRAME_FACES (f
) [facecode
], &face
);
717 oend
= OVERLAY_END (overlay_vec
[i
]);
718 oendpos
= OVERLAY_POSITION (oend
);
719 if (oendpos
> endpos
)
728 return intern_frame_face (f
, &face
);
731 /* Return the face ID to use to display a special glyph which selects
732 FACE_CODE as the face ID, assuming that ordinarily the face would
733 be BASIC_FACE. F is the frame. */
735 compute_glyph_face (f
, face_code
)
741 bcopy (FRAME_DEFAULT_FACE (f
), &face
, sizeof (face
));
743 if (face_code
>= 0 && face_code
< FRAME_N_FACES (f
)
744 && FRAME_FACES (f
) [face_code
] != 0)
745 merge_faces (FRAME_FACES (f
) [face_code
], &face
);
747 return intern_frame_face (f
, &face
);
750 /* Lisp interface. */
752 DEFUN ("frame-face-alist", Fframe_face_alist
, Sframe_face_alist
, 1, 1, 0,
757 CHECK_FRAME (frame
, 0);
758 return XFRAME (frame
)->face_alist
;
761 DEFUN ("set-frame-face-alist", Fset_frame_face_alist
, Sset_frame_face_alist
,
764 Lisp_Object frame
, value
;
766 CHECK_FRAME (frame
, 0);
767 XFRAME (frame
)->face_alist
= value
;
772 DEFUN ("make-face-internal", Fmake_face_internal
, Smake_face_internal
, 1, 1, 0,
773 "Create face number FACE-ID on all frames.")
778 int id
= XINT (face_id
);
780 CHECK_NUMBER (face_id
, 0);
781 if (id
< 0 || id
>= next_face_id
)
782 error ("Face id out of range");
784 for (rest
= Vframe_list
; !NILP (rest
); rest
= XCONS (rest
)->cdr
)
786 struct frame
*f
= XFRAME (XCONS (rest
)->car
);
788 ensure_face_ready (f
, id
);
794 DEFUN ("set-face-attribute-internal", Fset_face_attribute_internal
,
795 Sset_face_attribute_internal
, 4, 4, 0, "")
796 (face_id
, attr_name
, attr_value
, frame
)
797 Lisp_Object face_id
, attr_name
, attr_value
, frame
;
804 CHECK_FRAME (frame
, 0);
805 CHECK_NUMBER (face_id
, 0);
806 CHECK_SYMBOL (attr_name
, 0);
810 if (id
< 0 || id
>= next_face_id
)
811 error ("Face id out of range");
813 ensure_face_ready (f
, id
);
814 face
= FRAME_FACES (f
) [XFASTINT (face_id
)];
816 if (EQ (attr_name
, intern ("font")))
818 XFontStruct
*font
= load_font (f
, attr_value
);
819 unload_font (f
, face
->font
);
822 else if (EQ (attr_name
, intern ("foreground")))
824 unsigned long new_color
= load_color (f
, attr_value
);
825 unload_color (f
, face
->foreground
);
826 face
->foreground
= new_color
;
828 else if (EQ (attr_name
, intern ("background")))
830 unsigned long new_color
= load_color (f
, attr_value
);
831 unload_color (f
, face
->background
);
832 face
->background
= new_color
;
835 else if (EQ (attr_name
, intern ("background-pixmap")))
837 unsigned int w
, h
, d
;
838 unsigned long new_pixmap
= load_pixmap (f
, attr_value
, &w
, &h
, &d
, 0);
839 unload_pixmap (f
, face
->stipple
);
840 if (NILP (attr_value
))
842 face
->stipple
= new_pixmap
;
845 /* face->pixmap_depth = d; */
848 else if (EQ (attr_name
, intern ("underline")))
850 int new = !NILP (attr_value
);
851 face
->underline
= new;
854 error ("unknown face attribute");
859 if (FRAME_DEFAULT_FACE (f
)->gc
!= 0)
860 XFreeGC (x_current_display
, FRAME_DEFAULT_FACE (f
)->gc
);
861 build_face (f
, FRAME_DEFAULT_FACE (f
));
868 if (FRAME_MODE_LINE_FACE (f
)->gc
!= 0)
869 XFreeGC (x_current_display
, FRAME_MODE_LINE_FACE (f
)->gc
);
870 build_face (f
, FRAME_MODE_LINE_FACE (f
));
877 DEFUN ("internal-next-face-id", Finternal_next_face_id
, Sinternal_next_face_id
,
881 return make_number (next_face_id
++);
884 /* Return the face id for name NAME on frame FRAME.
885 (It should be the same for all frames,
886 but it's as easy to use the "right" frame to look it up
887 as to use any other one.) */
890 face_name_id_number (frame
, name
)
891 Lisp_Object frame
, name
;
895 CHECK_FRAME (frame
, 0);
896 tem
= Fcdr (Fassq (name
, XFRAME (frame
)->face_alist
));
897 CHECK_VECTOR (tem
, 0);
898 tem
= XVECTOR (tem
)->contents
[2];
899 CHECK_NUMBER (tem
, 0);
903 /* Emacs initialization. */
908 Qwindow
= intern ("window");
909 staticpro (&Qwindow
);
910 Qface
= intern ("face");
912 Qpriority
= intern ("priority");
913 staticpro (&Qpriority
);
915 defsubr (&Sframe_face_alist
);
916 defsubr (&Sset_frame_face_alist
);
917 defsubr (&Smake_face_internal
);
918 defsubr (&Sset_face_attribute_internal
);
919 defsubr (&Sinternal_next_face_id
);
922 #endif /* HAVE_X_WINDOWS */