summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2008-02-12 21:28:56 -0800
committerAaron Plattner <aplattner@nvidia.com>2008-02-12 21:28:56 -0800
commitfb518983907cf33ab8ee7e71ef79fe920b6b5a17 (patch)
tree16dd7342ea2734bcd6c0bafa23fae939af971f96 /src
parent429a78a02af06685581968d1be658f1fa33c2312 (diff)
1.0-96261.0-9626
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.inc4
-rw-r--r--src/XF86Config-parser/Configint.h212
-rw-r--r--src/XF86Config-parser/DRI.c152
-rw-r--r--src/XF86Config-parser/Device.c498
-rw-r--r--src/XF86Config-parser/Extensions.c102
-rw-r--r--src/XF86Config-parser/Files.c281
-rw-r--r--src/XF86Config-parser/Flags.c560
-rw-r--r--src/XF86Config-parser/Generate.c1330
-rw-r--r--src/XF86Config-parser/Input.c424
-rw-r--r--src/XF86Config-parser/Keyboard.c304
-rw-r--r--src/XF86Config-parser/Layout.c607
-rw-r--r--src/XF86Config-parser/Makefile62
-rw-r--r--src/XF86Config-parser/Makefile.inc58
-rw-r--r--src/XF86Config-parser/Module.c282
-rw-r--r--src/XF86Config-parser/Monitor.c889
-rw-r--r--src/XF86Config-parser/Pointer.c236
-rw-r--r--src/XF86Config-parser/Read.c401
-rw-r--r--src/XF86Config-parser/Scan.c975
-rw-r--r--src/XF86Config-parser/Screen.c679
-rw-r--r--src/XF86Config-parser/Util.c185
-rw-r--r--src/XF86Config-parser/Vendor.c245
-rw-r--r--src/XF86Config-parser/Video.c284
-rw-r--r--src/XF86Config-parser/Write.c114
-rw-r--r--src/XF86Config-parser/configProcs.h126
-rw-r--r--src/XF86Config-parser/xf86Parser.h737
-rw-r--r--src/XF86Config-parser/xf86tokens.h276
-rw-r--r--src/command-line.c37
-rw-r--r--src/command-line.h14
-rw-r--r--src/config-file.c80
-rw-r--r--src/config-file.h3
-rw-r--r--src/gtk+-2.x/Makefile.inc26
-rw-r--r--src/gtk+-2.x/ctkbanner.c228
-rw-r--r--src/gtk+-2.x/ctkbanner.h77
-rw-r--r--src/gtk+-2.x/ctkclocks.c14
-rw-r--r--src/gtk+-2.x/ctkconfig.c22
-rw-r--r--src/gtk+-2.x/ctkconfig.h4
-rw-r--r--src/gtk+-2.x/ctkcursorshadow.c25
-rw-r--r--src/gtk+-2.x/ctkdevice.c333
-rw-r--r--src/gtk+-2.x/ctkdisplayconfig.c9131
-rw-r--r--src/gtk+-2.x/ctkdisplayconfig.h197
-rw-r--r--src/gtk+-2.x/ctkdisplaydevice-crt.c183
-rw-r--r--src/gtk+-2.x/ctkdisplaydevice-crt.h7
-rw-r--r--src/gtk+-2.x/ctkdisplaydevice-dfp.c671
-rw-r--r--src/gtk+-2.x/ctkdisplaydevice-dfp.h12
-rw-r--r--src/gtk+-2.x/ctkdisplaydevice-tv.c595
-rw-r--r--src/gtk+-2.x/ctkdisplaydevice-tv.h33
-rw-r--r--src/gtk+-2.x/ctkdisplaydevice.c265
-rw-r--r--src/gtk+-2.x/ctkdisplaydevice.h90
-rw-r--r--src/gtk+-2.x/ctkdisplaylayout.c3690
-rw-r--r--src/gtk+-2.x/ctkdisplaylayout.h457
-rw-r--r--src/gtk+-2.x/ctkevent.c91
-rw-r--r--src/gtk+-2.x/ctkevent.h3
-rw-r--r--src/gtk+-2.x/ctkframelock.c175
-rw-r--r--src/gtk+-2.x/ctkglx.c90
-rw-r--r--src/gtk+-2.x/ctkgpu.c480
-rw-r--r--src/gtk+-2.x/ctkgpu.h (renamed from src/gtk+-2.x/ctkdevice.h)50
-rw-r--r--src/gtk+-2.x/ctkgvo-csc.c58
-rw-r--r--src/gtk+-2.x/ctkgvo-csc.h9
-rw-r--r--src/gtk+-2.x/ctkgvo.c215
-rw-r--r--src/gtk+-2.x/ctkgvo.h30
-rw-r--r--src/gtk+-2.x/ctkhelp.c24
-rw-r--r--src/gtk+-2.x/ctkimage.c5
-rw-r--r--src/gtk+-2.x/ctkimagesliders.c537
-rw-r--r--src/gtk+-2.x/ctkimagesliders.h22
-rw-r--r--src/gtk+-2.x/ctkmultisample.c26
-rw-r--r--src/gtk+-2.x/ctkopengl.c126
-rw-r--r--src/gtk+-2.x/ctkscreen.c474
-rw-r--r--src/gtk+-2.x/ctkscreen.h80
-rw-r--r--src/gtk+-2.x/ctkserver.c496
-rw-r--r--src/gtk+-2.x/ctkserver.h77
-rw-r--r--src/gtk+-2.x/ctkthermal.c12
-rw-r--r--src/gtk+-2.x/ctkui.c11
-rw-r--r--src/gtk+-2.x/ctkui.h5
-rw-r--r--src/gtk+-2.x/ctkutils.c11
-rw-r--r--src/gtk+-2.x/ctkutils.h5
-rw-r--r--src/gtk+-2.x/ctkvcsc.c255
-rw-r--r--src/gtk+-2.x/ctkvcsc.h77
-rw-r--r--src/gtk+-2.x/ctkwindow.c417
-rw-r--r--src/gtk+-2.x/ctkwindow.h10
-rw-r--r--src/gtk+-2.x/ctkxvideo.c16
-rw-r--r--src/image_data/Makefile.inc7
-rw-r--r--src/image_data/antialiasing_banner.h2
-rw-r--r--src/image_data/big_banner_bsd.h2
-rw-r--r--src/image_data/big_banner_penguin.h2
-rw-r--r--src/image_data/big_banner_sun.h2
-rw-r--r--src/image_data/blank_banner.h1485
-rw-r--r--src/image_data/bnc_cable.h2
-rw-r--r--src/image_data/clocks_banner.h2
-rw-r--r--src/image_data/color_correction_banner.h2
-rw-r--r--src/image_data/configuration_banner.h2
-rw-r--r--src/image_data/crt.h2
-rw-r--r--src/image_data/crt_banner.h2
-rw-r--r--src/image_data/cursor_banner.h2
-rw-r--r--src/image_data/dfp.h2
-rw-r--r--src/image_data/dfp_banner.h2
-rw-r--r--src/image_data/display_device_banner.h2
-rw-r--r--src/image_data/frame_lock_banner.h2
-rw-r--r--src/image_data/glx_banner.h2
-rw-r--r--src/image_data/gvo_banner_comp_sync_green.h2
-rw-r--r--src/image_data/gvo_banner_comp_sync_grey.h2
-rw-r--r--src/image_data/gvo_banner_comp_sync_red.h2
-rw-r--r--src/image_data/gvo_banner_comp_sync_yellow.h2
-rw-r--r--src/image_data/gvo_banner_left.h2
-rw-r--r--src/image_data/gvo_banner_right.h2
-rw-r--r--src/image_data/gvo_banner_sdi_sync_green.h2
-rw-r--r--src/image_data/gvo_banner_sdi_sync_grey.h2
-rw-r--r--src/image_data/gvo_banner_sdi_sync_red.h2
-rw-r--r--src/image_data/gvo_banner_sdi_sync_yellow.h2
-rw-r--r--src/image_data/gvo_banner_vid1_green.h2
-rw-r--r--src/image_data/gvo_banner_vid1_grey.h2
-rw-r--r--src/image_data/gvo_banner_vid1_red.h2
-rw-r--r--src/image_data/gvo_banner_vid1_yellow.h2
-rw-r--r--src/image_data/gvo_banner_vid2_green.h2
-rw-r--r--src/image_data/gvo_banner_vid2_grey.h2
-rw-r--r--src/image_data/gvo_banner_vid2_red.h2
-rw-r--r--src/image_data/gvo_banner_vid2_yellow.h2
-rw-r--r--src/image_data/help_banner.h2
-rw-r--r--src/image_data/image.h1
-rw-r--r--src/image_data/led_green.h2
-rw-r--r--src/image_data/led_grey.h2
-rw-r--r--src/image_data/led_red.h2
-rw-r--r--src/image_data/opengl_banner.h2
-rw-r--r--src/image_data/rj45_input.h2
-rw-r--r--src/image_data/rj45_output.h2
-rw-r--r--src/image_data/rj45_unused.h2
-rw-r--r--src/image_data/rotate_left_off.h2
-rw-r--r--src/image_data/rotate_left_on.h2
-rw-r--r--src/image_data/rotate_right_off.h2
-rw-r--r--src/image_data/rotate_right_on.h2
-rw-r--r--src/image_data/rotation_banner.h2
-rw-r--r--src/image_data/rotation_orientation_horiz.h2
-rw-r--r--src/image_data/rotation_orientation_horiz_flipped.h2
-rw-r--r--src/image_data/rotation_orientation_vert.h2
-rw-r--r--src/image_data/rotation_orientation_vert_flipped.h2
-rw-r--r--src/image_data/thermal_banner.h2
-rw-r--r--src/image_data/tv.h2
-rw-r--r--src/image_data/tv_banner.h2
-rw-r--r--src/image_data/xvideo_banner.h2
-rw-r--r--src/libXNVCtrl/Makefile.inc4
-rw-r--r--src/libXNVCtrl/NVCtrl.c76
-rw-r--r--src/libXNVCtrl/NVCtrl.h722
-rw-r--r--src/libXNVCtrl/NVCtrlLib.h19
-rw-r--r--src/libXNVCtrl/libXNVCtrl.abin16256 -> 17180 bytes
-rw-r--r--src/libXNVCtrl/nv_control.h31
-rw-r--r--src/libXNVCtrlAttributes/Makefile.inc4
-rw-r--r--src/libXNVCtrlAttributes/NvCtrlAttributes.c186
-rw-r--r--src/libXNVCtrlAttributes/NvCtrlAttributes.h24
-rw-r--r--src/libXNVCtrlAttributes/NvCtrlAttributesGlx.c2
-rw-r--r--src/libXNVCtrlAttributes/NvCtrlAttributesNvControl.c22
-rw-r--r--src/libXNVCtrlAttributes/NvCtrlAttributesPrivate.h12
-rw-r--r--src/libXNVCtrlAttributes/NvCtrlAttributesXrandr.c92
-rw-r--r--src/libXNVCtrlAttributes/NvCtrlAttributesXv.c2
-rw-r--r--src/msg.c33
-rw-r--r--src/msg.h1
-rw-r--r--src/nvidia-settings.c76
-rw-r--r--src/parse.c28
-rw-r--r--src/parse.h4
-rw-r--r--src/query-assign.c139
-rw-r--r--src/xpm_data/Makefile.inc7
-rw-r--r--src/xpm_data/mini_xpm.h26
-rw-r--r--src/xpm_data/x11_xpm.h67
161 files changed, 30918 insertions, 2366 deletions
diff --git a/src/Makefile.inc b/src/Makefile.inc
index 7c3e745..1e0f2a8 100644
--- a/src/Makefile.inc
+++ b/src/Makefile.inc
@@ -36,6 +36,7 @@ SRC += \
glxinfo.c
EXTRA_DIST += \
+ Makefile.inc \
command-line.h \
config-file.h \
msg.h \
@@ -43,3 +44,6 @@ EXTRA_DIST += \
query-assign.h \
nvgetopt.h \
glxinfo.h
+
+dist_list::
+ @ echo $(SRC) $(EXTRA_DIST)
diff --git a/src/XF86Config-parser/Configint.h b/src/XF86Config-parser/Configint.h
new file mode 100644
index 0000000..f91c6ee
--- /dev/null
+++ b/src/XF86Config-parser/Configint.h
@@ -0,0 +1,212 @@
+/*
+ *
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/*
+ * Copyright (c) 1997-2002 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+
+/*
+ * These definitions are used through out the configuration file parser, but
+ * they should not be visible outside of the parser.
+ */
+
+#ifndef _Configint_h_
+#define _Configint_h_
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include "xf86Parser.h"
+
+typedef struct
+{
+ int num; /* returned number */
+ char *str; /* private copy of the return-string */
+ double realnum; /* returned number as a real */
+}
+LexRec, *LexPtr;
+
+
+#include "configProcs.h"
+#include <stdlib.h>
+
+#define TEST_FREE(a) \
+ if (a) { \
+ free (a); \
+ a = NULL; \
+ }
+
+
+#define PARSE_PROLOGUE(typeptr,typerec) \
+ typeptr ptr; \
+ if ((ptr = (typeptr) calloc(1, sizeof(typerec))) == NULL) { \
+ return NULL; \
+ } \
+ memset(ptr, 0, sizeof(typerec));
+
+
+#define HANDLE_LIST(field,func,type) \
+{ \
+ type p = func(); \
+ if (p == NULL) \
+ { \
+ CLEANUP (ptr); \
+ return (NULL); \
+ } else { \
+ ptr->field = (type) \
+ xconfigAddListItem((GenericListPtr) ptr->field, \
+ (GenericListPtr) p); \
+ } \
+}
+
+
+#define Error(a,b) \
+ do { \
+ xconfigErrorMsg(ParseErrorMsg, a, b); \
+ CLEANUP (ptr); \
+ return NULL; \
+ } while (0) \
+
+/*
+ * These are defines for error messages to promote consistency.
+ * error messages are preceded by the line number, section and file name,
+ * so these messages should be about the specific keyword and syntax in error.
+ * To help limit namespace polution, end each with _MSG.
+ * limit messages to 70 characters if possible.
+ */
+
+#define BAD_OPTION_MSG \
+"The Option keyword requires 1 or 2 quoted strings to follow it."
+#define INVALID_KEYWORD_MSG \
+"\"%s\" is not a valid keyword in this section."
+#define INVALID_SECTION_MSG \
+"\"%s\" is not a valid section name."
+#define UNEXPECTED_EOF_MSG \
+"Unexpected EOF. Missing EndSection keyword?"
+#define QUOTE_MSG \
+"The %s keyword requires a quoted string to follow it."
+#define NUMBER_MSG \
+"The %s keyword requires a number to follow it."
+#define POSITIVE_INT_MSG \
+"The %s keyword requires a positive integer to follow it."
+#define ZAXISMAPPING_MSG \
+"The ZAxisMapping keyword requires 2 positive numbers or X or Y to follow it."
+#define AUTOREPEAT_MSG \
+"The AutoRepeat keyword requires 2 numbers (delay and rate) to follow it."
+#define XLEDS_MSG \
+"The XLeds keyword requries one or more numbers to follow it."
+#define DACSPEED_MSG \
+"The DacSpeed keyword must be followed by a list of up to %d numbers."
+#define DISPLAYSIZE_MSG \
+"The DisplaySize keyword must be followed by the width and height in mm."
+#define HORIZSYNC_MSG \
+"The HorizSync keyword must be followed by a list of numbers or ranges."
+#define VERTREFRESH_MSG \
+"The VertRefresh keyword must be followed by a list of numbers or ranges."
+#define VIEWPORT_MSG \
+"The Viewport keyword must be followed by an X and Y value."
+#define VIRTUAL_MSG \
+"The Virtual keyword must be followed by a width and height value."
+#define WEIGHT_MSG \
+"The Weight keyword must be followed by red, green and blue values."
+#define BLACK_MSG \
+"The Black keyword must be followed by red, green and blue values."
+#define WHITE_MSG \
+"The White keyword must be followed by red, green and blue values."
+#define SCREEN_MSG \
+"The Screen keyword must be followed by an optional number, a screen name\n" \
+"\tin quotes, and optional position/layout information."
+#define INVALID_SCR_MSG \
+"Invalid Screen line."
+#define INPUTDEV_MSG \
+"The InputDevice keyword must be followed by an input device name in quotes."
+#define INACTIVE_MSG \
+"The Inactive keyword must be followed by a Device name in quotes."
+#define UNDEFINED_SCREEN_MSG \
+"Undefined Screen \"%s\" referenced by ServerLayout \"%s\"."
+#define UNDEFINED_MONITOR_MSG \
+"Undefined Monitor \"%s\" referenced by Screen \"%s\"."
+#define UNDEFINED_MODES_MSG \
+"Undefined Modes Section \"%s\" referenced by Monitor \"%s\"."
+#define UNDEFINED_DEVICE_MSG \
+"Undefined Device \"%s\" referenced by Screen \"%s\"."
+#define UNDEFINED_ADAPTOR_MSG \
+"Undefined VideoAdaptor \"%s\" referenced by Screen \"%s\"."
+#define ADAPTOR_REF_TWICE_MSG \
+"VideoAdaptor \"%s\" already referenced by Screen \"%s\"."
+#define UNDEFINED_DEVICE_LAY_MSG \
+"Undefined Device \"%s\" referenced by ServerLayout \"%s\"."
+#define UNDEFINED_INPUT_MSG \
+"Undefined InputDevice \"%s\" referenced by ServerLayout \"%s\"."
+#define NO_IDENT_MSG \
+"This section must have an Identifier line."
+#define ONLY_ONE_MSG \
+"This section must have only one of either %s line."
+#define UNDEFINED_DRIVER_MSG \
+"Device section \"%s\" must have a Driver line."
+#define UNDEFINED_INPUTDRIVER_MSG \
+"InputDevice section \"%s\" must have a Driver line."
+#define INVALID_GAMMA_MSG \
+"gamma correction value(s) expected\n either one value or three r/g/b values."
+#define GROUP_MSG \
+"The Group keyword must be followed by either a group name in quotes or\n" \
+"\ta numerical group id."
+#define MULTIPLE_MSG \
+"Multiple \"%s\" lines."
+
+/* Warning messages */
+#define OBSOLETE_MSG \
+"Ignoring obsolete keyword \"%s\"."
+#define MOVED_TO_FLAGS_MSG \
+"Keyword \"%s\" is now an Option flag in the ServerFlags section."
+
+#endif /* _Configint_h_ */
diff --git a/src/XF86Config-parser/DRI.c b/src/XF86Config-parser/DRI.c
new file mode 100644
index 0000000..9936830
--- /dev/null
+++ b/src/XF86Config-parser/DRI.c
@@ -0,0 +1,152 @@
+/* DRI.c -- DRI Section in XF86Config file
+ * Created: Fri Mar 19 08:40:22 1999 by faith@precisioninsight.com
+ * Revised: Thu Jun 17 16:08:05 1999 by faith@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec DRITab[] =
+{
+ {ENDSECTION, "endsection"},
+ {GROUP, "group"},
+ {BUFFERS, "buffers"},
+ {MODE, "mode"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeBuffersList
+
+XConfigBuffersPtr
+xconfigParseBuffers (void)
+{
+ int token;
+ PARSE_PROLOGUE (XConfigBuffersPtr, XConfigBuffersRec)
+
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error("Buffers count expected", NULL);
+ ptr->count = val.num;
+
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error("Buffers size expected", NULL);
+ ptr->size = val.num;
+
+ if ((token = xconfigGetSubToken (&(ptr->comment))) == STRING) {
+ ptr->flags = val.str;
+ if ((token = xconfigGetToken (NULL)) == COMMENT)
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ else
+ xconfigUnGetToken(token);
+ }
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+#define CLEANUP xconfigFreeDRI
+
+XConfigDRIPtr
+xconfigParseDRISection (void)
+{
+ int token;
+ PARSE_PROLOGUE (XConfigDRIPtr, XConfigDRIRec);
+
+ /* Zero is a valid value for this. */
+ ptr->group = -1;
+ while ((token = xconfigGetToken (DRITab)) != ENDSECTION) {
+ switch (token)
+ {
+ case GROUP:
+ if ((token = xconfigGetSubToken (&(ptr->comment))) == STRING)
+ ptr->group_name = val.str;
+ else if (token == NUMBER)
+ ptr->group = val.num;
+ else
+ Error (GROUP_MSG, NULL);
+ break;
+ case MODE:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "Mode");
+ ptr->mode = val.num;
+ break;
+ case BUFFERS:
+ HANDLE_LIST (buffers, xconfigParseBuffers,
+ XConfigBuffersPtr);
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+void
+xconfigPrintDRISection (FILE * cf, XConfigDRIPtr ptr)
+{
+ /* we never need the DRI section for the NVIDIA driver */
+
+ return;
+}
+
+void
+xconfigFreeDRI (XConfigDRIPtr ptr)
+{
+ if (ptr == NULL)
+ return;
+
+ xconfigFreeBuffersList (ptr->buffers);
+ TEST_FREE (ptr->comment);
+ free (ptr);
+}
+
+void
+xconfigFreeBuffersList (XConfigBuffersPtr ptr)
+{
+ XConfigBuffersPtr prev;
+
+ while (ptr) {
+ TEST_FREE (ptr->flags);
+ TEST_FREE (ptr->comment);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
diff --git a/src/XF86Config-parser/Device.c b/src/XF86Config-parser/Device.c
new file mode 100644
index 0000000..a4c3f62
--- /dev/null
+++ b/src/XF86Config-parser/Device.c
@@ -0,0 +1,498 @@
+/*
+ *
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+#include <ctype.h>
+
+extern LexRec val;
+
+static
+XConfigSymTabRec DeviceTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {IDENTIFIER, "identifier"},
+ {VENDOR, "vendorname"},
+ {BOARD, "boardname"},
+ {CHIPSET, "chipset"},
+ {RAMDAC, "ramdac"},
+ {DACSPEED, "dacspeed"},
+ {CLOCKS, "clocks"},
+ {OPTION, "option"},
+ {VIDEORAM, "videoram"},
+ {BIOSBASE, "biosbase"},
+ {MEMBASE, "membase"},
+ {IOBASE, "iobase"},
+ {CLOCKCHIP, "clockchip"},
+ {CHIPID, "chipid"},
+ {CHIPREV, "chiprev"},
+ {CARD, "card"},
+ {DRIVER, "driver"},
+ {BUSID, "busid"},
+ {TEXTCLOCKFRQ, "textclockfreq"},
+ {IRQ, "irq"},
+ {SCREEN, "screen"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeDeviceList
+
+XConfigDevicePtr
+xconfigParseDeviceSection (void)
+{
+ int i;
+ int has_ident = FALSE;
+ int token;
+ PARSE_PROLOGUE (XConfigDevicePtr, XConfigDeviceRec)
+
+ /* Zero is a valid value for these */
+ ptr->chipid = -1;
+ ptr->chiprev = -1;
+ ptr->irq = -1;
+ ptr->screen = -1;
+ while ((token = xconfigGetToken (DeviceTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Identifier");
+ if (has_ident == TRUE)
+ Error (MULTIPLE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ has_ident = TRUE;
+ break;
+ case VENDOR:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Vendor");
+ ptr->vendor = val.str;
+ break;
+ case BOARD:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Board");
+ ptr->board = val.str;
+ break;
+ case CHIPSET:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Chipset");
+ ptr->chipset = val.str;
+ break;
+ case CARD:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Card");
+ ptr->card = val.str;
+ break;
+ case DRIVER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Driver");
+ ptr->driver = val.str;
+ break;
+ case RAMDAC:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Ramdac");
+ ptr->ramdac = val.str;
+ break;
+ case DACSPEED:
+ for (i = 0; i < CONF_MAXDACSPEEDS; i++)
+ ptr->dacSpeeds[i] = 0;
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ {
+ Error (DACSPEED_MSG, CONF_MAXDACSPEEDS);
+ }
+ else
+ {
+ ptr->dacSpeeds[0] = (int) (val.realnum * 1000.0 + 0.5);
+ for (i = 1; i < CONF_MAXDACSPEEDS; i++)
+ {
+ if (xconfigGetSubToken (&(ptr->comment)) == NUMBER)
+ ptr->dacSpeeds[i] = (int)
+ (val.realnum * 1000.0 + 0.5);
+ else
+ {
+ xconfigUnGetToken (token);
+ break;
+ }
+ }
+ }
+ break;
+ case VIDEORAM:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "VideoRam");
+ ptr->videoram = val.num;
+ break;
+ case BIOSBASE:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "BIOSBase");
+ ptr->bios_base = val.num;
+ break;
+ case MEMBASE:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "MemBase");
+ ptr->mem_base = val.num;
+ break;
+ case IOBASE:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "IOBase");
+ ptr->io_base = val.num;
+ break;
+ case CLOCKCHIP:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "ClockChip");
+ ptr->clockchip = val.str;
+ break;
+ case CHIPID:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "ChipID");
+ ptr->chipid = val.num;
+ break;
+ case CHIPREV:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "ChipRev");
+ ptr->chiprev = val.num;
+ break;
+
+ case CLOCKS:
+ token = xconfigGetSubToken(&(ptr->comment));
+ for( i = ptr->clocks;
+ token == NUMBER && i < CONF_MAXCLOCKS; i++ ) {
+ ptr->clock[i] = (int)(val.realnum * 1000.0 + 0.5);
+ token = xconfigGetSubToken(&(ptr->comment));
+ }
+ ptr->clocks = i;
+ xconfigUnGetToken (token);
+ break;
+ case TEXTCLOCKFRQ:
+ if ((token = xconfigGetSubToken(&(ptr->comment))) != NUMBER)
+ Error (NUMBER_MSG, "TextClockFreq");
+ ptr->textclockfreq = (int)(val.realnum * 1000.0 + 0.5);
+ break;
+ case OPTION:
+ ptr->options = xconfigParseOption(ptr->options);
+ break;
+ case BUSID:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "BusID");
+ ptr->busid = val.str;
+ break;
+ case IRQ:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (QUOTE_MSG, "IRQ");
+ ptr->irq = val.num;
+ break;
+ case SCREEN:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "Screen");
+ ptr->screen = val.num;
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ if (!has_ident)
+ Error (NO_IDENT_MSG, NULL);
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+void
+xconfigPrintDeviceSection (FILE * cf, XConfigDevicePtr ptr)
+{
+ int i;
+
+ while (ptr)
+ {
+ fprintf (cf, "Section \"Device\"\n");
+ if (ptr->comment)
+ fprintf (cf, "%s", ptr->comment);
+ if (ptr->identifier)
+ fprintf (cf, " Identifier \"%s\"\n", ptr->identifier);
+ if (ptr->driver)
+ fprintf (cf, " Driver \"%s\"\n", ptr->driver);
+ if (ptr->vendor)
+ fprintf (cf, " VendorName \"%s\"\n", ptr->vendor);
+ if (ptr->board)
+ fprintf (cf, " BoardName \"%s\"\n", ptr->board);
+ if (ptr->chipset)
+ fprintf (cf, " ChipSet \"%s\"\n", ptr->chipset);
+ if (ptr->card)
+ fprintf (cf, " Card \"%s\"\n", ptr->card);
+ if (ptr->ramdac)
+ fprintf (cf, " RamDac \"%s\"\n", ptr->ramdac);
+ if (ptr->dacSpeeds[0] > 0 ) {
+ fprintf (cf, " DacSpeed ");
+ for (i = 0; i < CONF_MAXDACSPEEDS
+ && ptr->dacSpeeds[i] > 0; i++ )
+ fprintf (cf, "%g ", (double) (ptr->dacSpeeds[i])/ 1000.0 );
+ fprintf (cf, "\n");
+ }
+ if (ptr->videoram)
+ fprintf (cf, " VideoRam %d\n", ptr->videoram);
+ if (ptr->bios_base)
+ fprintf (cf, " BiosBase 0x%lx\n", ptr->bios_base);
+ if (ptr->mem_base)
+ fprintf (cf, " MemBase 0x%lx\n", ptr->mem_base);
+ if (ptr->io_base)
+ fprintf (cf, " IOBase 0x%lx\n", ptr->io_base);
+ if (ptr->clockchip)
+ fprintf (cf, " ClockChip \"%s\"\n", ptr->clockchip);
+ if (ptr->chipid != -1)
+ fprintf (cf, " ChipId 0x%x\n", ptr->chipid);
+ if (ptr->chiprev != -1)
+ fprintf (cf, " ChipRev 0x%x\n", ptr->chiprev);
+
+ xconfigPrintOptionList(cf, ptr->options, 1);
+ if (ptr->clocks > 0 ) {
+ fprintf (cf, " Clocks ");
+ for (i = 0; i < ptr->clocks; i++ )
+ fprintf (cf, "%.1f ", (double)ptr->clock[i] / 1000.0 );
+ fprintf (cf, "\n");
+ }
+ if (ptr->textclockfreq) {
+ fprintf (cf, " TextClockFreq %.1f\n",
+ (double)ptr->textclockfreq / 1000.0);
+ }
+ if (ptr->busid)
+ fprintf (cf, " BusID \"%s\"\n", ptr->busid);
+ if (ptr->screen > -1)
+ fprintf (cf, " Screen %d\n", ptr->screen);
+ if (ptr->irq >= 0)
+ fprintf (cf, " IRQ %d\n", ptr->irq);
+ fprintf (cf, "EndSection\n\n");
+ ptr = ptr->next;
+ }
+}
+
+void
+xconfigFreeDeviceList (XConfigDevicePtr ptr)
+{
+ XConfigDevicePtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->identifier);
+ TEST_FREE (ptr->vendor);
+ TEST_FREE (ptr->board);
+ TEST_FREE (ptr->chipset);
+ TEST_FREE (ptr->card);
+ TEST_FREE (ptr->driver);
+ TEST_FREE (ptr->ramdac);
+ TEST_FREE (ptr->clockchip);
+ TEST_FREE (ptr->comment);
+ xconfigOptionListFree (ptr->options);
+
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+int
+xconfigValidateDevice (XConfigPtr p)
+{
+ XConfigDevicePtr device = p->devices;
+
+ if (!device) {
+ xconfigErrorMsg(ValidationErrorMsg, "At least one Device section "
+ "is required.");
+ return (FALSE);
+ }
+
+ while (device) {
+ if (!device->driver) {
+ xconfigErrorMsg(ValidationErrorMsg, UNDEFINED_DRIVER_MSG,
+ device->identifier);
+ return (FALSE);
+ }
+ device = device->next;
+ }
+ return (TRUE);
+}
+
+XConfigDevicePtr
+xconfigFindDevice (const char *ident, XConfigDevicePtr p)
+{
+ while (p)
+ {
+ if (xconfigNameCompare (ident, p->identifier) == 0)
+ return (p);
+
+ p = p->next;
+ }
+ return (NULL);
+}
+
+
+/*
+ * Determine what bus type the busID string represents. The start of the
+ * bus-dependent part of the string is returned as retID.
+ */
+
+static int isPci(const char* busID, const char **retID)
+{
+ char *p, *s;
+ int ret = FALSE;
+
+ /* If no type field, Default to PCI */
+ if (isdigit(busID[0])) {
+ if (retID)
+ *retID = busID;
+ return TRUE;
+ }
+
+ s = strdup(busID);
+ p = strtok(s, ":");
+ if (p == NULL || *p == 0) {
+ free(s);
+ return FALSE;
+ }
+ if (!xconfigNameCompare(p, "pci") || !xconfigNameCompare(p, "agp")) {
+ if (retID)
+ *retID = busID + strlen(p) + 1;
+ ret = TRUE;
+ }
+ free(s);
+ return ret;
+}
+
+
+/*
+ * Parse a BUS ID string, and return the PCI bus parameters if it was
+ * in the correct format for a PCI bus id.
+ */
+
+int xconfigParsePciBusString(const char *busID,
+ int *bus, int *device, int *func)
+{
+ /*
+ * The format is assumed to be "bus[@domain]:device[:func]", where domain,
+ * bus, device and func are decimal integers. domain and func may be
+ * omitted and assumed to be zero, although doing this isn't encouraged.
+ */
+
+ char *p, *s, *d;
+ const char *id;
+ int i;
+
+ if (!isPci(busID, &id))
+ return FALSE;
+
+ s = strdup(id);
+ p = strtok(s, ":");
+ if (p == NULL || *p == 0) {
+ free(s);
+ return FALSE;
+ }
+ d = strpbrk(p, "@");
+ if (d != NULL) {
+ *(d++) = 0;
+ for (i = 0; d[i] != 0; i++) {
+ if (!isdigit(d[i])) {
+ free(s);
+ return FALSE;
+ }
+ }
+ }
+ for (i = 0; p[i] != 0; i++) {
+ if (!isdigit(p[i])) {
+ free(s);
+ return FALSE;
+ }
+ }
+ *bus = atoi(p);
+ if (d != NULL && *d != 0)
+ *bus += atoi(d) << 8;
+ p = strtok(NULL, ":");
+ if (p == NULL || *p == 0) {
+ free(s);
+ return FALSE;
+ }
+ for (i = 0; p[i] != 0; i++) {
+ if (!isdigit(p[i])) {
+ free(s);
+ return FALSE;
+ }
+ }
+ *device = atoi(p);
+ *func = 0;
+ p = strtok(NULL, ":");
+ if (p == NULL || *p == 0) {
+ free(s);
+ return TRUE;
+ }
+ for (i = 0; p[i] != 0; i++) {
+ if (!isdigit(p[i])) {
+ free(s);
+ return FALSE;
+ }
+ }
+ *func = atoi(p);
+ free(s);
+ return TRUE;
+}
+
diff --git a/src/XF86Config-parser/Extensions.c b/src/XF86Config-parser/Extensions.c
new file mode 100644
index 0000000..7482a6d
--- /dev/null
+++ b/src/XF86Config-parser/Extensions.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2004 Red Hat Inc., Raleigh, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <kem@redhat.com>
+ *
+ */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec ExtensionsTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {OPTION, "option"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeExtensions
+
+XConfigExtensionsPtr
+xconfigParseExtensionsSection (void)
+{
+ int token;
+
+ PARSE_PROLOGUE (XConfigExtensionsPtr, XConfigExtensionsRec);
+
+ while ((token = xconfigGetToken (ExtensionsTab)) != ENDSECTION) {
+ switch (token) {
+ case OPTION:
+ ptr->options = xconfigParseOption(ptr->options);
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+void
+xconfigPrintExtensionsSection (FILE * cf, XConfigExtensionsPtr ptr)
+{
+ XConfigOptionPtr p;
+
+ if (ptr == NULL || ptr->options == NULL)
+ return;
+
+ p = ptr->options;
+ fprintf (cf, "Section \"Extensions\"\n");
+ if (ptr->comment) fprintf (cf, "%s", ptr->comment);
+ xconfigPrintOptionList(cf, p, 1);
+ fprintf (cf, "EndSection\n\n");
+}
+
+void
+xconfigFreeExtensions (XConfigExtensionsPtr ptr)
+{
+ if (ptr == NULL)
+ return;
+
+ xconfigOptionListFree (ptr->options);
+ TEST_FREE (ptr->comment);
+ free (ptr);
+}
diff --git a/src/XF86Config-parser/Files.c b/src/XF86Config-parser/Files.c
new file mode 100644
index 0000000..6493cd1
--- /dev/null
+++ b/src/XF86Config-parser/Files.c
@@ -0,0 +1,281 @@
+/*
+ *
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include <strings.h>
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec FilesTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {FONTPATH, "fontpath"},
+ {RGBPATH, "rgbpath"},
+ {MODULEPATH, "modulepath"},
+ {INPUTDEVICES, "inputdevices"},
+ {LOGFILEPATH, "logfile"},
+ {-1, ""},
+};
+
+static char *
+prependRoot (char *pathname)
+{
+ return pathname;
+}
+
+#define CLEANUP xconfigFreeFiles
+
+XConfigFilesPtr
+xconfigParseFilesSection (void)
+{
+ int i, j;
+ int k, l;
+ char *str;
+ int token;
+ PARSE_PROLOGUE (XConfigFilesPtr, XConfigFilesRec)
+
+ while ((token = xconfigGetToken (FilesTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case FONTPATH:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "FontPath");
+ j = FALSE;
+ str = prependRoot (val.str);
+ if (ptr->fontpath == NULL)
+ {
+ ptr->fontpath = malloc (1);
+ ptr->fontpath[0] = '\0';
+ i = strlen (str) + 1;
+ }
+ else
+ {
+ i = strlen (ptr->fontpath) + strlen (str) + 1;
+ if (ptr->fontpath[strlen (ptr->fontpath) - 1] != ',')
+ {
+ i++;
+ j = TRUE;
+ }
+ }
+ ptr->fontpath = realloc (ptr->fontpath, i);
+ if (j)
+ strcat (ptr->fontpath, ",");
+
+ strcat (ptr->fontpath, str);
+ free (val.str);
+ break;
+ case RGBPATH:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "RGBPath");
+ ptr->rgbpath = val.str;
+ break;
+ case MODULEPATH:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "ModulePath");
+ l = FALSE;
+ str = prependRoot (val.str);
+ if (ptr->modulepath == NULL)
+ {
+ ptr->modulepath = malloc (1);
+ ptr->modulepath[0] = '\0';
+ k = strlen (str) + 1;
+ }
+ else
+ {
+ k = strlen (ptr->modulepath) + strlen (str) + 1;
+ if (ptr->modulepath[strlen (ptr->modulepath) - 1] != ',')
+ {
+ k++;
+ l = TRUE;
+ }
+ }
+ ptr->modulepath = realloc (ptr->modulepath, k);
+ if (l)
+ strcat (ptr->modulepath, ",");
+
+ strcat (ptr->modulepath, str);
+ free (val.str);
+ break;
+ case INPUTDEVICES:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "InputDevices");
+ l = FALSE;
+ str = prependRoot (val.str);
+ if (ptr->inputdevs == NULL)
+ {
+ ptr->inputdevs = malloc (1);
+ ptr->inputdevs[0] = '\0';
+ k = strlen (str) + 1;
+ }
+ else
+ {
+ k = strlen (ptr->inputdevs) + strlen (str) + 1;
+ if (ptr->inputdevs[strlen (ptr->inputdevs) - 1] != ',')
+ {
+ k++;
+ l = TRUE;
+ }
+ }
+ ptr->inputdevs = realloc (ptr->inputdevs, k);
+ if (l)
+ strcat (ptr->inputdevs, ",");
+
+ strcat (ptr->inputdevs, str);
+ free (val.str);
+ break;
+ case LOGFILEPATH:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "LogFile");
+ ptr->logfile = val.str;
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+void
+xconfigPrintFileSection (FILE * cf, XConfigFilesPtr ptr)
+{
+ char *p, *s;
+
+ if (ptr == NULL)
+ return;
+
+ if (ptr->comment)
+ fprintf (cf, "%s", ptr->comment);
+ if (ptr->logfile)
+ fprintf (cf, " LogFile \"%s\"\n", ptr->logfile);
+ if (ptr->rgbpath)
+ fprintf (cf, " RgbPath \"%s\"\n", ptr->rgbpath);
+ if (ptr->modulepath)
+ {
+ s = ptr->modulepath;
+ p = index (s, ',');
+ while (p)
+ {
+ *p = '\000';
+ fprintf (cf, " ModulePath \"%s\"\n", s);
+ *p = ',';
+ s = p;
+ s++;
+ p = index (s, ',');
+ }
+ fprintf (cf, " ModulePath \"%s\"\n", s);
+ }
+ if (ptr->inputdevs)
+ {
+ s = ptr->inputdevs;
+ p = index (s, ',');
+ while (p)
+ {
+ *p = '\000';
+ fprintf (cf, " InputDevices \"%s\"\n", s);
+ *p = ',';
+ s = p;
+ s++;
+ p = index (s, ',');
+ }
+ fprintf (cf, " InputDevices \"%s\"\n", s);
+ }
+ if (ptr->fontpath)
+ {
+ s = ptr->fontpath;
+ p = index (s, ',');
+ while (p)
+ {
+ *p = '\000';
+ fprintf (cf, " FontPath \"%s\"\n", s);
+ *p = ',';
+ s = p;
+ s++;
+ p = index (s, ',');
+ }
+ fprintf (cf, " FontPath \"%s\"\n", s);
+ }
+}
+
+void
+xconfigFreeFiles (XConfigFilesPtr p)
+{
+ if (p == NULL)
+ return;
+
+ TEST_FREE (p->logfile);
+ TEST_FREE (p->rgbpath);
+ TEST_FREE (p->modulepath);
+ TEST_FREE (p->inputdevs);
+ TEST_FREE (p->fontpath);
+ TEST_FREE (p->comment);
+
+ free (p);
+}
diff --git a/src/XF86Config-parser/Flags.c b/src/XF86Config-parser/Flags.c
new file mode 100644
index 0000000..21413c9
--- /dev/null
+++ b/src/XF86Config-parser/Flags.c
@@ -0,0 +1,560 @@
+/*
+ *
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+#include <math.h>
+
+extern LexRec val;
+
+static XConfigSymTabRec ServerFlagsTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {NOTRAPSIGNALS, "notrapsignals"},
+ {DONTZAP, "dontzap"},
+ {DONTZOOM, "dontzoom"},
+ {DISABLEVIDMODE, "disablevidmodeextension"},
+ {ALLOWNONLOCAL, "allownonlocalxvidtune"},
+ {DISABLEMODINDEV, "disablemodindev"},
+ {MODINDEVALLOWNONLOCAL, "allownonlocalmodindev"},
+ {ALLOWMOUSEOPENFAIL, "allowmouseopenfail"},
+ {OPTION, "option"},
+ {BLANKTIME, "blanktime"},
+ {STANDBYTIME, "standbytime"},
+ {SUSPENDTIME, "suspendtime"},
+ {OFFTIME, "offtime"},
+ {DEFAULTLAYOUT, "defaultserverlayout"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeFlags
+
+XConfigFlagsPtr
+xconfigParseFlagsSection (void)
+{
+ int token;
+ PARSE_PROLOGUE (XConfigFlagsPtr, XConfigFlagsRec)
+
+ while ((token = xconfigGetToken (ServerFlagsTab)) != ENDSECTION)
+ {
+ int hasvalue = FALSE;
+ int strvalue = FALSE;
+ int tokentype;
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ /*
+ * these old keywords are turned into standard generic options.
+ * we fall through here on purpose
+ */
+ case DEFAULTLAYOUT:
+ strvalue = TRUE;
+ case BLANKTIME:
+ case STANDBYTIME:
+ case SUSPENDTIME:
+ case OFFTIME:
+ hasvalue = TRUE;
+ case NOTRAPSIGNALS:
+ case DONTZAP:
+ case DONTZOOM:
+ case DISABLEVIDMODE:
+ case ALLOWNONLOCAL:
+ case DISABLEMODINDEV:
+ case MODINDEVALLOWNONLOCAL:
+ case ALLOWMOUSEOPENFAIL:
+ {
+ int i = 0;
+ while (ServerFlagsTab[i].token != -1)
+ {
+ char *tmp;
+
+ if (ServerFlagsTab[i].token == token)
+ {
+ char *valstr = NULL;
+ /* can't use strdup because it calls malloc */
+ tmp = xconfigStrdup (ServerFlagsTab[i].name);
+ if (hasvalue)
+ {
+ tokentype = xconfigGetSubToken(&(ptr->comment));
+ if (strvalue) {
+ if (tokentype != STRING)
+ Error (QUOTE_MSG, tmp);
+ valstr = val.str;
+ } else {
+ if (tokentype != NUMBER)
+ Error (NUMBER_MSG, tmp);
+ valstr = malloc(16);
+ if (valstr)
+ sprintf(valstr, "%d", val.num);
+ }
+ }
+ ptr->options = xconfigAddNewOption
+ (ptr->options, tmp, valstr);
+ }
+ i++;
+ }
+ }
+ break;
+ case OPTION:
+ ptr->options = xconfigParseOption(ptr->options);
+ break;
+
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+void
+xconfigPrintServerFlagsSection (FILE * f, XConfigFlagsPtr flags)
+{
+ XConfigOptionPtr p;
+
+ if ((!flags) || (!flags->options))
+ return;
+ p = flags->options;
+ fprintf (f, "Section \"ServerFlags\"\n");
+ if (flags->comment)
+ fprintf (f, "%s", flags->comment);
+ xconfigPrintOptionList(f, p, 1);
+ fprintf (f, "EndSection\n\n");
+}
+
+static XConfigOptionPtr
+addNewOption2 (XConfigOptionPtr head, char *name, char *val, int used)
+{
+ XConfigOptionPtr new, old = NULL;
+
+ /* Don't allow duplicates */
+ if (head != NULL && (old = xconfigFindOption(head, name)) != NULL) {
+ TEST_FREE(old->name);
+ TEST_FREE(old->val);
+ new = old;
+ } else {
+ new = calloc (1, sizeof (XConfigOptionRec));
+ new->next = NULL;
+ }
+ new->name = name;
+ new->val = val;
+ new->used = used;
+
+ if (old == NULL)
+ return ((XConfigOptionPtr) xconfigAddListItem ((GenericListPtr) head,
+ (GenericListPtr) new));
+ else
+ return head;
+}
+
+XConfigOptionPtr
+xconfigAddNewOption (XConfigOptionPtr head, char *name, char *val)
+{
+ return addNewOption2(head, name, val, 0);
+}
+
+void
+xconfigFreeFlags (XConfigFlagsPtr flags)
+{
+ if (flags == NULL)
+ return;
+ xconfigOptionListFree (flags->options);
+ TEST_FREE(flags->comment);
+ free (flags);
+}
+
+XConfigOptionPtr
+xconfigOptionListDup (XConfigOptionPtr opt)
+{
+ XConfigOptionPtr newopt = NULL;
+
+ while (opt)
+ {
+ newopt = xconfigAddNewOption(newopt, xconfigStrdup(opt->name),
+ xconfigStrdup(opt->val));
+ newopt->used = opt->used;
+ if (opt->comment)
+ newopt->comment = xconfigStrdup(opt->comment);
+ opt = opt->next;
+ }
+ return newopt;
+}
+
+void
+xconfigOptionListFree (XConfigOptionPtr opt)
+{
+ XConfigOptionPtr prev;
+
+ while (opt)
+ {
+ TEST_FREE (opt->name);
+ TEST_FREE (opt->val);
+ TEST_FREE (opt->comment);
+ prev = opt;
+ opt = opt->next;
+ free (prev);
+ }
+}
+
+char *
+xconfigOptionName(XConfigOptionPtr opt)
+{
+ if (opt)
+ return opt->name;
+ return 0;
+}
+
+char *
+xconfigOptionValue(XConfigOptionPtr opt)
+{
+ if (opt)
+ return opt->val;
+ return 0;
+}
+
+XConfigOptionPtr
+xconfigNewOption(char *name, char *value)
+{
+ XConfigOptionPtr opt;
+
+ opt = calloc(1, sizeof (XConfigOptionRec));
+ if (!opt)
+ return NULL;
+
+ opt->used = 0;
+ opt->next = 0;
+ opt->name = name;
+ opt->val = value;
+
+ return opt;
+}
+
+XConfigOptionPtr
+xconfigRemoveOption(XConfigOptionPtr list, XConfigOptionPtr opt)
+{
+ XConfigOptionPtr prev = NULL;
+ XConfigOptionPtr p = list;
+
+ while (p) {
+ if (p == opt) {
+ if (prev) prev->next = opt->next;
+ if (list == opt) list = opt->next;
+
+ TEST_FREE(opt->name);
+ TEST_FREE(opt->val);
+ TEST_FREE(opt->comment);
+ free(opt);
+ break;
+ }
+ prev = p;
+ p = p->next;
+ }
+
+ return list;
+}
+
+XConfigOptionPtr
+xconfigNextOption(XConfigOptionPtr list)
+{
+ if (!list)
+ return NULL;
+ return list->next;
+}
+
+/*
+ * this function searches the given option list for the named option and
+ * returns a pointer to the option rec if found. If not found, it returns
+ * NULL
+ */
+
+XConfigOptionPtr
+xconfigFindOption (XConfigOptionPtr list, const char *name)
+{
+ while (list)
+ {
+ if (xconfigNameCompare (list->name, name) == 0)
+ return (list);
+ list = list->next;
+ }
+ return (NULL);
+}
+
+/*
+ * this function searches the given option list for the named option. If
+ * found and the option has a parameter, a pointer to the parameter is
+ * returned. If the option does not have a parameter an empty string is
+ * returned. If the option is not found, a NULL is returned.
+ */
+
+char *
+xconfigFindOptionValue (XConfigOptionPtr list, const char *name)
+{
+ XConfigOptionPtr p = xconfigFindOption (list, name);
+
+ if (p)
+ {
+ if (p->val)
+ return (p->val);
+ else
+ return "";
+ }
+ return (NULL);
+}
+
+/*
+ * this function searches the given option list for the named option. If
+ * found and the the value of the option is set to "1", "ON", "YES" or
+ * "TRUE", 1 is returned. Otherwise, 0 is returned.
+ */
+
+int
+xconfigFindOptionBoolean (XConfigOptionPtr list, const char *name)
+{
+ XConfigOptionPtr p = xconfigFindOption (list, name);
+
+ if (p && p->val)
+ {
+ if ( strcasecmp(p->val, "1") == 0 ||
+ strcasecmp(p->val, "ON") == 0 ||
+ strcasecmp(p->val, "YES") == 0 ||
+ strcasecmp(p->val, "TRUE") == 0 )
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+XConfigOptionPtr
+xconfigOptionListCreate( const char **options, int count, int used )
+{
+ XConfigOptionPtr p = NULL;
+ char *t1, *t2;
+ int i;
+
+ if (count == -1)
+ {
+ for (count = 0; options[count]; count++)
+ ;
+ }
+ if( (count % 2) != 0 )
+ {
+ xconfigErrorMsg(InternalErrorMsg, "xconfigOptionListCreate: count must "
+ "be an even number.\n");
+ return (NULL);
+ }
+ for (i = 0; i < count; i += 2)
+ {
+ /* can't use strdup because it calls malloc */
+ t1 = malloc (sizeof (char) *
+ (strlen (options[i]) + 1));
+ strcpy (t1, options[i]);
+ t2 = malloc (sizeof (char) *
+ (strlen (options[i + 1]) + 1));
+ strcpy (t2, options[i + 1]);
+ p = addNewOption2 (p, t1, t2, used);
+ }
+
+ return (p);
+}
+
+/* the 2 given lists are merged. If an option with the same name is present in
+ * both, the option from the user list - specified in the second argument -
+ * is used. The end result is a single valid list of options. Duplicates
+ * are freed, and the original lists are no longer guaranteed to be complete.
+ */
+XConfigOptionPtr
+xconfigOptionListMerge (XConfigOptionPtr head, XConfigOptionPtr tail)
+{
+ XConfigOptionPtr a, b, ap = NULL, bp = NULL;
+
+ a = tail;
+ b = head;
+ while (tail && b) {
+ if (xconfigNameCompare (a->name, b->name) == 0) {
+ if (b == head)
+ head = a;
+ else
+ bp->next = a;
+ if (a == tail)
+ tail = a->next;
+ else
+ ap->next = a->next;
+ a->next = b->next;
+ b->next = NULL;
+ xconfigOptionListFree (b);
+ b = a->next;
+ bp = a;
+ a = tail;
+ ap = NULL;
+ } else {
+ ap = a;
+ if (!(a = a->next)) {
+ a = tail;
+ bp = b;
+ b = b->next;
+ ap = NULL;
+ }
+ }
+ }
+
+ if (head) {
+ for (a = head; a->next; a = a->next)
+ ;
+ a->next = tail;
+ } else
+ head = tail;
+
+ return (head);
+}
+
+char *
+xconfigULongToString(unsigned long i)
+{
+ char *s;
+ int l;
+
+ l = (int)(ceil(log10((double)i) + 2.5));
+ s = malloc(l);
+ if (!s)
+ return NULL;
+ sprintf(s, "%lu", i);
+ return s;
+}
+
+XConfigOptionPtr
+xconfigParseOption(XConfigOptionPtr head)
+{
+ XConfigOptionPtr option, cnew, old;
+ char *name, *comment = NULL;
+ int token;
+
+ if ((token = xconfigGetSubToken(&comment)) != STRING) {
+ xconfigErrorMsg(ParseErrorMsg, BAD_OPTION_MSG);
+ if (comment)
+ free(comment);
+ return (head);
+ }
+
+ name = val.str;
+ if ((token = xconfigGetSubToken(&comment)) == STRING) {
+ option = xconfigNewOption(name, val.str);
+ option->comment = comment;
+ if ((token = xconfigGetToken(NULL)) == COMMENT)
+ option->comment = xconfigAddComment(option->comment, val.str);
+ else
+ xconfigUnGetToken(token);
+ }
+ else {
+ option = xconfigNewOption(name, NULL);
+ option->comment = comment;
+ if (token == COMMENT)
+ option->comment = xconfigAddComment(option->comment, val.str);
+ else
+ xconfigUnGetToken(token);
+ }
+
+ old = NULL;
+
+ /* Don't allow duplicates */
+ if (head != NULL && (old = xconfigFindOption(head, name)) != NULL) {
+ cnew = old;
+ free(option->name);
+ TEST_FREE(option->val);
+ TEST_FREE(option->comment);
+ free(option);
+ }
+ else
+ cnew = option;
+
+ if (old == NULL)
+ return ((XConfigOptionPtr)xconfigAddListItem((GenericListPtr)head,
+ (GenericListPtr)cnew));
+
+ return (head);
+}
+
+void
+xconfigPrintOptionList(FILE *fp, XConfigOptionPtr list, int tabs)
+{
+ int i;
+
+ if (!list)
+ return;
+ while (list) {
+ for (i = 0; i < tabs; i++)
+ fprintf(fp, " ");
+ if (list->val)
+ fprintf(fp, "Option \"%s\" \"%s\"", list->name, list->val);
+ else
+ fprintf(fp, "Option \"%s\"", list->name);
+ if (list->comment)
+ fprintf(fp, "%s", list->comment);
+ else
+ fputc('\n', fp);
+ list = list->next;
+ }
+}
diff --git a/src/XF86Config-parser/Generate.c b/src/XF86Config-parser/Generate.c
new file mode 100644
index 0000000..d61771a
--- /dev/null
+++ b/src/XF86Config-parser/Generate.c
@@ -0,0 +1,1330 @@
+/*
+ * nvidia-xconfig: A tool for manipulating X config files,
+ * specifically for use by the NVIDIA Linux graphics driver.
+ *
+ * Copyright (C) 2005 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ * Generate.c
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+
+#include "xf86Parser.h"
+#include "Configint.h"
+
+#define MOUSE_IDENTIFER "Mouse0"
+#define KEYBOARD_IDENTIFER "Keyboard0"
+
+#define SCREEN_IDENTIFIER "Screen%d"
+#define DEVICE_IDENTIFIER "Device%d"
+#define MONITOR_IDENTIFIER "Monitor%d"
+
+
+static int is_file(const char *filename);
+
+static void add_files(GenerateOptions *gop, XConfigPtr config);
+static void add_font_path(GenerateOptions *gop, XConfigPtr config);
+static void add_modules(GenerateOptions *gop, XConfigPtr config);
+
+static XConfigDevicePtr
+add_device(XConfigPtr config, int bus, int slot, char *boardname, int count);
+
+static void add_layout(GenerateOptions *gop, XConfigPtr config);
+
+static void add_inputref(XConfigPtr config, XConfigLayoutPtr layout,
+ char *name, char *coreKeyword);
+
+/*
+ * xconfigGenerate() - generate a new XConfig from scratch
+ */
+
+XConfigPtr xconfigGenerate(GenerateOptions *gop)
+{
+ XConfigPtr config;
+
+ config = xconfigAlloc(sizeof(XConfigRec));
+
+ /* add files, fonts, and modules */
+
+ add_files(gop, config);
+ add_font_path(gop, config);
+ add_modules(gop, config);
+
+ /* add the keyboard and mouse */
+
+ xconfigAddKeyboard(gop, config);
+ xconfigAddMouse(gop, config);
+
+ /* add the layout */
+
+ add_layout(gop, config);
+
+ return config;
+
+} /* xconfigGenerate() */
+
+
+
+/*
+ * xconfigGenerateAddScreen() - add a new screen to the config; bus
+ * and slot can be -1 to be ignored; boardname can be NULL to be
+ * ignored; count is used when building the identifier name, eg
+ * '"Screen%d", count'. Note that this does not append the screen to
+ * any layout's adjacency list.
+ */
+
+XConfigScreenPtr xconfigGenerateAddScreen(XConfigPtr config,
+ int bus, int slot,
+ char *boardname, int count)
+{
+ XConfigScreenPtr screen, s;
+ XConfigDevicePtr device;
+ XConfigMonitorPtr monitor;
+
+ monitor = xconfigAddMonitor(config, count);
+ device = add_device(config, bus, slot, boardname, count);
+
+ screen = xconfigAlloc(sizeof(XConfigScreenRec));
+
+ screen->identifier = xconfigAlloc(32);
+ snprintf(screen->identifier, 32, SCREEN_IDENTIFIER, count);
+
+ screen->device_name = xconfigStrdup(device->identifier);
+ screen->device = device;
+
+ screen->monitor_name = xconfigStrdup(monitor->identifier);
+ screen->monitor = monitor;
+
+ screen->defaultdepth = 24;
+
+ screen->displays = xconfigAddDisplay(screen->displays,
+ screen->defaultdepth);
+
+ /* append to the end of the screen list */
+
+ if (!config->screens) {
+ config->screens = screen;
+ } else {
+ for (s = config->screens; s->next; s = s->next);
+ s->next = screen;
+ }
+
+ return screen;
+
+} /* xconfigGenerateAddScreen() */
+
+
+
+/*
+ * assign_screen_adjacencies() - setup all the adjacency information
+ * for the X screens in the given layout. Nothing fancy here: just
+ * position all the screens horizontally, moving from left to right.
+ */
+
+void xconfigGenerateAssignScreenAdjacencies(XConfigLayoutPtr layout)
+{
+ XConfigAdjacencyPtr adj, prev = NULL;
+
+ for (adj = layout->adjacencies; adj; adj = adj->next) {
+
+ if (prev) {
+ adj->where = CONF_ADJ_RIGHTOF;
+ adj->refscreen = xconfigStrdup(prev->screen_name);
+ } else {
+ adj->x = adj->y = -1;
+ }
+
+ /* make sure all the obsolete positioning is empty */
+
+ adj->top = NULL;
+ adj->top_name = NULL;
+ adj->bottom = NULL;
+ adj->bottom_name = NULL;
+ adj->left = NULL;
+ adj->left_name = NULL;
+ adj->right = NULL;
+ adj->right_name = NULL;
+
+ prev = adj;
+ }
+
+} /* xconfigGenerateAssignScreenAdjacencies() */
+
+
+
+/*********************************************************************/
+
+
+
+/*
+ * is_file()
+ */
+
+static int is_file(const char *filename)
+{
+ return (access(filename, F_OK) == 0);
+
+} /* is_file() */
+
+
+/*
+ * find_libdir() - attempt to find the X server library path; this is
+ * either
+ *
+ * `pkg-config --variable=libdir xorg-server`
+ *
+ * or
+ *
+ * [X PROJECT ROOT]/lib
+ */
+
+static char *find_libdir(GenerateOptions *gop)
+{
+ struct stat stat_buf;
+ FILE *stream = NULL;
+ char *s, *libdir = NULL;
+
+ /*
+ * run the pkg-config command and read the output; if the output
+ * is a directory, then return that as the libdir
+ */
+
+ stream = popen("pkg-config --variable=libdir xorg-server", "r");
+
+ if (stream) {
+ char buf[256];
+
+ buf[0] = '\0';
+
+ while (1) {
+ if (fgets(buf, 255, stream) == NULL) break;
+
+ if (buf[0] != '\0') {
+
+ /* truncate any newline */
+
+ s = strchr(buf, '\n');
+ if (s) *s = '\0';
+
+ if ((stat(buf, &stat_buf) == 0) &&
+ (S_ISDIR(stat_buf.st_mode))) {
+
+ libdir = xconfigStrdup(buf);
+ break;
+ }
+ }
+ }
+
+ pclose(stream);
+
+ if (libdir) return libdir;
+ }
+
+ /* otherwise, just fallback to [X PROJECT ROOT]/lib */
+
+ return xconfigStrcat(gop->x_project_root, "/lib", NULL);
+
+} /* find_libdir() */
+
+
+
+/*
+ * add_files() -
+ */
+
+static void add_files(GenerateOptions *gop, XConfigPtr config)
+{
+ char *libdir = find_libdir(gop);
+
+ config->files = xconfigAlloc(sizeof(XConfigFilesRec));
+ config->files->rgbpath = xconfigStrcat(libdir, "/X11/rgb", NULL);
+
+ free(libdir);
+
+} /* add_files() */
+
+
+/*
+ * add_font_path() - scan through the __font_paths[] array,
+ * temporarily chop off the ":unscaled" appendage, and check for the
+ * file "fonts.dir" in the directory. If fonts.dir exists, append the
+ * path to config->files->fontpath.
+ */
+
+static void add_font_path(GenerateOptions *gop, XConfigPtr config)
+{
+ int i, ret;
+ char *path, *p, *orig, *fonts_dir, *libdir;
+
+ /*
+ * The below font path has been constructed from various examples
+ * and uses some suggests from the Font De-uglification HOWTO
+ */
+
+ static const char *__font_paths[] = {
+ "LIBDIR/X11/fonts/local/",
+ "LIBDIR/X11/fonts/misc/:unscaled",
+ "LIBDIR/X11/fonts/100dpi/:unscaled",
+ "LIBDIR/X11/fonts/75dpi/:unscaled",
+ "LIBDIR/X11/fonts/misc/",
+ "LIBDIR/X11/fonts/Type1/",
+ "LIBDIR/X11/fonts/CID/",
+ "LIBDIR/X11/fonts/Speedo/",
+ "LIBDIR/X11/fonts/100dpi/",
+ "LIBDIR/X11/fonts/75dpi/",
+ "LIBDIR/X11/fonts/cyrillic/",
+ "LIBDIR/X11/fonts/TTF/",
+ "LIBDIR/X11/fonts/truetype/",
+ "LIBDIR/X11/fonts/TrueType/",
+ "LIBDIR/X11/fonts/Type1/sun/",
+ "LIBDIR/X11/fonts/F3bitmaps/",
+ "/usr/local/share/fonts/ttfonts",
+ "/usr/share/fonts/default/Type1",
+ "/usr/lib/openoffice/share/fonts/truetype",
+ NULL
+ };
+
+ /*
+ * if a font server is running, set the font path to that
+ *
+ * XXX should we check the port the font server is using?
+ */
+#if defined(NV_SUNOS)
+ ret = system("ps -e -o fname | grep -v grep | egrep \"^xfs$\" > /dev/null");
+#elif defined(NV_BSD)
+ ret = system("ps -e -o comm | grep -v grep | egrep \"^xfs$\" > /dev/null");
+#else
+ ret = system("ps -C xfs 2>&1 > /dev/null");
+#endif
+ if (WEXITSTATUS(ret) == 0) {
+ config->files->fontpath = xconfigStrdup("unix/:7100");
+ } else {
+
+ /* get the X server libdir */
+
+ libdir = find_libdir(gop);
+
+ for (i = 0; __font_paths[i]; i++) {
+ path = xconfigStrdup(__font_paths[i]);
+
+ /* replace LIBDIR with libdir */
+
+ if (strncmp(path, "LIBDIR", 6) == 0) {
+ p = xconfigStrcat(libdir, path + 6, NULL);
+ free(path);
+ path = p;
+ }
+
+ /* temporarily chop off any ":unscaled" appendage */
+
+ p = strchr(path, ':');
+ if (p) *p = '\0';
+
+ /* skip this entry if the fonts.dir does not exist */
+
+ fonts_dir = xconfigStrcat(path, "/fonts.dir", NULL);
+ if (!is_file(fonts_dir)) {
+ /* does not exist */
+ free(path);
+ free(fonts_dir);
+ continue;
+ }
+ free(fonts_dir);
+
+ /* add the ":unscaled" back */
+
+ if (p) *p = ':';
+
+ /*
+ * either use this path as the fontpath, or append to the
+ * existing fontpath
+ */
+
+ if (config->files->fontpath) {
+ orig = config->files->fontpath;
+ config->files->fontpath = xconfigStrcat(orig, ",", path, NULL);
+ free(orig);
+ free(path);
+ } else {
+ config->files->fontpath = path;
+ }
+ }
+
+ /* free the libdir string */
+
+ free(libdir);
+ }
+} /* add_font_path() */
+
+
+
+/*
+ * add_modules()
+ */
+
+static void add_modules(GenerateOptions *gop, XConfigPtr config)
+{
+ XConfigLoadPtr l = NULL;
+
+ config->modules = xconfigAlloc(sizeof(XConfigModuleRec));
+
+ l = xconfigAddNewLoadDirective(l, xconfigStrdup("dbe"),
+ XCONFIG_LOAD_MODULE, NULL, FALSE);
+ l = xconfigAddNewLoadDirective(l, xconfigStrdup("extmod"),
+ XCONFIG_LOAD_MODULE, NULL, FALSE);
+ l = xconfigAddNewLoadDirective(l, xconfigStrdup("type1"),
+ XCONFIG_LOAD_MODULE, NULL, FALSE);
+#if defined(NV_SUNOS)
+ l = xconfigAddNewLoadDirective(l, xconfigStrdup("IA"),
+ XCONFIG_LOAD_MODULE, NULL, FALSE);
+ l = xconfigAddNewLoadDirective(l, xconfigStrdup("bitstream"),
+ XCONFIG_LOAD_MODULE, NULL, FALSE);
+#else
+ l = xconfigAddNewLoadDirective(l, xconfigStrdup("freetype"),
+ XCONFIG_LOAD_MODULE, NULL, FALSE);
+#endif
+ l = xconfigAddNewLoadDirective(l, xconfigStrdup("glx"),
+ XCONFIG_LOAD_MODULE, NULL, FALSE);
+
+ config->modules->loads = l;
+
+} /* add_modules() */
+
+
+
+/*
+ * xconfigAddMonitor() -
+ *
+ * XXX pass EDID values into this...
+ */
+
+XConfigMonitorPtr xconfigAddMonitor(XConfigPtr config, int count)
+{
+ XConfigMonitorPtr monitor, m;
+ XConfigOptionPtr opt = NULL;
+
+ /* XXX need to query resman for the EDID */
+
+ monitor = xconfigAlloc(sizeof(XConfigMonitorRec));
+
+ monitor->identifier = xconfigAlloc(32);
+ snprintf(monitor->identifier, 32, MONITOR_IDENTIFIER, count);
+ monitor->vendor = xconfigStrdup("Unknown"); /* XXX */
+ monitor->modelname = xconfigStrdup("Unknown"); /* XXX */
+
+ /* XXX check EDID for freq ranges */
+
+ monitor->n_hsync = 1;
+ monitor->hsync[0].lo = 30.0;
+ monitor->hsync[0].hi = 110.0;
+
+ monitor->n_vrefresh = 1;
+ monitor->vrefresh[0].lo = 50.0;
+ monitor->vrefresh[0].hi = 150.0;
+
+ opt = xconfigAddNewOption(opt, xconfigStrdup("DPMS"), NULL);
+
+ monitor->options = opt;
+
+ /* append to the end of the monitor list */
+
+ if (!config->monitors) {
+ config->monitors = monitor;
+ } else {
+ for (m = config->monitors; m->next; m = m->next);
+ m->next = monitor;
+ }
+
+ return monitor;
+
+} /* xconfigAddMonitor() */
+
+
+
+/*
+ * add_device()
+ */
+
+static XConfigDevicePtr
+add_device(XConfigPtr config, int bus, int slot, char *boardname, int count)
+{
+ XConfigDevicePtr device, d;
+
+ device = xconfigAlloc(sizeof(XConfigDeviceRec));
+
+ device->identifier = xconfigAlloc(32);
+ snprintf(device->identifier, 32, DEVICE_IDENTIFIER, count);
+ device->driver = xconfigStrdup("nvidia");
+ device->vendor = xconfigStrdup("NVIDIA Corporation");
+
+ if (bus != -1 && slot != -1) {
+ device->busid = xconfigAlloc(32);
+ snprintf(device->busid, 32, "PCI:%d:%d:0", bus, slot);
+ }
+
+ if (boardname) device->board = xconfigStrdup(boardname);
+
+ device->chipid = -1;
+ device->chiprev = -1;
+ device->irq = -1;
+ device->screen = -1;
+
+ /* append to the end of the device list */
+
+ if (!config->devices) {
+ config->devices = device;
+ } else {
+ for (d = config->devices; d->next; d = d->next);
+ d->next = device;
+ }
+
+ return device;
+
+} /* add_device() */
+
+
+
+XConfigDisplayPtr xconfigAddDisplay(XConfigDisplayPtr head, const int depth)
+{
+ XConfigDisplayPtr display;
+ XConfigModePtr mode = NULL;
+
+ mode = xconfigAddMode(mode, "640x480");
+ mode = xconfigAddMode(mode, "800x600");
+ mode = xconfigAddMode(mode, "1024x768");
+ mode = xconfigAddMode(mode, "1280x1024");
+ mode = xconfigAddMode(mode, "1600x1200");
+
+ display = xconfigAlloc(sizeof(XConfigDisplayRec));
+ display->depth = depth;
+ display->modes = mode;
+ display->frameX0 = -1;
+ display->frameY0 = -1;
+ display->black.red = -1;
+ display->white.red = -1;
+
+ display->next = head;
+
+ return display;
+}
+
+
+
+/*
+ * add_layout() - add a layout section to the XConfigPtr
+ */
+
+static void add_layout(GenerateOptions *gop, XConfigPtr config)
+{
+ XConfigLayoutPtr layout;
+ XConfigAdjacencyPtr adj;
+ XConfigScreenPtr screen;
+
+ /* assume 1 X screen */
+
+ screen = xconfigGenerateAddScreen(config, -1, -1, NULL, 0);
+
+ /* create layout */
+
+ layout = xconfigAlloc(sizeof(XConfigLayoutRec));
+
+ layout->identifier = xconfigStrdup("Layout0");
+
+ adj = xconfigAlloc(sizeof(XConfigAdjacencyRec));
+
+ adj->scrnum = 0;
+ adj->screen = screen;
+ adj->screen_name = xconfigStrdup(screen->identifier);
+
+ layout->adjacencies = adj;
+
+ xconfigGenerateAssignScreenAdjacencies(layout);
+
+ add_inputref(config, layout, MOUSE_IDENTIFER, "CorePointer");
+ add_inputref(config, layout, KEYBOARD_IDENTIFER, "CoreKeyboard");
+
+ layout->next = config->layouts;
+ config->layouts = layout;
+
+} /* add_layout() */
+
+
+
+/*
+ * add_inputref() - add a new XConfigInputrefPtr to the given layout
+ */
+
+static void add_inputref(XConfigPtr config, XConfigLayoutPtr layout,
+ char *name, char *coreKeyword)
+{
+ XConfigInputrefPtr inputRef;
+
+ inputRef = xconfigAlloc(sizeof(XConfigInputrefRec));
+ inputRef->input_name = xconfigStrdup(name);
+ inputRef->input = xconfigFindInput(inputRef->input_name, config->inputs);
+ inputRef->options =
+ xconfigAddNewOption(NULL, xconfigStrdup(coreKeyword), NULL);
+ inputRef->next = layout->inputs;
+ layout->inputs = inputRef;
+
+} /* add_inputref() */
+
+
+
+/*********************************************************************/
+
+/*
+ * Mouse detection
+ */
+
+
+typedef struct {
+ char *shortname; /* commandline name */
+ char *name; /* mouse name */
+ char *gpmproto; /* protocol used by gpm */
+ char *Xproto; /* XFree86 Protocol */
+ char *device; /* /dev/ file */
+ int emulate3; /* Emulate3Buttons */
+} MouseEntry;
+
+
+/*
+ * This table is based on data contained in
+ * /usr/lib/python2.2/site-packages/rhpl/mouse.py on Red Hat Fedora
+ * core 1. That file contains the following copyright:
+ *
+ *
+ *
+ * mouse.py: mouse configuration data
+ *
+ * Copyright 1999-2002 Red Hat, Inc.
+ *
+ * This software may be freely redistributed under the terms of the GNU
+ * library public license.
+ *
+ * You should have received a copy of the GNU Library Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+static const MouseEntry __mice[] = {
+ /* shortname name gpm protocol X protocol device emulate3 */
+ { "alpsps/2", "ALPS - GlidePoint (PS/2)", "ps/2", "GlidePointPS/2", "psaux", TRUE },
+ { "ascii", "ASCII - MieMouse (serial)", "ms3", "IntelliMouse", "ttyS", FALSE },
+ { "asciips/2", "ASCII - MieMouse (PS/2)", "ps/2", "NetMousePS/2", "psaux", TRUE },
+ { "atibm", "ATI - Bus Mouse", "Busmouse", "BusMouse", "atibm", TRUE },
+ { "generic", "Generic - 2 Button Mouse (serial)", "Microsoft", "Microsoft", "ttyS", TRUE },
+ { "generic3", "Generic - 3 Button Mouse (serial)", "Microsoft", "Microsoft", "ttyS", FALSE },
+ { "genericps/2", "Generic - 2 Button Mouse (PS/2)", "ps/2", "PS/2", "psaux", TRUE },
+ { "generic3ps/2", "Generic - 3 Button Mouse (PS/2)", "ps/2", "PS/2", "psaux", FALSE },
+ { "genericwheelps/2", "Generic - Wheel Mouse (PS/2)", "imps2", "IMPS/2", "psaux", FALSE },
+ { "genericusb", "Generic - 2 Button Mouse (USB)", "imps2", "IMPS/2", "input/mice", TRUE },
+ { "generic3usb", "Generic - 3 Button Mouse (USB)", "imps2", "IMPS/2", "input/mice", FALSE },
+ { "genericwheelusb", "Generic - Wheel Mouse (USB)", "imps2", "IMPS/2", "input/mice", FALSE },
+ { "geniusnm", "Genius - NetMouse (serial)", "ms3", "IntelliMouse", "ttyS", TRUE },
+ { "geniusnmps/2", "Genius - NetMouse (PS/2)", "netmouse", "NetMousePS/2", "psaux", TRUE },
+ { "geniusprops/2", "Genius - NetMouse Pro (PS/2)", "netmouse", "NetMousePS/2", "psaux", TRUE },
+ { "geniusscrollps/2", "Genius - NetScroll (PS/2)", "netmouse", "NetScrollPS/2", "psaux", TRUE },
+ { "geniusscrollps/2+", "Genius - NetScroll+ (PS/2)", "netmouse", "NetMousePS/2", "psaux", FALSE },
+ { "thinking", "Kensington - Thinking Mouse (serial)", "Microsoft", "ThinkingMouse", "ttyS", TRUE },
+ { "thinkingps/2", "Kensington - Thinking Mouse (PS/2)", "ps/2", "ThinkingMousePS/2", "psaux", TRUE },
+ { "logitech", "Logitech - C7 Mouse (serial, old C7 type)", "Logitech", "Logitech", "ttyS", FALSE },
+ { "logitechcc", "Logitech - CC Series (serial)", "logim", "MouseMan", "ttyS", FALSE },
+ { "logibm", "Logitech - Bus Mouse", "Busmouse", "BusMouse", "logibm", FALSE },
+ { "logimman", "Logitech - MouseMan/FirstMouse (serial)", "MouseMan", "MouseMan", "ttyS", FALSE },
+ { "logimmanps/2", "Logitech - MouseMan/FirstMouse (PS/2)", "ps/2", "PS/2", "psaux", FALSE },
+ { "logimman+", "Logitech - MouseMan+/FirstMouse+ (serial)", "pnp", "IntelliMouse", "ttyS", FALSE },
+ { "logimman+ps/2", "Logitech - MouseMan+/FirstMouse+ (PS/2)", "ps/2", "MouseManPlusPS/2", "psaux", FALSE },
+ { "logimmusb", "Logitech - MouseMan Wheel (USB)", "ps/2", "IMPS/2", "input/mice", FALSE },
+ { "logimmusboptical", "Logitech - Cordless Optical Mouse (USB)", "ps/2", "IMPS/2", "input/mice", FALSE },
+ { "microsoft", "Microsoft - Compatible Mouse (serial)", "Microsoft", "Microsoft", "ttyS", TRUE },
+ { "msnew", "Microsoft - Rev 2.1A or higher (serial)", "pnp", "Auto", "ttyS", TRUE },
+ { "msintelli", "Microsoft - IntelliMouse (serial)", "ms3", "IntelliMouse", "ttyS", FALSE },
+ { "msintellips/2", "Microsoft - IntelliMouse (PS/2)", "imps2", "IMPS/2", "psaux", FALSE },
+ { "msintelliusb", "Microsoft - IntelliMouse (USB)", "ps/2", "IMPS/2", "input/mice", FALSE },
+ { "msintelliusboptical","Microsoft - IntelliMouse Optical (USB)", "ps/2", "IMPS/2", "input/mice", FALSE },
+ { "msbm", "Microsoft - Bus Mouse", "Busmouse", "BusMouse", "inportbm", TRUE },
+ { "mousesystems", "Mouse Systems - Mouse (serial)", "MouseSystems", "MouseSystems", "ttyS", TRUE },
+ { "mmseries", "MM - Series (serial)", "MMSeries", "MMSeries", "ttyS", TRUE },
+ { "mmhittab", "MM - HitTablet (serial)", "MMHitTab", "MMHittab", "ttyS", TRUE },
+ { "sun", "Sun - Mouse", "sun", "sun", "sunmouse", FALSE },
+ { NULL, NULL, NULL, NULL, NULL, FALSE },
+};
+
+
+
+/*
+ * This table maps between the mouse protocol name used for gpm and
+ * for the X server "protocol" mouse option.
+ */
+
+typedef struct {
+ char *gpmproto;
+ char *Xproto;
+} ProtocolEntry;
+
+static const ProtocolEntry __protocols[] = {
+ /* gpm protocol X protocol */
+ { "ms3", "IntelliMouse" },
+ { "Busmouse", "BusMouse" },
+ { "Microsoft", "Microsoft" },
+ { "imps2", "IMPS/2" },
+ { "netmouse", "NetMousePS/2" },
+ { "Logitech", "Logitech" },
+ { "logim", "MouseMan" },
+ { "MouseMan", "MouseMan" },
+ { "ps/2", "PS/2" },
+ { "pnp", "Auto" },
+ { "MouseSystems", "MouseSystems" },
+ { "MMSeries", "MMSeries" },
+ { "MMHitTab", "MMHittab" },
+ { "sun", "sun" },
+ { NULL, NULL },
+};
+
+
+/*
+ * gpm_proto_to_X_proto() - map from gpm mouse protocol to X mouse
+ * protocol
+ */
+
+static char* gpm_proto_to_X_proto(const char *gpm)
+{
+ int i;
+
+ for (i = 0; __protocols[i].gpmproto; i++) {
+ if (strcmp(gpm, __protocols[i].gpmproto) == 0) {
+ return __protocols[i].Xproto;
+ }
+ }
+ return NULL;
+
+} /* gpm_proto_to_X_proto() */
+
+
+
+/*
+ * find_mouse_entry() - scan the __mice[] table for the entry that
+ * corresponds to the specified value; return a pointer to the
+ * matching entry in the table, if any.
+ */
+
+static const MouseEntry *find_mouse_entry(char *value)
+{
+ int i;
+
+ if (!value) return NULL;
+
+ for (i = 0; __mice[i].name; i++) {
+ if (strcmp(value, __mice[i].shortname) == 0) {
+ return &__mice[i];
+ }
+ }
+ return NULL;
+
+} /* find_mouse_entry() */
+
+
+
+/*
+ * find_closest_mouse_entry() - scan the __mice[] table for the entry that
+ * matches all of the specified values; any of the values can be NULL,
+ * in which case we do not use them as part of the comparison. Note
+ * that device is compared case sensitive, proto is compared case
+ * insensitive, and emulate3 is just a boolean.
+ */
+
+static const MouseEntry *find_closest_mouse_entry(const char *device,
+ const char *proto,
+ const char *emulate3_str)
+{
+ int i;
+ int emulate3 = FALSE;
+
+ /*
+ * translate the emulate3 string into a boolean we can use below
+ * for comparison
+ */
+
+ if ((emulate3_str) &&
+ ((strcasecmp(emulate3_str, "yes") == 0) ||
+ (strcasecmp(emulate3_str, "true") == 0) ||
+ (strcasecmp(emulate3_str, "1") == 0))) {
+ emulate3 = TRUE;
+ }
+
+ /*
+ * skip the "/dev/" part of the device filename
+ */
+
+ if (device && (strncmp(device, "/dev/", 5) == 0)) {
+ device += 5; /* strlen("/dev/") */
+ }
+
+ for (i = 0; __mice[i].name; i++) {
+ if ((device) && (strcmp(device, __mice[i].device) != 0)) continue;
+ if ((proto) && (strcasecmp(proto, __mice[i].Xproto)) != 0) continue;
+ if ((emulate3_str) && (emulate3 != __mice[i].emulate3)) continue;
+ return &__mice[i];
+ }
+
+ return NULL;
+
+} /* find_closest_mouse_entry() */
+
+
+
+/*
+ * find_config_entry() - scan the specified filename for the specified
+ * keyword; return the value that the keyword is assigned to, or NULL
+ * if any error occurs.
+ */
+
+static char *find_config_entry(const char *filename, const char *keyword)
+{
+ int fd = -1;
+ char *data = NULL;
+ char *value = NULL;
+ char *buf = NULL;
+ char *tmp, *start, *c, *end;
+ struct stat stat_buf;
+ size_t len;
+
+ if ((fd = open(filename, O_RDONLY)) == -1) goto done;
+
+ if (fstat(fd, &stat_buf) == -1) goto done;
+
+ if ((data = mmap(0, stat_buf.st_size, PROT_READ, MAP_SHARED,
+ fd, 0)) == (void *) -1) goto done;
+
+ /*
+ * create a sysmem copy of the buffer, so that we can explicitly
+ * NULL terminate it
+ */
+
+ buf = malloc(stat_buf.st_size + 1);
+
+ if (!buf) goto done;
+
+ memcpy(buf, data, stat_buf.st_size);
+ buf[stat_buf.st_size] = '\0';
+
+ /* search for the keyword */
+
+ start = buf;
+
+ while (TRUE) {
+ tmp = strstr(start, keyword);
+ if (!tmp) goto done;
+
+ /*
+ * make sure this line is not commented out: search back from
+ * tmp: if we hit a "#" before a newline, then this line is
+ * commented out and we should search again
+ */
+
+ c = tmp;
+ while ((c >= start) && (*c != '\n') && (*c != '#')) c--;
+
+ if (*c == '#') {
+ /* keyword was commented out... search again */
+ start = tmp+1;
+ } else {
+ /* keyword is not commented out */
+ break;
+ }
+ }
+
+ start = tmp + strlen(keyword);
+ end = strchr(start, '\n');
+ if (!end) goto done;
+
+ /* there must be something between the start and the end */
+
+ if (start == end) goto done;
+
+ /* take what is between as the value */
+
+ len = end - start;
+ value = xconfigAlloc(len + 1);
+ strncpy(value, start, len);
+ value[len] = '\0';
+
+ /* if the first and last characters are quotation marks, remove them */
+
+ if ((value[0] == '\"') && (value[len-1] == '\"')) {
+ tmp = xconfigAlloc(len - 1);
+ strncpy(tmp, value + 1, len - 2);
+ tmp[len-2] = '\0';
+ free(value);
+ value = tmp;
+ }
+
+ done:
+
+ if (buf) free(buf);
+ if (data) munmap(data, stat_buf.st_size);
+ if (fd != -1) close(fd);
+
+ return value;
+
+} /* find_config_entry() */
+
+
+
+/*
+ * xconfigGeneratePrintPossibleMice() - print the mouse table to stdout
+ */
+
+void xconfigGeneratePrintPossibleMice(void)
+{
+ int i;
+
+ printf("%-25s%-35s\n\n", "Short Name", "Name");
+
+ for (i = 0; __mice[i].name; i++) {
+ printf("%-25s%-35s\n", __mice[i].shortname, __mice[i].name);
+ }
+
+ printf("\n");
+
+} /* xconfigGeneratePrintPossibleMice() */
+
+
+
+/*
+ * xconfigAddMouse() - determine the mouse type, and then add an
+ * XConfigInputRec with the appropriate options.
+ *
+ * - if the user specified on the commandline, use that
+ *
+ * - if /etc/sysconfig/mouse exists and contains valid data, use
+ * that
+ *
+ * - if /etc/conf.d/gpm exists and contains valid data, use that
+ *
+ * - infer the settings from the commandline options gpm is using XXX?
+ *
+ * - default to "auto" on /dev/mouse
+ */
+
+int xconfigAddMouse(GenerateOptions *gop, XConfigPtr config)
+{
+ const MouseEntry *entry = NULL;
+ XConfigInputPtr input;
+ XConfigOptionPtr opt = NULL;
+ char *device_path, *comment = "default";
+
+ /* if the user specified on the commandline, use that */
+
+ if (gop->mouse) {
+ entry = find_mouse_entry(gop->mouse);
+ if (entry) {
+ comment = "commandline input";
+ } else {
+ xconfigErrorMsg(WarnMsg, "Unable to find mouse \"%s\".",
+ gop->mouse);
+ }
+ }
+
+ /*
+ * if /etc/sysconfig/mouse exists, and contains valid data, use
+ * that
+ */
+
+ if (!entry) {
+ char *protocol, *device, *emulate3;
+
+ device = find_config_entry("/etc/sysconfig/mouse", "DEVICE=");
+ protocol = find_config_entry("/etc/sysconfig/mouse", "XMOUSETYPE=");
+ emulate3 = find_config_entry("/etc/sysconfig/mouse", "XEMU3=");
+
+ if (device || protocol || emulate3) {
+ entry = find_closest_mouse_entry(device, protocol, emulate3);
+ if (entry) {
+ comment = "data in \"/etc/sysconfig/mouse\"";
+ }
+ }
+ }
+
+ /* if /etc/conf.d/gpm exists and contains valid data, use that */
+
+ if (!entry) {
+ char *protocol, *device;
+
+ protocol = find_config_entry("/etc/conf.d/gpm", "MOUSE=");
+ device = find_config_entry("/etc/conf.d/gpm", "MOUSEDEV=");
+
+ if (protocol && device) {
+ MouseEntry *e = xconfigAlloc(sizeof(MouseEntry));
+ e->shortname = "custom";
+ e->name = "inferred from /etc/conf.d/gpm";
+ e->gpmproto = protocol;
+ e->Xproto = gpm_proto_to_X_proto(protocol);
+ e->device = device + strlen("/dev/");
+ e->emulate3 = FALSE; // XXX?
+ entry = e;
+ comment = "data in \"/etc/conf.d/gpm\"";
+ }
+ }
+
+ /*
+ * XXX we could try to infer the settings from the commandline
+ * options gpm is using
+ */
+
+ if (!entry) {
+ /* XXX implement me */
+ }
+
+ /* at this point, we must have a mouse entry */
+
+ if (!entry) {
+ MouseEntry *e = xconfigAlloc(sizeof(MouseEntry));
+ e->Xproto = "auto";
+
+#if defined(NV_BSD)
+ e->device = "sysmouse";
+#else
+ if (access("/dev/psaux", F_OK) == 0) {
+ e->device = "psaux";
+ } else if (access("/dev/input/mice", F_OK) == 0) {
+ e->device = "input/mice";
+ } else {
+ e->device = "mouse";
+ }
+#endif
+ e->emulate3 = FALSE;
+ entry = e;
+ }
+
+ /* add a new mouse input section */
+
+ input = xconfigAlloc(sizeof(XConfigInputRec));
+
+ input->comment = xconfigStrcat(" # generated from ",
+ comment, "\n", NULL);
+ input->identifier = xconfigStrdup("Mouse0");
+ input->driver = xconfigStrdup("mouse");
+
+ device_path = xconfigStrcat("/dev/", entry->device, NULL);
+
+ opt = xconfigAddNewOption(opt, xconfigStrdup("Protocol"),
+ xconfigStrdup(entry->Xproto));
+ opt = xconfigAddNewOption(opt, xconfigStrdup("Device"), device_path);
+ opt = xconfigAddNewOption(opt, xconfigStrdup("Emulate3Buttons"),
+ entry->emulate3 ?
+ xconfigStrdup("yes") : xconfigStrdup("no"));
+
+ /*
+ * This will make wheel mice work, and non-wheel mice should
+ * ignore ZAxisMapping
+ */
+
+ opt = xconfigAddNewOption(opt, xconfigStrdup("ZAxisMapping"),
+ xconfigStrdup("4 5"));
+
+ input->options = opt;
+
+ input->next = config->inputs;
+ config->inputs = input;
+
+ return TRUE;
+
+} /* xconfigAddMouse() */
+
+
+
+
+
+/*********************************************************************/
+
+/*
+ * keyboard detection
+ */
+
+typedef struct {
+ char *keytable;
+ char *name;
+ char *layout; /* XkbLayout */
+ char *model; /* XkbModel */
+ char *variant; /* XkbVariant */
+ char *options; /* XkbOptions */
+} KeyboardEntry;
+
+
+/*
+ * This table is based on data contained in
+ * /usr/lib/python2.2/site-packages/rhpl/keyboard_models.py on Red Hat
+ * Fedora core 1. That file contains the following copyright:
+ *
+ *
+ * keyboard_models.py - keyboard model list
+ *
+ * Brent Fox <bfox@redhat.com>
+ * Mike Fulbright <msf@redhat.com>
+ * Jeremy Katz <katzj@redhat.com>
+ *
+ * Copyright 2002 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+static const KeyboardEntry __keyboards[] = {
+
+ /* keytable name layout model variant options */
+
+ { "be-latin1", "Belgian (be-latin1)", "be", "pc105", NULL, NULL },
+ { "bg", "Bulgarian", "bg,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "br-abnt2", "Brazilian (ABNT2)", "br", "abnt2", NULL, NULL },
+ { "cf", "French Canadian", "ca_enhanced", "pc105", NULL, NULL },
+ { "croat", "Croatian", "hr", "pc105", NULL, NULL },
+ { "cz-us-qwertz", "Czechoslovakian (qwertz)", "cz,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "cz-lat2", "Czechoslovakian", "cz_qwerty", "pc105", NULL, NULL },
+ { "de", "German", "de", "pc105", NULL, NULL },
+ { "de-latin1", "German (latin1)", "de", "pc105", NULL, NULL },
+ { "de-latin1-nodeadkeys", "German (latin1 w/ no deadkeys)", "de", "pc105", "nodeadkeys", NULL },
+ { "dvorak", "Dvorak", "dvorak", "pc105", NULL, NULL },
+ { "dk", "Danish", "dk", "pc105", NULL, NULL },
+ { "dk-latin1", "Danish (latin1)", "dk", "pc105", NULL, NULL },
+ { "es", "Spanish", "es", "pc105", NULL, NULL },
+ { "et", "Estonian", "ee", "pc105", NULL, NULL },
+ { "fi", "Finnish", "fi", "pc105", NULL, NULL },
+ { "fi-latin1", "Finnish (latin1)", "fi", "pc105", NULL, NULL },
+ { "fr", "French", "fr", "pc105", NULL, NULL },
+ { "fr-latin0", "French (latin0)", "fr", "pc105", NULL, NULL },
+ { "fr-latin1", "French (latin1)", "fr", "pc105", NULL, NULL },
+ { "fr-pc", "French (pc)", "fr", "pc105", NULL, NULL },
+ { "fr_CH", "Swiss French", "fr_CH", "pc105", NULL, NULL },
+ { "fr_CH-latin1", "Swiss French (latin1)", "fr_CH", "pc105", NULL, NULL },
+ { "gr", "Greek", "us,el", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "hu", "Hungarian", "hu", "pc105", NULL, NULL },
+ { "hu101", "Hungarian (101 key)", "hu", "pc105", NULL, NULL },
+ { "is-latin1", "Icelandic", "is", "pc105", NULL, NULL },
+ { "it", "Italian", "it", "pc105", NULL, NULL },
+ { "it-ibm", "Italian (IBM)", "it", "pc105", NULL, NULL },
+ { "it2", "Italian (it2)", "it", "pc105", NULL, NULL },
+ { "jp106", "Japanese", "jp", "jp106", NULL, NULL },
+ { "la-latin1", "Latin American", "la", "pc105", NULL, NULL },
+ { "mk-utf", "Macedonian", "mk,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "no", "Norwegian", "no", "pc105", NULL, NULL },
+ { "pl", "Polish", "pl", "pc105", NULL, NULL },
+ { "pt-latin1", "Portuguese", "pt", "pc105", NULL, NULL },
+ { "ro_win", "Romanian", "ro", "pc105", NULL, NULL },
+ { "ru", "Russian", "ru,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "ru-cp1251", "Russian (cp1251)", "ru,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "ru-ms", "Russian (Microsoft)", "ru,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "ru1", "Russian (ru1)", "ru,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "ru2", "Russian (ru2)", "ru,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "ru_win", "Russian (win)", "ru,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "speakup", "Speakup", "us", "pc105", NULL, NULL },
+ { "speakup-lt", "Speakup (laptop)", "us", "pc105", NULL, NULL },
+ { "sv-latin1", "Swedish", "se", "pc105", NULL, NULL },
+ { "sg", "Swiss German", "de_CH", "pc105", NULL, NULL },
+ { "sg-latin1", "Swiss German (latin1)", "de_CH", "pc105", NULL, NULL },
+ { "sk-qwerty", "Slovakian", "sk_qwerty", "pc105", NULL, NULL },
+ { "slovene", "Slovenian", "si", "pc105", NULL, NULL },
+ { "trq", "Turkish", "tr", "pc105", NULL, NULL },
+ { "uk", "United Kingdom", "gb", "pc105", NULL, NULL },
+ { "ua", "Ukrainian", "ua,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "us-acentos", "U.S. International", "us_intl", "pc105", NULL, NULL },
+ { "us", "U.S. English", "us", "pc105", NULL, NULL },
+ { NULL, NULL, NULL, NULL, NULL, NULL },
+};
+
+
+
+/*
+ * find_keyboard_entry() - scan the __keyboards[] table for the entry that
+ * corresponds to the specified value; return a pointer to the
+ * matching entry in the table, if any.
+ */
+
+static const KeyboardEntry *find_keyboard_entry(char *value)
+{
+ int i;
+
+ if (!value) return NULL;
+
+ for (i = 0; __keyboards[i].name; i++) {
+ if (strcmp(value, __keyboards[i].keytable) == 0) {
+ return &__keyboards[i];
+ }
+ }
+ return NULL;
+
+} /* find_keyboard_entry() */
+
+
+
+/*
+ * xconfigGeneratePrintPossibleKeyboards() - print the keyboard table
+ */
+
+void xconfigGeneratePrintPossibleKeyboards(void)
+{
+ int i;
+
+ printf("%-25s%-35s\n\n", "Short Name", "Name");
+
+ for (i = 0; __keyboards[i].name; i++) {
+ printf("%-25s%-35s\n", __keyboards[i].keytable, __keyboards[i].name);
+ }
+
+ printf("\n");
+
+} /* xconfigGeneratePrintPossibleKeyboards() */
+
+
+
+/*
+ * xconfigAddKeyboard() - determine the keyboard type, and then add an
+ * XConfigInputRec with the appropriate options.
+ *
+ * How to detect the keyboard:
+ *
+ * - if the user specified on the command line, use that
+ *
+ * - if /etc/sysconfig/keyboard exists, and contains a valid
+ * KEYTABLE entry, use that
+ */
+
+int xconfigAddKeyboard(GenerateOptions *gop, XConfigPtr config)
+{
+ char *value, *comment = "default";
+ const KeyboardEntry *entry = NULL;
+
+ XConfigInputPtr input;
+ XConfigOptionPtr opt = NULL;
+
+ /*
+ * if the user specified on the command line, use that
+ */
+
+ if (gop->keyboard) {
+ entry = find_keyboard_entry(gop->keyboard);
+ if (entry) {
+ comment = "commandline input";
+ } else {
+ xconfigErrorMsg(WarnMsg, "Unable to find keyboard \"%s\".",
+ gop->keyboard);
+ }
+ }
+
+ /*
+ * if /etc/sysconfig/keyboard exists, and contains a valid
+ * KEYTABLE entry, use that
+ */
+
+ if (!entry) {
+ value = find_config_entry("/etc/sysconfig/keyboard", "KEYTABLE=");
+ entry = find_keyboard_entry(value);
+ if (value) {
+ free(value);
+ }
+ if (entry) {
+ comment = "data in \"/etc/sysconfig/keyboard\"";
+ }
+ }
+
+ /* add a new keyboard input section */
+
+ input = xconfigAlloc(sizeof(XConfigInputRec));
+
+ input->comment = xconfigStrcat(" # generated from ",
+ comment, "\n", NULL);
+ input->identifier = xconfigStrdup("Keyboard0");
+
+ /*
+ * determine which keyboard driver should be used (either "kbd" or
+ * "keyboard"); if the user specified a keyboard driver use that;
+ * if 'ROOT/lib/modules/input/kbd_drv.(o|so)' exists, use "kbd";
+ * otherwise, use "keyboard".
+ * On Solaris, use the default "keyboard"
+ */
+
+ if (gop->keyboard_driver) {
+ input->driver = gop->keyboard_driver;
+ } else {
+#if defined(NV_SUNOS) || defined(NV_BSD)
+ input->driver = xconfigStrdup("keyboard");
+#else
+ if (gop->xserver == X_IS_XORG) {
+ input->driver = xconfigStrdup("kbd");
+ } else {
+ input->driver = xconfigStrdup("keyboard");
+ }
+#endif
+ }
+
+ /*
+ * set additional keyboard options, based on the Keyboard table
+ * entry we found above
+ */
+
+ if (entry && entry->layout)
+ opt = xconfigAddNewOption(opt,
+ xconfigStrdup("XkbLayout"),
+ xconfigStrdup(entry->layout));
+ if (entry && entry->model)
+ opt = xconfigAddNewOption(opt,
+ xconfigStrdup("XkbModel"),
+ xconfigStrdup(entry->model));
+ if (entry && entry->variant)
+ opt = xconfigAddNewOption(opt,
+ xconfigStrdup("XkbVariant"),
+ xconfigStrdup(entry->variant));
+ if (entry && entry->options)
+ opt = xconfigAddNewOption(opt,
+ xconfigStrdup("XkbOptions"),
+ xconfigStrdup(entry->options));
+
+ input->options = opt;
+
+ input->next = config->inputs;
+ config->inputs = input;
+
+ return TRUE;
+
+} /* xconfigAddKeyboard() */
diff --git a/src/XF86Config-parser/Input.c b/src/XF86Config-parser/Input.c
new file mode 100644
index 0000000..1665600
--- /dev/null
+++ b/src/XF86Config-parser/Input.c
@@ -0,0 +1,424 @@
+/*
+ *
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static
+XConfigSymTabRec InputTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {IDENTIFIER, "identifier"},
+ {OPTION, "option"},
+ {DRIVER, "driver"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeInputList
+
+XConfigInputPtr
+xconfigParseInputSection (void)
+{
+ int has_ident = FALSE;
+ int token;
+ PARSE_PROLOGUE (XConfigInputPtr, XConfigInputRec)
+
+ while ((token = xconfigGetToken (InputTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Identifier");
+ if (has_ident == TRUE)
+ Error (MULTIPLE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ has_ident = TRUE;
+ break;
+ case DRIVER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Driver");
+ ptr->driver = val.str;
+ break;
+ case OPTION:
+ ptr->options = xconfigParseOption(ptr->options);
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ if (!has_ident)
+ Error (NO_IDENT_MSG, NULL);
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+void
+xconfigPrintInputSection (FILE * cf, XConfigInputPtr ptr)
+{
+ while (ptr)
+ {
+ fprintf (cf, "Section \"InputDevice\"\n");
+ if (ptr->comment)
+ fprintf (cf, "%s", ptr->comment);
+ if (ptr->identifier)
+ fprintf (cf, " Identifier \"%s\"\n", ptr->identifier);
+ if (ptr->driver)
+ fprintf (cf, " Driver \"%s\"\n", ptr->driver);
+ xconfigPrintOptionList(cf, ptr->options, 1);
+ fprintf (cf, "EndSection\n\n");
+ ptr = ptr->next;
+ }
+}
+
+void
+xconfigFreeInputList (XConfigInputPtr ptr)
+{
+ XConfigInputPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->identifier);
+ TEST_FREE (ptr->driver);
+ TEST_FREE (ptr->comment);
+ xconfigOptionListFree (ptr->options);
+
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+int
+xconfigValidateInput (XConfigPtr p)
+{
+ XConfigInputPtr input = p->inputs;
+
+#if 0 /* Enable this later */
+ if (!input) {
+ xconfigErrorMsg(ValidationErrorMsg, "At least one InputDevice section "
+ "is required.");
+ return (FALSE);
+ }
+#endif
+
+ while (input) {
+ if (!input->driver) {
+ xconfigErrorMsg(ValidationErrorMsg, UNDEFINED_INPUTDRIVER_MSG,
+ input->identifier);
+ return (FALSE);
+ }
+ input = input->next;
+ }
+ return (TRUE);
+}
+
+XConfigInputPtr
+xconfigFindInput (const char *ident, XConfigInputPtr p)
+{
+ while (p)
+ {
+ if (xconfigNameCompare (ident, p->identifier) == 0)
+ return (p);
+
+ p = p->next;
+ }
+ return (NULL);
+}
+
+XConfigInputPtr
+xconfigFindInputByDriver (const char *driver, XConfigInputPtr p)
+{
+ while (p)
+ {
+ if (xconfigNameCompare (driver, p->driver) == 0)
+ return (p);
+
+ p = p->next;
+ }
+ return (NULL);
+}
+
+
+
+static int getCoreInputDevice(GenerateOptions *gop,
+ XConfigPtr config,
+ XConfigLayoutPtr layout,
+ const int mouse,
+ const char *coreKeyword,
+ const char *implicitDriverName,
+ const char *defaultDriver0,
+ const char *defaultDriver1,
+ const char *foundMsg0,
+ const char *foundMsg1)
+{
+ XConfigInputPtr input, core = NULL;
+ XConfigInputrefPtr inputRef;
+ int found, firstTry;
+ const char *found_msg = NULL;
+
+ /*
+ * First check if the core input device has been specified in the
+ * active ServerLayout. If more than one is specified, remove the
+ * core attribute from the later ones.
+ */
+
+ for (inputRef = layout->inputs; inputRef; inputRef = inputRef->next) {
+ XConfigOptionPtr opt1 = NULL, opt2 = NULL;
+
+ input = inputRef->input;
+
+ opt1 = xconfigFindOption(input->options, coreKeyword);
+ opt2 = xconfigFindOption(inputRef->options, coreKeyword);
+
+ if (opt1 || opt2) {
+ if (!core) {
+ core = input;
+ } else {
+ if (opt1) input->options =
+ xconfigRemoveOption(input->options, opt1);
+ if (opt2) inputRef->options =
+ xconfigRemoveOption(inputRef->options, opt2);
+ xconfigErrorMsg(WarnMsg, "Duplicate %s devices; removing %s "
+ "attribute from \"%s\"\n",
+ coreKeyword, coreKeyword, input->identifier);
+ }
+ }
+ }
+
+ /*
+ * XXX XFree86 allows the commandline to override the core input
+ * devices; let's not bother with that, here.
+ */
+
+ /*
+ * if we didn't find a core input device above in the
+ * serverLayout, scan through the config's entire input list and
+ * pick the first one with the coreKeyword.
+ */
+
+ if (!core) {
+ for (input = config->inputs; input; input = input->next) {
+ if (xconfigFindOption(input->options, coreKeyword)) {
+ core = input;
+ found_msg = foundMsg0;
+ break;
+ }
+ }
+ }
+
+ /*
+ * if we didn't find a core input device above, then select the
+ * first input with the correct driver
+ */
+
+ firstTry = TRUE;
+
+ tryAgain:
+
+ if (!core) {
+ input = xconfigFindInput(implicitDriverName, config->inputs);
+ if (!input && defaultDriver0) {
+ input = xconfigFindInputByDriver(defaultDriver0, config->inputs);
+ }
+ if (!input && defaultDriver1) {
+ input = xconfigFindInputByDriver(defaultDriver1, config->inputs);
+ }
+ if (input) {
+ core = input;
+ found_msg = foundMsg1;
+ }
+ }
+
+ /*
+ * if we didn't find a core input device above, then that means we
+ * don't have any input devices of this type; try to add a new
+ * input device of this type, and then try again to find a core
+ * input device
+ */
+
+ if (!core && firstTry) {
+ firstTry = FALSE;
+
+ xconfigErrorMsg(WarnMsg, "Unable to find %s in X configuration; "
+ "attempting to add new %s section.",
+ coreKeyword, coreKeyword);
+
+ if (mouse) {
+ xconfigAddMouse(gop, config);
+ } else {
+ xconfigAddKeyboard(gop, config);
+ }
+ goto tryAgain;
+ }
+
+ /*
+ * if we *still* can't find a core input device, print a warning
+ * message and give up; hopefully the X server's builtin config
+ * will do.
+ */
+
+ if (!core) {
+ xconfigErrorMsg(WarnMsg, "Unable to determine %s; will rely on X "
+ "server's built-in default configuration.",
+ coreKeyword);
+
+ /* don't return FALSE here -- we don't want nvidia-xconfig to fail */
+
+ return TRUE;
+ }
+
+
+ /*
+ * make sure the core input device is in the layout's input list
+ */
+
+ found = FALSE;
+ for (inputRef = layout->inputs; inputRef; inputRef = inputRef->next) {
+ if (inputRef->input == core) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found) {
+ inputRef = calloc(1, sizeof(XConfigInputrefRec));
+ inputRef->input = core;
+ inputRef->input_name = strdup(core->identifier);
+ inputRef->next = layout->inputs;
+ layout->inputs = inputRef;
+ }
+
+ /*
+ * make sure the core input device has the core keyword set
+ */
+
+ for (inputRef = layout->inputs; inputRef; inputRef = inputRef->next) {
+ if (inputRef->input == core) {
+ XConfigOptionPtr opt1 = NULL, opt2 = NULL;
+
+ opt1 = xconfigFindOption(inputRef->input->options, coreKeyword);
+ opt2 = xconfigFindOption(inputRef->options, coreKeyword);
+
+ if (!opt1 && !opt2) {
+ inputRef->options = xconfigAddNewOption(inputRef->options,
+ strdup(coreKeyword),
+ NULL);
+ }
+ break;
+ }
+ }
+
+ if (found_msg) {
+ xconfigErrorMsg(WarnMsg, "The %s device was not specified explicitly "
+ "in the layout; using the %s.\n", coreKeyword, found_msg);
+ }
+
+ return TRUE;
+}
+
+
+
+/*
+ * xconfigCheckCoreInputDevices() - check that the specified layout has a
+ * corePointer and coreKeyboard. If it does not have them, they will
+ * be added from the current list of input devices.
+ */
+
+int xconfigCheckCoreInputDevices(GenerateOptions *gop,
+ XConfigPtr config,
+ XConfigLayoutPtr layout)
+{
+ int ret;
+
+ ret = getCoreInputDevice(gop,
+ config,
+ layout,
+ TRUE,
+ "CorePointer",
+ CONF_IMPLICIT_POINTER,
+ "mouse", NULL,
+ "first CorePointer in the config input list",
+ "first mouse device");
+
+ if (!ret) return FALSE;
+
+ ret = getCoreInputDevice(gop,
+ config,
+ layout,
+ FALSE,
+ "CoreKeyboard",
+ CONF_IMPLICIT_KEYBOARD,
+ "keyboard", "kbd",
+ "first CoreKeyboard in the config input list",
+ "first keyboard device");
+ if (!ret) return FALSE;
+
+ return TRUE;
+}
diff --git a/src/XF86Config-parser/Keyboard.c b/src/XF86Config-parser/Keyboard.c
new file mode 100644
index 0000000..26bbb73
--- /dev/null
+++ b/src/XF86Config-parser/Keyboard.c
@@ -0,0 +1,304 @@
+/*
+ *
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+#include "ctype.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec KeyboardTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {KPROTOCOL, "protocol"},
+ {AUTOREPEAT, "autorepeat"},
+ {XLEDS, "xleds"},
+ {PANIX106, "panix106"},
+ {XKBKEYMAP, "xkbkeymap"},
+ {XKBCOMPAT, "xkbcompat"},
+ {XKBTYPES, "xkbtypes"},
+ {XKBKEYCODES, "xkbkeycodes"},
+ {XKBGEOMETRY, "xkbgeometry"},
+ {XKBSYMBOLS, "xkbsymbols"},
+ {XKBDISABLE, "xkbdisable"},
+ {XKBRULES, "xkbrules"},
+ {XKBMODEL, "xkbmodel"},
+ {XKBLAYOUT, "xkblayout"},
+ {XKBVARIANT, "xkbvariant"},
+ {XKBOPTIONS, "xkboptions"},
+ /* The next two have become ServerFlags options */
+ {VTINIT, "vtinit"},
+ {VTSYSREQ, "vtsysreq"},
+ /* Obsolete keywords */
+ {SERVERNUM, "servernumlock"},
+ {LEFTALT, "leftalt"},
+ {RIGHTALT, "rightalt"},
+ {RIGHTALT, "altgr"},
+ {SCROLLLOCK_TOK, "scrolllock"},
+ {RIGHTCTL, "rightctl"},
+ {-1, ""},
+};
+
+/* Obsolete */
+static XConfigSymTabRec KeyMapTab[] =
+{
+ {CONF_KM_META, "meta"},
+ {CONF_KM_COMPOSE, "compose"},
+ {CONF_KM_MODESHIFT, "modeshift"},
+ {CONF_KM_MODELOCK, "modelock"},
+ {CONF_KM_SCROLLLOCK, "scrolllock"},
+ {CONF_KM_CONTROL, "control"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeInputList
+
+XConfigInputPtr
+xconfigParseKeyboardSection (void)
+{
+ char *s, *s1, *s2;
+ int l;
+ int token, ntoken;
+ PARSE_PROLOGUE (XConfigInputPtr, XConfigInputRec)
+
+ while ((token = xconfigGetToken (KeyboardTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case KPROTOCOL:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Protocol");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("Protocol"),
+ val.str);
+ break;
+ case AUTOREPEAT:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (AUTOREPEAT_MSG, NULL);
+ s1 = xconfigULongToString(val.num);
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (AUTOREPEAT_MSG, NULL);
+ s2 = xconfigULongToString(val.num);
+ l = strlen(s1) + 1 + strlen(s2) + 1;
+ s = malloc(l);
+ sprintf(s, "%s %s", s1, s2);
+ free(s1);
+ free(s2);
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("AutoRepeat"), s);
+ break;
+ case XLEDS:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (XLEDS_MSG, NULL);
+ s = xconfigULongToString(val.num);
+ l = strlen(s) + 1;
+ while ((token = xconfigGetSubToken(&(ptr->comment))) == NUMBER)
+ {
+ s1 = xconfigULongToString(val.num);
+ l += (1 + strlen(s1));
+ s = realloc(s, l);
+ strcat(s, " ");
+ strcat(s, s1);
+ free(s1);
+ }
+ xconfigUnGetToken (token);
+ break;
+ case SERVERNUM:
+ xconfigErrorMsg(ParseWarningMsg, OBSOLETE_MSG,
+ xconfigTokenString());
+ break;
+ case LEFTALT:
+ case RIGHTALT:
+ case SCROLLLOCK_TOK:
+ case RIGHTCTL:
+ xconfigErrorMsg(ParseWarningMsg, OBSOLETE_MSG,
+ xconfigTokenString());
+ break;
+ ntoken = xconfigGetToken (KeyMapTab);
+ switch (ntoken)
+ {
+ case EOF_TOKEN:
+ xconfigErrorMsg(ParseErrorMsg, UNEXPECTED_EOF_MSG);
+ CLEANUP (ptr);
+ return (NULL);
+ break;
+
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ break;
+ case VTINIT:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "VTInit");
+ xconfigErrorMsg(ParseWarningMsg, MOVED_TO_FLAGS_MSG, "VTInit");
+ break;
+ case VTSYSREQ:
+ xconfigErrorMsg(ParseWarningMsg,
+ MOVED_TO_FLAGS_MSG, "VTSysReq");
+ break;
+ case XKBDISABLE:
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbDisable"),
+ NULL);
+ break;
+ case XKBKEYMAP:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBKeymap");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbKeymap"),
+ val.str);
+ break;
+ case XKBCOMPAT:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBCompat");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbCompat"),
+ val.str);
+ break;
+ case XKBTYPES:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBTypes");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbTypes"),
+ val.str);
+ break;
+ case XKBKEYCODES:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBKeycodes");
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbKeycodes"),
+ val.str);
+ break;
+ case XKBGEOMETRY:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBGeometry");
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbGeometry"),
+ val.str);
+ break;
+ case XKBSYMBOLS:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBSymbols");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbSymbols"),
+ val.str);
+ break;
+ case XKBRULES:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBRules");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbRules"),
+ val.str);
+ break;
+ case XKBMODEL:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBModel");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbModel"),
+ val.str);
+ break;
+ case XKBLAYOUT:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBLayout");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbLayout"),
+ val.str);
+ break;
+ case XKBVARIANT:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBVariant");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbVariant"),
+ val.str);
+ break;
+ case XKBOPTIONS:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBOptions");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbOptions"),
+ val.str);
+ break;
+ case PANIX106:
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("Panix106"),
+ NULL);
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ ptr->identifier = xconfigStrdup(CONF_IMPLICIT_KEYBOARD);
+ ptr->driver = xconfigStrdup("keyboard");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("CoreKeyboard"), NULL);
+
+ return ptr;
+}
+
diff --git a/src/XF86Config-parser/Layout.c b/src/XF86Config-parser/Layout.c
new file mode 100644
index 0000000..1e62d26
--- /dev/null
+++ b/src/XF86Config-parser/Layout.c
@@ -0,0 +1,607 @@
+/*
+ *
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+#include <string.h>
+
+extern LexRec val;
+
+static XConfigSymTabRec LayoutTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {SCREEN, "screen"},
+ {IDENTIFIER, "identifier"},
+ {INACTIVE, "inactive"},
+ {INPUTDEVICE, "inputdevice"},
+ {OPTION, "option"},
+ {-1, ""},
+};
+
+static XConfigSymTabRec AdjTab[] =
+{
+ {RIGHTOF, "rightof"},
+ {LEFTOF, "leftof"},
+ {ABOVE, "above"},
+ {BELOW, "below"},
+ {RELATIVE, "relative"},
+ {ABSOLUTE, "absolute"},
+ {-1, ""},
+};
+
+
+static int addImpliedLayout(XConfigPtr config, const char *screenName);
+
+
+#define CLEANUP xconfigFreeLayoutList
+
+XConfigLayoutPtr
+xconfigParseLayoutSection (void)
+{
+ int has_ident = FALSE;
+ int token;
+ PARSE_PROLOGUE (XConfigLayoutPtr, XConfigLayoutRec)
+
+ while ((token = xconfigGetToken (LayoutTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Identifier");
+ if (has_ident == TRUE)
+ Error (MULTIPLE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ has_ident = TRUE;
+ break;
+ case INACTIVE:
+ {
+ XConfigInactivePtr iptr;
+
+ iptr = calloc (1, sizeof (XConfigInactiveRec));
+ iptr->next = NULL;
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (INACTIVE_MSG, NULL);
+ iptr->device_name = val.str;
+ ptr->inactives = (XConfigInactivePtr)
+ xconfigAddListItem((GenericListPtr) ptr->inactives,
+ (GenericListPtr) iptr);
+ }
+ break;
+ case SCREEN:
+ {
+ XConfigAdjacencyPtr aptr;
+ int absKeyword = 0;
+
+ aptr = calloc (1, sizeof (XConfigAdjacencyRec));
+ aptr->next = NULL;
+ aptr->scrnum = -1;
+ aptr->where = CONF_ADJ_OBSOLETE;
+ aptr->x = 0;
+ aptr->y = 0;
+ aptr->refscreen = NULL;
+ if ((token = xconfigGetSubToken (&(ptr->comment))) == NUMBER)
+ aptr->scrnum = val.num;
+ else
+ xconfigUnGetToken (token);
+ token = xconfigGetSubToken(&(ptr->comment));
+ if (token != STRING)
+ Error (SCREEN_MSG, NULL);
+ aptr->screen_name = val.str;
+
+ token = xconfigGetSubTokenWithTab(&(ptr->comment), AdjTab);
+ switch (token)
+ {
+ case RIGHTOF:
+ aptr->where = CONF_ADJ_RIGHTOF;
+ break;
+ case LEFTOF:
+ aptr->where = CONF_ADJ_LEFTOF;
+ break;
+ case ABOVE:
+ aptr->where = CONF_ADJ_ABOVE;
+ break;
+ case BELOW:
+ aptr->where = CONF_ADJ_BELOW;
+ break;
+ case RELATIVE:
+ aptr->where = CONF_ADJ_RELATIVE;
+ break;
+ case ABSOLUTE:
+ aptr->where = CONF_ADJ_ABSOLUTE;
+ absKeyword = 1;
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ xconfigUnGetToken (token);
+ token = xconfigGetSubToken(&(ptr->comment));
+ if (token == STRING)
+ aptr->where = CONF_ADJ_OBSOLETE;
+ else
+ aptr->where = CONF_ADJ_ABSOLUTE;
+ }
+ switch (aptr->where)
+ {
+ case CONF_ADJ_ABSOLUTE:
+ if (absKeyword)
+ token = xconfigGetSubToken(&(ptr->comment));
+ if (token == NUMBER)
+ {
+ aptr->x = val.num;
+ token = xconfigGetSubToken(&(ptr->comment));
+ if (token != NUMBER)
+ Error(INVALID_SCR_MSG, NULL);
+ aptr->y = val.num;
+ } else {
+ if (absKeyword)
+ Error(INVALID_SCR_MSG, NULL);
+ else
+ xconfigUnGetToken (token);
+ }
+ break;
+ case CONF_ADJ_RIGHTOF:
+ case CONF_ADJ_LEFTOF:
+ case CONF_ADJ_ABOVE:
+ case CONF_ADJ_BELOW:
+ case CONF_ADJ_RELATIVE:
+ token = xconfigGetSubToken(&(ptr->comment));
+ if (token != STRING)
+ Error(INVALID_SCR_MSG, NULL);
+ aptr->refscreen = val.str;
+ if (aptr->where == CONF_ADJ_RELATIVE)
+ {
+ token = xconfigGetSubToken(&(ptr->comment));
+ if (token != NUMBER)
+ Error(INVALID_SCR_MSG, NULL);
+ aptr->x = val.num;
+ token = xconfigGetSubToken(&(ptr->comment));
+ if (token != NUMBER)
+ Error(INVALID_SCR_MSG, NULL);
+ aptr->y = val.num;
+ }
+ break;
+ case CONF_ADJ_OBSOLETE:
+ /* top */
+ aptr->top_name = val.str;
+
+ /* bottom */
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (SCREEN_MSG, NULL);
+ aptr->bottom_name = val.str;
+
+ /* left */
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (SCREEN_MSG, NULL);
+ aptr->left_name = val.str;
+
+ /* right */
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (SCREEN_MSG, NULL);
+ aptr->right_name = val.str;
+
+ }
+ ptr->adjacencies = (XConfigAdjacencyPtr)
+ xconfigAddListItem((GenericListPtr) ptr->adjacencies,
+ (GenericListPtr) aptr);
+ }
+ break;
+ case INPUTDEVICE:
+ {
+ XConfigInputrefPtr iptr;
+
+ iptr = calloc (1, sizeof (XConfigInputrefRec));
+ iptr->next = NULL;
+ iptr->options = NULL;
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (INPUTDEV_MSG, NULL);
+ iptr->input_name = val.str;
+ while ((token = xconfigGetSubToken (&(ptr->comment))) == STRING)
+ {
+ iptr->options =
+ xconfigAddNewOption (iptr->options, val.str, NULL);
+ }
+ xconfigUnGetToken (token);
+ ptr->inputs = (XConfigInputrefPtr)
+ xconfigAddListItem((GenericListPtr) ptr->inputs,
+ (GenericListPtr) iptr);
+ }
+ break;
+ case OPTION:
+ ptr->options = xconfigParseOption(ptr->options);
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ if (!has_ident)
+ Error (NO_IDENT_MSG, NULL);
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+void
+xconfigPrintLayoutSection (FILE * cf, XConfigLayoutPtr ptr)
+{
+ XConfigAdjacencyPtr aptr;
+ XConfigInactivePtr iptr;
+ XConfigInputrefPtr inptr;
+ XConfigOptionPtr optr;
+
+ while (ptr)
+ {
+ fprintf (cf, "Section \"ServerLayout\"\n");
+ if (ptr->comment)
+ fprintf (cf, "%s", ptr->comment);
+ if (ptr->identifier)
+ fprintf (cf, " Identifier \"%s\"\n", ptr->identifier);
+
+ for (aptr = ptr->adjacencies; aptr; aptr = aptr->next)
+ {
+ fprintf (cf, " Screen ");
+ if (aptr->scrnum >= 0)
+ fprintf (cf, "%2d", aptr->scrnum);
+ else
+ fprintf (cf, " ");
+ fprintf (cf, " \"%s\"", aptr->screen_name);
+ switch(aptr->where)
+ {
+ case CONF_ADJ_OBSOLETE:
+ fprintf (cf, " \"%s\"", aptr->top_name);
+ fprintf (cf, " \"%s\"", aptr->bottom_name);
+ fprintf (cf, " \"%s\"", aptr->right_name);
+ fprintf (cf, " \"%s\"\n", aptr->left_name);
+ break;
+ case CONF_ADJ_ABSOLUTE:
+ if (aptr->x != -1)
+ fprintf (cf, " %d %d\n", aptr->x, aptr->y);
+ else
+ fprintf (cf, "\n");
+ break;
+ case CONF_ADJ_RIGHTOF:
+ fprintf (cf, " RightOf \"%s\"\n", aptr->refscreen);
+ break;
+ case CONF_ADJ_LEFTOF:
+ fprintf (cf, " LeftOf \"%s\"\n", aptr->refscreen);
+ break;
+ case CONF_ADJ_ABOVE:
+ fprintf (cf, " Above \"%s\"\n", aptr->refscreen);
+ break;
+ case CONF_ADJ_BELOW:
+ fprintf (cf, " Below \"%s\"\n", aptr->refscreen);
+ break;
+ case CONF_ADJ_RELATIVE:
+ fprintf (cf, " Relative \"%s\" %d %d\n", aptr->refscreen,
+ aptr->x, aptr->y);
+ break;
+ }
+ }
+ for (iptr = ptr->inactives; iptr; iptr = iptr->next)
+ fprintf (cf, " Inactive \"%s\"\n", iptr->device_name);
+ for (inptr = ptr->inputs; inptr; inptr = inptr->next)
+ {
+ fprintf (cf, " InputDevice \"%s\"", inptr->input_name);
+ for (optr = inptr->options; optr; optr = optr->next)
+ {
+ fprintf(cf, " \"%s\"", optr->name);
+ }
+ fprintf(cf, "\n");
+ }
+ xconfigPrintOptionList(cf, ptr->options, 1);
+ fprintf (cf, "EndSection\n\n");
+ ptr = ptr->next;
+ }
+}
+
+void
+xconfigFreeLayoutList (XConfigLayoutPtr ptr)
+{
+ XConfigLayoutPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->identifier);
+ TEST_FREE (ptr->comment);
+ xconfigFreeAdjacencyList (ptr->adjacencies);
+ xconfigFreeInputrefList (ptr->inputs);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+void
+xconfigFreeAdjacencyList (XConfigAdjacencyPtr ptr)
+{
+ XConfigAdjacencyPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->screen_name);
+ TEST_FREE (ptr->top_name);
+ TEST_FREE (ptr->bottom_name);
+ TEST_FREE (ptr->left_name);
+ TEST_FREE (ptr->right_name);
+
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+
+}
+
+void
+xconfigFreeInputrefList (XConfigInputrefPtr ptr)
+{
+ XConfigInputrefPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->input_name);
+ xconfigOptionListFree (ptr->options);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+
+}
+
+#define CheckScreen(str, ptr)\
+if (str[0] != '\0') \
+{ \
+screen = xconfigFindScreen (str, p->conf_screen_lst); \
+if (!screen) \
+{ \
+ xconfigErrorMsg(ValidationErrorMsg, UNDEFINED_SCREEN_MSG, \
+ str, layout->identifier); \
+ return (FALSE); \
+} \
+else \
+ ptr = screen; \
+}
+
+int
+xconfigValidateLayout (XConfigPtr p)
+{
+ XConfigLayoutPtr layout = p->layouts;
+ XConfigAdjacencyPtr adj;
+ XConfigInactivePtr iptr;
+ XConfigInputrefPtr inputRef;
+ XConfigScreenPtr screen;
+ XConfigDevicePtr device;
+ XConfigInputPtr input;
+
+ /*
+ * if we do not have a layout, just return TRUE; we'll add a
+ * layout later during the Sanitize step
+ */
+
+ if (!layout) return TRUE;
+
+ while (layout)
+ {
+ adj = layout->adjacencies;
+ while (adj)
+ {
+ /* the first one can't be "" but all others can */
+ screen = xconfigFindScreen (adj->screen_name, p->screens);
+ if (!screen)
+ {
+ xconfigErrorMsg(ValidationErrorMsg, UNDEFINED_SCREEN_MSG,
+ adj->screen_name, layout->identifier);
+ return (FALSE);
+ }
+ else
+ adj->screen = screen;
+
+#if 0
+ CheckScreen (adj->top_name, adj->top);
+ CheckScreen (adj->bottom_name, adj->bottom);
+ CheckScreen (adj->left_name, adj->left);
+ CheckScreen (adj->right_name, adj->right);
+#endif
+
+ adj = adj->next;
+ }
+
+ /* I not believe the "inactives" list is used for anything */
+
+ iptr = layout->inactives;
+ while (iptr)
+ {
+ device = xconfigFindDevice (iptr->device_name,
+ p->devices);
+ if (!device)
+ {
+ xconfigErrorMsg(ValidationErrorMsg, UNDEFINED_DEVICE_MSG,
+ iptr->device_name, layout->identifier);
+ return (FALSE);
+ }
+ else
+ iptr->device = device;
+ iptr = iptr->next;
+ }
+
+ /*
+ * the layout->inputs list is also updated in
+ * getCoreInputDevice() when no core input device is found in
+ * the layout's input list
+ */
+
+ inputRef = layout->inputs;
+ while (inputRef)
+ {
+ input = xconfigFindInput (inputRef->input_name,
+ p->inputs);
+ if (!input)
+ {
+ xconfigErrorMsg(ValidationErrorMsg, UNDEFINED_INPUT_MSG,
+ inputRef->input_name, layout->identifier);
+ return (FALSE);
+ }
+ else {
+ inputRef->input = input;
+ }
+ inputRef = inputRef->next;
+ }
+ layout = layout->next;
+ }
+ return (TRUE);
+}
+
+int
+xconfigSanitizeLayout(XConfigPtr p,
+ const char *screenName,
+ GenerateOptions *gop)
+{
+ XConfigLayoutPtr layout = p->layouts;
+
+ /* add an implicit layout if none exist */
+
+ if (!p->layouts) {
+ if (!addImpliedLayout(p, screenName)) {
+ return FALSE;
+ }
+ }
+
+ /* check that input devices are assigned for each layout */
+
+ for (layout = p->layouts; layout; layout = layout->next) {
+ if (!xconfigCheckCoreInputDevices(gop, p, layout)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+XConfigLayoutPtr
+xconfigFindLayout (const char *name, XConfigLayoutPtr list)
+{
+ while (list)
+ {
+ if (xconfigNameCompare (list->identifier, name) == 0)
+ return (list);
+ list = list->next;
+ }
+ return (NULL);
+}
+
+
+static int addImpliedLayout(XConfigPtr config, const char *screenName)
+{
+ XConfigScreenPtr screen;
+ XConfigLayoutPtr layout;
+ XConfigAdjacencyPtr adj;
+
+ if (config->layouts) return TRUE;
+
+ /*
+ * which screen section is the active one?
+ *
+ * If there is a -screen option, use that one, otherwise use the first
+ * screen in the config's list.
+ */
+
+ if (screenName) {
+ screen = xconfigFindScreen(screenName, config->screens);
+ if (!screen) {
+ xconfigErrorMsg(ErrorMsg, "No Screen section called \"%s\"\n",
+ screenName);
+ return FALSE;
+ }
+ } else {
+ screen = config->screens;
+ }
+
+ xconfigErrorMsg(WarnMsg, "No Layout specified, constructing implicit "
+ "layout section using screen \"%s\".\n",
+ screen->identifier);
+
+ /* allocate the new layout section */
+
+ layout = calloc(1, sizeof(XConfigLayoutRec));
+
+ layout->identifier = xconfigStrdup("Default Layout");
+
+ adj = calloc(1, sizeof(XConfigAdjacencyRec));
+ adj->scrnum = -1;
+ adj->screen = screen;
+ adj->screen_name = xconfigStrdup(screen->identifier);
+
+ layout->adjacencies = adj;
+
+ config->layouts = layout;
+
+ /* validate the Layout here to setup all the pointers */
+
+ if (!xconfigValidateLayout(config)) return FALSE;
+
+ return TRUE;
+}
diff --git a/src/XF86Config-parser/Makefile b/src/XF86Config-parser/Makefile
new file mode 100644
index 0000000..ef973a6
--- /dev/null
+++ b/src/XF86Config-parser/Makefile
@@ -0,0 +1,62 @@
+SRC = \
+ DRI.c \
+ Device.c \
+ Files.c \
+ Flags.c \
+ Input.c \
+ Keyboard.c \
+ Layout.c \
+ Module.c \
+ Monitor.c \
+ Pointer.c \
+ Screen.c \
+ Vendor.c \
+ Video.c \
+ Read.c \
+ Scan.c \
+ Write.c \
+ Util.c \
+ Extensions.c \
+ Generate.c
+
+OBJS = $(SRC:%.c=%.o)
+DEPS = $(SRC:%.c=%.d)
+
+ifndef CC
+ CC = gcc
+endif
+
+CFLAGS = -Wall -g
+
+ifdef NV_CFLAGS
+ CFLAGS += $(NV_CFLAGS)
+endif
+
+ifndef RANLIB
+ RANLIB = ranlib
+endif
+
+LIB = libXF86Config-parser.a
+LIB_O = $(LIB:%.a=%.o)
+
+default all: $(LIB)
+
+.PHONY: clean clobber
+
+$(LIB): $(OBJS)
+ $(LD) -r -o $(LIB_O) $(OBJS)
+ $(AR) ruv $(LIB) $(LIB_O)
+ $(RANLIB) $(LIB)
+
+%.o: %.c
+ $(CC) -c $(CFLAGS) $< -o $@
+
+%.d: %.c
+ @set -e; $(CC) -MM $(CPPFLAGS) $< \
+ | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
+ [ -s $@ ] || rm -f $@
+
+clean clobber:
+ rm -rf *.o *~ *.d $(LIB) $(LIB_O)
+
+-include $(DEPS)
diff --git a/src/XF86Config-parser/Makefile.inc b/src/XF86Config-parser/Makefile.inc
new file mode 100644
index 0000000..d41889f
--- /dev/null
+++ b/src/XF86Config-parser/Makefile.inc
@@ -0,0 +1,58 @@
+#
+# nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+# and Linux systems.
+#
+# Copyright (C) 2004 NVIDIA Corporation.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of Version 2 of the GNU General Public
+# License as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
+# of the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the:
+#
+# Free Software Foundation, Inc.
+# 59 Temple Place - Suite 330
+# Boston, MA 02111-1307, USA
+#
+
+#
+# src files and headers
+#
+
+SRC += \
+ Device.c \
+ DRI.c \
+ Extensions.c \
+ Files.c \
+ Flags.c \
+ Generate.c \
+ Input.c \
+ Keyboard.c \
+ Layout.c \
+ Module.c \
+ Monitor.c \
+ Pointer.c \
+ Read.c \
+ Scan.c \
+ Screen.c \
+ Util.c \
+ Vendor.c \
+ Video.c \
+ Write.c
+
+EXTRA_DIST += \
+ Makefile.inc \
+ Configint.h \
+ configProcs.h \
+ Makefile \
+ xf86Parser.h \
+ xf86tokens.h
+
+dist_list::
+ @ echo $(SRC) $(EXTRA_DIST)
diff --git a/src/XF86Config-parser/Module.c b/src/XF86Config-parser/Module.c
new file mode 100644
index 0000000..0605367
--- /dev/null
+++ b/src/XF86Config-parser/Module.c
@@ -0,0 +1,282 @@
+/*
+ *
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec SubModuleTab[] =
+{
+ {ENDSUBSECTION, "endsubsection"},
+ {OPTION, "option"},
+ {-1, ""},
+};
+
+static XConfigSymTabRec ModuleTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {LOAD, "load"},
+ {LOAD_DRIVER, "loaddriver"},
+ {SUBSECTION, "subsection"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeModules
+
+XConfigLoadPtr
+xconfigParseModuleSubSection (XConfigLoadPtr head, char *name)
+{
+ int token;
+ PARSE_PROLOGUE (XConfigLoadPtr, XConfigLoadRec)
+
+ ptr->name = name;
+ ptr->type = XCONFIG_LOAD_MODULE;
+ ptr->opt = NULL;
+ ptr->next = NULL;
+
+ while ((token = xconfigGetToken (SubModuleTab)) != ENDSUBSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case OPTION:
+ ptr->opt = xconfigParseOption(ptr->opt);
+ break;
+ case EOF_TOKEN:
+ xconfigErrorMsg(ParseErrorMsg, UNEXPECTED_EOF_MSG);
+ free(ptr);
+ return NULL;
+ default:
+ xconfigErrorMsg(ParseErrorMsg, INVALID_KEYWORD_MSG,
+ xconfigTokenString());
+ free(ptr);
+ return NULL;
+ break;
+ }
+
+ }
+
+ return ((XConfigLoadPtr) xconfigAddListItem ((GenericListPtr) head,
+ (GenericListPtr) ptr));
+}
+
+XConfigModulePtr
+xconfigParseModuleSection (void)
+{
+ int token;
+ PARSE_PROLOGUE (XConfigModulePtr, XConfigModuleRec)
+
+ while ((token = xconfigGetToken (ModuleTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case LOAD:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Load");
+ ptr->loads =
+ xconfigAddNewLoadDirective (ptr->loads, val.str,
+ XCONFIG_LOAD_MODULE, NULL, TRUE);
+ break;
+ case LOAD_DRIVER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "LoadDriver");
+ ptr->loads =
+ xconfigAddNewLoadDirective (ptr->loads, val.str,
+ XCONFIG_LOAD_DRIVER, NULL, TRUE);
+ break;
+ case SUBSECTION:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "SubSection");
+ ptr->loads =
+ xconfigParseModuleSubSection (ptr->loads, val.str);
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+void
+xconfigPrintModuleSection (FILE * cf, XConfigModulePtr ptr)
+{
+ XConfigLoadPtr lptr;
+
+ if (ptr == NULL)
+ return;
+
+ if (ptr->comment)
+ fprintf(cf, "%s", ptr->comment);
+ for (lptr = ptr->loads; lptr; lptr = lptr->next)
+ {
+ switch (lptr->type)
+ {
+ case XCONFIG_LOAD_MODULE:
+ if( lptr->opt == NULL ) {
+ fprintf (cf, " Load \"%s\"", lptr->name);
+ if (lptr->comment)
+ fprintf(cf, "%s", lptr->comment);
+ else
+ fputc('\n', cf);
+ }
+ else
+ {
+ fprintf (cf, " SubSection \"%s\"\n", lptr->name);
+ if (lptr->comment)
+ fprintf(cf, "%s", lptr->comment);
+ xconfigPrintOptionList(cf, lptr->opt, 2);
+ fprintf (cf, " EndSubSection\n");
+ }
+ break;
+ case XCONFIG_LOAD_DRIVER:
+ fprintf (cf, " LoadDriver \"%s\"", lptr->name);
+ if (lptr->comment)
+ fprintf(cf, "%s", lptr->comment);
+ else
+ fputc('\n', cf);
+ break;
+#if 0
+ default:
+ fprintf (cf, "# Unknown type \"%s\"\n", lptr->name);
+ break;
+#endif
+ }
+ }
+}
+
+XConfigLoadPtr
+xconfigAddNewLoadDirective (XConfigLoadPtr head, char *name, int type,
+ XConfigOptionPtr opts, int do_token)
+{
+ XConfigLoadPtr new;
+ int token;
+
+ new = calloc (1, sizeof (XConfigLoadRec));
+ new->name = name;
+ new->type = type;
+ new->opt = opts;
+ new->next = NULL;
+
+ if (do_token) {
+ if ((token = xconfigGetToken(NULL)) == COMMENT)
+ new->comment = xconfigAddComment(new->comment, val.str);
+ else
+ xconfigUnGetToken(token);
+ }
+
+ return ((XConfigLoadPtr) xconfigAddListItem ((GenericListPtr) head,
+ (GenericListPtr) new));
+}
+
+XConfigLoadPtr
+xconfigRemoveLoadDirective(XConfigLoadPtr head, XConfigLoadPtr load)
+{
+ XConfigLoadPtr prev = NULL;
+ XConfigLoadPtr l = head;
+
+ while (l) {
+ if (l == load) {
+ if (prev) prev->next = load->next;
+ if (head == load) head = load->next;
+ TEST_FREE(load->name);
+ TEST_FREE(load->comment);
+ xconfigOptionListFree(load->opt);
+ free(load);
+ break;
+ }
+
+ prev = l;
+ l = l->next;
+ }
+
+ return head;
+}
+
+void
+xconfigFreeModules (XConfigModulePtr ptr)
+{
+ XConfigLoadPtr lptr;
+ XConfigLoadPtr prev;
+
+ if (ptr == NULL)
+ return;
+ lptr = ptr->loads;
+ while (lptr)
+ {
+ TEST_FREE (lptr->name);
+ TEST_FREE (lptr->comment);
+ prev = lptr;
+ lptr = lptr->next;
+ free (prev);
+ }
+ TEST_FREE (ptr->comment);
+ free (ptr);
+}
diff --git a/src/XF86Config-parser/Monitor.c b/src/XF86Config-parser/Monitor.c
new file mode 100644
index 0000000..8c273c4
--- /dev/null
+++ b/src/XF86Config-parser/Monitor.c
@@ -0,0 +1,889 @@
+/*
+ *
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec MonitorTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {IDENTIFIER, "identifier"},
+ {VENDOR, "vendorname"},
+ {MODEL, "modelname"},
+ {USEMODES, "usemodes"},
+ {MODELINE, "modeline"},
+ {DISPLAYSIZE, "displaysize"},
+ {HORIZSYNC, "horizsync"},
+ {VERTREFRESH, "vertrefresh"},
+ {MODE, "mode"},
+ {GAMMA, "gamma"},
+ {OPTION, "option"},
+ {-1, ""},
+};
+
+static XConfigSymTabRec ModesTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {IDENTIFIER, "identifier"},
+ {MODELINE, "modeline"},
+ {MODE, "mode"},
+ {-1, ""},
+};
+
+static XConfigSymTabRec TimingTab[] =
+{
+ {TT_INTERLACE, "interlace"},
+ {TT_PHSYNC, "+hsync"},
+ {TT_NHSYNC, "-hsync"},
+ {TT_PVSYNC, "+vsync"},
+ {TT_NVSYNC, "-vsync"},
+ {TT_CSYNC, "composite"},
+ {TT_PCSYNC, "+csync"},
+ {TT_NCSYNC, "-csync"},
+ {TT_DBLSCAN, "doublescan"},
+ {TT_HSKEW, "hskew"},
+ {TT_BCAST, "bcast"},
+ {TT_VSCAN, "vscan"},
+ {TT_CUSTOM, "CUSTOM"},
+ {-1, ""},
+};
+
+static XConfigSymTabRec ModeTab[] =
+{
+ {DOTCLOCK, "dotclock"},
+ {HTIMINGS, "htimings"},
+ {VTIMINGS, "vtimings"},
+ {FLAGS, "flags"},
+ {HSKEW, "hskew"},
+ {BCAST, "bcast"},
+ {VSCAN, "vscan"},
+ {ENDMODE, "endmode"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeModeLineList
+
+XConfigModeLinePtr
+xconfigParseModeLine (void)
+{
+ int token;
+ PARSE_PROLOGUE (XConfigModeLinePtr, XConfigModeLineRec)
+
+ /* Identifier */
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error ("ModeLine identifier expected", NULL);
+ ptr->identifier = val.str;
+
+ /* DotClock */
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("ModeLine dotclock expected", NULL);
+ ptr->clock = (int) (val.realnum * 1000.0 + 0.5);
+
+ /* HDisplay */
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("ModeLine Hdisplay expected", NULL);
+ ptr->hdisplay = val.num;
+
+ /* HSyncStart */
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("ModeLine HSyncStart expected", NULL);
+ ptr->hsyncstart = val.num;
+
+ /* HSyncEnd */
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("ModeLine HSyncEnd expected", NULL);
+ ptr->hsyncend = val.num;
+
+ /* HTotal */
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("ModeLine HTotal expected", NULL);
+ ptr->htotal = val.num;
+
+ /* VDisplay */
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("ModeLine Vdisplay expected", NULL);
+ ptr->vdisplay = val.num;
+
+ /* VSyncStart */
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("ModeLine VSyncStart expected", NULL);
+ ptr->vsyncstart = val.num;
+
+ /* VSyncEnd */
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("ModeLine VSyncEnd expected", NULL);
+ ptr->vsyncend = val.num;
+
+ /* VTotal */
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("ModeLine VTotal expected", NULL);
+ ptr->vtotal = val.num;
+
+ token = xconfigGetSubTokenWithTab (&(ptr->comment), TimingTab);
+ while ((token == TT_INTERLACE) || (token == TT_PHSYNC) ||
+ (token == TT_NHSYNC) || (token == TT_PVSYNC) ||
+ (token == TT_NVSYNC) || (token == TT_CSYNC) ||
+ (token == TT_PCSYNC) || (token == TT_NCSYNC) ||
+ (token == TT_DBLSCAN) || (token == TT_HSKEW) ||
+ (token == TT_VSCAN) || (token == TT_BCAST))
+ {
+ switch (token)
+ {
+
+ case TT_INTERLACE:
+ ptr->flags |= XCONFIG_MODE_INTERLACE;
+ break;
+ case TT_PHSYNC:
+ ptr->flags |= XCONFIG_MODE_PHSYNC;
+ break;
+ case TT_NHSYNC:
+ ptr->flags |= XCONFIG_MODE_NHSYNC;
+ break;
+ case TT_PVSYNC:
+ ptr->flags |= XCONFIG_MODE_PVSYNC;
+ break;
+ case TT_NVSYNC:
+ ptr->flags |= XCONFIG_MODE_NVSYNC;
+ break;
+ case TT_CSYNC:
+ ptr->flags |= XCONFIG_MODE_CSYNC;
+ break;
+ case TT_PCSYNC:
+ ptr->flags |= XCONFIG_MODE_PCSYNC;
+ break;
+ case TT_NCSYNC:
+ ptr->flags |= XCONFIG_MODE_NCSYNC;
+ break;
+ case TT_DBLSCAN:
+ ptr->flags |= XCONFIG_MODE_DBLSCAN;
+ break;
+ case TT_HSKEW:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "Hskew");
+ ptr->hskew = val.num;
+ ptr->flags |= XCONFIG_MODE_HSKEW;
+ break;
+ case TT_BCAST:
+ ptr->flags |= XCONFIG_MODE_BCAST;
+ break;
+ case TT_VSCAN:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "Vscan");
+ ptr->vscan = val.num;
+ ptr->flags |= XCONFIG_MODE_VSCAN;
+ break;
+ case TT_CUSTOM:
+ ptr->flags |= XCONFIG_MODE_CUSTOM;
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ token = xconfigGetSubTokenWithTab (&(ptr->comment), TimingTab);
+ }
+ xconfigUnGetToken (token);
+
+ return (ptr);
+}
+
+XConfigModeLinePtr
+xconfigParseVerboseMode (void)
+{
+ int token, token2;
+ int had_dotclock = 0, had_htimings = 0, had_vtimings = 0;
+ PARSE_PROLOGUE (XConfigModeLinePtr, XConfigModeLineRec)
+
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error ("Mode name expected", NULL);
+ ptr->identifier = val.str;
+ while ((token = xconfigGetToken (ModeTab)) != ENDMODE)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case DOTCLOCK:
+ if ((token = xconfigGetSubToken (&(ptr->comment))) != NUMBER)
+ Error (NUMBER_MSG, "DotClock");
+ ptr->clock = (int) (val.realnum * 1000.0 + 0.5);
+ had_dotclock = 1;
+ break;
+ case HTIMINGS:
+ if (xconfigGetSubToken (&(ptr->comment)) == NUMBER)
+ ptr->hdisplay = val.num;
+ else
+ Error ("Horizontal display expected", NULL);
+
+ if (xconfigGetSubToken (&(ptr->comment)) == NUMBER)
+ ptr->hsyncstart = val.num;
+ else
+ Error ("Horizontal sync start expected", NULL);
+
+ if (xconfigGetSubToken (&(ptr->comment)) == NUMBER)
+ ptr->hsyncend = val.num;
+ else
+ Error ("Horizontal sync end expected", NULL);
+
+ if (xconfigGetSubToken (&(ptr->comment)) == NUMBER)
+ ptr->htotal = val.num;
+ else
+ Error ("Horizontal total expected", NULL);
+ had_htimings = 1;
+ break;
+ case VTIMINGS:
+ if (xconfigGetSubToken (&(ptr->comment)) == NUMBER)
+ ptr->vdisplay = val.num;
+ else
+ Error ("Vertical display expected", NULL);
+
+ if (xconfigGetSubToken (&(ptr->comment)) == NUMBER)
+ ptr->vsyncstart = val.num;
+ else
+ Error ("Vertical sync start expected", NULL);
+
+ if (xconfigGetSubToken (&(ptr->comment)) == NUMBER)
+ ptr->vsyncend = val.num;
+ else
+ Error ("Vertical sync end expected", NULL);
+
+ if (xconfigGetSubToken (&(ptr->comment)) == NUMBER)
+ ptr->vtotal = val.num;
+ else
+ Error ("Vertical total expected", NULL);
+ had_vtimings = 1;
+ break;
+ case FLAGS:
+ token = xconfigGetSubToken (&(ptr->comment));
+ if (token != STRING)
+ Error (QUOTE_MSG, "Flags");
+ while (token == STRING)
+ {
+ token2 = xconfigGetStringToken (TimingTab);
+ switch (token2)
+ {
+ case TT_INTERLACE:
+ ptr->flags |= XCONFIG_MODE_INTERLACE;
+ break;
+ case TT_PHSYNC:
+ ptr->flags |= XCONFIG_MODE_PHSYNC;
+ break;
+ case TT_NHSYNC:
+ ptr->flags |= XCONFIG_MODE_NHSYNC;
+ break;
+ case TT_PVSYNC:
+ ptr->flags |= XCONFIG_MODE_PVSYNC;
+ break;
+ case TT_NVSYNC:
+ ptr->flags |= XCONFIG_MODE_NVSYNC;
+ break;
+ case TT_CSYNC:
+ ptr->flags |= XCONFIG_MODE_CSYNC;
+ break;
+ case TT_PCSYNC:
+ ptr->flags |= XCONFIG_MODE_PCSYNC;
+ break;
+ case TT_NCSYNC:
+ ptr->flags |= XCONFIG_MODE_NCSYNC;
+ break;
+ case TT_DBLSCAN:
+ ptr->flags |= XCONFIG_MODE_DBLSCAN;
+ break;
+ case TT_CUSTOM:
+ ptr->flags |= XCONFIG_MODE_CUSTOM;
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error ("Unknown flag string", NULL);
+ break;
+ }
+ token = xconfigGetSubToken (&(ptr->comment));
+ }
+ xconfigUnGetToken (token);
+ break;
+ case HSKEW:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("Horizontal skew expected", NULL);
+ ptr->flags |= XCONFIG_MODE_HSKEW;
+ ptr->hskew = val.num;
+ break;
+ case VSCAN:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("Vertical scan count expected", NULL);
+ ptr->flags |= XCONFIG_MODE_VSCAN;
+ ptr->vscan = val.num;
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error ("Unexepcted token in verbose \"Mode\" entry\n", NULL);
+ }
+ }
+ if (!had_dotclock)
+ Error ("the dotclock is missing", NULL);
+ if (!had_htimings)
+ Error ("the horizontal timings are missing", NULL);
+ if (!had_vtimings)
+ Error ("the vertical timings are missing", NULL);
+
+ return (ptr);
+}
+
+#undef CLEANUP
+
+#define CLEANUP xconfigFreeMonitorList
+
+XConfigMonitorPtr
+xconfigParseMonitorSection (void)
+{
+ int has_ident = FALSE;
+ int token;
+ PARSE_PROLOGUE (XConfigMonitorPtr, XConfigMonitorRec)
+
+ while ((token = xconfigGetToken (MonitorTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Identifier");
+ if (has_ident == TRUE)
+ Error (MULTIPLE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ has_ident = TRUE;
+ break;
+ case VENDOR:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Vendor");
+ ptr->vendor = val.str;
+ break;
+ case MODEL:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "ModelName");
+ ptr->modelname = val.str;
+ break;
+ case MODE:
+ HANDLE_LIST (modelines, xconfigParseVerboseMode,
+ XConfigModeLinePtr);
+ break;
+ case MODELINE:
+ HANDLE_LIST (modelines, xconfigParseModeLine,
+ XConfigModeLinePtr);
+ break;
+ case DISPLAYSIZE:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (DISPLAYSIZE_MSG, NULL);
+ ptr->width = val.realnum;
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (DISPLAYSIZE_MSG, NULL);
+ ptr->height = val.realnum;
+ break;
+
+ case HORIZSYNC:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (HORIZSYNC_MSG, NULL);
+ do {
+ ptr->hsync[ptr->n_hsync].lo = val.realnum;
+ switch (token = xconfigGetSubToken (&(ptr->comment)))
+ {
+ case COMMA:
+ ptr->hsync[ptr->n_hsync].hi =
+ ptr->hsync[ptr->n_hsync].lo;
+ break;
+ case DASH:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER ||
+ (float)val.realnum < ptr->hsync[ptr->n_hsync].lo)
+ Error (HORIZSYNC_MSG, NULL);
+ ptr->hsync[ptr->n_hsync].hi = val.realnum;
+ if ((token = xconfigGetSubToken (&(ptr->comment))) == COMMA)
+ break;
+ ptr->n_hsync++;
+ goto HorizDone;
+ default:
+ /* We cannot currently know if a '\n' was found,
+ * or this is a real error
+ */
+ ptr->hsync[ptr->n_hsync].hi =
+ ptr->hsync[ptr->n_hsync].lo;
+ ptr->n_hsync++;
+ goto HorizDone;
+ }
+ if (ptr->n_hsync >= CONF_MAX_HSYNC)
+ Error ("Sorry. Too many horizontal sync intervals.", NULL);
+ ptr->n_hsync++;
+ } while ((token = xconfigGetSubToken (&(ptr->comment))) == NUMBER);
+HorizDone:
+ xconfigUnGetToken (token);
+ break;
+
+ case VERTREFRESH:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (VERTREFRESH_MSG, NULL);
+ do {
+ ptr->vrefresh[ptr->n_vrefresh].lo = val.realnum;
+ switch (token = xconfigGetSubToken (&(ptr->comment)))
+ {
+ case COMMA:
+ ptr->vrefresh[ptr->n_vrefresh].hi =
+ ptr->vrefresh[ptr->n_vrefresh].lo;
+ break;
+ case DASH:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER ||
+ (float)val.realnum < ptr->vrefresh[ptr->n_vrefresh].lo)
+ Error (VERTREFRESH_MSG, NULL);
+ ptr->vrefresh[ptr->n_vrefresh].hi = val.realnum;
+ if ((token = xconfigGetSubToken (&(ptr->comment))) == COMMA)
+ break;
+ ptr->n_vrefresh++;
+ goto VertDone;
+ default:
+ /* We cannot currently know if a '\n' was found,
+ * or this is a real error
+ */
+ ptr->vrefresh[ptr->n_vrefresh].hi =
+ ptr->vrefresh[ptr->n_vrefresh].lo;
+ ptr->n_vrefresh++;
+ goto VertDone;
+ }
+ if (ptr->n_vrefresh >= CONF_MAX_VREFRESH)
+ Error ("Sorry. Too many vertical refresh intervals.", NULL);
+ ptr->n_vrefresh++;
+ } while ((token = xconfigGetSubToken (&(ptr->comment))) == NUMBER);
+VertDone:
+ xconfigUnGetToken (token);
+ break;
+
+ case GAMMA:
+ if( xconfigGetSubToken (&(ptr->comment)) != NUMBER )
+ {
+ Error (INVALID_GAMMA_MSG, NULL);
+ }
+ else
+ {
+ ptr->gamma_red = ptr->gamma_green =
+ ptr->gamma_blue = val.realnum;
+ if( xconfigGetSubToken (&(ptr->comment)) == NUMBER )
+ {
+ ptr->gamma_green = val.realnum;
+ if( xconfigGetSubToken (&(ptr->comment)) == NUMBER )
+ {
+ ptr->gamma_blue = val.realnum;
+ }
+ else
+ {
+ Error (INVALID_GAMMA_MSG, NULL);
+ }
+ }
+ else
+ xconfigUnGetToken (token);
+ }
+ break;
+ case OPTION:
+ ptr->options = xconfigParseOption(ptr->options);
+ break;
+ case USEMODES:
+ {
+ XConfigModesLinkPtr mptr;
+
+ if ((token = xconfigGetSubToken (&(ptr->comment))) != STRING)
+ Error (QUOTE_MSG, "UseModes");
+
+ /* add to the end of the list of modes sections
+ referenced here */
+ mptr = calloc (1, sizeof (XConfigModesLinkRec));
+ mptr->next = NULL;
+ mptr->modes_name = val.str;
+ mptr->modes = NULL;
+ ptr->modes_sections = (XConfigModesLinkPtr)
+ xconfigAddListItem((GenericListPtr)ptr->modes_sections,
+ (GenericListPtr)mptr);
+ }
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ xconfigErrorMsg(ParseErrorMsg, INVALID_KEYWORD_MSG,
+ xconfigTokenString());
+ CLEANUP (ptr);
+ return NULL;
+ break;
+ }
+ }
+
+ if (!has_ident)
+ Error (NO_IDENT_MSG, NULL);
+
+ return ptr;
+}
+
+#undef CLEANUP
+#define CLEANUP xconfigFreeModesList
+
+XConfigModesPtr
+xconfigParseModesSection (void)
+{
+ int has_ident = FALSE;
+ int token;
+ PARSE_PROLOGUE (XConfigModesPtr, XConfigModesRec)
+
+ while ((token = xconfigGetToken (ModesTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Identifier");
+ if (has_ident == TRUE)
+ Error (MULTIPLE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ has_ident = TRUE;
+ break;
+ case MODE:
+ HANDLE_LIST (modelines, xconfigParseVerboseMode,
+ XConfigModeLinePtr);
+ break;
+ case MODELINE:
+ HANDLE_LIST (modelines, xconfigParseModeLine,
+ XConfigModeLinePtr);
+ break;
+ default:
+ xconfigErrorMsg(ParseErrorMsg, INVALID_KEYWORD_MSG,
+ xconfigTokenString());
+ CLEANUP (ptr);
+ return NULL;
+ break;
+ }
+ }
+
+ if (!has_ident)
+ Error (NO_IDENT_MSG, NULL);
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+void
+xconfigPrintMonitorSection (FILE * cf, XConfigMonitorPtr ptr)
+{
+ int i;
+ XConfigModeLinePtr mlptr;
+ XConfigModesLinkPtr mptr;
+
+ while (ptr)
+ {
+ mptr = ptr->modes_sections;
+ fprintf (cf, "Section \"Monitor\"\n");
+ if (ptr->comment)
+ fprintf (cf, "%s", ptr->comment);
+ if (ptr->identifier)
+ fprintf (cf, " Identifier \"%s\"\n", ptr->identifier);
+ if (ptr->vendor)
+ fprintf (cf, " VendorName \"%s\"\n", ptr->vendor);
+ if (ptr->modelname)
+ fprintf (cf, " ModelName \"%s\"\n", ptr->modelname);
+ while (mptr) {
+ fprintf (cf, " UseModes \"%s\"\n", mptr->modes_name);
+ mptr = mptr->next;
+ }
+ if (ptr->width)
+ fprintf (cf, " DisplaySize %d %d\n",
+ ptr->width,
+ ptr->height);
+ for (i = 0; i < ptr->n_hsync; i++)
+ {
+ fprintf (cf, " HorizSync %2.1f - %2.1f\n",
+ ptr->hsync[i].lo,
+ ptr->hsync[i].hi);
+ }
+ for (i = 0; i < ptr->n_vrefresh; i++)
+ {
+ fprintf (cf, " VertRefresh %2.1f - %2.1f\n",
+ ptr->vrefresh[i].lo,
+ ptr->vrefresh[i].hi);
+ }
+ if (ptr->gamma_red) {
+ if (ptr->gamma_red == ptr->gamma_green
+ && ptr->gamma_red == ptr->gamma_blue)
+ {
+ fprintf (cf, " Gamma %.4g\n",
+ ptr->gamma_red);
+ } else {
+ fprintf (cf, " Gamma %.4g %.4g %.4g\n",
+ ptr->gamma_red,
+ ptr->gamma_green,
+ ptr->gamma_blue);
+ }
+ }
+ for (mlptr = ptr->modelines; mlptr; mlptr = mlptr->next)
+ {
+ fprintf (cf, " ModeLine \"%s\" %2.1f ",
+ mlptr->identifier, mlptr->clock / 1000.0);
+ fprintf (cf, "%d %d %d %d %d %d %d %d",
+ mlptr->hdisplay, mlptr->hsyncstart,
+ mlptr->hsyncend, mlptr->htotal,
+ mlptr->vdisplay, mlptr->vsyncstart,
+ mlptr->vsyncend, mlptr->vtotal);
+ if (mlptr->flags & XCONFIG_MODE_PHSYNC)
+ fprintf (cf, " +hsync");
+ if (mlptr->flags & XCONFIG_MODE_NHSYNC)
+ fprintf (cf, " -hsync");
+ if (mlptr->flags & XCONFIG_MODE_PVSYNC)
+ fprintf (cf, " +vsync");
+ if (mlptr->flags & XCONFIG_MODE_NVSYNC)
+ fprintf (cf, " -vsync");
+ if (mlptr->flags & XCONFIG_MODE_INTERLACE)
+ fprintf (cf, " interlace");
+ if (mlptr->flags & XCONFIG_MODE_CSYNC)
+ fprintf (cf, " composite");
+ if (mlptr->flags & XCONFIG_MODE_PCSYNC)
+ fprintf (cf, " +csync");
+ if (mlptr->flags & XCONFIG_MODE_NCSYNC)
+ fprintf (cf, " -csync");
+ if (mlptr->flags & XCONFIG_MODE_DBLSCAN)
+ fprintf (cf, " doublescan");
+ if (mlptr->flags & XCONFIG_MODE_HSKEW)
+ fprintf (cf, " hskew %d", mlptr->hskew);
+ if (mlptr->flags & XCONFIG_MODE_BCAST)
+ fprintf (cf, " bcast");
+ fprintf (cf, "\n");
+ }
+ xconfigPrintOptionList(cf, ptr->options, 1);
+ fprintf (cf, "EndSection\n\n");
+ ptr = ptr->next;
+ }
+}
+
+void
+xconfigPrintModesSection (FILE * cf, XConfigModesPtr ptr)
+{
+ XConfigModeLinePtr mlptr;
+
+ while (ptr)
+ {
+ fprintf (cf, "Section \"Modes\"\n");
+ if (ptr->comment)
+ fprintf (cf, "%s", ptr->comment);
+ if (ptr->identifier)
+ fprintf (cf, " Identifier \"%s\"\n", ptr->identifier);
+ for (mlptr = ptr->modelines; mlptr; mlptr = mlptr->next)
+ {
+ fprintf (cf, " ModeLine \"%s\" %2.1f ",
+ mlptr->identifier, mlptr->clock / 1000.0);
+ fprintf (cf, "%d %d %d %d %d %d %d %d",
+ mlptr->hdisplay, mlptr->hsyncstart,
+ mlptr->hsyncend, mlptr->htotal,
+ mlptr->vdisplay, mlptr->vsyncstart,
+ mlptr->vsyncend, mlptr->vtotal);
+ if (mlptr->flags & XCONFIG_MODE_PHSYNC)
+ fprintf (cf, " +hsync");
+ if (mlptr->flags & XCONFIG_MODE_NHSYNC)
+ fprintf (cf, " -hsync");
+ if (mlptr->flags & XCONFIG_MODE_PVSYNC)
+ fprintf (cf, " +vsync");
+ if (mlptr->flags & XCONFIG_MODE_NVSYNC)
+ fprintf (cf, " -vsync");
+ if (mlptr->flags & XCONFIG_MODE_INTERLACE)
+ fprintf (cf, " interlace");
+ if (mlptr->flags & XCONFIG_MODE_CSYNC)
+ fprintf (cf, " composite");
+ if (mlptr->flags & XCONFIG_MODE_PCSYNC)
+ fprintf (cf, " +csync");
+ if (mlptr->flags & XCONFIG_MODE_NCSYNC)
+ fprintf (cf, " -csync");
+ if (mlptr->flags & XCONFIG_MODE_DBLSCAN)
+ fprintf (cf, " doublescan");
+ if (mlptr->flags & XCONFIG_MODE_HSKEW)
+ fprintf (cf, " hskew %d", mlptr->hskew);
+ if (mlptr->flags & XCONFIG_MODE_VSCAN)
+ fprintf (cf, " vscan %d", mlptr->vscan);
+ if (mlptr->flags & XCONFIG_MODE_BCAST)
+ fprintf (cf, " bcast");
+ if (mlptr->comment)
+ fprintf (cf, "%s", mlptr->comment);
+ else
+ fprintf (cf, "\n");
+ }
+ fprintf (cf, "EndSection\n\n");
+ ptr = ptr->next;
+ }
+}
+
+void
+xconfigFreeMonitorList (XConfigMonitorPtr ptr)
+{
+ XConfigMonitorPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->identifier);
+ TEST_FREE (ptr->vendor);
+ TEST_FREE (ptr->modelname);
+ TEST_FREE (ptr->comment);
+ xconfigOptionListFree (ptr->options);
+ xconfigFreeModeLineList (ptr->modelines);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+void
+xconfigFreeModesList (XConfigModesPtr ptr)
+{
+ XConfigModesPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->identifier);
+ TEST_FREE (ptr->comment);
+ xconfigFreeModeLineList (ptr->modelines);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+void
+xconfigFreeModeLineList (XConfigModeLinePtr ptr)
+{
+ XConfigModeLinePtr prev;
+ while (ptr)
+ {
+ TEST_FREE (ptr->identifier);
+ TEST_FREE (ptr->comment);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+XConfigMonitorPtr
+xconfigFindMonitor (const char *ident, XConfigMonitorPtr p)
+{
+ while (p)
+ {
+ if (xconfigNameCompare (ident, p->identifier) == 0)
+ return (p);
+
+ p = p->next;
+ }
+ return (NULL);
+}
+
+XConfigModesPtr
+xconfigFindModes (const char *ident, XConfigModesPtr p)
+{
+ while (p)
+ {
+ if (xconfigNameCompare (ident, p->identifier) == 0)
+ return (p);
+
+ p = p->next;
+ }
+ return (NULL);
+}
+
+XConfigModeLinePtr
+xconfigFindModeLine (const char *ident, XConfigModeLinePtr p)
+{
+ while (p)
+ {
+ if (xconfigNameCompare (ident, p->identifier) == 0)
+ return (p);
+
+ p = p->next;
+ }
+ return (NULL);
+}
+
+int
+xconfigValidateMonitor (XConfigPtr p, XConfigScreenPtr screen)
+{
+ XConfigMonitorPtr monitor = screen->monitor;
+ XConfigModesLinkPtr modeslnk = monitor->modes_sections;
+ XConfigModesPtr modes;
+ while(modeslnk)
+ {
+ modes = xconfigFindModes (modeslnk->modes_name, p->modes);
+ if (!modes)
+ {
+ xconfigErrorMsg(ValidationErrorMsg, UNDEFINED_MODES_MSG,
+ modeslnk->modes_name, screen->identifier);
+ return (FALSE);
+ }
+ modeslnk->modes = modes;
+ modeslnk = modeslnk->next;
+ }
+ return (TRUE);
+}
diff --git a/src/XF86Config-parser/Pointer.c b/src/XF86Config-parser/Pointer.c
new file mode 100644
index 0000000..d1e282a
--- /dev/null
+++ b/src/XF86Config-parser/Pointer.c
@@ -0,0 +1,236 @@
+/*
+ *
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec PointerTab[] =
+{
+ {PROTOCOL, "protocol"},
+ {EMULATE3, "emulate3buttons"},
+ {EM3TIMEOUT, "emulate3timeout"},
+ {ENDSUBSECTION, "endsubsection"},
+ {ENDSECTION, "endsection"},
+ {PDEVICE, "device"},
+ {PDEVICE, "port"},
+ {BAUDRATE, "baudrate"},
+ {SAMPLERATE, "samplerate"},
+ {CLEARDTR, "cleardtr"},
+ {CLEARRTS, "clearrts"},
+ {CHORDMIDDLE, "chordmiddle"},
+ {PRESOLUTION, "resolution"},
+ {DEVICE_NAME, "devicename"},
+ {ALWAYSCORE, "alwayscore"},
+ {PBUTTONS, "buttons"},
+ {ZAXISMAPPING, "zaxismapping"},
+ {-1, ""},
+};
+
+static XConfigSymTabRec ZMapTab[] =
+{
+ {XAXIS, "x"},
+ {YAXIS, "y"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeInputList
+
+XConfigInputPtr
+xconfigParsePointerSection (void)
+{
+ char *s, *s1, *s2;
+ int l;
+ int token;
+ PARSE_PROLOGUE (XConfigInputPtr, XConfigInputRec)
+
+ while ((token = xconfigGetToken (PointerTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case PROTOCOL:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Protocol");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("Protocol"),
+ val.str);
+ break;
+ case PDEVICE:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Device");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("Device"),
+ val.str);
+ break;
+ case EMULATE3:
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("Emulate3Buttons"),
+ NULL);
+ break;
+ case EM3TIMEOUT:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER || val.num < 0)
+ Error (POSITIVE_INT_MSG, "Emulate3Timeout");
+ s = xconfigULongToString(val.num);
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("Emulate3Timeout"),
+ s);
+ break;
+ case CHORDMIDDLE:
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("ChordMiddle"),
+ NULL);
+ break;
+ case PBUTTONS:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER || val.num < 0)
+ Error (POSITIVE_INT_MSG, "Buttons");
+ s = xconfigULongToString(val.num);
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("Buttons"), s);
+ break;
+ case BAUDRATE:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER || val.num < 0)
+ Error (POSITIVE_INT_MSG, "BaudRate");
+ s = xconfigULongToString(val.num);
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("BaudRate"), s);
+ break;
+ case SAMPLERATE:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER || val.num < 0)
+ Error (POSITIVE_INT_MSG, "SampleRate");
+ s = xconfigULongToString(val.num);
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("SampleRate"), s);
+ break;
+ case PRESOLUTION:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER || val.num < 0)
+ Error (POSITIVE_INT_MSG, "Resolution");
+ s = xconfigULongToString(val.num);
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("Resolution"), s);
+ break;
+ case CLEARDTR:
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("ClearDTR"), NULL);
+ break;
+ case CLEARRTS:
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("ClearRTS"), NULL);
+ break;
+ case ZAXISMAPPING:
+ switch (xconfigGetToken(ZMapTab)) {
+ case NUMBER:
+ if (val.num < 0)
+ Error (ZAXISMAPPING_MSG, NULL);
+ s1 = xconfigULongToString(val.num);
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER ||
+ val.num < 0)
+ Error (ZAXISMAPPING_MSG, NULL);
+ s2 = xconfigULongToString(val.num);
+ l = strlen(s1) + 1 + strlen(s2) + 1;
+ s = malloc(l);
+ sprintf(s, "%s %s", s1, s2);
+ free(s1);
+ free(s2);
+ break;
+ case XAXIS:
+ s = xconfigStrdup("x");
+ break;
+ case YAXIS:
+ s = xconfigStrdup("y");
+ break;
+ default:
+ Error (ZAXISMAPPING_MSG, NULL);
+ break;
+ }
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("ZAxisMapping"),
+ s);
+ break;
+ case ALWAYSCORE:
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ ptr->identifier = xconfigStrdup(CONF_IMPLICIT_POINTER);
+ ptr->driver = xconfigStrdup("mouse");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("CorePointer"), NULL);
+
+ return ptr;
+}
+
+#undef CLEANUP
+
diff --git a/src/XF86Config-parser/Read.c b/src/XF86Config-parser/Read.c
new file mode 100644
index 0000000..7d21e44
--- /dev/null
+++ b/src/XF86Config-parser/Read.c
@@ -0,0 +1,401 @@
+/*
+ *
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec TopLevelTab[] =
+{
+ {SECTION, "section"},
+ {-1, ""},
+};
+
+
+#define CLEANUP xconfigFreeConfig
+
+#define READ_HANDLE_RETURN(f,func) \
+ if ((ptr->f=func) == NULL) { \
+ xconfigFreeConfig(ptr); \
+ return XCONFIG_RETURN_PARSE_ERROR; \
+ }
+
+#define READ_HANDLE_LIST(field,func,type) \
+{ \
+ type p = func(); \
+ if (p == NULL) { \
+ xconfigFreeConfig(ptr); \
+ return XCONFIG_RETURN_PARSE_ERROR; \
+ } else { \
+ ptr->field = (type) \
+ xconfigAddListItem((GenericListPtr) ptr->field, \
+ (GenericListPtr) p); \
+ } \
+}
+
+#define READ_ERROR(a,b) \
+ do { \
+ xconfigErrorMsg(ParseErrorMsg, a, b); \
+ xconfigFreeConfig(ptr); \
+ return XCONFIG_RETURN_PARSE_ERROR; \
+ } while (0) \
+
+
+
+/*
+ * xconfigReadConfigFile() - read the open XConfig file, returning the
+ * parsed data as XConfigPtr.
+ */
+
+XConfigError xconfigReadConfigFile(XConfigPtr *configPtr)
+{
+ int token;
+ XConfigPtr ptr = NULL;
+
+ *configPtr = NULL;
+
+ ptr = xconfigAlloc(sizeof(XConfigRec));
+
+ while ((token = xconfigGetToken(TopLevelTab)) != EOF_TOKEN) {
+
+ switch (token) {
+
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+
+ case SECTION:
+ if (xconfigGetSubToken(&(ptr->comment)) != STRING) {
+ xconfigErrorMsg(ParseErrorMsg, QUOTE_MSG, "Section");
+ xconfigFreeConfig(ptr);
+ return XCONFIG_RETURN_PARSE_ERROR;
+ }
+
+ xconfigSetSection(val.str);
+
+ if (xconfigNameCompare(val.str, "files") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_RETURN(files, xconfigParseFilesSection());
+ }
+ else if (xconfigNameCompare(val.str, "serverflags") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_RETURN(flags, xconfigParseFlagsSection());
+ }
+ else if (xconfigNameCompare(val.str, "keyboard") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_LIST(inputs, xconfigParseKeyboardSection,
+ XConfigInputPtr);
+ }
+ else if (xconfigNameCompare(val.str, "pointer") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_LIST(inputs, xconfigParsePointerSection,
+ XConfigInputPtr);
+ }
+ else if (xconfigNameCompare(val.str, "videoadaptor") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_LIST(videoadaptors,
+ xconfigParseVideoAdaptorSection,
+ XConfigVideoAdaptorPtr);
+ }
+ else if (xconfigNameCompare(val.str, "device") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_LIST(devices, xconfigParseDeviceSection,
+ XConfigDevicePtr);
+ }
+ else if (xconfigNameCompare(val.str, "monitor") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_LIST(monitors, xconfigParseMonitorSection,
+ XConfigMonitorPtr);
+ }
+ else if (xconfigNameCompare(val.str, "modes") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_LIST(modes, xconfigParseModesSection,
+ XConfigModesPtr);
+ }
+ else if (xconfigNameCompare(val.str, "screen") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_LIST(screens, xconfigParseScreenSection,
+ XConfigScreenPtr);
+ }
+ else if (xconfigNameCompare(val.str, "inputdevice") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_LIST(inputs, xconfigParseInputSection,
+ XConfigInputPtr);
+ }
+ else if (xconfigNameCompare(val.str, "module") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_RETURN(modules, xconfigParseModuleSection());
+ }
+ else if (xconfigNameCompare(val.str, "serverlayout") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_LIST(layouts, xconfigParseLayoutSection,
+ XConfigLayoutPtr);
+ }
+ else if (xconfigNameCompare(val.str, "vendor") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_LIST(vendors, xconfigParseVendorSection,
+ XConfigVendorPtr);
+ }
+ else if (xconfigNameCompare(val.str, "dri") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_RETURN(dri, xconfigParseDRISection());
+ }
+ else if (xconfigNameCompare (val.str, "extensions") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_RETURN(extensions, xconfigParseExtensionsSection());
+ }
+ else
+ {
+ READ_ERROR(INVALID_SECTION_MSG, xconfigTokenString());
+ free(val.str);
+ val.str = NULL;
+ }
+ break;
+
+ default:
+ READ_ERROR(INVALID_KEYWORD_MSG, xconfigTokenString());
+ free(val.str);
+ val.str = NULL;
+ }
+ }
+
+ if (xconfigValidateConfig(ptr)) {
+ ptr->filename = strdup(xconfigGetConfigFileName());
+ *configPtr = ptr;
+ return XCONFIG_RETURN_SUCCESS;
+ } else {
+ xconfigFreeConfig(ptr);
+ return XCONFIG_RETURN_VALIDATION_ERROR;
+ }
+}
+
+#undef CLEANUP
+
+
+/*
+ * This function resolves name references and reports errors if the named
+ * objects cannot be found.
+ */
+
+int xconfigValidateConfig(XConfigPtr p)
+{
+ if (!xconfigValidateDevice(p))
+ return FALSE;
+ if (!xconfigValidateScreen(p))
+ return FALSE;
+ if (!xconfigValidateInput(p))
+ return FALSE;
+ if (!xconfigValidateLayout(p))
+ return FALSE;
+
+ return(TRUE);
+}
+
+
+
+/*
+ * This function fixes up any problems that it finds in the config,
+ * when possible.
+ */
+
+int xconfigSanitizeConfig(XConfigPtr p,
+ const char *screenName,
+ GenerateOptions *gop)
+{
+ if (!xconfigSanitizeScreen(p))
+ return FALSE;
+
+ if (!xconfigSanitizeLayout(p, screenName, gop))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+
+/*
+ * adds an item to the end of the linked list. Any record whose first field
+ * is a GenericListRec can be cast to this type and used with this function.
+ * A pointer to the head of the list is returned to handle the addition of
+ * the first item.
+ */
+GenericListPtr
+xconfigAddListItem (GenericListPtr head, GenericListPtr new)
+{
+ GenericListPtr p = head;
+ GenericListPtr last = NULL;
+
+ while (p)
+ {
+ last = p;
+ p = p->next;
+ }
+
+ if (last)
+ {
+ last->next = new;
+ return (head);
+ }
+ else
+ return (new);
+}
+
+
+/*
+ * removes an item from the linked list. Any record whose first field
+ * is a GenericListRec can be cast to this type and used with this function.
+ * A pointer to the head of the list is returned to handle the removal of
+ * the first item.
+ */
+GenericListPtr
+xconfigRemoveListItem (GenericListPtr head, GenericListPtr item)
+{
+ GenericListPtr cur = head;
+ GenericListPtr prev = NULL;
+
+ while (cur)
+ {
+ if (cur == item)
+ {
+ if (prev) prev->next = item->next;
+ if (head == item) head = item->next;
+ break;
+ }
+ prev = cur;
+ cur = cur->next;
+ }
+
+ return head;
+}
+
+
+/*
+ * Test if one chained list contains the other.
+ * In this case both list have the same endpoint (provided they don't loop)
+ */
+int
+xconfigItemNotSublist(GenericListPtr list_1, GenericListPtr list_2)
+{
+ GenericListPtr p = list_1;
+ GenericListPtr last_1 = NULL, last_2 = NULL;
+
+ while (p) {
+ last_1 = p;
+ p = p->next;
+ }
+
+ p = list_2;
+ while (p) {
+ last_2 = p;
+ p = p->next;
+ }
+
+ return (!(last_1 == last_2));
+}
+
+void
+xconfigFreeConfig (XConfigPtr p)
+{
+ if (p == NULL)
+ return;
+
+ xconfigFreeFiles (p->files);
+ xconfigFreeModules (p->modules);
+ xconfigFreeFlags (p->flags);
+ xconfigFreeMonitorList (p->monitors);
+ xconfigFreeModesList (p->modes);
+ xconfigFreeVideoAdaptorList (p->videoadaptors);
+ xconfigFreeDeviceList (p->devices);
+ xconfigFreeScreenList (p->screens);
+ xconfigFreeLayoutList (p->layouts);
+ xconfigFreeInputList (p->inputs);
+ xconfigFreeVendorList (p->vendors);
+ xconfigFreeDRI (p->dri);
+ TEST_FREE(p->comment);
+
+ free (p);
+}
diff --git a/src/XF86Config-parser/Scan.c b/src/XF86Config-parser/Scan.c
new file mode 100644
index 0000000..4e694ba
--- /dev/null
+++ b/src/XF86Config-parser/Scan.c
@@ -0,0 +1,975 @@
+/*
+ *
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#if !defined(X_NOT_POSIX)
+#if defined(_POSIX_SOURCE)
+#include <limits.h>
+#else
+#define _POSIX_SOURCE
+#include <limits.h>
+#undef _POSIX_SOURCE
+#endif /* _POSIX_SOURCE */
+#endif /* !X_NOT_POSIX */
+#if !defined(PATH_MAX)
+#if defined(MAXPATHLEN)
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif /* MAXPATHLEN */
+#endif /* !PATH_MAX */
+
+#if !defined(MAXHOSTNAMELEN)
+#define MAXHOSTNAMELEN 32
+#endif /* !MAXHOSTNAMELEN */
+
+#include "Configint.h"
+#include "xf86tokens.h"
+
+#define CONFIG_BUF_LEN 1024
+
+static int StringToToken (char *, XConfigSymTabRec *);
+
+static FILE *configFile = NULL;
+static const char **builtinConfig = NULL;
+static int builtinIndex = 0;
+static int configPos = 0; /* current readers position */
+static char *configBuf, *configRBuf; /* buffer for lines */
+static int pushToken = LOCK_TOKEN;
+static int eol_seen = 0; /* private state to handle comments */
+LexRec val;
+
+int configLineNo = 0; /* linenumber */
+char *configSection = NULL; /* name of current section being parsed */
+char *configPath; /* path to config file */
+
+
+
+
+static int xconfigIsAlpha(char c)
+{
+ return (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')));
+}
+
+static int xconfigIsDigit(char c)
+{
+ return ((c >= '0') && (c <= '9'));
+}
+
+static int xconfigIsUpper(char c)
+{
+ return ((c >= 'A') && (c <= 'Z'));
+}
+
+static char xconfigToLower(char c)
+{
+ if ((c >= 'A') && (c <= 'Z')) {
+ return c + ('a' - 'A');
+ } else {
+ return c;
+ }
+}
+
+
+/*
+ * xconfigStrToUL --
+ *
+ * A portable, but restricted, version of strtoul(). It only understands
+ * hex, octal, and decimal. But it's good enough for our needs.
+ */
+
+static unsigned int xconfigStrToUL (char *str)
+{
+ int base = 10;
+ char *p = str;
+ unsigned int tot = 0;
+
+ if (*p == '0')
+ {
+ p++;
+ if ((*p == 'x') || (*p == 'X'))
+ {
+ p++;
+ base = 16;
+ }
+ else
+ base = 8;
+ }
+ while (*p)
+ {
+ if ((*p >= '0') && (*p <= ((base == 8) ? '7' : '9')))
+ {
+ tot = tot * base + (*p - '0');
+ }
+ else if ((base == 16) && (*p >= 'a') && (*p <= 'f'))
+ {
+ tot = tot * base + 10 + (*p - 'a');
+ }
+ else if ((base == 16) && (*p >= 'A') && (*p <= 'F'))
+ {
+ tot = tot * base + 10 + (*p - 'A');
+ }
+ else
+ {
+ return (tot);
+ }
+ p++;
+ }
+ return (tot);
+}
+
+
+
+/*
+ * xconfigGetToken --
+ * Read next Token form the config file. Handle the global variable
+ * pushToken.
+ */
+
+int xconfigGetToken (XConfigSymTabRec * tab)
+{
+ int c, i;
+
+ /*
+ * First check whether pushToken has a different value than LOCK_TOKEN.
+ * In this case rBuf[] contains a valid STRING/TOKEN/NUMBER. But in the
+ * oth * case the next token must be read from the input.
+ */
+ if (pushToken == EOF_TOKEN)
+ return (EOF_TOKEN);
+ else if (pushToken == LOCK_TOKEN)
+ {
+ /*
+ * eol_seen is only set for the first token after a newline.
+ */
+ eol_seen = 0;
+
+ c = configBuf[configPos];
+
+ /*
+ * Get start of next Token. EOF is handled,
+ * whitespaces are skipped.
+ */
+
+again:
+ if (!c)
+ {
+ char *ret;
+ if (configFile)
+ ret = fgets (configBuf, CONFIG_BUF_LEN - 1, configFile);
+ else {
+ if (builtinConfig[builtinIndex] == NULL)
+ ret = NULL;
+ else {
+ ret = strncpy(configBuf, builtinConfig[builtinIndex],
+ CONFIG_BUF_LEN);
+ builtinIndex++;
+ }
+ }
+ if (ret == NULL)
+ {
+ return (pushToken = EOF_TOKEN);
+ }
+ configLineNo++;
+ configPos = 0;
+ eol_seen = 1;
+ }
+
+ i = 0;
+ for (;;) {
+ c = configBuf[configPos++];
+ configRBuf[i++] = c;
+ switch (c) {
+ case ' ':
+ case '\t':
+ case '\r':
+ continue;
+ case '\n':
+ i = 0;
+ continue;
+ }
+ break;
+ }
+ if (c == '\0')
+ goto again;
+
+ if (c == '#')
+ {
+ do
+ {
+ configRBuf[i++] = (c = configBuf[configPos++]);
+ }
+ while ((c != '\n') && (c != '\r') && (c != '\0'));
+ configRBuf[i] = '\0';
+ /* XXX no private copy.
+ * Use xconfigAddComment when setting a comment.
+ */
+ val.str = configRBuf;
+ return (COMMENT);
+ }
+
+ /* GJA -- handle '-' and ',' * Be careful: "-hsync" is a keyword. */
+ else if ((c == ',') && !xconfigIsAlpha(configBuf[configPos]))
+ {
+ return COMMA;
+ }
+ else if ((c == '-') && !xconfigIsAlpha(configBuf[configPos]))
+ {
+ return DASH;
+ }
+
+ /*
+ * Numbers are returned immediately ...
+ */
+ if (xconfigIsDigit(c))
+ {
+ int base;
+
+ if (c == '0')
+ if ((configBuf[configPos] == 'x') ||
+ (configBuf[configPos] == 'X'))
+ base = 16;
+ else
+ base = 8;
+ else
+ base = 10;
+
+ configRBuf[0] = c;
+ i = 1;
+ while (xconfigIsDigit(c = configBuf[configPos++]) ||
+ (c == '.') || (c == 'x') || (c == 'X') ||
+ ((base == 16) && (((c >= 'a') && (c <= 'f')) ||
+ ((c >= 'A') && (c <= 'F')))))
+ configRBuf[i++] = c;
+ configPos--; /* GJA -- one too far */
+ configRBuf[i] = '\0';
+ val.num = xconfigStrToUL (configRBuf);
+ val.realnum = atof (configRBuf);
+ return (NUMBER);
+ }
+
+ /*
+ * All Strings START with a \" ...
+ */
+ else if (c == '\"')
+ {
+ i = -1;
+ do
+ {
+ configRBuf[++i] = (c = configBuf[configPos++]);
+ }
+ while ((c != '\"') && (c != '\n') && (c != '\r') && (c != '\0'));
+ configRBuf[i] = '\0';
+ val.str = malloc (strlen (configRBuf) + 1);
+ strcpy (val.str, configRBuf); /* private copy ! */
+ return (STRING);
+ }
+
+ /*
+ * ... and now we MUST have a valid token. The search is
+ * handled later along with the pushed tokens.
+ */
+ else
+ {
+ configRBuf[0] = c;
+ i = 0;
+ do
+ {
+ configRBuf[++i] = (c = configBuf[configPos++]);;
+ }
+ while ((c != ' ') &&
+ (c != '\t') &&
+ (c != '\n') &&
+ (c != '\r') &&
+ (c != '\0') &&
+ (c != '#'));
+
+ --configPos;
+ configRBuf[i] = '\0';
+ i = 0;
+ }
+
+ }
+ else
+ {
+
+ /*
+ * Here we deal with pushed tokens. Reinitialize pushToken again. If
+ * the pushed token was NUMBER || STRING return them again ...
+ */
+ int temp = pushToken;
+ pushToken = LOCK_TOKEN;
+
+ if (temp == COMMA || temp == DASH)
+ return (temp);
+ if (temp == NUMBER || temp == STRING)
+ return (temp);
+ }
+
+ /*
+ * Joop, at last we have to lookup the token ...
+ */
+ if (tab)
+ {
+ i = 0;
+ while (tab[i].token != -1)
+ if (xconfigNameCompare (configRBuf, tab[i].name) == 0)
+ return (tab[i].token);
+ else
+ i++;
+ }
+
+ return (ERROR_TOKEN); /* Error catcher */
+}
+
+int xconfigGetSubToken (char **comment)
+{
+ int token;
+
+ for (;;) {
+ token = xconfigGetToken(NULL);
+ if (token == COMMENT) {
+ if (comment)
+ *comment = xconfigAddComment(*comment, val.str);
+ }
+ else
+ return (token);
+ }
+ /*NOTREACHED*/
+}
+
+int xconfigGetSubTokenWithTab (char **comment, XConfigSymTabRec *tab)
+{
+ int token;
+
+ for (;;) {
+ token = xconfigGetToken(tab);
+ if (token == COMMENT) {
+ if (comment)
+ *comment = xconfigAddComment(*comment, val.str);
+ }
+ else
+ return (token);
+ }
+ /*NOTREACHED*/
+}
+
+void xconfigUnGetToken (int token)
+{
+ pushToken = token;
+}
+
+char *xconfigTokenString (void)
+{
+ return configRBuf;
+}
+
+static int pathIsAbsolute(const char *path)
+{
+ if (path && path[0] == '/')
+ return 1;
+ return 0;
+}
+
+/* A path is "safe" if it is relative and if it contains no ".." elements. */
+static int pathIsSafe(const char *path)
+{
+ if (pathIsAbsolute(path))
+ return 0;
+
+ /* Compare with ".." */
+ if (!strcmp(path, ".."))
+ return 0;
+
+ /* Look for leading "../" */
+ if (!strncmp(path, "../", 3))
+ return 0;
+
+ /* Look for trailing "/.." */
+ if ((strlen(path) > 3) && !strcmp(path + strlen(path) - 3, "/.."))
+ return 0;
+
+ /* Look for "/../" */
+ if (strstr(path, "/../"))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * This function substitutes the following escape sequences:
+ *
+ * %A cmdline argument as an absolute path (must be absolute to match)
+ * %R cmdline argument as a relative path
+ * %S cmdline argument as a "safe" path (relative, and no ".." elements)
+ * %X default config file name ("XF86Config")
+ * %H hostname
+ * %E config file environment ($XF86CONFIG) as an absolute path
+ * %F config file environment ($XF86CONFIG) as a relative path
+ * %G config file environment ($XF86CONFIG) as a safe path
+ * %D $HOME
+ * %P projroot
+ * %M major version number
+ * %% %
+ * %& UNIXOS2 only: prepend X11ROOT env var
+ */
+
+#ifndef XCONFIGFILE
+#define XCONFIGFILE "xorg.conf"
+#endif
+#ifndef PROJECTROOT
+#define PROJECTROOT "/usr/X11R6"
+#endif
+#ifndef XCONFENV
+#define XCONFENV "XF86CONFIG"
+#endif
+#define XFREE86CFGFILE "XF86Config"
+#ifndef X_VERSION_MAJOR
+#ifdef XVERSION
+#if XVERSION > 40000000
+#define X_VERSION_MAJOR (XVERSION / 10000000)
+#else
+#define X_VERSION_MAJOR (XVERSION / 1000)
+#endif
+#else
+#define X_VERSION_MAJOR 4
+#endif
+#endif
+
+#define BAIL_OUT do { \
+ free(result); \
+ return NULL; \
+ } while (0)
+
+#define CHECK_LENGTH do { \
+ if (l > PATH_MAX) { \
+ BAIL_OUT; \
+ } \
+ } while (0)
+
+#define APPEND_STR(s) do { \
+ if (strlen(s) + l > PATH_MAX) { \
+ BAIL_OUT; \
+ } else { \
+ strcpy(result + l, s); \
+ l += strlen(s); \
+ } \
+ } while (0)
+
+static char *DoSubstitution(const char *template,
+ const char *cmdline,
+ const char *projroot,
+ int *cmdlineUsed, int *envUsed, char *XConfigFile)
+{
+ char *result;
+ int i, l;
+ static const char *env = NULL, *home = NULL;
+ static char *hostname = NULL;
+ static char majorvers[3] = "";
+
+ if (!template)
+ return NULL;
+
+ if (cmdlineUsed)
+ *cmdlineUsed = 0;
+ if (envUsed)
+ *envUsed = 0;
+
+ result = malloc(PATH_MAX + 1);
+ l = 0;
+ for (i = 0; template[i]; i++) {
+ if (template[i] != '%') {
+ result[l++] = template[i];
+ CHECK_LENGTH;
+ } else {
+ switch (template[++i]) {
+ case 'A':
+ if (cmdline && pathIsAbsolute(cmdline)) {
+ APPEND_STR(cmdline);
+ if (cmdlineUsed)
+ *cmdlineUsed = 1;
+ } else
+ BAIL_OUT;
+ break;
+ case 'R':
+ if (cmdline && !pathIsAbsolute(cmdline)) {
+ APPEND_STR(cmdline);
+ if (cmdlineUsed)
+ *cmdlineUsed = 1;
+ } else
+ BAIL_OUT;
+ break;
+ case 'S':
+ if (cmdline && pathIsSafe(cmdline)) {
+ APPEND_STR(cmdline);
+ if (cmdlineUsed)
+ *cmdlineUsed = 1;
+ } else
+ BAIL_OUT;
+ break;
+ case 'X':
+ APPEND_STR(XConfigFile);
+ break;
+ case 'H':
+ if (!hostname) {
+ if ((hostname = malloc(MAXHOSTNAMELEN + 1))) {
+ if (gethostname(hostname, MAXHOSTNAMELEN) == 0) {
+ hostname[MAXHOSTNAMELEN] = '\0';
+ } else {
+ free(hostname);
+ hostname = NULL;
+ }
+ }
+ }
+ if (hostname)
+ APPEND_STR(hostname);
+ break;
+ case 'E':
+ if (!env)
+ env = getenv(XCONFENV);
+ if (env && pathIsAbsolute(env)) {
+ APPEND_STR(env);
+ if (envUsed)
+ *envUsed = 1;
+ } else
+ BAIL_OUT;
+ break;
+ case 'F':
+ if (!env)
+ env = getenv(XCONFENV);
+ if (env && !pathIsAbsolute(env)) {
+ APPEND_STR(env);
+ if (envUsed)
+ *envUsed = 1;
+ } else
+ BAIL_OUT;
+ break;
+ case 'G':
+ if (!env)
+ env = getenv(XCONFENV);
+ if (env && pathIsSafe(env)) {
+ APPEND_STR(env);
+ if (envUsed)
+ *envUsed = 1;
+ } else
+ BAIL_OUT;
+ break;
+ case 'D':
+ if (!home)
+ home = getenv("HOME");
+ if (home && pathIsAbsolute(home))
+ APPEND_STR(home);
+ else
+ BAIL_OUT;
+ break;
+ case 'P':
+ if (projroot && pathIsAbsolute(projroot))
+ APPEND_STR(projroot);
+ else
+ BAIL_OUT;
+ break;
+ case 'M':
+ if (!majorvers[0]) {
+ sprintf(majorvers, "%d", X_VERSION_MAJOR);
+ }
+ APPEND_STR(majorvers);
+ break;
+ case '%':
+ result[l++] = '%';
+ CHECK_LENGTH;
+ break;
+ default:
+ xconfigErrorMsg(InternalErrorMsg,
+ "invalid escape %%%c found in path template\n",
+ template[i]);
+ BAIL_OUT;
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+/*
+ * xconfigOpenConfigFile --
+ *
+ * This function takes a config file search path (optional), a
+ * command-line specified file name (optional) and the ProjectRoot
+ * path (optional) and locates and opens a config file based on that
+ * information. If a command-line file name is specified, then this
+ * function fails if none of the located files.
+ *
+ * The return value is a pointer to the actual name of the file that
+ * was opened. When no file is found, the return value is NULL.
+ *
+ * The escape sequences allowed in the search path are defined above.
+ *
+ */
+
+
+/*
+ * __root_configpath[] - this is the XconfigConfig search path used by
+ * XFree86 when the server runs as root.
+ */
+
+static const char __root_configpath[] =
+"%A," /* <cmdline> */
+"%R," /* <cmdline> (as relative path) */
+"/etc/X11/%R," /* /etc/X11/<cmdline> */
+"%P/etc/X11/%R," /* /usr/X11R6/etc/X11/<cmdline> */
+"%E," /* $XF86CONFIG */
+"%F," /* $XF86CONFIG (as relative path) */
+"/etc/X11/%F," /* /etc/X11/$XF86CONFIG */
+"%P/etc/X11/%F," /* /usr/X11R6/etc/X11/$XF86CONFIG */
+"%D/%X," /* $HOME/XF86Config */
+"/etc/X11/%X-%M," /* /etc/X11/XF86Config-4 */
+"/etc/X11/%X," /* /etc/X11/XF86Config */
+"/etc/%X," /* /etc/XF86Config */
+"%P/etc/X11/%X.%H," /* /usr/X11R6/etc/X11/XF86Config.<hostname> */
+"%P/etc/X11/%X-%M," /* /usr/X11R6/etc/X11/XF86Config-4 */
+"%P/etc/X11/%X," /* /usr/X11R6/etc/X11/XF86Config */
+"%P/lib/X11/%X.%H," /* /usr/X11R6/lib/X11/XF86Config.<hostname> */
+"%P/lib/X11/%X-%M," /* /usr/X11R6/lib/X11/XF86Config-4 */
+"%P/lib/X11/%X"; /* /usr/X11R6/lib/X11/XF86Config */
+
+
+
+/*
+ * __user_configpath[] - this is the XF86Config search path used by
+ * XFree86 when the server runs as a normal user
+ */
+
+static const char __user_configpath[] =
+"%A," /* <cmdline> XXX */
+"%R," /* <cmdline> (as relative path) XXX */
+"/etc/X11/%S," /* /etc/X11/<cmdline> */
+"%P/etc/X11/%S," /* /usr/X11R6/etc/X11/<cmdline> */
+"/etc/X11/%G," /* /etc/X11/$XF86CONFIG */
+"%P/etc/X11/%G," /* /usr/X11R6/etc/X11/$XF86CONFIG */
+"/etc/X11/%X-%M," /* /etc/X11/XF86Config-4 */
+"/etc/X11/%X," /* /etc/X11/XF86Config */
+"/etc/%X," /* /etc/XF86Config */
+"%P/etc/X11/%X.%H," /* /usr/X11R6/etc/X11/XF86Config.<hostname> */
+"%P/etc/X11/%X-%M," /* /usr/X11R6/etc/X11/XF86Config-4 */
+"%P/etc/X11/%X," /* /usr/X11R6/etc/X11/XF86Config */
+"%P/lib/X11/%X.%H," /* /usr/X11R6/lib/X11/XF86Config.<hostname> */
+"%P/lib/X11/%X-%M," /* /usr/X11R6/lib/X11/XF86Config-4 */
+"%P/lib/X11/%X"; /* /usr/X11R6/lib/X11/XF86Config */
+
+
+
+const char *xconfigOpenConfigFile(const char *cmdline, const char *projroot)
+{
+ const char *searchpath;
+ char *pathcopy;
+ const char *template;
+ int cmdlineUsed = 0;
+
+ configFile = NULL;
+ configPos = 0; /* current readers position */
+ configLineNo = 0; /* linenumber */
+ pushToken = LOCK_TOKEN;
+
+ /*
+ * select the search path: XFree86 uses a slightly different path
+ * depending on whether the user is root
+ */
+
+ if (getuid() == 0) {
+ searchpath = __root_configpath;
+ } else {
+ searchpath = __user_configpath;
+ }
+
+ if (!projroot) projroot = PROJECTROOT;
+
+ pathcopy = strdup(searchpath);
+
+ template = strtok(pathcopy, ",");
+
+ /* First, search for a config file. */
+ while (template && !configFile) {
+ if ((configPath = DoSubstitution(template, cmdline, projroot,
+ &cmdlineUsed, NULL, XCONFIGFILE))) {
+ if ((configFile = fopen(configPath, "r")) != 0) {
+ if (cmdline && !cmdlineUsed) {
+ fclose(configFile);
+ configFile = NULL;
+ }
+ }
+ }
+ if (configPath && !configFile) {
+ free(configPath);
+ configPath = NULL;
+ }
+ template = strtok(NULL, ",");
+ }
+
+ /* Then search for fallback */
+ if (!configFile) {
+ strcpy(pathcopy, searchpath);
+ template = strtok(pathcopy, ",");
+
+ while (template && !configFile) {
+ if ((configPath = DoSubstitution(template, cmdline, projroot,
+ &cmdlineUsed, NULL,
+ XFREE86CFGFILE))) {
+ if ((configFile = fopen(configPath, "r")) != 0) {
+ if (cmdline && !cmdlineUsed) {
+ fclose(configFile);
+ configFile = NULL;
+ }
+ }
+ }
+ if (configPath && !configFile) {
+ free(configPath);
+ configPath = NULL;
+ }
+ template = strtok(NULL, ",");
+ }
+ }
+
+ free(pathcopy);
+
+ if (!configFile) {
+ return NULL;
+ }
+
+ configBuf = malloc(CONFIG_BUF_LEN);
+ configRBuf = malloc(CONFIG_BUF_LEN);
+ configBuf[0] = '\0';
+
+ return configPath;
+}
+
+void xconfigCloseConfigFile (void)
+{
+ free (configPath);
+ configPath = NULL;
+ free (configRBuf);
+ configRBuf = NULL;
+ free (configBuf);
+ configBuf = NULL;
+
+ if (configFile) {
+ fclose (configFile);
+ configFile = NULL;
+ } else {
+ builtinConfig = NULL;
+ builtinIndex = 0;
+ }
+}
+
+
+char *xconfigGetConfigFileName(void)
+{
+ return configPath;
+}
+
+
+void
+xconfigSetSection (char *section)
+{
+ if (configSection)
+ free(configSection);
+ configSection = malloc(strlen (section) + 1);
+ strcpy (configSection, section);
+}
+
+/*
+ * xconfigGetToken --
+ * Lookup a string if it is actually a token in disguise.
+ */
+
+
+char *
+xconfigAddComment(char *cur, char *add)
+{
+ char *str;
+ int len, curlen, iscomment, hasnewline = 0, endnewline;
+
+ if (add == NULL || add[0] == '\0')
+ return (cur);
+
+ if (cur) {
+ curlen = strlen(cur);
+ if (curlen)
+ hasnewline = cur[curlen - 1] == '\n';
+ eol_seen = 0;
+ }
+ else
+ curlen = 0;
+
+ str = add;
+ iscomment = 0;
+ while (*str) {
+ if (*str != ' ' && *str != '\t')
+ break;
+ ++str;
+ }
+ iscomment = (*str == '#');
+
+ len = strlen(add);
+ endnewline = add[len - 1] == '\n';
+ len += 1 + iscomment + (!hasnewline) + (!endnewline) + eol_seen;
+
+ if ((str = realloc(cur, len + curlen)) == NULL)
+ return (cur);
+
+ cur = str;
+
+ if (eol_seen || (curlen && !hasnewline))
+ cur[curlen++] = '\n';
+ if (!iscomment)
+ cur[curlen++] = '#';
+ strcpy(cur + curlen, add);
+ if (!endnewline)
+ strcat(cur, "\n");
+
+ return (cur);
+}
+
+int
+xconfigGetStringToken (XConfigSymTabRec * tab)
+{
+ return StringToToken (val.str, tab);
+}
+
+static int
+StringToToken (char *str, XConfigSymTabRec * tab)
+{
+ int i;
+
+ for (i = 0; tab[i].token != -1; i++)
+ {
+ if (!xconfigNameCompare (tab[i].name, str))
+ return tab[i].token;
+ }
+ return (ERROR_TOKEN);
+}
+
+
+/*
+ * Compare two names. The characters '_', ' ', and '\t' are ignored
+ * in the comparison.
+ */
+int
+xconfigNameCompare (const char *s1, const char *s2)
+{
+ char c1, c2;
+
+ if (!s1 || *s1 == 0) {
+ if (!s2 || *s2 == 0)
+ return (0);
+ else
+ return (1);
+ }
+
+ while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
+ s1++;
+ while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
+ s2++;
+ c1 = (xconfigIsUpper(*s1) ? xconfigToLower(*s1) : *s1);
+ c2 = (xconfigIsUpper(*s2) ? xconfigToLower(*s2) : *s2);
+ while (c1 == c2)
+ {
+ if (c1 == '\0')
+ return (0);
+ s1++;
+ s2++;
+ while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
+ s1++;
+ while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
+ s2++;
+ c1 = (xconfigIsUpper(*s1) ? xconfigToLower(*s1) : *s1);
+ c2 = (xconfigIsUpper(*s2) ? xconfigToLower(*s2) : *s2);
+ }
+ return (c1 - c2);
+}
+
+/*
+ * Compare two modelines. The modeline identifiers and comments are
+ * ignored in the comparison.
+ */
+int
+xconfigModelineCompare(XConfigModeLinePtr m1, XConfigModeLinePtr m2)
+{
+ if (!m1 && !m2)
+ return (0);
+
+ if (!m1 || !m2)
+ return (1);
+
+ if (m1->clock != m2->clock &&
+ m1->hdisplay != m2->hdisplay &&
+ m1->hsyncstart != m2->hsyncstart &&
+ m1->hsyncend != m2->hsyncend &&
+ m1->htotal != m2->htotal &&
+ m1->vdisplay != m2->vdisplay &&
+ m1->vsyncstart != m2->vsyncstart &&
+ m1->vsyncend != m2->vsyncend &&
+ m1->vtotal != m2->vtotal &&
+ m1->vscan != m2->vscan &&
+ m1->flags != m2->flags &&
+ m1->hskew != m2->hskew)
+ return (1);
+ return (0);
+}
diff --git a/src/XF86Config-parser/Screen.c b/src/XF86Config-parser/Screen.c
new file mode 100644
index 0000000..f58d76b
--- /dev/null
+++ b/src/XF86Config-parser/Screen.c
@@ -0,0 +1,679 @@
+/*
+ *
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec DisplayTab[] =
+{
+ {ENDSUBSECTION, "endsubsection"},
+ {MODES, "modes"},
+ {VIEWPORT, "viewport"},
+ {VIRTUAL, "virtual"},
+ {VISUAL, "visual"},
+ {BLACK_TOK, "black"},
+ {WHITE_TOK, "white"},
+ {DEPTH, "depth"},
+ {BPP, "fbbpp"},
+ {WEIGHT, "weight"},
+ {OPTION, "option"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeDisplayList
+
+XConfigDisplayPtr
+xconfigParseDisplaySubSection (void)
+{
+ int token;
+ PARSE_PROLOGUE (XConfigDisplayPtr, XConfigDisplayRec)
+
+ ptr->black.red = ptr->black.green = ptr->black.blue = -1;
+ ptr->white.red = ptr->white.green = ptr->white.blue = -1;
+ ptr->frameX0 = ptr->frameY0 = -1;
+ while ((token = xconfigGetToken (DisplayTab)) != ENDSUBSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case VIEWPORT:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (VIEWPORT_MSG, NULL);
+ ptr->frameX0 = val.num;
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (VIEWPORT_MSG, NULL);
+ ptr->frameY0 = val.num;
+ break;
+ case VIRTUAL:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (VIRTUAL_MSG, NULL);
+ ptr->virtualX = val.num;
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (VIRTUAL_MSG, NULL);
+ ptr->virtualY = val.num;
+ break;
+ case DEPTH:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "Display");
+ ptr->depth = val.num;
+ break;
+ case BPP:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "Display");
+ ptr->bpp = val.num;
+ break;
+ case VISUAL:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Display");
+ ptr->visual = val.str;
+ break;
+ case WEIGHT:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (WEIGHT_MSG, NULL);
+ ptr->weight.red = val.num;
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (WEIGHT_MSG, NULL);
+ ptr->weight.green = val.num;
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (WEIGHT_MSG, NULL);
+ ptr->weight.blue = val.num;
+ break;
+ case BLACK_TOK:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (BLACK_MSG, NULL);
+ ptr->black.red = val.num;
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (BLACK_MSG, NULL);
+ ptr->black.green = val.num;
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (BLACK_MSG, NULL);
+ ptr->black.blue = val.num;
+ break;
+ case WHITE_TOK:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (WHITE_MSG, NULL);
+ ptr->white.red = val.num;
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (WHITE_MSG, NULL);
+ ptr->white.green = val.num;
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (WHITE_MSG, NULL);
+ ptr->white.blue = val.num;
+ break;
+ case MODES:
+ {
+ XConfigModePtr mptr;
+
+ while ((token =
+ xconfigGetSubTokenWithTab(&(ptr->comment),
+ DisplayTab)) == STRING)
+ {
+ mptr = calloc (1, sizeof (XConfigModeRec));
+ mptr->mode_name = val.str;
+ mptr->next = NULL;
+ ptr->modes = (XConfigModePtr)
+ xconfigAddListItem ((GenericListPtr) ptr->modes,
+ (GenericListPtr) mptr);
+ }
+ xconfigUnGetToken (token);
+ }
+ break;
+ case OPTION:
+ ptr->options = xconfigParseOption(ptr->options);
+ break;
+
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+static XConfigSymTabRec ScreenTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {IDENTIFIER, "identifier"},
+ {OBSDRIVER, "driver"},
+ {MDEVICE, "device"},
+ {MONITOR, "monitor"},
+ {VIDEOADAPTOR, "videoadaptor"},
+ {SCREENNO, "screenno"},
+ {SUBSECTION, "subsection"},
+ {DEFAULTDEPTH, "defaultcolordepth"},
+ {DEFAULTDEPTH, "defaultdepth"},
+ {DEFAULTBPP, "defaultbpp"},
+ {DEFAULTFBBPP, "defaultfbbpp"},
+ {OPTION, "option"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeScreenList
+XConfigScreenPtr
+xconfigParseScreenSection (void)
+{
+ int has_ident = FALSE;
+ int has_driver= FALSE;
+ int token;
+
+ PARSE_PROLOGUE (XConfigScreenPtr, XConfigScreenRec)
+
+ while ((token = xconfigGetToken (ScreenTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ if (has_ident || has_driver)
+ Error (ONLY_ONE_MSG,"Identifier or Driver");
+ has_ident = TRUE;
+ break;
+ case OBSDRIVER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Driver");
+ ptr->obsolete_driver = val.str;
+ if (has_ident || has_driver)
+ Error (ONLY_ONE_MSG,"Identifier or Driver");
+ has_driver = TRUE;
+ break;
+ case DEFAULTDEPTH:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "DefaultDepth");
+ ptr->defaultdepth = val.num;
+ break;
+ case DEFAULTBPP:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "DefaultBPP");
+ ptr->defaultbpp = val.num;
+ break;
+ case DEFAULTFBBPP:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "DefaultFbBPP");
+ ptr->defaultfbbpp = val.num;
+ break;
+ case MDEVICE:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Device");
+ ptr->device_name = val.str;
+ break;
+ case MONITOR:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Monitor");
+ ptr->monitor_name = val.str;
+ break;
+ case VIDEOADAPTOR:
+ {
+ XConfigAdaptorLinkPtr aptr;
+
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "VideoAdaptor");
+
+ /* Don't allow duplicates */
+ for (aptr = ptr->adaptors; aptr;
+ aptr = (XConfigAdaptorLinkPtr) aptr->next)
+ if (xconfigNameCompare (val.str, aptr->adaptor_name) == 0)
+ break;
+
+ if (aptr == NULL)
+ {
+ aptr = calloc (1, sizeof (XConfigAdaptorLinkRec));
+ aptr->next = NULL;
+ aptr->adaptor_name = val.str;
+ ptr->adaptors = (XConfigAdaptorLinkPtr)
+ xconfigAddListItem ((GenericListPtr) ptr->adaptors,
+ (GenericListPtr) aptr);
+ }
+ }
+ break;
+ case OPTION:
+ ptr->options = xconfigParseOption(ptr->options);
+ break;
+ case SUBSECTION:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "SubSection");
+ {
+ free(val.str);
+ HANDLE_LIST (displays, xconfigParseDisplaySubSection,
+ XConfigDisplayPtr);
+ }
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ if (!has_ident && !has_driver)
+ Error (NO_IDENT_MSG, NULL);
+
+ return ptr;
+}
+
+void
+xconfigPrintScreenSection (FILE * cf, XConfigScreenPtr ptr)
+{
+ XConfigAdaptorLinkPtr aptr;
+ XConfigDisplayPtr dptr;
+ XConfigModePtr mptr;
+
+ while (ptr)
+ {
+ fprintf (cf, "Section \"Screen\"\n");
+ if (ptr->comment)
+ fprintf (cf, "%s", ptr->comment);
+ if (ptr->identifier)
+ fprintf (cf, " Identifier \"%s\"\n", ptr->identifier);
+ if (ptr->obsolete_driver)
+ fprintf (cf, " Driver \"%s\"\n", ptr->obsolete_driver);
+ if (ptr->device_name)
+ fprintf (cf, " Device \"%s\"\n", ptr->device_name);
+ if (ptr->monitor_name)
+ fprintf (cf, " Monitor \"%s\"\n", ptr->monitor_name);
+ if (ptr->defaultdepth)
+ fprintf (cf, " DefaultDepth %d\n",
+ ptr->defaultdepth);
+ if (ptr->defaultbpp)
+ fprintf (cf, " DefaultBPP %d\n",
+ ptr->defaultbpp);
+ if (ptr->defaultfbbpp)
+ fprintf (cf, " DefaultFbBPP %d\n",
+ ptr->defaultfbbpp);
+ xconfigPrintOptionList(cf, ptr->options, 1);
+ for (aptr = ptr->adaptors; aptr; aptr = aptr->next)
+ {
+ fprintf (cf, " VideoAdaptor \"%s\"\n", aptr->adaptor_name);
+ }
+ for (dptr = ptr->displays; dptr; dptr = dptr->next)
+ {
+ fprintf (cf, " SubSection \"Display\"\n");
+ if (dptr->comment)
+ fprintf (cf, "%s", dptr->comment);
+ if (dptr->frameX0 >= 0 || dptr->frameY0 >= 0)
+ {
+ fprintf (cf, " Viewport %d %d\n",
+ dptr->frameX0, dptr->frameY0);
+ }
+ if (dptr->virtualX != 0 || dptr->virtualY != 0)
+ {
+ fprintf (cf, " Virtual %d %d\n",
+ dptr->virtualX, dptr->virtualY);
+ }
+ if (dptr->depth)
+ {
+ fprintf (cf, " Depth %d\n", dptr->depth);
+ }
+ if (dptr->bpp)
+ {
+ fprintf (cf, " FbBPP %d\n", dptr->bpp);
+ }
+ if (dptr->visual)
+ {
+ fprintf (cf, " Visual \"%s\"\n", dptr->visual);
+ }
+ if (dptr->weight.red != 0)
+ {
+ fprintf (cf, " Weight %d %d %d\n",
+ dptr->weight.red, dptr->weight.green, dptr->weight.blue);
+ }
+ if (dptr->black.red != -1)
+ {
+ fprintf (cf, " Black 0x%04x 0x%04x 0x%04x\n",
+ dptr->black.red, dptr->black.green, dptr->black.blue);
+ }
+ if (dptr->white.red != -1)
+ {
+ fprintf (cf, " White 0x%04x 0x%04x 0x%04x\n",
+ dptr->white.red, dptr->white.green, dptr->white.blue);
+ }
+ if (dptr->modes)
+ {
+ fprintf (cf, " Modes ");
+ }
+ for (mptr = dptr->modes; mptr; mptr = mptr->next)
+ {
+ fprintf (cf, " \"%s\"", mptr->mode_name);
+ }
+ if (dptr->modes)
+ {
+ fprintf (cf, "\n");
+ }
+ xconfigPrintOptionList(cf, dptr->options, 2);
+ fprintf (cf, " EndSubSection\n");
+ }
+ fprintf (cf, "EndSection\n\n");
+ ptr = ptr->next;
+ }
+
+}
+
+void
+xconfigFreeScreenList (XConfigScreenPtr ptr)
+{
+ XConfigScreenPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->identifier);
+ TEST_FREE (ptr->monitor_name);
+ TEST_FREE (ptr->device_name);
+ TEST_FREE (ptr->comment);
+ xconfigOptionListFree (ptr->options);
+ xconfigFreeAdaptorLinkList (ptr->adaptors);
+ xconfigFreeDisplayList (ptr->displays);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+void
+xconfigFreeAdaptorLinkList (XConfigAdaptorLinkPtr ptr)
+{
+ XConfigAdaptorLinkPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->adaptor_name);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+void
+xconfigFreeDisplayList (XConfigDisplayPtr ptr)
+{
+ XConfigDisplayPtr prev;
+
+ while (ptr)
+ {
+ xconfigFreeModeList (ptr->modes);
+ xconfigOptionListFree (ptr->options);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+void
+xconfigFreeModeList (XConfigModePtr ptr)
+{
+ XConfigModePtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->mode_name);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+int
+xconfigValidateScreen (XConfigPtr p)
+{
+ XConfigScreenPtr screen = p->screens;
+ XConfigMonitorPtr monitor;
+ XConfigDevicePtr device;
+ XConfigAdaptorLinkPtr adaptor;
+
+ if (!screen)
+ {
+ xconfigErrorMsg(ValidationErrorMsg, "At least one Screen section "
+ "is required.");
+ return (FALSE);
+ }
+
+ while (screen)
+ {
+ if (screen->obsolete_driver && !screen->identifier)
+ screen->identifier = screen->obsolete_driver;
+
+ monitor = xconfigFindMonitor (screen->monitor_name, p->monitors);
+ if (screen->monitor_name)
+ {
+ if (!monitor)
+ {
+ xconfigErrorMsg(ValidationErrorMsg, UNDEFINED_MONITOR_MSG,
+ screen->monitor_name, screen->identifier);
+ return (FALSE);
+ }
+ else
+ {
+ screen->monitor = monitor;
+ if (!xconfigValidateMonitor(p, screen))
+ return (FALSE);
+ }
+ }
+
+ device = xconfigFindDevice (screen->device_name, p->devices);
+ if (!device)
+ {
+ xconfigErrorMsg(ValidationErrorMsg, UNDEFINED_DEVICE_MSG,
+ screen->device_name, screen->identifier);
+ return (FALSE);
+ }
+ else
+ screen->device = device;
+
+ adaptor = screen->adaptors;
+ while (adaptor) {
+ adaptor->adaptor = xconfigFindVideoAdaptor(adaptor->adaptor_name,
+ p->videoadaptors);
+ if (!adaptor->adaptor) {
+ xconfigErrorMsg(ValidationErrorMsg, UNDEFINED_ADAPTOR_MSG,
+ adaptor->adaptor_name,
+ screen->identifier);
+ return (FALSE);
+ } else if (adaptor->adaptor->fwdref) {
+ xconfigErrorMsg(ValidationErrorMsg, ADAPTOR_REF_TWICE_MSG,
+ adaptor->adaptor_name,
+ adaptor->adaptor->fwdref);
+ return (FALSE);
+ }
+
+ adaptor->adaptor->fwdref = xconfigStrdup(screen->identifier);
+ adaptor = adaptor->next;
+ }
+
+ screen = screen->next;
+ }
+
+ return (TRUE);
+}
+
+int xconfigSanitizeScreen(XConfigPtr p)
+{
+ XConfigScreenPtr screen = p->screens;
+ XConfigMonitorPtr monitor;
+
+ while (screen) {
+
+ /*
+ * if no monitor for this screen (either the monitor name, or
+ * the actual monitor pointer), find a monitor: resolve
+ * discrepancies between screen->monitor_name and
+ * screen->monitor; otherwise use the first monitor in the
+ * config; if we still don't have a monitor, add a new one
+ */
+
+ if (!screen->monitor_name || !screen->monitor) {
+
+ monitor = NULL;
+
+ if (!monitor && screen->monitor) {
+ monitor = screen->monitor;
+ }
+
+ if (!monitor && screen->monitor_name) {
+ monitor = xconfigFindMonitor(screen->monitor_name,
+ p->monitors);
+ }
+
+ if (!monitor && p->monitors) {
+ monitor = p->monitors;
+ }
+
+ if (!monitor) {
+ monitor = xconfigAddMonitor(p, 0);
+ }
+
+ if (monitor) {
+ screen->monitor = monitor;
+
+ if (screen->monitor_name) {
+ free(screen->monitor_name);
+ }
+
+ screen->monitor_name = xconfigStrdup(monitor->identifier);
+
+ if (!xconfigValidateMonitor(p, screen))
+ return (FALSE);
+ }
+ }
+
+ screen = screen->next;
+ }
+
+ return TRUE;
+}
+
+
+
+XConfigScreenPtr
+xconfigFindScreen (const char *ident, XConfigScreenPtr p)
+{
+ while (p)
+ {
+ if (xconfigNameCompare (ident, p->identifier) == 0)
+ return (p);
+
+ p = p->next;
+ }
+ return (NULL);
+}
+
+XConfigModePtr
+xconfigFindMode (const char *name, XConfigModePtr p)
+{
+ while (p)
+ {
+ if (xconfigNameCompare (name, p->mode_name) == 0)
+ return (p);
+
+ p = p->next;
+ }
+ return (NULL);
+}
+
+XConfigModePtr
+xconfigAddMode(XConfigModePtr head, const char *name)
+{
+ XConfigModePtr mode;
+
+ mode = xconfigAlloc(sizeof(XConfigModeRec));
+ mode->mode_name = xconfigStrdup(name);
+
+ mode->next = head;
+
+ return mode;
+
+}
+
+
+XConfigModePtr
+xconfigRemoveMode(XConfigModePtr head, const char *name)
+{
+ XConfigModePtr prev = NULL;
+ XConfigModePtr m = head;
+
+ while (m) {
+ if (xconfigNameCompare(m->mode_name, name) == 0) {
+ if (prev) prev->next = m->next;
+ if (head == m) head = m->next;
+ free(m->mode_name);
+ free(m);
+ break;
+ }
+ prev = m;
+ m = m->next;
+ }
+
+ return head;
+}
+
+
+
diff --git a/src/XF86Config-parser/Util.c b/src/XF86Config-parser/Util.c
new file mode 100644
index 0000000..f149afa
--- /dev/null
+++ b/src/XF86Config-parser/Util.c
@@ -0,0 +1,185 @@
+/*
+ * nvidia-xconfig: A tool for manipulating X config files,
+ * specifically for use by the NVIDIA Linux graphics driver.
+ *
+ * Copyright (C) 2005 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ * Util.c
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "xf86Parser.h"
+#include "Configint.h"
+
+void *xconfigAlloc(size_t size)
+{
+ void *m = malloc(size);
+
+ if (!m) {
+ fprintf(stderr, "memory allocation failure (%s)! \n", strerror(errno));
+ exit(1);
+ }
+ memset((char *) m, 0, size);
+ return m;
+
+} /* xconfigAlloc() */
+
+
+/*
+ * xconfigStrdup() - wrapper for strdup() that checks the return
+ * value; if an error occurs, an error is printed to stderr and exit
+ * is called -- this function will only return on success.
+ */
+
+char *xconfigStrdup(const char *s)
+{
+ char *m;
+
+ if (!s) return NULL;
+
+ m = strdup(s);
+
+ if (!m) {
+ fprintf(stderr, "memory allocation failure during strdup (%s)! \n",
+ strerror(errno));
+ exit(1);
+ }
+ return m;
+
+} /* xconfigStrdup() */
+
+
+/*
+ * xconfigStrcat() - allocate a new string, copying all given strings
+ * into it. taken from glib
+ */
+
+char *xconfigStrcat(const char *str, ...)
+{
+ unsigned int l;
+ va_list args;
+ char *s;
+ char *concat;
+
+ l = 1 + strlen(str);
+ va_start(args, str);
+ s = va_arg(args, char *);
+
+ while (s) {
+ l += strlen(s);
+ s = va_arg(args, char *);
+ }
+ va_end(args);
+
+ concat = xconfigAlloc(l);
+ concat[0] = 0;
+
+ strcat(concat, str);
+ va_start(args, str);
+ s = va_arg(args, char *);
+ while (s) {
+ strcat(concat, s);
+ s = va_arg(args, char *);
+ }
+ va_end(args);
+
+ return concat;
+
+} /* xconfigStrcat() */
+
+
+
+
+
+
+#define NV_FMT_BUF_LEN 64
+
+extern int configLineNo;
+extern char *configSection;
+extern char *configPath;
+
+void xconfigErrorMsg(MsgType t, char *fmt, ...)
+{
+ va_list ap;
+ int len, current_len = NV_FMT_BUF_LEN;
+ char *b, *pre = NULL, *msg;
+ char scratch[64];
+
+ b = xconfigAlloc(current_len);
+
+ while (1) {
+ va_start(ap, fmt);
+ len = vsnprintf(b, current_len, fmt, ap);
+ va_end(ap);
+
+ if ((len > -1) && (len < current_len)) {
+ break;
+ } else if (len > -1) {
+ current_len = len + 1;
+ } else {
+ current_len += NV_FMT_BUF_LEN;
+ }
+
+ free(b);
+ b = xconfigAlloc(current_len);
+ }
+
+ switch (t) {
+ case ParseErrorMsg:
+ sprintf(scratch, "%d", configLineNo);
+ pre = xconfigStrcat("Parse error on line ", scratch, " of section ",
+ configSection, " in file ", configPath, ".\n", NULL);
+ break;
+ case ParseWarningMsg:
+ sprintf(scratch, "%d", configLineNo);
+ pre = xconfigStrcat("Parse warning on line ", scratch, " of section ",
+ configSection, " in file ", configPath, ".\n", NULL);
+ break;
+ case ValidationErrorMsg:
+ pre = xconfigStrcat("Data incomplete in file ", configPath, ".\n", NULL);
+ break;
+ case InternalErrorMsg: break;
+ case WriteErrorMsg: break;
+ case WarnMsg: break;
+ case ErrorMsg: break;
+ case DebugMsg: break;
+ case UnknownMsg: break;
+ }
+
+ if (pre) {
+ msg = xconfigStrcat(pre, b, NULL);
+ } else {
+ msg = strdup(b);
+ }
+
+ /* call back into the host to print the message */
+
+ xconfigPrint(t, msg);
+
+
+ free(b);
+ free(msg);
+ if (pre) free(pre);
+}
diff --git a/src/XF86Config-parser/Vendor.c b/src/XF86Config-parser/Vendor.c
new file mode 100644
index 0000000..7f6beba
--- /dev/null
+++ b/src/XF86Config-parser/Vendor.c
@@ -0,0 +1,245 @@
+/*
+ *
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec VendorSubTab[] =
+{
+ {ENDSUBSECTION, "endsubsection"},
+ {IDENTIFIER, "identifier"},
+ {OPTION, "option"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeVendorSubList
+
+XConfigVendSubPtr
+xconfigParseVendorSubSection (void)
+{
+ int has_ident = FALSE;
+ int token;
+ PARSE_PROLOGUE (XConfigVendSubPtr, XConfigVendSubRec)
+
+ while ((token = xconfigGetToken (VendorSubTab)) != ENDSUBSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xconfigGetSubToken (&(ptr->comment)))
+ Error (QUOTE_MSG, "Identifier");
+ if (has_ident == TRUE)
+ Error (MULTIPLE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ has_ident = TRUE;
+ break;
+ case OPTION:
+ ptr->options = xconfigParseOption(ptr->options);
+ break;
+
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+static XConfigSymTabRec VendorTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {IDENTIFIER, "identifier"},
+ {OPTION, "option"},
+ {SUBSECTION, "subsection"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeVendorList
+
+XConfigVendorPtr
+xconfigParseVendorSection (void)
+{
+ int has_ident = FALSE;
+ int token;
+ PARSE_PROLOGUE (XConfigVendorPtr, XConfigVendorRec)
+
+ while ((token = xconfigGetToken (VendorTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Identifier");
+ if (has_ident == TRUE)
+ Error (MULTIPLE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ has_ident = TRUE;
+ break;
+ case OPTION:
+ ptr->options = xconfigParseOption(ptr->options);
+ break;
+ case SUBSECTION:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "SubSection");
+ {
+ HANDLE_LIST (subs, xconfigParseVendorSubSection,
+ XConfigVendSubPtr);
+ }
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+
+ }
+
+ if (!has_ident)
+ Error (NO_IDENT_MSG, NULL);
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+void
+xconfigPrintVendorSection (FILE * cf, XConfigVendorPtr ptr)
+{
+ XConfigVendSubPtr pptr;
+
+ while (ptr)
+ {
+ fprintf (cf, "Section \"Vendor\"\n");
+ if (ptr->comment)
+ fprintf (cf, "%s", ptr->comment);
+ if (ptr->identifier)
+ fprintf (cf, " Identifier \"%s\"\n", ptr->identifier);
+
+ xconfigPrintOptionList(cf, ptr->options, 1);
+ for (pptr = ptr->subs; pptr; pptr = pptr->next)
+ {
+ fprintf (cf, " SubSection \"Vendor\"\n");
+ if (pptr->comment)
+ fprintf (cf, "%s", pptr->comment);
+ if (pptr->identifier)
+ fprintf (cf, " Identifier \"%s\"\n", pptr->identifier);
+ xconfigPrintOptionList(cf, pptr->options, 2);
+ fprintf (cf, " EndSubSection\n");
+ }
+ fprintf (cf, "EndSection\n\n");
+ ptr = ptr->next;
+ }
+}
+
+void
+xconfigFreeVendorList (XConfigVendorPtr p)
+{
+ if (p == NULL)
+ return;
+ xconfigFreeVendorSubList (p->subs);
+ TEST_FREE (p->identifier);
+ TEST_FREE (p->comment);
+ xconfigOptionListFree (p->options);
+ free (p);
+}
+
+void
+xconfigFreeVendorSubList (XConfigVendSubPtr ptr)
+{
+ XConfigVendSubPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->identifier);
+ TEST_FREE (ptr->name);
+ TEST_FREE (ptr->comment);
+ xconfigOptionListFree (ptr->options);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+XConfigVendorPtr
+xconfigFindVendor (const char *name, XConfigVendorPtr list)
+{
+ while (list)
+ {
+ if (xconfigNameCompare (list->identifier, name) == 0)
+ return (list);
+ list = list->next;
+ }
+ return (NULL);
+}
+
diff --git a/src/XF86Config-parser/Video.c b/src/XF86Config-parser/Video.c
new file mode 100644
index 0000000..a09d7f7
--- /dev/null
+++ b/src/XF86Config-parser/Video.c
@@ -0,0 +1,284 @@
+/*
+ *
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec VideoPortTab[] =
+{
+ {ENDSUBSECTION, "endsubsection"},
+ {IDENTIFIER, "identifier"},
+ {OPTION, "option"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeVideoPortList
+
+XConfigVideoPortPtr
+xconfigParseVideoPortSubSection (void)
+{
+ int has_ident = FALSE;
+ int token;
+ PARSE_PROLOGUE (XConfigVideoPortPtr, XConfigVideoPortRec)
+
+ while ((token = xconfigGetToken (VideoPortTab)) != ENDSUBSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Identifier");
+ if (has_ident == TRUE)
+ Error (MULTIPLE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ has_ident = TRUE;
+ break;
+ case OPTION:
+ ptr->options = xconfigParseOption(ptr->options);
+ break;
+
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+static XConfigSymTabRec VideoAdaptorTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {IDENTIFIER, "identifier"},
+ {VENDOR, "vendorname"},
+ {BOARD, "boardname"},
+ {BUSID, "busid"},
+ {DRIVER, "driver"},
+ {OPTION, "option"},
+ {SUBSECTION, "subsection"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeVideoAdaptorList
+
+XConfigVideoAdaptorPtr
+xconfigParseVideoAdaptorSection (void)
+{
+ int has_ident = FALSE;
+ int token;
+
+ PARSE_PROLOGUE (XConfigVideoAdaptorPtr, XConfigVideoAdaptorRec)
+
+ while ((token = xconfigGetToken (VideoAdaptorTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ if (has_ident == TRUE)
+ Error (MULTIPLE_MSG, "Identifier");
+ has_ident = TRUE;
+ break;
+ case VENDOR:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Vendor");
+ ptr->vendor = val.str;
+ break;
+ case BOARD:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Board");
+ ptr->board = val.str;
+ break;
+ case BUSID:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "BusID");
+ ptr->busid = val.str;
+ break;
+ case DRIVER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Driver");
+ ptr->driver = val.str;
+ break;
+ case OPTION:
+ ptr->options = xconfigParseOption(ptr->options);
+ break;
+ case SUBSECTION:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "SubSection");
+ {
+ HANDLE_LIST (ports, xconfigParseVideoPortSubSection,
+ XConfigVideoPortPtr);
+ }
+ break;
+
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ if (!has_ident)
+ Error (NO_IDENT_MSG, NULL);
+
+ return ptr;
+}
+
+void
+xconfigPrintVideoAdaptorSection (FILE * cf, XConfigVideoAdaptorPtr ptr)
+{
+ XConfigVideoPortPtr pptr;
+
+ while (ptr)
+ {
+ fprintf (cf, "Section \"VideoAdaptor\"\n");
+ if (ptr->comment)
+ fprintf (cf, "%s", ptr->comment);
+ if (ptr->identifier)
+ fprintf (cf, " Identifier \"%s\"\n", ptr->identifier);
+ if (ptr->vendor)
+ fprintf (cf, " VendorName \"%s\"\n", ptr->vendor);
+ if (ptr->board)
+ fprintf (cf, " BoardName \"%s\"\n", ptr->board);
+ if (ptr->busid)
+ fprintf (cf, " BusID \"%s\"\n", ptr->busid);
+ if (ptr->driver)
+ fprintf (cf, " Driver \"%s\"\n", ptr->driver);
+ xconfigPrintOptionList(cf, ptr->options, 1);
+ for (pptr = ptr->ports; pptr; pptr = pptr->next)
+ {
+ fprintf (cf, " SubSection \"VideoPort\"\n");
+ if (pptr->comment)
+ fprintf (cf, "%s", pptr->comment);
+ if (pptr->identifier)
+ fprintf (cf, " Identifier \"%s\"\n", pptr->identifier);
+ xconfigPrintOptionList(cf, pptr->options, 2);
+ fprintf (cf, " EndSubSection\n");
+ }
+ fprintf (cf, "EndSection\n\n");
+ ptr = ptr->next;
+ }
+
+}
+
+void
+xconfigFreeVideoAdaptorList (XConfigVideoAdaptorPtr ptr)
+{
+ XConfigVideoAdaptorPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->identifier);
+ TEST_FREE (ptr->vendor);
+ TEST_FREE (ptr->board);
+ TEST_FREE (ptr->busid);
+ TEST_FREE (ptr->driver);
+ TEST_FREE (ptr->fwdref);
+ TEST_FREE (ptr->comment);
+ xconfigFreeVideoPortList (ptr->ports);
+ xconfigOptionListFree (ptr->options);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+void
+xconfigFreeVideoPortList (XConfigVideoPortPtr ptr)
+{
+ XConfigVideoPortPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->identifier);
+ TEST_FREE (ptr->comment);
+ xconfigOptionListFree (ptr->options);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+XConfigVideoAdaptorPtr
+xconfigFindVideoAdaptor (const char *ident, XConfigVideoAdaptorPtr p)
+{
+ while (p)
+ {
+ if (xconfigNameCompare (ident, p->identifier) == 0)
+ return (p);
+
+ p = p->next;
+ }
+ return (NULL);
+}
diff --git a/src/XF86Config-parser/Write.c b/src/XF86Config-parser/Write.c
new file mode 100644
index 0000000..a1658e2
--- /dev/null
+++ b/src/XF86Config-parser/Write.c
@@ -0,0 +1,114 @@
+/*
+ *
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <errno.h>
+
+int xconfigWriteConfigFile (const char *filename, XConfigPtr cptr)
+{
+ FILE *cf;
+
+ if ((cf = fopen(filename, "w")) == NULL)
+ {
+ xconfigErrorMsg(WriteErrorMsg, "Unable to open the file \"%s\" for "
+ "writing (%s).\n", filename, strerror(errno));
+ return FALSE;
+ }
+
+ if (cptr->comment)
+ fprintf (cf, "%s\n", cptr->comment);
+
+ xconfigPrintLayoutSection (cf, cptr->layouts);
+
+ fprintf (cf, "Section \"Files\"\n");
+ xconfigPrintFileSection (cf, cptr->files);
+ fprintf (cf, "EndSection\n\n");
+
+ fprintf (cf, "Section \"Module\"\n");
+ xconfigPrintModuleSection (cf, cptr->modules);
+ fprintf (cf, "EndSection\n\n");
+
+ xconfigPrintVendorSection (cf, cptr->vendors);
+
+ xconfigPrintServerFlagsSection (cf, cptr->flags);
+
+ xconfigPrintInputSection (cf, cptr->inputs);
+
+ xconfigPrintVideoAdaptorSection (cf, cptr->videoadaptors);
+
+ xconfigPrintModesSection (cf, cptr->modes);
+
+ xconfigPrintMonitorSection (cf, cptr->monitors);
+
+ xconfigPrintDeviceSection (cf, cptr->devices);
+
+ xconfigPrintScreenSection (cf, cptr->screens);
+
+ xconfigPrintDRISection (cf, cptr->dri);
+
+ xconfigPrintExtensionsSection (cf, cptr->extensions);
+
+ fclose(cf);
+ return TRUE;
+}
diff --git a/src/XF86Config-parser/configProcs.h b/src/XF86Config-parser/configProcs.h
new file mode 100644
index 0000000..59bac71
--- /dev/null
+++ b/src/XF86Config-parser/configProcs.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 1997-2001 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+/* Private procs. Public procs are in xf86Parser.h and xf86Optrec.h */
+
+#include "xf86Parser.h"
+
+
+/* Device.c */
+XConfigDevicePtr xconfigParseDeviceSection(void);
+void xconfigPrintDeviceSection(FILE *cf, XConfigDevicePtr ptr);
+int xconfigValidateDevice(XConfigPtr p);
+
+/* Files.c */
+XConfigFilesPtr xconfigParseFilesSection(void);
+void xconfigPrintFileSection(FILE *cf, XConfigFilesPtr ptr);
+
+/* Flags.c */
+XConfigFlagsPtr xconfigParseFlagsSection(void);
+void xconfigPrintServerFlagsSection(FILE *f, XConfigFlagsPtr flags);
+
+/* Input.c */
+XConfigInputPtr xconfigParseInputSection(void);
+void xconfigPrintInputSection(FILE *f, XConfigInputPtr ptr);
+int xconfigValidateInput (XConfigPtr p);
+
+/* Keyboard.c */
+XConfigInputPtr xconfigParseKeyboardSection(void);
+
+/* Layout.c */
+XConfigLayoutPtr xconfigParseLayoutSection(void);
+void xconfigPrintLayoutSection(FILE *cf, XConfigLayoutPtr ptr);
+int xconfigValidateLayout(XConfigPtr p);
+int xconfigSanitizeLayout(XConfigPtr p, const char *screenName,
+ GenerateOptions *gop);
+
+/* Module.c */
+XConfigLoadPtr xconfigParseModuleSubSection(XConfigLoadPtr head, char *name);
+XConfigModulePtr xconfigParseModuleSection(void);
+void xconfigPrintModuleSection(FILE *cf, XConfigModulePtr ptr);
+
+/* Monitor.c */
+XConfigModeLinePtr xconfigParseModeLine(void);
+XConfigModeLinePtr xconfigParseVerboseMode(void);
+XConfigMonitorPtr xconfigParseMonitorSection(void);
+XConfigModesPtr xconfigParseModesSection(void);
+void xconfigPrintMonitorSection(FILE *cf, XConfigMonitorPtr ptr);
+void xconfigPrintModesSection(FILE *cf, XConfigModesPtr ptr);
+int xconfigValidateMonitor(XConfigPtr p, XConfigScreenPtr screen);
+
+/* Pointer.c */
+XConfigInputPtr xconfigParsePointerSection(void);
+
+/* Screen.c */
+XConfigDisplayPtr xconfigParseDisplaySubSection(void);
+XConfigScreenPtr xconfigParseScreenSection(void);
+void xconfigPrintScreenSection(FILE *cf, XConfigScreenPtr ptr);
+int xconfigValidateScreen(XConfigPtr p);
+int xconfigSanitizeScreen(XConfigPtr p);
+
+/* Vendor.c */
+XConfigVendorPtr xconfigParseVendorSection(void);
+XConfigVendSubPtr xconfigParseVendorSubSection (void);
+void xconfigPrintVendorSection(FILE * cf, XConfigVendorPtr ptr);
+
+/* Video.c */
+XConfigVideoPortPtr xconfigParseVideoPortSubSection(void);
+XConfigVideoAdaptorPtr xconfigParseVideoAdaptorSection(void);
+void xconfigPrintVideoAdaptorSection(FILE *cf, XConfigVideoAdaptorPtr ptr);
+
+/* Read.c */
+int xconfigValidateConfig(XConfigPtr p);
+
+/* Scan.c */
+int xconfigGetToken(XConfigSymTabRec *tab);
+int xconfigGetSubToken(char **comment);
+int xconfigGetSubTokenWithTab(char **comment, XConfigSymTabRec *tab);
+void xconfigUnGetToken(int token);
+char *xconfigTokenString(void);
+void xconfigSetSection(char *section);
+int xconfigGetStringToken(XConfigSymTabRec *tab);
+char *xconfigGetConfigFileName(void);
+
+/* Write.c */
+
+/* DRI.c */
+XConfigBuffersPtr xconfigParseBuffers (void);
+XConfigDRIPtr xconfigParseDRISection (void);
+void xconfigPrintDRISection (FILE * cf, XConfigDRIPtr ptr);
+
+/* Util.c */
+void *xconfigAlloc(size_t size);
+void xconfigErrorMsg(MsgType, char *fmt, ...);
+
+/* Extensions.c */
+XConfigExtensionsPtr xconfigParseExtensionsSection (void);
+void xconfigPrintExtensionsSection (FILE * cf, XConfigExtensionsPtr ptr);
+
+/* Generate.c */
+XConfigMonitorPtr xconfigAddMonitor(XConfigPtr config, int count);
+int xconfigAddMouse(GenerateOptions *gop, XConfigPtr config);
+int xconfigAddKeyboard(GenerateOptions *gop, XConfigPtr config);
diff --git a/src/XF86Config-parser/xf86Parser.h b/src/XF86Config-parser/xf86Parser.h
new file mode 100644
index 0000000..40b8162
--- /dev/null
+++ b/src/XF86Config-parser/xf86Parser.h
@@ -0,0 +1,737 @@
+/*
+ *
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+
+/*
+ * This file specifies the external interface for the X configuration
+ * file parser; based loosely on the XFree86 and Xorg X server
+ * configuration code.
+ */
+
+
+#ifndef _xf86Parser_h_
+#define _xf86Parser_h_
+
+#include <stdio.h>
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+// Unix variations: Linux
+#if !defined(NV_LINUX) && defined(__linux__)
+# define NV_LINUX
+#endif // defined(__linux__)
+
+// Unix variations: SunOS
+#if !defined(NV_SUNOS) && defined(__sun__) || defined(__sun)
+# define NV_SUNOS
+#endif // defined(__sun__)
+
+// Unix variations: FreeBSD
+#if !defined(NV_BSD) && defined(__FreeBSD__)
+# define NV_BSD
+#endif // defined(__FreeBSD__)
+
+
+/*
+ * return codes
+ */
+
+typedef enum {
+ XCONFIG_RETURN_SUCCESS = 0,
+ XCONFIG_RETURN_NO_XCONFIG_FOUND,
+ XCONFIG_RETURN_PARSE_ERROR,
+ XCONFIG_RETURN_ALLOCATION_ERROR,
+ XCONFIG_RETURN_VALIDATION_ERROR,
+ XCONFIG_RETURN_INVALID_COMMAND_LINE,
+ XCONFIG_RETURN_SANITY_ERROR,
+ XCONFIG_RETURN_WRITE_ERROR
+} XConfigError;
+
+
+/*
+ * Message types
+ */
+
+typedef enum {
+ ParseErrorMsg,
+ ParseWarningMsg,
+ ValidationErrorMsg,
+ InternalErrorMsg,
+ WriteErrorMsg,
+ WarnMsg,
+ ErrorMsg,
+ DebugMsg,
+ UnknownMsg
+} MsgType;
+
+
+/*
+ * The user of libXF86Config-parser should provide an implementation
+ * of xconfigPrint()
+ */
+
+void xconfigPrint(MsgType t, const char *msg);
+
+
+/*
+ * all records that need to be linked lists should contain a next
+ * pointer as their first field, so that they can be cast as a
+ * GenericListRec
+ */
+
+typedef struct { void *next; } GenericListRec, *GenericListPtr;
+
+
+
+/*
+ * Options are stored in the XConfigOptionRec structure
+ */
+
+typedef struct __xconfigoptionrec {
+ struct __xconfigoptionrec *next;
+ char *name;
+ char *val;
+ int used;
+ char *comment;
+} XConfigOptionRec, *XConfigOptionPtr;
+
+
+
+/*
+ * Files Section
+ */
+
+typedef struct {
+ char *logfile;
+ char *rgbpath;
+ char *modulepath;
+ char *inputdevs;
+ char *fontpath;
+ char *comment;
+} XConfigFilesRec, *XConfigFilesPtr;
+
+/* Values for load_type */
+#define XCONFIG_LOAD_MODULE 0
+#define XCONFIG_LOAD_DRIVER 1
+
+
+
+/*
+ * Modules Section
+ */
+
+typedef struct __xconfigloadrec {
+ struct __xconfigloadrec *next;
+ int type;
+ char *name;
+ XConfigOptionPtr opt;
+ char *comment;
+} XConfigLoadRec, *XConfigLoadPtr;
+
+typedef struct {
+ XConfigLoadPtr loads;
+ char *comment;
+} XConfigModuleRec, *XConfigModulePtr;
+
+#define CONF_IMPLICIT_KEYBOARD "Implicit Core Keyboard"
+
+#define CONF_IMPLICIT_POINTER "Implicit Core Pointer"
+
+
+
+/*
+ * Modeline structure
+ */
+
+#define XCONFIG_MODE_PHSYNC 0x0001
+#define XCONFIG_MODE_NHSYNC 0x0002
+#define XCONFIG_MODE_PVSYNC 0x0004
+#define XCONFIG_MODE_NVSYNC 0x0008
+#define XCONFIG_MODE_INTERLACE 0x0010
+#define XCONFIG_MODE_DBLSCAN 0x0020
+#define XCONFIG_MODE_CSYNC 0x0040
+#define XCONFIG_MODE_PCSYNC 0x0080
+#define XCONFIG_MODE_NCSYNC 0x0100
+#define XCONFIG_MODE_HSKEW 0x0200 /* hskew provided */
+#define XCONFIG_MODE_BCAST 0x0400
+#define XCONFIG_MODE_CUSTOM 0x0800 /* timing numbers customized by editor */
+#define XCONFIG_MODE_VSCAN 0x1000
+
+typedef struct __xconfigconfmodelinerec {
+ struct __xconfigconfmodelinerec *next;
+ char *identifier;
+ int clock;
+ int hdisplay;
+ int hsyncstart;
+ int hsyncend;
+ int htotal;
+ int vdisplay;
+ int vsyncstart;
+ int vsyncend;
+ int vtotal;
+ int vscan;
+ int flags;
+ int hskew;
+ char *comment;
+} XConfigModeLineRec, *XConfigModeLinePtr;
+
+
+
+/*
+ * VideoPort and VideoAdapter XXX what are these?
+ */
+
+typedef struct __xconfigconfvideoportrec {
+ struct __xconfigconfvideoportrec *next;
+ char *identifier;
+ XConfigOptionPtr options;
+ char *comment;
+} XConfigVideoPortRec, *XConfigVideoPortPtr;
+
+typedef struct __xconfigconfvideoadaptorrec {
+ struct __xconfigconfvideoadaptorrec *next;
+ char *identifier;
+ char *vendor;
+ char *board;
+ char *busid;
+ char *driver;
+ XConfigOptionPtr options;
+ XConfigVideoPortPtr ports;
+ char *fwdref;
+ char *comment;
+} XConfigVideoAdaptorRec, *XConfigVideoAdaptorPtr;
+
+
+
+/*
+ * Monitor Section
+ */
+
+#define CONF_MAX_HSYNC 8
+#define CONF_MAX_VREFRESH 8
+
+typedef struct { float hi, lo; } parser_range;
+
+typedef struct { int red, green, blue; } parser_rgb;
+
+typedef struct __xconfigconfmodesrec {
+ struct __xconfigconfmodesrec *next;
+ char *identifier;
+ XConfigModeLinePtr modelines;
+ char *comment;
+} XConfigModesRec, *XConfigModesPtr;
+
+typedef struct __xconfigconfmodeslinkrec {
+ struct __xconfigconfmodeslinkrec *next;
+ char *modes_name;
+ XConfigModesPtr modes;
+} XConfigModesLinkRec, *XConfigModesLinkPtr;
+
+typedef struct __xconfigconfmonitorrec {
+ struct __xconfigconfmonitorrec *next;
+ char *identifier;
+ char *vendor;
+ char *modelname;
+ int width; /* in mm */
+ int height; /* in mm */
+ XConfigModeLinePtr modelines;
+ int n_hsync;
+ parser_range hsync[CONF_MAX_HSYNC];
+ int n_vrefresh;
+ parser_range vrefresh[CONF_MAX_VREFRESH];
+ float gamma_red;
+ float gamma_green;
+ float gamma_blue;
+ XConfigOptionPtr options;
+ XConfigModesLinkPtr modes_sections;
+ char *comment;
+} XConfigMonitorRec, *XConfigMonitorPtr;
+
+
+
+/*
+ * Device Section
+ */
+
+#define CONF_MAXDACSPEEDS 4
+#define CONF_MAXCLOCKS 128
+
+typedef struct __xconfigconfdevicerec {
+ struct __xconfigconfdevicerec *next;
+ char *identifier;
+ char *vendor;
+ char *board;
+ char *chipset;
+ char *busid;
+ char *card;
+ char *driver;
+ char *ramdac;
+ int dacSpeeds[CONF_MAXDACSPEEDS];
+ int videoram;
+ int textclockfreq;
+ unsigned long bios_base;
+ unsigned long mem_base;
+ unsigned long io_base;
+ char *clockchip;
+ int clocks;
+ int clock[CONF_MAXCLOCKS];
+ int chipid;
+ int chiprev;
+ int irq;
+ int screen;
+ XConfigOptionPtr options;
+ char *comment;
+} XConfigDeviceRec, *XConfigDevicePtr;
+
+
+
+/*
+ * Screen Section
+ */
+
+typedef struct __xconfigmoderec {
+ struct __xconfigmoderec *next;
+ char *mode_name;
+} XConfigModeRec, *XConfigModePtr;
+
+typedef struct __xconfigconfdisplayrec {
+ struct __xconfigconfdisplayrec *next;
+ int frameX0;
+ int frameY0;
+ int virtualX;
+ int virtualY;
+ int depth;
+ int bpp;
+ char *visual;
+ parser_rgb weight;
+ parser_rgb black;
+ parser_rgb white;
+ XConfigModePtr modes;
+ XConfigOptionPtr options;
+ char *comment;
+} XConfigDisplayRec, *XConfigDisplayPtr;
+
+typedef struct __xconfigconfadaptorlinkrec {
+ struct __xconfigconfadaptorlinkrec *next;
+ char *adaptor_name;
+ XConfigVideoAdaptorPtr adaptor;
+} XConfigAdaptorLinkRec, *XConfigAdaptorLinkPtr;
+
+typedef struct __xconfigconfscreenrec {
+ struct __xconfigconfscreenrec *next;
+ char *identifier;
+ char *obsolete_driver;
+ int defaultdepth;
+ int defaultbpp;
+ int defaultfbbpp;
+ char *monitor_name;
+ XConfigMonitorPtr monitor;
+ char *device_name;
+ XConfigDevicePtr device;
+ XConfigAdaptorLinkPtr adaptors;
+ XConfigDisplayPtr displays;
+ XConfigOptionPtr options;
+ char *comment;
+} XConfigScreenRec, *XConfigScreenPtr;
+
+
+
+/*
+ * Input Section
+ */
+
+typedef struct __xconfigconfinputrec {
+ struct __xconfigconfinputrec *next;
+ char *identifier;
+ char *driver;
+ XConfigOptionPtr options;
+ char *comment;
+} XConfigInputRec, *XConfigInputPtr;
+
+
+
+/*
+ * Input Reference; used by layout to store list of XConfigInputPtrs
+ */
+
+typedef struct __xconfigconfinputrefrec {
+ struct __xconfigconfinputrefrec *next;
+ XConfigInputPtr input;
+ char *input_name;
+ XConfigOptionPtr options;
+} XConfigInputrefRec, *XConfigInputrefPtr;
+
+
+
+/*
+ * Adjacency structure; used by layout to store list of
+ * XConfigScreenPtrs
+ */
+
+/* Values for adj_where */
+#define CONF_ADJ_OBSOLETE -1
+#define CONF_ADJ_ABSOLUTE 0
+#define CONF_ADJ_RIGHTOF 1
+#define CONF_ADJ_LEFTOF 2
+#define CONF_ADJ_ABOVE 3
+#define CONF_ADJ_BELOW 4
+#define CONF_ADJ_RELATIVE 5
+
+typedef struct __xconfigconfadjacencyrec {
+ struct __xconfigconfadjacencyrec *next;
+ int scrnum;
+ XConfigScreenPtr screen;
+ char *screen_name;
+ XConfigScreenPtr top;
+ char *top_name;
+ XConfigScreenPtr bottom;
+ char *bottom_name;
+ XConfigScreenPtr left;
+ char *left_name;
+ XConfigScreenPtr right;
+ char *right_name;
+ int where;
+ int x;
+ int y;
+ char *refscreen;
+} XConfigAdjacencyRec, *XConfigAdjacencyPtr;
+
+
+
+/*
+ * XConfigInactiveRec XXX what is this?
+ */
+
+typedef struct __xconfigconfinactiverec {
+ struct __xconfigconfinactiverec *next;
+ char *device_name;
+ XConfigDevicePtr device;
+} XConfigInactiveRec, *XConfigInactivePtr;
+
+
+
+/*
+ * Layout Section
+ */
+
+typedef struct __xconfigconflayoutrec {
+ struct __xconfigconflayoutrec *next;
+ char *identifier;
+ XConfigAdjacencyPtr adjacencies;
+ XConfigInactivePtr inactives;
+ XConfigInputrefPtr inputs;
+ XConfigOptionPtr options;
+ char *comment;
+} XConfigLayoutRec, *XConfigLayoutPtr;
+
+
+
+/*
+ * Vendor Section XXX what is this?
+ */
+
+typedef struct __xconfigconfvendsubrec {
+ struct __xconfigconfvendsubrec *next;
+ char *name;
+ char *identifier;
+ XConfigOptionPtr options;
+ char *comment;
+} XConfigVendSubRec, *XConfigVendSubPtr;
+
+typedef struct __xconfigconfvendorrec {
+ struct __xconfigconfvendorrec *next;
+ char *identifier;
+ XConfigOptionPtr options;
+ XConfigVendSubPtr subs;
+ char *comment;
+} XConfigVendorRec, *XConfigVendorPtr;
+
+
+
+/*
+ * DRI section
+ */
+
+typedef struct __xconfigconfbuffersrec {
+ struct __xconfigconfbuffersrec *next;
+ int count;
+ int size;
+ char *flags;
+ char *comment;
+} XConfigBuffersRec, *XConfigBuffersPtr;
+
+typedef struct {
+ char *group_name;
+ int group;
+ int mode;
+ XConfigBuffersPtr buffers;
+ char * comment;
+} XConfigDRIRec, *XConfigDRIPtr;
+
+
+
+/*
+ * ServerFlags Section
+ */
+
+typedef struct {
+ XConfigOptionPtr options;
+ char *comment;
+} XConfigFlagsRec, *XConfigFlagsPtr;
+
+
+
+/*
+ * Extensions Section
+ */
+
+typedef struct
+{
+ XConfigOptionPtr options;
+ char *comment;
+}
+XConfigExtensionsRec, *XConfigExtensionsPtr;
+
+
+/*
+ * Configuration file structure
+ */
+
+typedef struct {
+ XConfigFilesPtr files;
+ XConfigModulePtr modules;
+ XConfigFlagsPtr flags;
+ XConfigVideoAdaptorPtr videoadaptors;
+ XConfigModesPtr modes;
+ XConfigMonitorPtr monitors;
+ XConfigDevicePtr devices;
+ XConfigScreenPtr screens;
+ XConfigInputPtr inputs;
+ XConfigLayoutPtr layouts;
+ XConfigVendorPtr vendors;
+ XConfigDRIPtr dri;
+ XConfigExtensionsPtr extensions;
+ char *comment;
+ char *filename;
+} XConfigRec, *XConfigPtr;
+
+typedef struct {
+ int token; /* id of the token */
+ char *name; /* pointer to the LOWERCASED name */
+} XConfigSymTabRec, *XConfigSymTabPtr;
+
+
+/*
+ * data structure containing options; used during generation of X
+ * config, and when sanitizing an existing config
+ */
+
+#define X_IS_XF86 0
+#define X_IS_XORG 1
+
+typedef struct {
+ int xserver;
+ char *x_project_root;
+ char *keyboard;
+ char *mouse;
+ char *keyboard_driver;
+} GenerateOptions;
+
+
+/*
+ * Functions for open, reading, and writing XConfig files.
+ */
+const char *xconfigOpenConfigFile(const char *, const char *);
+XConfigError xconfigReadConfigFile(XConfigPtr *);
+int xconfigSanitizeConfig(XConfigPtr p, const char *screenName,
+ GenerateOptions *gop);
+void xconfigCloseConfigFile(void);
+int xconfigWriteConfigFile(const char *, XConfigPtr);
+
+void xconfigFreeConfig(XConfigPtr p);
+
+/*
+ * Functions for searching for entries in lists
+ */
+
+XConfigDevicePtr xconfigFindDevice(const char *ident, XConfigDevicePtr p);
+XConfigLayoutPtr xconfigFindLayout(const char *name, XConfigLayoutPtr list);
+XConfigMonitorPtr xconfigFindMonitor(const char *ident, XConfigMonitorPtr p);
+XConfigModesPtr xconfigFindModes(const char *ident, XConfigModesPtr p);
+XConfigModeLinePtr xconfigFindModeLine(const char *ident,
+ XConfigModeLinePtr p);
+XConfigScreenPtr xconfigFindScreen(const char *ident, XConfigScreenPtr p);
+XConfigModePtr xconfigFindMode(const char *name, XConfigModePtr p);
+XConfigInputPtr xconfigFindInput(const char *ident, XConfigInputPtr p);
+XConfigInputPtr xconfigFindInputByDriver(const char *driver,
+ XConfigInputPtr p);
+XConfigVendorPtr xconfigFindVendor(const char *name, XConfigVendorPtr list);
+XConfigVideoAdaptorPtr xconfigFindVideoAdaptor(const char *ident,
+ XConfigVideoAdaptorPtr p);
+
+/*
+ * Functions for freeing lists
+ */
+
+void xconfigFreeDeviceList(XConfigDevicePtr ptr);
+void xconfigFreeFiles(XConfigFilesPtr p);
+void xconfigFreeFlags(XConfigFlagsPtr flags);
+void xconfigFreeInputList(XConfigInputPtr ptr);
+void xconfigFreeLayoutList(XConfigLayoutPtr ptr);
+void xconfigFreeAdjacencyList(XConfigAdjacencyPtr ptr);
+void xconfigFreeInputrefList(XConfigInputrefPtr ptr);
+void xconfigFreeModules(XConfigModulePtr ptr);
+void xconfigFreeMonitorList(XConfigMonitorPtr ptr);
+void xconfigFreeModesList(XConfigModesPtr ptr);
+void xconfigFreeModeLineList(XConfigModeLinePtr ptr);
+void xconfigFreeScreenList(XConfigScreenPtr ptr);
+void xconfigFreeAdaptorLinkList(XConfigAdaptorLinkPtr ptr);
+void xconfigFreeDisplayList(XConfigDisplayPtr ptr);
+void xconfigFreeModeList(XConfigModePtr ptr);
+void xconfigFreeVendorList(XConfigVendorPtr p);
+void xconfigFreeVendorSubList(XConfigVendSubPtr ptr);
+void xconfigFreeVideoAdaptorList(XConfigVideoAdaptorPtr ptr);
+void xconfigFreeVideoPortList(XConfigVideoPortPtr ptr);
+void xconfigFreeBuffersList (XConfigBuffersPtr ptr);
+void xconfigFreeDRI(XConfigDRIPtr ptr);
+void xconfigFreeExtensions(XConfigExtensionsPtr ptr);
+
+
+/*
+ * item/list manipulation
+ */
+
+GenericListPtr xconfigAddListItem(GenericListPtr head, GenericListPtr c_new);
+GenericListPtr xconfigRemoveListItem(GenericListPtr list, GenericListPtr item);
+int xconfigItemNotSublist(GenericListPtr list_1, GenericListPtr list_2);
+char *xconfigAddComment(char *cur, char *add);
+XConfigLoadPtr xconfigAddNewLoadDirective(XConfigLoadPtr head,
+ char *name, int type,
+ XConfigOptionPtr opts, int do_token);
+XConfigLoadPtr xconfigRemoveLoadDirective(XConfigLoadPtr head,
+ XConfigLoadPtr load);
+
+/*
+ * Functions for manipulating Options
+ */
+
+XConfigOptionPtr xconfigAddNewOption(XConfigOptionPtr head,
+ char *name, char *val);
+XConfigOptionPtr xconfigRemoveOption(XConfigOptionPtr list,
+ XConfigOptionPtr opt);
+XConfigOptionPtr xconfigOptionListDup(XConfigOptionPtr opt);
+void xconfigOptionListFree(XConfigOptionPtr opt);
+char *xconfigOptionName(XConfigOptionPtr opt);
+char *xconfigOptionValue(XConfigOptionPtr opt);
+XConfigOptionPtr xconfigNewOption(char *name, char *value);
+XConfigOptionPtr xconfigNextOption(XConfigOptionPtr list);
+XConfigOptionPtr xconfigFindOption(XConfigOptionPtr list, const char *name);
+char *xconfigFindOptionValue(XConfigOptionPtr list,
+ const char *name);
+int xconfigFindOptionBoolean (XConfigOptionPtr,
+ const char *name);
+XConfigOptionPtr xconfigOptionListCreate(const char **options,
+ int count, int used);
+XConfigOptionPtr xconfigOptionListMerge(XConfigOptionPtr head,
+ XConfigOptionPtr tail);
+
+/*
+ * Miscellaneous utility routines
+ */
+
+char *xconfigStrdup(const char *s);
+char *xconfigStrcat(const char *str, ...);
+int xconfigNameCompare(const char *s1, const char *s2);
+int xconfigModelineCompare(XConfigModeLinePtr m1, XConfigModeLinePtr m2);
+char *xconfigULongToString(unsigned long i);
+XConfigOptionPtr xconfigParseOption(XConfigOptionPtr head);
+void xconfigPrintOptionList(FILE *fp, XConfigOptionPtr list, int tabs);
+int xconfigParsePciBusString(const char *busID,
+ int *bus, int *device, int *func);
+
+XConfigDisplayPtr
+xconfigAddDisplay(XConfigDisplayPtr head, const int depth);
+
+XConfigModePtr
+xconfigAddMode(XConfigModePtr head, const char *name);
+
+XConfigModePtr
+xconfigRemoveMode(XConfigModePtr head, const char *name);
+
+
+XConfigPtr xconfigGenerate(GenerateOptions *gop);
+
+XConfigScreenPtr xconfigGenerateAddScreen(XConfigPtr config, int bus, int slot,
+ char *boardname, int count);
+
+void xconfigGenerateAssignScreenAdjacencies(XConfigLayoutPtr layout);
+
+void xconfigGeneratePrintPossibleMice(void);
+void xconfigGeneratePrintPossibleKeyboards(void);
+
+/*
+ * check (and update, if necessary) the inputs in the specified layout
+ * section
+ */
+
+int xconfigCheckCoreInputDevices(GenerateOptions *gop,
+ XConfigPtr config, XConfigLayoutPtr layout);
+
+#endif /* _xf86Parser_h_ */
diff --git a/src/XF86Config-parser/xf86tokens.h b/src/XF86Config-parser/xf86tokens.h
new file mode 100644
index 0000000..1189bc0
--- /dev/null
+++ b/src/XF86Config-parser/xf86tokens.h
@@ -0,0 +1,276 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/parser/xf86tokens.h,v 1.20 2003/08/24 17:37:09 dawes Exp $ */
+/*
+ *
+ * Copyright (c) 1997 Metro Link Incorporated
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the Metro Link shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Metro Link.
+ *
+ */
+/*
+ * Copyright (c) 1997-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+
+#ifndef _xf86_tokens_h
+#define _xf86_tokens_h
+
+/* Undefine symbols that some OSs might define */
+#undef IOBASE
+
+/*
+ * Each token should have a unique value regardless of the section
+ * it is used in.
+ */
+
+typedef enum {
+ /* errno-style tokens */
+ EOF_TOKEN = -4,
+ LOCK_TOKEN = -3,
+ ERROR_TOKEN = -2,
+
+ /* value type tokens */
+ NUMBER = 1,
+ STRING,
+
+ /* Tokens that can appear in many sections */
+ SECTION,
+ SUBSECTION,
+ ENDSECTION,
+ ENDSUBSECTION,
+ IDENTIFIER,
+ VENDOR,
+ DASH,
+ COMMA,
+ OPTION,
+ COMMENT,
+
+ /* Frequency units */
+ HRZ,
+ KHZ,
+ MHZ,
+
+ /* File tokens */
+ FONTPATH,
+ RGBPATH,
+ MODULEPATH,
+ INPUTDEVICES,
+ LOGFILEPATH,
+
+ /* Server Flag tokens. These are deprecated in favour of generic Options */
+ NOTRAPSIGNALS,
+ DONTZAP,
+ DONTZOOM,
+ DISABLEVIDMODE,
+ ALLOWNONLOCAL,
+ DISABLEMODINDEV,
+ MODINDEVALLOWNONLOCAL,
+ ALLOWMOUSEOPENFAIL,
+ BLANKTIME,
+ STANDBYTIME,
+ SUSPENDTIME,
+ OFFTIME,
+ DEFAULTLAYOUT,
+
+ /* Monitor tokens */
+ MODEL,
+ MODELINE,
+ DISPLAYSIZE,
+ HORIZSYNC,
+ VERTREFRESH,
+ MODE,
+ GAMMA,
+ USEMODES,
+
+ /* Modes tokens */
+ /* no new ones */
+
+ /* Mode tokens */
+ DOTCLOCK,
+ HTIMINGS,
+ VTIMINGS,
+ FLAGS,
+ HSKEW,
+ BCAST,
+ VSCAN,
+ ENDMODE,
+
+ /* Screen tokens */
+ OBSDRIVER,
+ MDEVICE,
+ MONITOR,
+ SCREENNO,
+ DEFAULTDEPTH,
+ DEFAULTBPP,
+ DEFAULTFBBPP,
+
+ /* VideoAdaptor tokens */
+ VIDEOADAPTOR,
+
+ /* Mode timing tokens */
+ TT_INTERLACE,
+ TT_PHSYNC,
+ TT_NHSYNC,
+ TT_PVSYNC,
+ TT_NVSYNC,
+ TT_CSYNC,
+ TT_PCSYNC,
+ TT_NCSYNC,
+ TT_DBLSCAN,
+ TT_HSKEW,
+ TT_BCAST,
+ TT_VSCAN,
+ TT_CUSTOM,
+
+ /* Module tokens */
+ LOAD,
+ LOAD_DRIVER,
+
+ /* Device tokens */
+ DRIVER,
+ CHIPSET,
+ CLOCKS,
+ VIDEORAM,
+ BOARD,
+ IOBASE,
+ RAMDAC,
+ DACSPEED,
+ BIOSBASE,
+ MEMBASE,
+ CLOCKCHIP,
+ CHIPID,
+ CHIPREV,
+ CARD,
+ BUSID,
+ TEXTCLOCKFRQ,
+ IRQ,
+
+ /* Keyboard tokens */
+ AUTOREPEAT,
+ XLEDS,
+ KPROTOCOL,
+ XKBKEYMAP,
+ XKBCOMPAT,
+ XKBTYPES,
+ XKBKEYCODES,
+ XKBGEOMETRY,
+ XKBSYMBOLS,
+ XKBDISABLE,
+ PANIX106,
+ XKBRULES,
+ XKBMODEL,
+ XKBLAYOUT,
+ XKBVARIANT,
+ XKBOPTIONS,
+ /* The next two have become ServerFlags options */
+ VTINIT,
+ VTSYSREQ,
+ /* Obsolete keyboard tokens */
+ SERVERNUM,
+ LEFTALT,
+ RIGHTALT,
+ SCROLLLOCK_TOK,
+ RIGHTCTL,
+ /* arguments for the above obsolete tokens */
+ CONF_KM_META,
+ CONF_KM_COMPOSE,
+ CONF_KM_MODESHIFT,
+ CONF_KM_MODELOCK,
+ CONF_KM_SCROLLLOCK,
+ CONF_KM_CONTROL,
+
+ /* Pointer tokens */
+ EMULATE3,
+ BAUDRATE,
+ SAMPLERATE,
+ PRESOLUTION,
+ CLEARDTR,
+ CLEARRTS,
+ CHORDMIDDLE,
+ PROTOCOL,
+ PDEVICE,
+ EM3TIMEOUT,
+ DEVICE_NAME,
+ ALWAYSCORE,
+ PBUTTONS,
+ ZAXISMAPPING,
+
+ /* Pointer Z axis mapping tokens */
+ XAXIS,
+ YAXIS,
+
+ /* Display tokens */
+ MODES,
+ VIEWPORT,
+ VIRTUAL,
+ VISUAL,
+ BLACK_TOK,
+ WHITE_TOK,
+ DEPTH,
+ BPP,
+ WEIGHT,
+
+ /* Layout Tokens */
+ SCREEN,
+ INACTIVE,
+ INPUTDEVICE,
+
+ /* Adjaceny Tokens */
+ RIGHTOF,
+ LEFTOF,
+ ABOVE,
+ BELOW,
+ RELATIVE,
+ ABSOLUTE,
+
+ /* Vendor Tokens */
+ VENDORNAME,
+
+ /* DRI Tokens */
+ GROUP,
+ BUFFERS
+} ParserTokens;
+
+#endif /* _xf86_tokens_h */
diff --git a/src/command-line.c b/src/command-line.c
index 199db69..0a918e6 100644
--- a/src/command-line.c
+++ b/src/command-line.c
@@ -51,6 +51,14 @@ static char *tilde_expansion(char *str);
static char *nvstrcat(const char *str, ...);
/*
+ * verbosity, controls output of errors, warnings and other
+ * information (used by msg.c).
+ */
+
+int __verbosity = VERBOSITY_DEFAULT;
+
+
+/*
* print_version() - print version information
*/
@@ -110,6 +118,17 @@ static const NVGetoptOption __options[] = {
"the X server, and exit. This mode of operation is useful to place "
"in your .xinitrc file, for example." },
+ { "no-config", 'n', 0, NULL,
+ "Do not load the configuration file. This mode of operation is useful "
+ "if nvidia-settings has difficulties starting due to problems with "
+ "applying settings in the configuration file." },
+
+ { "verbose", 'V', NVGETOPT_HAS_ARGUMENT, NULL,
+ "Controls how much information is printed. Valid values are 'errors' "
+ "(print error messages), 'warnings' (print error and warning messages), "
+ "and 'all' (print error, warning and other informational messages). By "
+ "default, only errors are printed." },
+
{ "assign", 'a', NVGETOPT_HAS_ARGUMENT, print_assign_help, NULL },
{ "query", 'q', NVGETOPT_HAS_ARGUMENT, print_query_help, NULL },
@@ -292,8 +311,24 @@ Options *parse_command_line(int argc, char *argv[], char *dpy)
switch (c) {
case 'v': print_version(); exit(0); break;
case 'h': print_help(); exit(0); break;
- case 'l': op->load = 1; break;
+ case 'l': op->only_load = 1; break;
+ case 'n': op->no_load = 1; break;
case 'c': op->ctrl_display = strval; break;
+ case 'V':
+ __verbosity = VERBOSITY_DEFAULT;
+ if (nv_strcasecmp(strval, "errors") == NV_TRUE) {
+ __verbosity = VERBOSITY_ERROR;
+ } else if (nv_strcasecmp(strval, "warnings") == NV_TRUE) {
+ __verbosity = VERBOSITY_WARNING;
+ } else if (nv_strcasecmp(strval, "all") == NV_TRUE) {
+ __verbosity = VERBOSITY_ALL;
+ } else {
+ nv_error_msg("Invalid verbosity level '%s'. Please run "
+ "`%s --help` for usage information.\n",
+ strval, argv[0]);
+ exit(0);
+ }
+ break;
case 'a':
n = op->num_assignments;
op->assignments = realloc(op->assignments, sizeof(char *) * (n+1));
diff --git a/src/command-line.h b/src/command-line.h
index 0591751..fd1ed7f 100644
--- a/src/command-line.h
+++ b/src/command-line.h
@@ -29,6 +29,12 @@
#define DEFAULT_RC_FILE "~/.nvidia-settings-rc"
+#define VERBOSITY_ERROR 0 /* errors only */
+#define VERBOSITY_WARNING 1 /* errors and warnings */
+#define VERBOSITY_ALL 2 /* errors, warnings and other info */
+
+#define VERBOSITY_DEFAULT VERBOSITY_ERROR
+
/*
* Options structure -- stores the parameters specified on the
* commandline.
@@ -69,11 +75,17 @@ typedef struct {
* array.
*/
- int load; /*
+ int only_load; /*
* If true, just read the configuration file,
* send the attributes to the X server, and
* exit.
*/
+
+ int no_load; /*
+ * If true, do not load the configuration file.
+ * The attributes are not sent to the X Server.
+ */
+
} Options;
diff --git a/src/config-file.c b/src/config-file.c
index c620795..0ebd8d1 100644
--- a/src/config-file.c
+++ b/src/config-file.c
@@ -46,6 +46,7 @@
#include <ctype.h>
#include <stdlib.h>
#include <time.h>
+#include <locale.h>
#include "NvCtrlAttributes.h"
@@ -79,9 +80,8 @@ static void save_gui_parsed_attributes(ParsedAttributeWrapper *w,
static float get_color_value(int attr,
float c[3], float b[3], float g[3]);
-static int parse_config_properties(const char *line, ConfigProperties *conf);
-
-static void init_config_properties(ConfigProperties *conf);
+static int parse_config_property(const char *file, const char *line,
+ ConfigProperties *conf);
static void write_config_properties(FILE *stream, ConfigProperties *conf);
@@ -97,6 +97,9 @@ static void write_config_properties(FILE *stream, ConfigProperties *conf);
* message is printed to stderr, NV_FALSE is returned, and nothing is
* sent to the X server.
*
+ * NOTE: The conf->locale should have already been setup by calling
+ * init_config_properties() prior to calling this function.
+ *
* XXX should we do any sort of versioning to handle compatibility
* problems in the future?
*/
@@ -106,13 +109,9 @@ int nv_read_config_file(const char *file, const char *display_name,
{
int fd, ret, length;
struct stat stat_buf;
- char *buf;
+ char *buf, *locale;
ParsedAttributeWrapper *w = NULL;
- /* initialize the ConfigProperties */
-
- init_config_properties(conf);
-
/* open the file */
fd = open(file, O_RDONLY);
@@ -149,19 +148,28 @@ int nv_read_config_file(const char *file, const char *display_name,
file, strerror(errno));
return NV_FALSE;
}
-
- /* parse the actual text in the file */
+
+
+ /*
+ * save the current locale, parse the actual text in the file
+ * and restore the saved locale (could be changed).
+ */
+
+ locale = strdup(conf->locale);
w = parse_config_file(buf, file, length, conf);
+ setlocale(LC_ALL, locale);
+ free(locale);
+
+ /* unmap and close the file */
+
if (munmap (buf, stat_buf.st_size) == -1) {
nv_error_msg("Unable to unmap file '%s' after reading (%s).",
file, strerror(errno));
return NV_FALSE;
}
- /* close the file */
-
close(fd);
if (!w) return NV_FALSE;
@@ -479,7 +487,7 @@ static ParsedAttributeWrapper *parse_config_file(char *buf, const char *file,
/* first, see if this line is a config property */
- if (!parse_config_properties(tmp, conf)) {
+ if (!parse_config_property(file, tmp, conf)) {
w = realloc(w, sizeof(ParsedAttributeWrapper) * (n+1));
@@ -674,9 +682,10 @@ ConfigPropertiesTableEntry configPropertyTable[] = {
* property, return NV_FALSE.
*/
-static int parse_config_properties(const char *line, ConfigProperties *conf)
+static int parse_config_property(const char *file, const char *line, ConfigProperties *conf)
{
char *no_spaces, *s;
+ char *locale;
ConfigPropertiesTableEntry *t;
int ret = NV_FALSE;
unsigned int flag;
@@ -691,23 +700,34 @@ static int parse_config_properties(const char *line, ConfigProperties *conf)
*s = '\0';
- for (t = configPropertyTable, flag = 0; t->name; t++) {
- if (nv_strcasecmp(no_spaces, t->name)) {
- flag = t->flag;
- break;
+ if (nv_strcasecmp(no_spaces, "RcFileLocale")) {
+ locale = ++s;
+ if (setlocale(LC_ALL, locale) == NULL) {
+ nv_warning_msg("Error parsing configuration file '%s': could "
+ "not set the specified locale '%s'.",
+ file, locale);
+ ret = NV_TRUE;
+ goto done;
+ }
+ } else {
+ for (t = configPropertyTable, flag = 0; t->name; t++) {
+ if (nv_strcasecmp(no_spaces, t->name)) {
+ flag = t->flag;
+ break;
+ }
}
- }
- if (!flag) goto done;
+ if (!flag) goto done;
- s++;
+ s++;
- if (nv_strcasecmp(s, "yes")) {
- conf->booleans |= flag;
- } else if (nv_strcasecmp(s, "no")) {
- conf->booleans &= ~flag;
- } else {
- goto done;
+ if (nv_strcasecmp(s, "yes")) {
+ conf->booleans |= flag;
+ } else if (nv_strcasecmp(s, "no")) {
+ conf->booleans &= ~flag;
+ } else {
+ goto done;
+ }
}
ret = NV_TRUE;
@@ -735,6 +755,8 @@ static void write_config_properties(FILE *stream, ConfigProperties *conf)
fprintf(stream, "# ConfigProperties:\n");
fprintf(stream, "\n");
+ fprintf(stream, "RcFileLocale = %s\n", conf->locale);
+
for (t = configPropertyTable; t->name; t++) {
fprintf(stream, "%s = %s\n", t->name,
(t->flag & conf->booleans) ? "Yes" : "No");
@@ -748,7 +770,7 @@ static void write_config_properties(FILE *stream, ConfigProperties *conf)
* structure.
*/
-static void init_config_properties(ConfigProperties *conf)
+void init_config_properties(ConfigProperties *conf)
{
memset(conf, 0, sizeof(ConfigProperties));
@@ -758,4 +780,6 @@ static void init_config_properties(ConfigProperties *conf)
CONFIG_PROPERTIES_SLIDER_TEXT_ENTRIES |
CONFIG_PROPERTIES_SHOW_QUIT_DIALOG);
+ conf->locale = strdup(setlocale(LC_ALL, NULL));
+
} /* init_config_properties() */
diff --git a/src/config-file.h b/src/config-file.h
index c0516d4..ae787ce 100644
--- a/src/config-file.h
+++ b/src/config-file.h
@@ -43,9 +43,12 @@
typedef struct {
unsigned int booleans;
+ char *locale;
} ConfigProperties;
+void init_config_properties(ConfigProperties *conf);
+
int nv_read_config_file(const char *, const char *,
ParsedAttribute *, ConfigProperties *);
diff --git a/src/gtk+-2.x/Makefile.inc b/src/gtk+-2.x/Makefile.inc
index 9794f16..90ca4a9 100644
--- a/src/gtk+-2.x/Makefile.inc
+++ b/src/gtk+-2.x/Makefile.inc
@@ -40,10 +40,8 @@ SRC += \
ctkwindow.c \
ctkopengl.c \
ctkglx.c \
- ctkdevice.c \
ctkhelp.c \
ctkimagesliders.c \
- ctkdisplaydevice.c \
ctkdisplaydevice-crt.c \
ctkdisplaydevice-tv.c \
ctkdisplaydevice-dfp.c \
@@ -55,10 +53,18 @@ SRC += \
ctkclocks.c \
ctkutils.c \
ctkedid.c \
- ctkimage.c
+ ctkimage.c \
+ ctkserver.c \
+ ctkdisplaylayout.c \
+ ctkdisplayconfig.c \
+ ctkscreen.c \
+ ctkgpu.c \
+ ctkbanner.c \
+ ctkvcsc.c
EXTRA_DIST += \
+ Makefile.inc \
ctkxvideo.h \
ctkcursorshadow.h \
ctkui.h \
@@ -73,10 +79,8 @@ EXTRA_DIST += \
ctkwindow.h \
ctkopengl.h \
ctkglx.h \
- ctkdevice.h \
ctkhelp.h \
ctkimagesliders.h \
- ctkdisplaydevice.h \
ctkdisplaydevice-crt.h \
ctkdisplaydevice-tv.h \
ctkdisplaydevice-dfp.h \
@@ -89,4 +93,14 @@ EXTRA_DIST += \
ctkclocks.h \
ctkutils.h \
ctkedid.h \
- ctkimage.h
+ ctkimage.h \
+ ctkserver.h \
+ ctkdisplaylayout.h \
+ ctkdisplayconfig.h \
+ ctkscreen.h \
+ ctkgpu.h \
+ ctkbanner.h \
+ ctkvcsc.h
+
+dist_list::
+ @ echo $(SRC) $(EXTRA_DIST)
diff --git a/src/gtk+-2.x/ctkbanner.c b/src/gtk+-2.x/ctkbanner.c
new file mode 100644
index 0000000..5921535
--- /dev/null
+++ b/src/gtk+-2.x/ctkbanner.c
@@ -0,0 +1,228 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2006 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
+ * of the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+#include <gtk/gtk.h>
+
+#include "image.h"
+#include "ctkbanner.h"
+
+static void
+ctk_banner_class_init (CtkBannerClass *);
+
+static void
+ctk_banner_finalize (GObject *);
+
+static gboolean
+ctk_banner_expose_event (GtkWidget *, GdkEventExpose *);
+
+static void
+ctk_banner_size_request (GtkWidget *, GtkRequisition *);
+
+static gboolean
+ctk_banner_configure_event (GtkWidget *, GdkEventConfigure *);
+
+static GObjectClass *parent_class;
+
+
+GType ctk_banner_get_type(
+ void
+)
+{
+ static GType ctk_banner_type = 0;
+
+ if (!ctk_banner_type) {
+ static const GTypeInfo ctk_banner_info = {
+ sizeof (CtkBannerClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) ctk_banner_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (CtkBanner),
+ 0, /* n_preallocs */
+ NULL, /* instance_init */
+ };
+
+ ctk_banner_type = g_type_register_static(GTK_TYPE_DRAWING_AREA,
+ "CtkBanner", &ctk_banner_info, 0);
+ }
+
+ return ctk_banner_type;
+}
+
+static void ctk_banner_class_init(
+ CtkBannerClass *ctk_banner_class
+)
+{
+ GObjectClass *gobject_class;
+ GtkWidgetClass *widget_class;
+
+ widget_class = (GtkWidgetClass *) ctk_banner_class;
+ gobject_class = (GObjectClass *) ctk_banner_class;
+
+ parent_class = g_type_class_peek_parent(ctk_banner_class);
+
+ gobject_class->finalize = ctk_banner_finalize;
+
+ widget_class->expose_event = ctk_banner_expose_event;
+ widget_class->size_request = ctk_banner_size_request;
+ widget_class->configure_event = ctk_banner_configure_event;
+}
+
+static void ctk_banner_finalize(
+ GObject *object
+)
+{
+ CtkBanner *ctk_banner = CTK_BANNER(object);
+
+ g_object_unref(ctk_banner->gdk_img_pixbuf);
+ g_object_unref(ctk_banner->gdk_img_fill_pixbuf);
+
+ if (ctk_banner->gdk_pixbuf)
+ g_object_unref(ctk_banner->gdk_pixbuf);
+
+ free_decompressed_image(ctk_banner->image_data, NULL);
+}
+
+static gboolean ctk_banner_expose_event(
+ GtkWidget *widget,
+ GdkEventExpose *event
+)
+{
+ CtkBanner *ctk_banner = CTK_BANNER(widget);
+
+ gdk_draw_pixbuf(widget->window,
+ widget->style->fg_gc[GTK_STATE_NORMAL],
+ ctk_banner->gdk_pixbuf,
+ 0, 0, 0, 0, -1, -1,
+ GDK_RGB_DITHER_NORMAL, 0, 0);
+
+ return FALSE;
+}
+
+static gboolean ctk_banner_configure_event(
+ GtkWidget *widget,
+ GdkEventConfigure *event
+)
+{
+ CtkBanner *ctk_banner = CTK_BANNER(widget);
+ gboolean has_alpha = FALSE;
+
+ if ((event->width < ctk_banner->img->width) ||
+ (event->height < ctk_banner->img->height))
+ return FALSE;
+
+ if (ctk_banner->gdk_pixbuf)
+ g_object_unref(ctk_banner->gdk_pixbuf);
+
+ /* RGBA */
+ if (ctk_banner->img->bytes_per_pixel == 4)
+ has_alpha = TRUE;
+
+ ctk_banner->gdk_pixbuf =
+ gdk_pixbuf_new(GDK_COLORSPACE_RGB, has_alpha, 8,
+ MAX(event->width, ctk_banner->img->width),
+ MAX(event->height, ctk_banner->img->height));
+
+ gdk_pixbuf_copy_area(ctk_banner->gdk_img_pixbuf,
+ 0, 0, ctk_banner->img->fill_column_index,
+ ctk_banner->img->height,
+ ctk_banner->gdk_pixbuf,
+ 0, 0);
+
+ gdk_pixbuf_scale(ctk_banner->gdk_img_fill_pixbuf,
+ ctk_banner->gdk_pixbuf,
+ ctk_banner->img->fill_column_index, 0,
+ MAX((event->width - ctk_banner->img->width), 1),
+ ctk_banner->img->height, 0.0f, 0.0f,
+ (ctk_banner->img->fill_column_index +
+ MAX((event->width - ctk_banner->img->width), 1)),
+ 1.0f, GDK_INTERP_NEAREST);
+
+ gdk_pixbuf_copy_area(ctk_banner->gdk_img_pixbuf,
+ ctk_banner->img->fill_column_index, 0,
+ ctk_banner->img->fill_column_index,
+ ctk_banner->img->height,
+ ctk_banner->gdk_pixbuf,
+ (gdk_pixbuf_get_width(ctk_banner->gdk_pixbuf) -
+ ctk_banner->img->fill_column_index),
+ 0);
+
+ return FALSE;
+}
+
+static void ctk_banner_size_request(
+ GtkWidget *widget,
+ GtkRequisition *requisition
+)
+{
+ CtkBanner *ctk_banner = CTK_BANNER(widget);
+
+ requisition->width = ctk_banner->img->width;
+ requisition->height = ctk_banner->img->height;
+}
+
+GtkWidget* ctk_banner_new(const nv_image_t *img)
+{
+ GObject *object;
+ CtkBanner *ctk_banner;
+ guint8 *image_data;
+ gboolean has_alpha = FALSE;
+
+ if (!img->fill_column_index) return NULL;
+
+ image_data = decompress_image_data(img);
+ if (!image_data) return NULL;
+
+ object = g_object_new(CTK_TYPE_BANNER, NULL);
+
+ ctk_banner = CTK_BANNER(object);
+
+ ctk_banner->image_data = image_data;
+
+ ctk_banner->img = img;
+ ctk_banner->gdk_pixbuf = NULL;
+
+ /* RGBA */
+ if (ctk_banner->img->bytes_per_pixel == 4)
+ has_alpha = TRUE;
+
+ ctk_banner->gdk_img_pixbuf =
+ gdk_pixbuf_new_from_data(image_data, GDK_COLORSPACE_RGB,
+ has_alpha, 8, img->width, img->height,
+ img->width * img->bytes_per_pixel,
+ NULL, NULL);
+
+ ctk_banner->gdk_img_fill_pixbuf =
+ gdk_pixbuf_new(GDK_COLORSPACE_RGB, has_alpha, 8,
+ 1, ctk_banner->img->height);
+
+ gdk_pixbuf_copy_area(ctk_banner->gdk_img_pixbuf,
+ ctk_banner->img->fill_column_index, 0, 1,
+ ctk_banner->img->height,
+ ctk_banner->gdk_img_fill_pixbuf,
+ 0, 0);
+
+ return GTK_WIDGET(object);
+}
diff --git a/src/gtk+-2.x/ctkbanner.h b/src/gtk+-2.x/ctkbanner.h
new file mode 100644
index 0000000..7f9df73
--- /dev/null
+++ b/src/gtk+-2.x/ctkbanner.h
@@ -0,0 +1,77 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2006 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
+ * of the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+#ifndef __CTK_BANNER_H__
+#define __CTK_BANNER_H__
+
+#include "image.h"
+
+G_BEGIN_DECLS
+
+#define CTK_TYPE_BANNER (ctk_banner_get_type())
+
+#define CTK_BANNER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), CTK_TYPE_BANNER, CtkBanner))
+
+#define CTK_BANNER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), CTK_TYPE_BANNER, CtkBannerClass))
+
+#define CTK_IS_BANNER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CTK_TYPE_BANNER))
+
+#define CTK_IS_BANNER_CLASS(class) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), CTK_TYPE_BANNER))
+
+#define CTK_BANNER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_BANNER, CtkBannerClass))
+
+
+typedef struct _CtkBanner CtkBanner;
+typedef struct _CtkBannerClass CtkBannerClass;
+
+struct _CtkBanner
+{
+ GtkDrawingArea parent;
+
+ const nv_image_t *img;
+
+ guint8 *image_data;
+
+ GdkPixbuf *gdk_img_pixbuf;
+ GdkPixbuf *gdk_img_fill_pixbuf;
+ GdkPixbuf *gdk_pixbuf;
+};
+
+struct _CtkBannerClass
+{
+ GtkDrawingAreaClass parent_class;
+};
+
+GType ctk_banner_get_type (void) G_GNUC_CONST;
+GtkWidget* ctk_banner_new (const nv_image_t *);
+
+G_END_DECLS
+
+#endif /* __CTK_BANNER_H__ */
+
diff --git a/src/gtk+-2.x/ctkclocks.c b/src/gtk+-2.x/ctkclocks.c
index 9835ec4..023b593 100644
--- a/src/gtk+-2.x/ctkclocks.c
+++ b/src/gtk+-2.x/ctkclocks.c
@@ -692,11 +692,6 @@ GtkWidget* ctk_clocks_new(NvCtrlAttributeHandle *handle,
CTK_EVENT_NAME(NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS),
G_CALLBACK(clocks_received),
(gpointer) ctk_object);
-
- g_signal_connect(G_OBJECT(ctk_event),
- CTK_EVENT_NAME(NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS),
- G_CALLBACK(clocks_received),
- (gpointer) ctk_object);
g_signal_connect(G_OBJECT(ctk_event),
CTK_EVENT_NAME(NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE),
@@ -1150,6 +1145,10 @@ static void sync_gui_to_modify_clocks(CtkClocks *ctk_object, int which_clocks)
GET_GPU_CLOCK(clk_ranges.u.range.min),
GET_GPU_CLOCK(clk_ranges.u.range.max));
+ g_signal_handlers_unblock_by_func(G_OBJECT(gtk_adjustment_gpu),
+ G_CALLBACK(adjustment_value_changed),
+ (gpointer) ctk_object);
+
gtk_range = GTK_RANGE(CTK_SCALE(ctk_object->mem_clk_scale)->gtk_scale);
gtk_adjustment_mem = GTK_ADJUSTMENT(gtk_range->adjustment);
@@ -1166,11 +1165,6 @@ static void sync_gui_to_modify_clocks(CtkClocks *ctk_object, int which_clocks)
G_CALLBACK(adjustment_value_changed),
(gpointer) ctk_object);
- g_signal_handlers_unblock_by_func(G_OBJECT(gtk_adjustment_gpu),
- G_CALLBACK(adjustment_value_changed),
- (gpointer) ctk_object);
-
-
/* Update the gui sensitivity */
sync_gui_sensitivity(ctk_object);
diff --git a/src/gtk+-2.x/ctkconfig.c b/src/gtk+-2.x/ctkconfig.c
index cf3abe6..8ce1421 100644
--- a/src/gtk+-2.x/ctkconfig.c
+++ b/src/gtk+-2.x/ctkconfig.c
@@ -714,6 +714,7 @@ void ctk_config_add_timer(CtkConfig *ctk_config,
gpointer data)
{
GtkTreeIter iter;
+ gchar *s = g_strdup(descr);
/* Timer defaults to user enabled/owner disabled */
@@ -722,7 +723,7 @@ void ctk_config_add_timer(CtkConfig *ctk_config,
USER_ENABLE_COLUMN, TRUE,
OWNER_ENABLE_COLUMN, FALSE,
TIME_INTERVAL_COLUMN, interval,
- DESCRIPTION_COLUMN, descr,
+ DESCRIPTION_COLUMN, s,
FUNCTION_COLUMN, function,
DATA_COLUMN, data, -1);
@@ -746,6 +747,7 @@ void ctk_config_remove_timer(CtkConfig *ctk_config, GSourceFunc function)
guint handle;
gboolean user_enabled;
gboolean owner_enabled;
+ gchar *descr;
model = GTK_TREE_MODEL(ctk_config->list_store);
@@ -756,6 +758,7 @@ void ctk_config_remove_timer(CtkConfig *ctk_config, GSourceFunc function)
FUNCTION_COLUMN, &func,
USER_ENABLE_COLUMN, &user_enabled,
OWNER_ENABLE_COLUMN, &owner_enabled,
+ DESCRIPTION_COLUMN, &descr,
HANDLE_COLUMN, &handle, -1);
if (func == function) {
@@ -764,6 +767,7 @@ void ctk_config_remove_timer(CtkConfig *ctk_config, GSourceFunc function)
if (user_enabled && owner_enabled) {
g_source_remove(handle);
}
+ g_free(descr);
gtk_list_store_remove(ctk_config->list_store, &iter);
break;
}
@@ -780,7 +784,7 @@ void ctk_config_remove_timer(CtkConfig *ctk_config, GSourceFunc function)
}
}
-void ctk_config_start_timer(CtkConfig *ctk_config, GSourceFunc function)
+void ctk_config_start_timer(CtkConfig *ctk_config, GSourceFunc function, gpointer data)
{
GtkTreeModel *model;
GtkTreeIter iter;
@@ -790,7 +794,7 @@ void ctk_config_start_timer(CtkConfig *ctk_config, GSourceFunc function)
guint interval;
gboolean user_enabled;
gboolean owner_enabled;
- gpointer data;
+ gpointer model_data;
model = GTK_TREE_MODEL(ctk_config->list_store);
@@ -801,10 +805,10 @@ void ctk_config_start_timer(CtkConfig *ctk_config, GSourceFunc function)
OWNER_ENABLE_COLUMN, &owner_enabled,
HANDLE_COLUMN, &handle,
FUNCTION_COLUMN, &func,
- DATA_COLUMN, &data,
+ DATA_COLUMN, &model_data,
TIME_INTERVAL_COLUMN, &interval,
-1);
- if (func == function) {
+ if ((func == function) && (model_data == data)) {
/* Start the timer if is enabled by the user and
it is not already running. */
@@ -822,7 +826,7 @@ void ctk_config_start_timer(CtkConfig *ctk_config, GSourceFunc function)
}
}
-void ctk_config_stop_timer(CtkConfig *ctk_config, GSourceFunc function)
+void ctk_config_stop_timer(CtkConfig *ctk_config, GSourceFunc function, gpointer data)
{
GtkTreeModel *model;
GtkTreeIter iter;
@@ -832,7 +836,7 @@ void ctk_config_stop_timer(CtkConfig *ctk_config, GSourceFunc function)
guint interval;
gboolean user_enabled;
gboolean owner_enabled;
- gpointer data;
+ gpointer model_data;
model = GTK_TREE_MODEL(ctk_config->list_store);
@@ -843,10 +847,10 @@ void ctk_config_stop_timer(CtkConfig *ctk_config, GSourceFunc function)
OWNER_ENABLE_COLUMN, &owner_enabled,
HANDLE_COLUMN, &handle,
FUNCTION_COLUMN, &func,
- DATA_COLUMN, &data,
+ DATA_COLUMN, &model_data,
TIME_INTERVAL_COLUMN, &interval,
-1);
- if (func == function) {
+ if ((func == function) && (model_data == data)) {
/* Remove the timer if was running. */
diff --git a/src/gtk+-2.x/ctkconfig.h b/src/gtk+-2.x/ctkconfig.h
index 8599701..c978600 100644
--- a/src/gtk+-2.x/ctkconfig.h
+++ b/src/gtk+-2.x/ctkconfig.h
@@ -101,8 +101,8 @@ GtkTextBuffer *ctk_config_create_help (GtkTextTagTable *);
void ctk_config_add_timer(CtkConfig *, guint, gchar *, GSourceFunc, gpointer);
void ctk_config_remove_timer(CtkConfig *, GSourceFunc);
-void ctk_config_start_timer(CtkConfig *, GSourceFunc);
-void ctk_config_stop_timer(CtkConfig *, GSourceFunc);
+void ctk_config_start_timer(CtkConfig *, GSourceFunc, gpointer);
+void ctk_config_stop_timer(CtkConfig *, GSourceFunc, gpointer);
gboolean ctk_config_slider_text_entry_shown(CtkConfig *);
diff --git a/src/gtk+-2.x/ctkcursorshadow.c b/src/gtk+-2.x/ctkcursorshadow.c
index 2da653e..9d91bd4 100644
--- a/src/gtk+-2.x/ctkcursorshadow.c
+++ b/src/gtk+-2.x/ctkcursorshadow.c
@@ -849,13 +849,10 @@ static void init_color_selector(CtkCursorShadow *ctk_cursor_shadow)
GtkWidget *window;
GtkWidget *vbox;
GtkWidget *hbox;
- GtkWidget *frame;
- GtkWidget *image;
+ GtkWidget *banner;
GtkWidget *hseparator;
GtkWidget *button;
GtkWidget *alignment;
- const nv_image_t *img;
- guint8 *image_buffer = NULL;
guint ret;
/* create the color selector window */
@@ -866,7 +863,7 @@ static void init_color_selector(CtkCursorShadow *ctk_cursor_shadow)
/* create a vbox to pack all the window contents in */
- vbox = gtk_vbox_new(FALSE, 5);
+ vbox = gtk_vbox_new(FALSE, 10);
gtk_container_add(GTK_CONTAINER(window), vbox);
/* add a banner */
@@ -874,22 +871,8 @@ static void init_color_selector(CtkCursorShadow *ctk_cursor_shadow)
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
- frame = gtk_frame_new(NULL);
- gtk_box_pack_start(GTK_BOX(hbox), frame, FALSE, FALSE, 0);
-
- gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
-
- img = &cursor_banner_image;
-
- image_buffer = decompress_image_data(img);
-
- image = gtk_image_new_from_pixbuf
- (gdk_pixbuf_new_from_data(image_buffer, GDK_COLORSPACE_RGB,
- FALSE, 8, img->width, img->height,
- img->width * img->bytes_per_pixel,
- free_decompressed_image, NULL));
-
- gtk_container_add(GTK_CONTAINER(frame), image);
+ banner = ctk_banner_image_new(&cursor_banner_image);
+ gtk_box_pack_start(GTK_BOX(hbox), banner, TRUE, TRUE, 0);
/* create the color selector */
diff --git a/src/gtk+-2.x/ctkdevice.c b/src/gtk+-2.x/ctkdevice.c
deleted file mode 100644
index d64e888..0000000
--- a/src/gtk+-2.x/ctkdevice.c
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
- * and Linux systems.
- *
- * Copyright (C) 2004 NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of Version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
- * of the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the:
- *
- * Free Software Foundation, Inc.
- * 59 Temple Place - Suite 330
- * Boston, MA 02111-1307, USA
- *
- */
-
-#include <gtk/gtk.h>
-#include "NvCtrlAttributes.h"
-
-#include <stdio.h>
-
-#include "big_banner_penguin.h"
-#include "big_banner_bsd.h"
-#include "big_banner_sun.h"
-
-#include "image.h"
-
-#include "ctkdevice.h"
-#include "ctkhelp.h"
-#include "ctkutils.h"
-#define N_GDK_PIXBUFS 45
-
-
-GType ctk_device_get_type(
- void
-)
-{
- static GType ctk_device_type = 0;
-
- if (!ctk_device_type) {
- static const GTypeInfo info_ctk_device = {
- sizeof (CtkDeviceClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- NULL, /* class_init */
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (CtkDevice),
- 0, /* n_preallocs */
- NULL, /* instance_init */
- };
-
- ctk_device_type =
- g_type_register_static(GTK_TYPE_VBOX,
- "CtkDevice", &info_ctk_device, 0);
- }
-
- return ctk_device_type;
-}
-
-
-
-GtkWidget* ctk_device_new(
- NvCtrlAttributeHandle *handle
-)
-{
- GObject *object;
- CtkDevice *ctk_device;
- GtkWidget *label;
- GtkWidget *vbox;
- GtkWidget *hbox;
- GtkWidget *frame;
- GtkWidget *image;
- GtkWidget *hseparator;
- GtkWidget *table;
- GtkWidget *alignment;
-
- guint8 *image_buffer = NULL;
- const nv_image_t *img;
-
- char *product_name, *bus_type, *vbios_version, *video_ram, *irq;
- char *os, *arch, *version, *bus_rate, *bus;
- ReturnStatus ret;
- gint tmp, os_val;
-
- gchar *__unknown = "Unknown";
-
- /*
- * get the data that we will display below
- *
- * XXX should be able to update any of this if an attribute
- * changes.
- */
-
- /* NV_CTRL_STRING_PRODUCT_NAME */
-
- ret = NvCtrlGetStringAttribute(handle, NV_CTRL_STRING_PRODUCT_NAME,
- &product_name);
- if (ret != NvCtrlSuccess) product_name = "Unknown GPU";
-
- /* NV_CTRL_BUS_TYPE */
-
- ret = NvCtrlGetAttribute(handle, NV_CTRL_BUS_TYPE, &tmp);
- bus_type = NULL;
- if (ret == NvCtrlSuccess) {
- if (tmp == NV_CTRL_BUS_TYPE_AGP) bus_type = "AGP";
- if (tmp == NV_CTRL_BUS_TYPE_PCI) bus_type = "PCI";
- if (tmp == NV_CTRL_BUS_TYPE_PCI_EXPRESS) bus_type = "PCI Express";
- if (tmp == NV_CTRL_BUS_TYPE_INTEGRATED) bus_type = "Integrated";
- }
- if (!bus_type) bus_type = __unknown;
-
- /* NV_CTRL_BUS_RATE */
-
- bus_rate = NULL;
- if (tmp == NV_CTRL_BUS_TYPE_AGP ||
- tmp == NV_CTRL_BUS_TYPE_PCI_EXPRESS) {
- ret = NvCtrlGetAttribute(handle, NV_CTRL_BUS_RATE, &tmp);
- if (ret == NvCtrlSuccess) {
- bus_rate = g_strdup_printf("%dX", tmp);
- }
- }
-
- if (bus_rate != NULL) {
- bus = g_strdup_printf("%s %s", bus_type, bus_rate);
- g_free(bus_rate);
- } else {
- bus = g_strdup(bus_type);
- }
-
- /* NV_CTRL_STRING_VBIOS_VERSION */
-
- ret = NvCtrlGetStringAttribute(handle, NV_CTRL_STRING_VBIOS_VERSION,
- &vbios_version);
- if (ret != NvCtrlSuccess) vbios_version = __unknown;
-
- /* NV_CTRL_VIDEO_RAM */
-
- ret = NvCtrlGetAttribute(handle, NV_CTRL_VIDEO_RAM, &tmp);
- if (ret != NvCtrlSuccess) tmp = 0;
- video_ram = g_strdup_printf("%d MB", tmp >> 10);
-
- /* NV_CTRL_IRQ */
-
- ret = NvCtrlGetAttribute(handle, NV_CTRL_IRQ, &tmp);
- if (ret != NvCtrlSuccess) tmp = 0;
- irq = g_strdup_printf("%d", tmp);
-
- /* NV_CTRL_OPERATING_SYSTEM */
-
- os_val = NV_CTRL_OPERATING_SYSTEM_LINUX;
- ret = NvCtrlGetAttribute(handle, NV_CTRL_OPERATING_SYSTEM, &os_val);
- os = NULL;
- if (ret == NvCtrlSuccess) {
- if (os_val == NV_CTRL_OPERATING_SYSTEM_LINUX) os = "Linux";
- else if (os_val == NV_CTRL_OPERATING_SYSTEM_FREEBSD) os = "FreeBSD";
- else if (os_val == NV_CTRL_OPERATING_SYSTEM_SUNOS) os = "SunOS";
- }
- if (!os) os = __unknown;
-
- /* NV_CTRL_ARCHITECTURE */
-
- ret = NvCtrlGetAttribute(handle, NV_CTRL_ARCHITECTURE, &tmp);
- arch = NULL;
- if (ret == NvCtrlSuccess) {
- if (tmp == NV_CTRL_ARCHITECTURE_X86) arch = "x86";
- if (tmp == NV_CTRL_ARCHITECTURE_X86_64) arch = "x86_64";
- if (tmp == NV_CTRL_ARCHITECTURE_IA64) arch = "ia64";
- }
- if (!arch) arch = __unknown;
- os = g_strdup_printf("%s-%s", os, arch);
-
- /* NV_CTRL_STRING_NVIDIA_DRIVER_VERSION */
-
- ret = NvCtrlGetStringAttribute(handle,
- NV_CTRL_STRING_NVIDIA_DRIVER_VERSION,
- &version);
- if (ret != NvCtrlSuccess) version = __unknown;
-
-
-
- /* now, create the object */
-
- object = g_object_new(CTK_TYPE_DEVICE, NULL);
- ctk_device = CTK_DEVICE(object);
-
- /* cache the attribute handle */
-
- ctk_device->handle = handle;
-
- /* set container properties of the object */
-
- gtk_box_set_spacing(GTK_BOX(ctk_device), 10);
-
- /* banner */
-
- alignment = gtk_alignment_new(0, 0, 0, 0);
- gtk_box_pack_start(GTK_BOX(ctk_device), alignment, FALSE, FALSE, 0);
-
- frame = gtk_frame_new(NULL);
- gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
- gtk_container_add(GTK_CONTAINER(alignment), frame);
-
- if (os_val == NV_CTRL_OPERATING_SYSTEM_LINUX) {
- img = &big_banner_penguin_image;
- } else if (os_val == NV_CTRL_OPERATING_SYSTEM_FREEBSD) {
- img = &big_banner_bsd_image;
- } else if (os_val == NV_CTRL_OPERATING_SYSTEM_SUNOS) {
- img = &big_banner_sun_image;
- } else {
- img = &big_banner_penguin_image; /* Should never get here */
- }
-
- image_buffer = decompress_image_data(img);
-
- image = gtk_image_new_from_pixbuf
- (gdk_pixbuf_new_from_data(image_buffer, GDK_COLORSPACE_RGB,
- FALSE, 8, img->width, img->height,
- img->width * img->bytes_per_pixel,
- free_decompressed_image, NULL));
-
- gtk_container_add(GTK_CONTAINER(frame), image);
-
- /*
- * Device information: TOP->MIDDLE - LEFT->RIGHT
- *
- * This displays basic display adatper information, including
- * product name, bios version, bus type, video ram and interrupt
- * line.
- */
-
- vbox = gtk_vbox_new(FALSE, 5);
- gtk_box_pack_start(GTK_BOX(ctk_device), vbox, TRUE, TRUE, 0);
-
- hbox = gtk_hbox_new(FALSE, 0);
- gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
-
- label = gtk_label_new("Graphics Card Information");
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- hseparator = gtk_hseparator_new();
- gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5);
-
- table = gtk_table_new(7, 2, FALSE);
- gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
-
- gtk_table_set_row_spacings(GTK_TABLE(table), 3);
- gtk_table_set_col_spacings(GTK_TABLE(table), 15);
-
- gtk_container_set_border_width(GTK_CONTAINER(table), 5);
-
-
- add_table_row(table, 0, 0, "Graphics Processor:", product_name);
- add_table_row(table, 1, 0, "Bus Type:", bus);
- add_table_row(table, 2, 0, "VBIOS Version:", vbios_version);
- add_table_row(table, 3, 0, "Video Memory:", video_ram);
- add_table_row(table, 4, 0, "IRQ:", irq);
- add_table_row(table, 5, 0, "Operating System:", os);
- add_table_row(table, 6, 0, "NVIDIA Driver Version:", version);
-
- g_free(bus);
- g_free(video_ram);
- g_free(irq);
- g_free(os);
-
- gtk_widget_show_all(GTK_WIDGET(object));
-
- return GTK_WIDGET(object);
-}
-
-
-GtkTextBuffer *ctk_device_create_help(GtkTextTagTable *table,
- const gchar *screen_name)
-{
- GtkTextIter i;
- GtkTextBuffer *b;
-
- b = gtk_text_buffer_new(table);
-
- gtk_text_buffer_get_iter_at_offset(b, &i, 0);
-
- ctk_help_title(b, &i, "Graphics Card Information Help");
-
- ctk_help_para(b, &i, "This page in the NVIDIA "
- "X Server Control Panel describes basic "
- "information about the Graphics Processing Unit "
- "(GPU) on which the X screen '%s' is running.",
- screen_name);
-
- ctk_help_heading(b, &i, "Graphics Processor");
- ctk_help_para(b, &i, "This is the product name of the GPU.");
-
- ctk_help_heading(b, &i, "Bus Type");
- ctk_help_para(b, &i, "This is the bus type which is "
- "used to connect the NVIDIA GPU to the rest of "
- "your computer; possible values are AGP, PCI, "
- "PCI Express and Integrated.");
-
- ctk_help_heading(b, &i, "VBIOS Version");
- ctk_help_para(b, &i, "This is the Video BIOS version.");
-
-
- ctk_help_heading(b, &i, "Video Memory");
- ctk_help_para(b, &i, "This is the amount of video memory on your "
- "graphics card.");
-
- ctk_help_heading(b, &i, "IRQ");
- ctk_help_para(b, &i, "This is the interrupt request line assigned to "
- "this GPU.");
-
- ctk_help_heading(b, &i, "Operating System");
- ctk_help_para(b, &i, "This is the operating system on which the NVIDIA "
- "X driver is running; possible values are "
- "'Linux' and 'FreeBSD'. This also specifies the platform "
- "on which the operating system is running, such as x86, "
- "x86_64, or ia64");
-
- ctk_help_heading(b, &i, "NVIDIA Driver Version");
- ctk_help_para(b, &i, "This is the version of the NVIDIA Accelerated "
- "Graphics Driver currently in use.");
-
- ctk_help_finish(b);
-
- return b;
-}
diff --git a/src/gtk+-2.x/ctkdisplayconfig.c b/src/gtk+-2.x/ctkdisplayconfig.c
new file mode 100644
index 0000000..cc53c86
--- /dev/null
+++ b/src/gtk+-2.x/ctkdisplayconfig.c
@@ -0,0 +1,9131 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
+ * of the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+#include <stdlib.h> /* malloc */
+#include <unistd.h> /* lseek, close */
+#include <string.h> /* strlen, strdup */
+#include <errno.h>
+
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pwd.h>
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <NvCtrlAttributes.h>
+
+#include <X11/Xlib.h>
+#include <X11/Xproto.h>
+
+#include "msg.h"
+
+#include "blank_banner.h"
+
+#include "ctkimage.h"
+#include "ctkevent.h"
+#include "ctkhelp.h"
+#include "ctkdisplayconfig.h"
+#include "ctkdisplaylayout.h"
+
+
+void layout_selected_callback(nvLayoutPtr layout, void *data);
+void layout_modified_callback(nvLayoutPtr layout, void *data);
+
+static void setup_layout_frame(CtkDisplayConfig *ctk_object);
+
+static void setup_display_frame(CtkDisplayConfig *ctk_object);
+
+static void display_config_clicked(GtkWidget *widget, gpointer user_data);
+
+static void display_resolution_changed(GtkWidget *widget, gpointer user_data);
+static void display_refresh_changed(GtkWidget *widget, gpointer user_data);
+
+static void display_position_type_changed(GtkWidget *widget, gpointer user_data);
+static void display_position_offset_activate(GtkWidget *widget, gpointer user_data);
+static void display_position_relative_changed(GtkWidget *widget, gpointer user_data);
+
+static void display_panning_activate(GtkWidget *widget, gpointer user_data);
+
+static void setup_screen_frame(CtkDisplayConfig *ctk_object);
+
+static void screen_depth_changed(GtkWidget *widget, gpointer user_data);
+
+static void screen_position_type_changed(GtkWidget *widget, gpointer user_data);
+static void screen_position_offset_activate(GtkWidget *widget, gpointer user_data);
+static void screen_position_relative_changed(GtkWidget *widget, gpointer user_data);
+
+static void screen_metamode_clicked(GtkWidget *widget, gpointer user_data);
+static void screen_metamode_activate(GtkWidget *widget, gpointer user_data);
+static void screen_metamode_add_clicked(GtkWidget *widget, gpointer user_data);
+static void screen_metamode_delete_clicked(GtkWidget *widget, gpointer user_data);
+
+static void xconfig_preview_clicked(GtkWidget *widget, gpointer user_data);
+static void xconfig_file_clicked(GtkWidget *widget, gpointer user_data);
+
+static void xinerama_state_toggled(GtkWidget *widget, gpointer user_data);
+static void apply_clicked(GtkWidget *widget, gpointer user_data);
+static void save_clicked(GtkWidget *widget, gpointer user_data);
+static void probe_clicked(GtkWidget *widget, gpointer user_data);
+static void advanced_clicked(GtkWidget *widget, gpointer user_data);
+static void reset_clicked(GtkWidget *widget, gpointer user_data);
+static void validation_details_clicked(GtkWidget *widget, gpointer user_data);
+
+
+
+
+/*** D E F I N I T I O N S ***************************************************/
+
+
+#define DEFAULT_SWITCH_MODE_TIMEOUT 15 /* When switching modes, this is the
+ * number of seconds the user has to
+ * accept the new mode before we switch
+ * back to the original mode.
+ */
+
+#define TAB " "
+#define BIGTAB " "
+
+#define GTK_RESPONSE_USER_DISPLAY_ENABLE_TWINVIEW 1
+#define GTK_RESPONSE_USER_DISPLAY_ENABLE_XSCREEN 2
+
+typedef void (* apply_token_func)(char *token, char *value,
+ void *data);
+
+typedef struct SwitchModeCallbackInfoRec {
+ CtkDisplayConfig *ctk_object;
+ int screen;
+} SwitchModeCallbackInfo;
+
+
+
+
+/*** G L O B A L S ***********************************************************/
+
+static int __position_table[] = { CONF_ADJ_ABSOLUTE,
+ CONF_ADJ_RIGHTOF,
+ CONF_ADJ_LEFTOF,
+ CONF_ADJ_ABOVE,
+ CONF_ADJ_BELOW,
+ CONF_ADJ_RELATIVE };
+
+
+/* Layout tooltips */
+
+static const char * __layout_xinerama_button_help =
+"The Enable Xinerama checkbox enables the Xinerama X extension; Changing "
+"this option will require restarting your X server.";
+
+
+/* Display tooltips */
+
+static const char * __dpy_resolution_mnu_help =
+"The Resolution drop-down allows you to select a desired resolution "
+"for the currently selected display device.";
+
+static const char * __dpy_refresh_mnu_help =
+"The Refresh drop-down allows you to select a desired refresh rate "
+"for the currently selected display device. Note that the selected "
+"resolution may restrict the available refresh rates.";
+
+static const char * __dpy_position_type_help =
+"The Position Type drop-down allows you to set how the selected display "
+"device is placed within the X Screen.";
+
+static const char * __dpy_position_relative_help =
+"The Position Relative drop-down allows you to set which other display "
+"device (within the X Screen) the selected display device should be "
+"relative to.";
+
+static const char * __dpy_position_offset_help =
+"The Position Offset identifies the top left of the display device "
+"as an offset from the top left of the X Screen position.";
+
+static const char * __dpy_panning_help =
+"The Panning Domain sets the total width/height that the display "
+"device may pan within.";
+
+
+/* Screen tooltips */
+
+static const char * __screen_depth_help =
+"The Depth drop-down allows setting of the color quality for the selected "
+"screen; Changing this option will require restarting your X server.";
+
+static const char * __screen_position_type_help =
+"The Position Type drop-down allows you to set how the selected screen "
+"is placed within the X Server layout; Changing this option will require "
+"restarting your X server.";
+
+static const char * __screen_position_relative_help =
+"The Position Relative drop-down allows you to set which other Screen "
+"the selected screen should be relative to; Changing this option will "
+"require restarting your X server.";
+
+static const char * __screen_position_offset_help =
+"The Position Offset identifies the top left of the selected Screen as "
+"an offset from the top left of the X Server layout in absolute coordinates; "
+"Changing this option will require restarting your X server.";
+
+static const char * __screen_metamode_help =
+"The MetaMode selection menu allows you to set the currently displayed "
+"MetaMode for the selected screen; This option can be applied to "
+"your currently running X server.";
+
+static const char * __screen_metamode_add_button_help =
+"The Add MetaMode button allows you to create a new MetaMode for the "
+"selected screen; This option can be applied to your currently "
+"running X server.";
+
+static const char * __screen_metamode_delete_button_help =
+"The Delete MetaMode button allows you to delete the currently selected "
+"MetaMode for the screen; This option can be applied to your currently "
+"running X server.";
+
+
+/* General button tooltips */
+
+static const char * __apply_button_help =
+"The Apply button allows you to apply changes made to the server layout.";
+
+static const char * __probe_button_help =
+"The probe button allows you to probe for new display devices that may "
+"have been hotplugged.";
+
+static const char * __advanced_button_help =
+"The Advanced/Basic button toggles between a basic view, and an advanced view "
+"with extra configuration options.";
+
+static const char * __reset_button_help =
+"The Reset button will re-probe the X Server for current configuration. Any "
+"alterations you may have made (and not applied) will be lost.";
+
+static const char * __save_button_help =
+"The Save to X Configuration File button allows you to save the current "
+"X Server configuration settings to an X Configuration file.";
+
+
+
+
+/*** F U N C T I O N S *******************************************************/
+
+
+/** get_display_type_str() *******************************************
+ *
+ * Returns the type name of a display (CRT, CRT-1, DFP ..)
+ *
+ * If 'generic' is set to 1, then a generic version of the name is
+ * returned.
+ *
+ **/
+
+static gchar *get_display_type_str(unsigned int device_mask, int be_generic)
+{
+ unsigned int bit = 0;
+ int num;
+ gchar *name = NULL;
+ gchar *type_name;
+
+
+ /* Get the generic type name of the display */
+ if (device_mask & 0x000000FF) {
+ name = g_strdup("CRT");
+ bit = (device_mask & 0x000000FF);
+
+ } else if (device_mask & 0x0000FF00) {
+ name = g_strdup("TV");
+ bit = (device_mask & 0x0000FF00) >> 8;
+
+ } else if (device_mask & 0x00FF0000) {
+ name = g_strdup("DFP");
+ bit = (device_mask & 0x00FF0000) >> 16;
+ }
+
+ if (be_generic || !name) {
+ return name;
+ }
+
+
+ /* Add the specific display number to the name */
+ num = 0;
+ while (bit) {
+ num++;
+ bit >>= 1;
+ }
+ if (num) {
+ num--;
+ }
+
+ type_name = g_strdup_printf("%s-%d", name, num);
+ g_free(name);
+
+ return type_name;
+
+} /* get_display_type_str() */
+
+
+
+/** get_mode_str() ***************************************************
+ *
+ * Returns the mode string of a mode:
+ *
+ * "mode_name @WxH +X+Y"
+ *
+ **/
+
+static gchar * get_mode_str(nvModePtr mode, int be_generic)
+{
+ gchar *mode_str;
+ gchar *tmp;
+
+
+ /* Make sure the mode has everything it needs to be displayed */
+ if (!mode || !mode->display || !mode->display->gpu || !mode->metamode) {
+ return NULL;
+ }
+
+
+ /* Don't display dummy modes */
+ if (be_generic && mode->dummy && !mode->modeline) {
+ return NULL;
+ }
+
+
+ /* Only one display, be very generic (no 'CRT:' in metamode) */
+ if (be_generic && mode->display->gpu->num_displays == 1) {
+ mode_str = g_strdup("");
+
+ /* If there's more than one CRT/DFP/TV, we can't be generic. */
+ } else {
+ int generic = be_generic;
+
+ if ((mode->display->device_mask & 0x000000FF) &&
+ (mode->display->device_mask !=
+ (mode->display->gpu->connected_displays & 0x000000FF))) {
+ generic = 0;
+ }
+ if ((mode->display->device_mask & 0x0000FF00) &&
+ (mode->display->device_mask !=
+ (mode->display->gpu->connected_displays & 0x0000FF00))) {
+ generic = 0;
+ }
+ if ((mode->display->device_mask & 0x00FF0000) &&
+ (mode->display->device_mask !=
+ (mode->display->gpu->connected_displays & 0x00FF0000))) {
+ generic = 0;
+ }
+
+ /* Get the display type */
+ tmp = get_display_type_str(mode->display->device_mask, generic);
+ mode_str = g_strconcat(tmp, ": ", NULL);
+ g_free(tmp);
+ }
+
+
+ /* NULL mode */
+ if (!mode->modeline) {
+ tmp = g_strconcat(mode_str, "NULL", NULL);
+ g_free(mode_str);
+ return tmp;
+ }
+
+
+ /* Mode name */
+ tmp = g_strconcat(mode_str, mode->modeline->data.identifier, NULL);
+ g_free(mode_str);
+ mode_str = tmp;
+
+
+ /* Panning domain */
+ if (!be_generic || (mode->pan[W] != mode->dim[W] ||
+ mode->pan[H] != mode->dim[H])) {
+ tmp = g_strdup_printf("%s @%dx%d",
+ mode_str, mode->pan[W], mode->pan[H]);
+ g_free(mode_str);
+ mode_str = tmp;
+ }
+
+
+ /* Offset */
+
+ /*
+ * XXX Later, we'll want to allow the user to select how
+ * the metamodes are generated:
+ *
+ * Programability:
+ * make mode->dim relative to screen->dim
+ *
+ * Coherency:
+ * make mode->dim relative to mode->metamode->edim
+ *
+ *
+ * XXX Also, we may want to take in consideration the
+ * TwinViewOrientation when writing out position
+ * information.
+ */
+
+ tmp = g_strdup_printf("%s +%d+%d",
+ mode_str,
+ /* Make mode position relative */
+ mode->dim[X] - mode->metamode->edim[X],
+ mode->dim[Y] - mode->metamode->edim[Y]);
+ g_free(mode_str);
+ mode_str = tmp;
+
+
+ return mode_str;
+
+} /* get_mode_str() */
+
+
+
+/** get_display_from_gpu() *******************************************
+ *
+ * Returns the display with the matching device_mask
+ *
+ **/
+
+static nvDisplayPtr get_display_from_gpu(nvGpuPtr gpu,
+ unsigned int device_mask)
+{
+ nvDisplayPtr display;
+
+ for (display = gpu->displays; display; display = display->next) {
+ if (display->device_mask == device_mask) return display;
+ }
+
+ return NULL;
+
+} /* get_display_from_gpu() */
+
+
+
+/** get_cur_screen_pos() *********************************************
+ *
+ * Grabs a copy of the currently selected screen position.
+ *
+ **/
+
+static void get_cur_screen_pos(CtkDisplayConfig *ctk_object)
+{
+ nvDisplayPtr display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+ if (!display || !display->screen) return;
+
+ ctk_object->cur_screen_pos[X] = display->screen->dim[X];
+ ctk_object->cur_screen_pos[Y] = display->screen->dim[Y];
+
+} /* get_cur_screen_pos() */
+
+
+
+/** check_screen_pos_changed() ***************************************
+ *
+ * Checks to see if the screen's position changed. If so this
+ * function sets the apply_possible flag to FALSE.
+ *
+ **/
+
+static void check_screen_pos_changed(CtkDisplayConfig *ctk_object)
+{
+ int old_dim[2];
+
+ /* Cache the old position */
+ old_dim[X] = ctk_object->cur_screen_pos[X];
+ old_dim[Y] = ctk_object->cur_screen_pos[Y];
+
+ /* Get the new position */
+ get_cur_screen_pos(ctk_object);
+
+ if (old_dim[X] != ctk_object->cur_screen_pos[X] ||
+ old_dim[Y] != ctk_object->cur_screen_pos[Y]) {
+ ctk_object->apply_possible = FALSE;
+ }
+
+} /* check_screen_pos_changed() */
+
+
+/** find_closest_mode_with_modeline() ********************************
+ *
+ * Helper function that returns the mode index of the display's mode
+ * that best matches the given modeline.
+ *
+ * A best match is:
+ *
+ * - The modelines are the same.
+ * - The modelines match in width & height.
+ *
+ **/
+
+static int find_closest_mode_with_modeline(nvDisplayPtr display,
+ nvModeLinePtr modeline)
+{
+ nvModePtr mode;
+ int mode_idx;
+ int match_idx = -1;
+
+ mode_idx = 0;
+ for (mode = display->modes; mode; mode = mode->next) {
+ if (mode->modeline->data.vdisplay == modeline->data.vdisplay &&
+ mode->modeline->data.hdisplay == modeline->data.hdisplay) {
+ match_idx = mode_idx;
+ }
+ if (mode->modeline == modeline) break;
+ mode_idx++;
+ }
+
+ return match_idx;
+
+} /* find_closest_mode_with_modeline() */
+
+
+
+/** Parsing Tools ****************************************************
+ *
+ * Some tools for parsing strings
+ *
+ */
+
+static const char *skip_whitespace(const char *str)
+{
+ while (*str &&
+ (*str == ' ' || *str == '\t' ||
+ *str == '\n' || *str == '\r')) {
+ str++;
+ }
+ return str;
+}
+
+static void chop_whitespace(char *str)
+{
+ char *tmp = str + strlen(str) -1;
+
+ while (tmp >= str &&
+ (*tmp == ' ' || *tmp == '\t' ||
+ *tmp == '\n' || *tmp == '\r')) {
+ *tmp = '\0';
+ tmp++;
+ }
+}
+
+static const char *skip_integer(const char *str)
+{
+ if (*str == '-' || *str == '+') {
+ str++;
+ }
+ while (*str && *str >= '0' && *str <= '9') {
+ str++;
+ }
+ return str;
+}
+
+static const char *read_integer(const char *str, int *num)
+{
+ str = skip_whitespace(str);
+ *num = atoi(str);
+ str = skip_integer(str);
+ return skip_whitespace(str);
+}
+
+static const char *read_pair(const char *str, char separator, int *a, int *b)
+{
+ str = read_integer(str, a);
+ if (!str) return NULL;
+ if (separator) {
+ if (*str != separator) return NULL;
+ str++;
+ }
+ return read_integer(str, b);
+}
+
+static const char *read_name(const char *str, char **name, char term)
+{
+ const char *tmp;
+
+ str = skip_whitespace(str);
+ tmp = str;
+ while (*str && *str != term) {
+ str++;
+ }
+ *name = (char *)calloc(1, str -tmp +1);
+ if (!(*name)) {
+ return NULL;
+ }
+ strncpy(*name, tmp, str -tmp);
+ if (*str == term) {
+ str++;
+ }
+ return skip_whitespace(str);
+}
+
+/* Convert 'CRT-1' display device type names into a device_mask
+ * '0x00000002' bitmask
+ */
+static const char *read_display_name(const char *str, unsigned int *bit)
+{
+ if (!str || !bit) {
+ return NULL;
+ }
+
+ str = skip_whitespace(str);
+ if (!strncmp(str, "CRT-", 4)) {
+ *bit = 1 << (atoi(str+4));
+
+ } else if (!strncmp(str, "TV-", 3)) {
+ *bit = (1 << (atoi(str+3))) << 8;
+
+ } else if (!strncmp(str, "DFP-", 4)) {
+ *bit = (1 << (atoi(str+4))) << 16;
+
+ } else {
+ return NULL;
+ }
+
+ while (*str && *str != ':') {
+ str++;
+ }
+ if (*str == ':') {
+ str++;
+ }
+
+ return skip_whitespace(str);
+}
+
+static int read_float_range(char *str, float *min, float *max)
+{
+ if (!str) return 0;
+
+ str = (char *)skip_whitespace(str);
+ *min = atof(str);
+ str = strstr(str, "-");
+ if (!str) return 0;
+ str++;
+ *max = atof(str);
+
+ return 1;
+}
+
+
+
+/** apply_modeline_token() *******************************************
+ *
+ * Modifies the modeline structure given with the token/value pair
+ * given.
+ *
+ **/
+
+static void apply_modeline_token(char *token, char *value, void *data)
+{
+ nvModeLinePtr modeline = (nvModeLinePtr) data;
+
+ if (!modeline || !token || !strlen(token)) {
+ return;
+ }
+
+ /* Modeline Source */
+ if (!strcasecmp("source", token)) {
+ if (!value || !strlen(value)) {
+ nv_warning_msg("Modeline 'source' token requires a value!");
+ } else if (!strcasecmp("xserver", value)) {
+ modeline->source |= MODELINE_SOURCE_XSERVER;
+ } else if (!strcasecmp("xconfig", value)) {
+ modeline->source |= MODELINE_SOURCE_XCONFIG;
+ } else if (!strcasecmp("builtin", value)) {
+ modeline->source |= MODELINE_SOURCE_BUILTIN;
+ } else if (!strcasecmp("vesa", value)) {
+ modeline->source |= MODELINE_SOURCE_VESA;
+ } else if (!strcasecmp("edid", value)) {
+ modeline->source |= MODELINE_SOURCE_EDID;
+ } else if (!strcasecmp("nv-control", value)) {
+ modeline->source |= MODELINE_SOURCE_NVCONTROL;
+ } else {
+ nv_warning_msg("Unknown modeline source '%s'", value);
+ }
+
+ /* X Config name */
+ } else if (!strcasecmp("xconfig-name", token)) {
+ if (!value || !strlen(value)) {
+ nv_warning_msg("Modeline 'xconfig-name' token requires a value!");
+ } else {
+ if (modeline->xconfig_name) {
+ free(modeline->xconfig_name);
+ }
+ modeline->xconfig_name = g_strdup(value);
+ }
+
+ /* Unknown token */
+ } else {
+ nv_warning_msg("Unknown modeline token value pair: %s=%s",
+ token, value);
+ }
+
+} /* apply_modeline_token() */
+
+
+
+/** apply_metamode_token() *******************************************
+ *
+ * Modifies the metamode structure given with the token/value pair
+ * given.
+ *
+ **/
+
+static void apply_metamode_token(char *token, char *value, void *data)
+{
+ nvMetaModePtr metamode = (nvMetaModePtr) data;
+
+ if (!metamode || !token || !strlen(token)) {
+ return;
+ }
+
+ /* Metamode ID */
+ if (!strcasecmp("id", token)) {
+ if (!value || !strlen(value)) {
+ nv_warning_msg("MetaMode 'id' token requires a value!");
+ } else {
+ metamode->id = atoi(value);
+ }
+
+ /* Modeline Source */
+ } else if (!strcasecmp("source", token)) {
+ if (!value || !strlen(value)) {
+ nv_warning_msg("MetaMode 'source' token requires a value!");
+ } else if (!strcasecmp("xconfig", value)) {
+ metamode->source |= METAMODE_SOURCE_XCONFIG;
+ } else if (!strcasecmp("implicit", value)) {
+ metamode->source |= METAMODE_SOURCE_IMPLICIT;
+ } else if (!strcasecmp("nv-control", value)) {
+ metamode->source |= METAMODE_SOURCE_NVCONTROL;
+ } else {
+ nv_warning_msg("Unknown MetaMode source '%s'", value);
+ }
+
+ /* Switchable */
+ } else if (!strcasecmp("switchable", token)) {
+ if (!value || !strlen(value)) {
+ nv_warning_msg("MetaMode 'switchable' token requires a value!");
+ } else {
+ if (!strcasecmp(value, "yes")) {
+ metamode->switchable = TRUE;
+ } else {
+ metamode->switchable = FALSE;
+ }
+ }
+
+ /* Unknown token */
+ } else {
+ nv_warning_msg("Unknown MetaMode token value pair: %s=%s",
+ token, value);
+ }
+
+} /* apply_metamode_token */
+
+
+
+/** apply_monitor_token() ********************************************
+ *
+ * Returns the source string of a refresh/sync range.
+ *
+ **/
+
+static void apply_monitor_token(char *token, char *value, void *data)
+{
+ char **source = (char **)data;
+
+ if (!source || !token || !strlen(token)) {
+ return;
+ }
+
+ /* Metamode ID */
+ if (!strcasecmp("source", token)) {
+ if (*source) free(*source);
+ *source = strdup(value);
+
+ /* Unknown token */
+ } else {
+ nv_warning_msg("Unknown monitor range token value pair: %s=%s",
+ token, value);
+ }
+
+} /* apply_monitor_token() */
+
+
+
+/** apply_screen_info_token() ****************************************
+ *
+ * Modifies the ScreenInfo structure (pointed to by data) with
+ * information from the token-value pair given. Currently accepts
+ * position and width/height data.
+ *
+ **/
+
+typedef struct _ScreenInfo {
+ int x;
+ int y;
+ int width;
+ int height;
+} ScreenInfo;
+
+static void apply_screen_info_token(char *token, char *value, void *data)
+{
+ ScreenInfo *screen_info = (ScreenInfo *)data;
+
+ if (!screen_info || !token || !strlen(token)) {
+ return;
+ }
+
+ /* X */
+ if (!strcasecmp("x", token)) {
+ screen_info->x = atoi(value);
+
+ /* Y */
+ } else if (!strcasecmp("y", token)) {
+ screen_info->y = atoi(value);
+
+ /* Width */
+ } else if (!strcasecmp("width", token)) {
+ screen_info->width = atoi(value);
+
+ /* Height */
+ } else if (!strcasecmp("height", token)) {
+ screen_info->height = atoi(value);
+
+ /* Unknown token */
+ } else {
+ nv_warning_msg("Unknown screen info token value pair: %s=%s",
+ token, value);
+ }
+
+} /* apply_screen_info_token() */
+
+
+
+/** parse_tokens() ***************************************************
+ *
+ * Parses the given tring for "token=value, token=value, ..." pairs
+ * and dispatches the handeling of tokens to the given function with
+ * the given data as an extra argument.
+ *
+ **/
+
+static Bool parse_tokens(const char *str, apply_token_func func, void *data)
+{
+ char *token;
+ char *value;
+
+
+ if (str) {
+
+ /* Parse each token */
+ while (*str) {
+
+ /* Read the token */
+ str = read_name(str, &token, '=');
+ if (!str) return FALSE;
+
+ /* Read the value */
+ str = read_name(str, &value, ',');
+ if (!str) return FALSE;
+
+ /* Remove trailing whitespace */
+ chop_whitespace(token);
+ chop_whitespace(value);
+
+ func(token, value, data);
+
+ free(token);
+ free(value);
+ }
+ }
+
+ return TRUE;
+
+} /* parse_tokens() */
+
+
+
+/** parse_modeline() *************************************************
+ *
+ * Converts a modeline string to an X config modeline structure that
+ * the XF86Parser backend can read.
+ *
+ *
+ * Modeline strings have this format:
+ *
+ * "mode_name" dot_clock timings flags
+ *
+ **/
+
+nvModeLinePtr parse_modeline(const char *modeline_str)
+{
+ nvModeLinePtr modeline = NULL;
+ const char *str = modeline_str;
+ char *tmp;
+ char *tokens;
+
+
+ if (!str) return NULL;
+
+ modeline = (nvModeLinePtr)calloc(1, sizeof(nvModeLine));
+ if (!modeline) return NULL;
+
+ /* Parse the modeline tokens */
+ tmp = strstr(str, "::");
+ if (tmp) {
+ tokens = strdup(str);
+ tokens[ tmp-str ] = '\0';
+ str = tmp +2;
+ parse_tokens(tokens, apply_modeline_token, (void *)modeline);
+ free(tokens);
+ }
+
+ /* Read the mode name */
+ str = skip_whitespace(str);
+ if (!str || *str != '"') goto fail;
+ str++;
+ str = read_name(str, &(modeline->data.identifier), '"');
+ if (!str) goto fail;
+
+ /* Read dot clock */
+ {
+ int digits = 100;
+
+ str = read_integer(str, &(modeline->data.clock));
+ modeline->data.clock *= 1000;
+ if (*str == '.') {
+ str++;
+ while (digits &&
+ *str &&
+ *str != ' ' && *str != '\t' &&
+ *str != '\n' && *str != '\r') {
+
+ modeline->data.clock += digits * (*str - '0');
+ digits /= 10;
+ str++;
+ }
+ }
+ str = skip_whitespace(str);
+ }
+
+ str = read_integer(str, &(modeline->data.hdisplay));
+ str = read_integer(str, &(modeline->data.hsyncstart));
+ str = read_integer(str, &(modeline->data.hsyncend));
+ str = read_integer(str, &(modeline->data.htotal));
+ str = read_integer(str, &(modeline->data.vdisplay));
+ str = read_integer(str, &(modeline->data.vsyncstart));
+ str = read_integer(str, &(modeline->data.vsyncend));
+ str = read_integer(str, &(modeline->data.vtotal));
+
+
+ /* Parse modeline flags */
+ while ((str = read_name(str, &tmp, ' ')) && strlen(tmp)) {
+
+ if (!xconfigNameCompare(tmp, "+hsync")) {
+ modeline->data.flags |= XCONFIG_MODE_PHSYNC;
+ }
+ else if (!xconfigNameCompare(tmp, "-hsync")) {
+ modeline->data.flags |= XCONFIG_MODE_NHSYNC;
+ }
+ else if (!xconfigNameCompare(tmp, "+vsync")) {
+ modeline->data.flags |= XCONFIG_MODE_PVSYNC;
+ }
+ else if (!xconfigNameCompare(tmp, "-vsync")) {
+ modeline->data.flags |= XCONFIG_MODE_NVSYNC;
+ }
+ else if (!xconfigNameCompare(tmp, "interlace")) {
+ modeline->data.flags |= XCONFIG_MODE_INTERLACE;
+ }
+ else if (!xconfigNameCompare(tmp, "doublescan")) {
+ modeline->data.flags |= XCONFIG_MODE_DBLSCAN;
+ }
+ else if (!xconfigNameCompare(tmp, "composite")) {
+ modeline->data.flags |= XCONFIG_MODE_CSYNC;
+ }
+ else if (!xconfigNameCompare(tmp, "+csync")) {
+ modeline->data.flags |= XCONFIG_MODE_PCSYNC;
+ }
+ else if (!xconfigNameCompare(tmp, "-csync")) {
+ modeline->data.flags |= XCONFIG_MODE_NCSYNC;
+ }
+ else if (!xconfigNameCompare(tmp, "hskew")) {
+ str = read_integer(str, &(modeline->data.hskew));
+ if (!str) {
+ free(tmp);
+ goto fail;
+ }
+ modeline->data.flags |= XCONFIG_MODE_HSKEW;
+ }
+ else if (!xconfigNameCompare(tmp, "bcast")) {
+ modeline->data.flags |= XCONFIG_MODE_BCAST;
+ }
+ else if (!xconfigNameCompare(tmp, "CUSTOM")) {
+ modeline->data.flags |= XCONFIG_MODE_CUSTOM;
+ }
+ else if (!xconfigNameCompare(tmp, "vscan")) {
+ str = read_integer(str, &(modeline->data.vscan));
+ if (!str) {
+ free(tmp);
+ goto fail;
+ }
+ modeline->data.flags |= XCONFIG_MODE_VSCAN;
+ }
+ else {
+ nv_warning_msg("Invalid modeline keyword '%s' in modeline '%s'",
+ tmp, modeline_str);
+ goto fail;
+ }
+ free(tmp);
+ }
+
+ return modeline;
+
+
+ /* Handle failures */
+ fail:
+ free(modeline);
+ return NULL;
+
+} /* parse_modeline() */
+
+
+
+/** parse_mode() *****************************************************
+ *
+ * Makes a mode structure from the mode string given.
+ *
+ *
+ * Currently supported mode syntax:
+ *
+ * "mode_name" +X+Y @WxH
+ *
+ **/
+
+nvModePtr parse_mode(nvDisplayPtr display, const char *mode_str)
+{
+ nvModePtr mode;
+ char *mode_name; /* Modeline reference name */
+ const char *str = mode_str;
+
+
+
+ if (!str || !display || !display->modelines) return NULL;
+
+
+ /* Allocate a Mode structure */
+ mode = (nvModePtr)calloc(1, sizeof(nvMode));
+ if (!mode) return NULL;
+
+ mode->display = display;
+
+
+ /* Read the mode name */
+ str = read_name(str, &mode_name, ' ');
+ if (!str || !mode_name) goto fail;
+
+
+ /* Match the mode name to one of the modelines */
+ mode->modeline = display->modelines;
+ while (mode->modeline) {
+ if (!strcmp(mode_name, mode->modeline->data.identifier)) {
+ break;
+ }
+ mode->modeline = mode->modeline->next;
+ }
+ free(mode_name);
+
+
+ /* If we can't find a matching modeline, show device as off
+ * using the width & height of whatever the first modeline is.
+ * XXX Hopefully this is the default width/height.
+ */
+ if (!mode->modeline) {
+ if (strcmp(mode_str, "NULL")) {
+ nv_warning_msg("Mode name '%s' does not match any modelines for "
+ "display device '%s' in modeline '%s'.",
+ mode_name, display->name, mode_str);
+ }
+ mode->dim[W] = display->modelines->data.hdisplay;
+ mode->dim[H] = display->modelines->data.vdisplay;
+ mode->pan[W] = mode->dim[W];
+ mode->pan[H] = mode->dim[H];
+ return mode;
+ }
+
+
+ /* Setup default size and panning of display */
+ mode->dim[W] = mode->modeline->data.hdisplay;
+ mode->dim[H] = mode->modeline->data.vdisplay;
+ mode->pan[W] = mode->dim[W];
+ mode->pan[H] = mode->dim[H];
+
+
+ /* Read mode information */
+ while (*str) {
+
+ /* Read panning */
+ if (*str == '@') {
+ str++;
+ str = read_pair(str, 'x',
+ &(mode->pan[W]), &(mode->pan[H]));
+ }
+
+ /* Read position */
+ else if (*str == '+') {
+ str++;
+ str = read_pair(str, 0,
+ &(mode->dim[X]), &(mode->dim[Y]));
+ }
+
+ /* Mode parse error - Ack! */
+ else {
+ str = NULL;
+ }
+
+ /* Catch errors */
+ if (!str) goto fail;
+ }
+
+
+ /* These are the same for now */
+ mode->pan[X] = mode->dim[X];
+ mode->pan[Y] = mode->dim[Y];
+
+
+ /* Panning can't be smaller than dimensions */
+ if (mode->pan[W] < mode->dim[W]) {
+ mode->pan[W] = mode->dim[W];
+ }
+ if (mode->pan[W] < mode->dim[W]) {
+ mode->pan[W] = mode->dim[W];
+ }
+
+ return mode;
+
+
+ /* Handle failures */
+ fail:
+ if (mode) {
+ free(mode);
+ }
+
+ return NULL;
+
+} /* parse_mode() */
+
+
+
+/** xconfigPrint() ******************************************************
+ *
+ * xconfigPrint() - this is the one entry point that a user of the
+ * XF86Config-Parser library must provide.
+ *
+ **/
+
+void xconfigPrint(MsgType t, const char *msg)
+{
+ typedef struct {
+ MsgType msg_type;
+ char *prefix;
+ FILE *stream;
+ int newline;
+ } MessageTypeAttributes;
+
+ char *prefix = NULL;
+ int i, newline = FALSE;
+ FILE *stream = stdout;
+
+ const MessageTypeAttributes msg_types[] = {
+ { ParseErrorMsg, "PARSE ERROR: ", stderr, TRUE },
+ { ParseWarningMsg, "PARSE WARNING: ", stderr, TRUE },
+ { ValidationErrorMsg, "VALIDATION ERROR: ", stderr, TRUE },
+ { InternalErrorMsg, "INTERNAL ERROR: ", stderr, TRUE },
+ { WriteErrorMsg, "ERROR: ", stderr, TRUE },
+ { WarnMsg, "WARNING: ", stderr, TRUE },
+ { ErrorMsg, "ERROR: ", stderr, TRUE },
+ { DebugMsg, "DEBUG: ", stdout, FALSE },
+ { UnknownMsg, NULL, stdout, FALSE },
+ };
+
+ for (i = 0; msg_types[i].msg_type != UnknownMsg; i++) {
+ if (msg_types[i].msg_type == t) {
+ prefix = msg_types[i].prefix;
+ newline = msg_types[i].newline;
+ stream = msg_types[i].stream;
+ break;
+ }
+ }
+
+ if (newline) printf("\n");
+ printf("%s %s\n", prefix, msg);
+ if (newline) printf("\n");
+
+} /* xconfigPrint */
+
+
+
+/* Layout save/write functions ***************************************/
+
+
+/** get_display_mode_str() *******************************************
+ *
+ * Returns the mode string of the display's 'mode_idx''s
+ * mode.
+ *
+ **/
+static gchar *get_display_mode_str(nvDisplayPtr display, int mode_idx,
+ int be_generic)
+{
+ nvModePtr mode = display->modes;
+
+ while (mode && mode_idx) {
+ mode = mode->next;
+ mode_idx--;
+ }
+
+ if (mode) {
+ return get_mode_str(mode, be_generic);
+ }
+
+ return NULL;
+
+} /* get_display_mode_str() */
+
+
+
+/** get_screen_metamode_str() ****************************************
+ *
+ * Returns a screen's metamode string for the given metamode index
+ * as:
+ *
+ * "mode1_1, mode1_2, mode1_3 ... "
+ *
+ **/
+
+static gchar *get_screen_metamode_str(nvScreenPtr screen, int metamode_idx,
+ int be_generic)
+{
+ nvDisplayPtr display;
+
+ gchar *metamode_str = NULL;
+ gchar *mode_str;
+ gchar *tmp;
+
+ for (display = screen->gpu->displays; display; display = display->next) {
+
+ if (display->screen != screen) continue; /* Display not in screen */
+
+ mode_str = get_display_mode_str(display, metamode_idx, be_generic);
+ if (!mode_str) continue;
+
+ if (!metamode_str) {
+ metamode_str = mode_str;
+ } else {
+ tmp = g_strdup_printf("%s, %s", metamode_str, mode_str);
+ g_free(mode_str);
+ g_free(metamode_str);
+ metamode_str = tmp;
+ }
+ }
+
+ return metamode_str;
+
+} /* get_screen_metamode_str() */
+
+
+
+/** get_screen_metamode_strs() ***************************************
+ *
+ * Returns the metamode strings of a screen:
+ *
+ * "mode1_1, mode1_2, mode1_3 ... ; mode 2_1, mode 2_2, mode 2_3 ... ; ..."
+ *
+ **/
+
+static gchar *get_screen_metamode_strs(nvScreenPtr screen, int be_generic,
+ int cur_mode_first)
+{
+ gchar *metamode_strs = NULL;
+ gchar *metamode_str;
+ gchar *tmp;
+ int metamode_idx;
+ nvMetaModePtr metamode;
+
+
+ /* The current mode should appear first in the list */
+ if (cur_mode_first) {
+ metamode_strs = get_screen_metamode_str(screen,
+ screen->cur_metamode_idx,
+ be_generic);
+ }
+
+ for (metamode_idx = 0, metamode = screen->metamodes;
+ (metamode_idx < screen->num_metamodes) && metamode;
+ metamode_idx++, metamode = metamode->next) {
+
+ /* Only write out metamodes that were specified by the user */
+ if (!(metamode->source & METAMODE_SOURCE_USER)) continue;
+
+ /* The current mode was already included */
+ if (cur_mode_first && (metamode_idx == screen->cur_metamode_idx))
+ continue;
+
+ metamode_str = get_screen_metamode_str(screen, metamode_idx,
+ be_generic);
+ if (!metamode_str) continue;
+
+ if (!metamode_strs) {
+ metamode_strs = metamode_str;
+ } else {
+ tmp = g_strconcat(metamode_strs, "; ", metamode_str, NULL);
+ g_free(metamode_str);
+ g_free(metamode_strs);
+ metamode_strs = tmp;
+ }
+ }
+
+ return metamode_strs;
+
+} /* get_screen_metamode_strs() */
+
+
+
+
+/* Metamode functions ************************************************/
+
+
+/** remove_modes_from_display() **************************************
+ *
+ * Removes all modes currently referenced by this screen, also
+ * freeing any memory used.
+ *
+ **/
+
+static void remove_modes_from_display(nvDisplayPtr display)
+{
+ nvModePtr mode;
+
+ if (display) {
+ while (display->modes) {
+ mode = display->modes;
+ display->modes = mode->next;
+ free(mode);
+ }
+ display->num_modes = 0;
+ display->cur_mode = NULL;
+ }
+
+} /* remove_modes_from_display() */
+
+
+
+/** add_metamode_to_screen() *****************************************
+ *
+ * Parses a metamode string and adds the appropreate modes to the
+ * screen's display devices (at the end of the list)
+ *
+ */
+
+static Bool add_metamode_to_screen(nvScreenPtr screen, char *metamode_str,
+ gchar **err_str)
+{
+ char *mode_str;
+ char *str = NULL;
+ char *tmp;
+ char *tokens;
+ nvMetaModePtr metamode;
+
+
+ if (!screen || !screen->gpu || !metamode_str) goto fail;
+
+
+ metamode = (nvMetaModePtr)calloc(1, sizeof(nvMetaMode));
+ if (!metamode) goto fail;
+
+
+ /* Copy the string so we can split it up */
+ str = strdup(metamode_str);
+ if (!str) goto fail;
+
+
+ /* Read the MetaMode ID */
+ tmp = strstr(str, "::");
+ if (tmp) {
+ tokens = strdup(str);
+ tokens[ tmp-str ] = '\0';
+ tmp += 2;
+ parse_tokens(tokens, apply_metamode_token, (void *)metamode);
+ free(tokens);
+ } else {
+ /* No tokens? Try the old "ID: METAMODE_STR" syntax */
+ tmp = (char *)read_integer(str, &(metamode->id));
+ metamode->source = METAMODE_SOURCE_NVCONTROL;
+ if (*tmp == ':') {
+ tmp++;
+ }
+ }
+
+
+ /* Add the metamode at the end of the screen's metamode list */
+ screen->metamodes =
+ (nvMetaModePtr)xconfigAddListItem((GenericListPtr)screen->metamodes,
+ (GenericListPtr)metamode);
+
+
+ /* Split up the metamode into separate modes */
+ for (mode_str = strtok(tmp, ",");
+ mode_str;
+ mode_str = strtok(NULL, ",")) {
+
+ nvModePtr mode;
+ unsigned int device_mask;
+ nvDisplayPtr display;
+ const char *orig_mode_str = skip_whitespace(mode_str);
+
+
+ /* Parse the display device bitmask from the name */
+ mode_str = (char *)read_display_name(mode_str, &device_mask);
+ if (!mode_str) {
+ *err_str = g_strdup_printf("Failed to read a display device name "
+ "on screen %d (on GPU-%d)\nwhile "
+ "parsing metamode:\n\n'%s'",
+ screen->scrnum,
+ NvCtrlGetTargetId(screen->gpu->handle),
+ orig_mode_str);
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+
+ /* Match device bitmask to an existing display */
+ display = get_display_from_gpu(screen->gpu, device_mask);
+ if (!display) {
+ *err_str = g_strdup_printf("Failed to find display device 0x%08x "
+ "on screen %d (on GPU-%d)\nwhile "
+ "parsing metamode:\n\n'%s'",
+ device_mask,
+ screen->scrnum,
+ NvCtrlGetTargetId(screen->gpu->handle),
+ orig_mode_str);
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+
+ /* Parse the mode */
+ mode = parse_mode(display, mode_str);
+ if (!mode) {
+ *err_str = g_strdup_printf("Failed to parse mode '%s'\non "
+ "screen %d (on GPU-%d)\nfrom "
+ "metamode:\n\n'%s'",
+ mode_str, screen->scrnum,
+ NvCtrlGetTargetId(screen->gpu->handle),
+ orig_mode_str);
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+
+ /* Make the mode part of the metamode */
+ mode->metamode = metamode;
+
+
+ /* Make the display part of the screen */
+ display->screen = screen;
+
+
+ /* Set the panning offset */
+ mode->pan[X] = mode->dim[X];
+ mode->pan[Y] = mode->dim[Y];
+
+
+ /* Add the mode at the end of the display's mode list */
+ display->modes =
+ (nvModePtr)xconfigAddListItem((GenericListPtr)display->modes,
+ (GenericListPtr)mode);
+ display->num_modes++;
+
+ } /* Done parsing a single metamode */
+
+ free(str);
+ return TRUE;
+
+
+ /* Failure case */
+ fail:
+
+ /* XXX We should probably track which modes were added and remove
+ * them at this point. For now, just assume the caller will
+ * remove all the modes and bail.
+ */
+
+ free(str);
+ return FALSE;
+
+} /* add_metamode_to_screen() */
+
+
+
+/** check_screen_metamodes() *****************************************
+ *
+ * Makes sure all displays associated with the screen have the right
+ * number of mode entries.
+ *
+ **/
+
+static Bool check_screen_metamodes(nvScreenPtr screen)
+{
+ nvDisplayPtr display;
+ nvMetaModePtr metamode;
+ nvModePtr mode;
+ nvModePtr last_mode = NULL;
+
+
+ for (display = screen->gpu->displays; display; display = display->next) {
+
+ if (display->screen != screen) continue;
+
+ if (display->num_modes == screen->num_metamodes) continue;
+
+ mode = display->modes;
+ metamode = screen->metamodes;
+ while (mode && metamode) {
+ mode = mode->next;
+ metamode = metamode->next;
+ if (mode) {
+ last_mode = mode;
+ }
+ }
+
+ /* Each display must have as many modes as it's screen has metamodes */
+ while (metamode) {
+
+ /* Create a dumy mode */
+ mode = parse_mode(display, "NULL");
+ mode->dummy = 1;
+ mode->metamode = metamode;
+
+ /* Duplicate position information of the last mode */
+ if (last_mode) {
+ mode->dim[X] = last_mode->dim[X];
+ mode->dim[Y] = last_mode->dim[Y];
+ mode->pan[X] = last_mode->pan[X];
+ mode->pan[Y] = last_mode->pan[Y];
+ mode->position_type = last_mode->position_type;
+ mode->relative_to = last_mode->relative_to;
+ }
+
+ /* Add the mode at the end of display's mode list */
+ display->modes =
+ (nvModePtr)xconfigAddListItem((GenericListPtr)display->modes,
+ (GenericListPtr)mode);
+ display->num_modes++;
+
+ metamode = metamode->next;
+ }
+
+ /* XXX Shouldn't need to remove extra modes.
+ while (mode) {
+ }
+ */
+ }
+
+ return TRUE;
+
+} /* check_screen_metamodes() */
+
+
+
+/** assign_dummy_metamode_positions() ********************************
+ *
+ * Assign the initial (top left) position of dummy modes to
+ * match the top left of the first non-dummy mode
+ *
+ */
+
+static void assign_dummy_metamode_positions(nvScreenPtr screen)
+{
+ nvDisplayPtr display;
+ nvModePtr ok_mode;
+ nvModePtr mode;
+
+
+ for (display = screen->gpu->displays; display; display = display->next) {
+ if (display->screen != screen) continue;
+
+ /* Get the first non-dummy mode */
+ for (ok_mode = display->modes; ok_mode; ok_mode = ok_mode->next) {
+ if (!ok_mode->dummy) break;
+ }
+
+ if (ok_mode) {
+ for (mode = display->modes; mode; mode = mode->next) {
+ if (!mode->dummy) continue;
+ mode->dim[X] = ok_mode->dim[X];
+ mode->pan[X] = ok_mode->dim[X];
+ mode->dim[Y] = ok_mode->dim[Y];
+ mode->pan[Y] = ok_mode->dim[Y];
+ }
+ }
+ }
+
+} /* assign_dummy_metamode_positions() */
+
+
+
+/** remove_metamodes_from_screen() ***********************************
+ *
+ * Removes all metamodes currently referenced by this screen, also
+ * freeing any memory used.
+ *
+ **/
+
+static void remove_metamodes_from_screen(nvScreenPtr screen)
+{
+ nvGpuPtr gpu;
+ nvDisplayPtr display;
+ nvMetaModePtr metamode;
+
+ if (screen) {
+ gpu = screen->gpu;
+
+ /* Remove the modes from this screen's displays */
+ if (gpu) {
+ for (display = gpu->displays; display; display = display->next) {
+
+ if (display->screen != screen) continue;
+
+ remove_modes_from_display(display);
+ }
+ }
+
+ /* Clear the screen's metamode list */
+ while (screen->metamodes) {
+ metamode = screen->metamodes;
+ screen->metamodes = metamode->next;
+ free(metamode->string);
+ free(metamode);
+ }
+ screen->num_metamodes = 0;
+ screen->cur_metamode = NULL;
+ screen->cur_metamode_idx = -1;
+ }
+
+} /* remove_metamodes_from_screen() */
+
+
+
+/** add_metamodes_to_screen() ****************************************
+ *
+ * Adds all the appropreate modes on all display devices of this
+ * screen by parsing all the metamode strings.
+ *
+ */
+
+static Bool add_metamodes_to_screen(nvScreenPtr screen, gchar **err_str)
+{
+ nvDisplayPtr display;
+
+ char *metamode_strs = NULL; /* Screen's list metamode strings */
+ char *cur_metamode_str; /* Current metamode */
+
+ char *str; /* Temp pointer for parsing */
+ int len;
+ ReturnStatus ret;
+ int i;
+
+
+
+ /* Get the list of metamodes for the screen */
+ ret = NvCtrlGetBinaryAttribute(screen->handle, 0,
+ NV_CTRL_BINARY_DATA_METAMODES,
+ (unsigned char **)&metamode_strs,
+ &len);
+ if (ret != NvCtrlSuccess) {
+ *err_str = g_strdup_printf("Failed to query list of metamodes on\n"
+ "screen %d (on GPU-%d).",
+ screen->scrnum,
+ NvCtrlGetTargetId(screen->gpu->handle));
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+
+ /* Get the current metamode for the screen */
+ ret = NvCtrlGetStringAttribute(screen->handle,
+ NV_CTRL_STRING_CURRENT_METAMODE,
+ &cur_metamode_str);
+ if (ret != NvCtrlSuccess) {
+ *err_str = g_strdup_printf("Failed to query current metamode of\n"
+ "screen %d (on GPU-%d).",
+ screen->scrnum,
+ NvCtrlGetTargetId(screen->gpu->handle));
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+
+ /* Remove any existing modes on all displays */
+ remove_metamodes_from_screen(screen);
+
+
+ /* Parse each mode in the metamode strings */
+ str = metamode_strs;
+ while (str && strlen(str)) {
+
+ /* Add the individual metamodes to the screen,
+ * This populates the display device's mode list.
+ */
+ if (!add_metamode_to_screen(screen, str, err_str)) {
+ nv_warning_msg("Failed to add metamode '%s' to screen %d (on "
+ "GPU-%d).",
+ str, screen->scrnum,
+ NvCtrlGetTargetId(screen->gpu->handle));
+ goto fail;
+ }
+
+ /* Keep track of the current metamode */
+ if (!strcmp(str, cur_metamode_str)) {
+ screen->cur_metamode_idx = screen->num_metamodes;
+ }
+
+ /* Keep count of the metamode */
+ screen->num_metamodes++;
+
+ /* Make sure each display device gets a mode */
+ check_screen_metamodes(screen);
+
+ /* Go to the next metamode */
+ str += strlen(str) +1;
+ }
+ XFree(metamode_strs);
+
+
+ /* Assign the top left position of dummy modes */
+ assign_dummy_metamode_positions(screen);
+
+
+ /* Make the screen point at the current metamode */
+ screen->cur_metamode = screen->metamodes;
+ for (i = 0; i < screen->cur_metamode_idx; i++) {
+ screen->cur_metamode = screen->cur_metamode->next;
+ }
+
+
+ /* Make each display within the screen point to the current mode.
+ * Also, count the number of displays on the screen
+ */
+ screen->num_displays = 0;
+ for (display = screen->gpu->displays; display; display = display->next) {
+
+ if (display->screen != screen) continue; /* Display not in screen */
+
+ screen->num_displays++;
+ screen->displays_mask |= display->device_mask;
+
+ display->cur_mode = display->modes;
+ for (i = 0; i < screen->cur_metamode_idx; i++) {
+ display->cur_mode = display->cur_mode->next;
+ }
+ }
+
+ return TRUE;
+
+
+ /* Failure case */
+ fail:
+
+ /* Remove modes we may have added */
+ remove_metamodes_from_screen(screen);
+
+ XFree(metamode_strs);
+ return FALSE;
+
+} /* add_metamodes_to_screen() */
+
+
+
+/* Screen functions **************************************************/
+
+
+/** remove_display_from_screen() *************************************
+ *
+ * Removes a display device from the screen
+ *
+ */
+static void remove_display_from_screen(nvDisplayPtr display)
+{
+ nvGpuPtr gpu;
+ nvScreenPtr screen;
+ nvDisplayPtr other;
+ nvModePtr mode;
+
+
+ if (display && display->screen) {
+ screen = display->screen;
+ gpu = display->gpu;
+
+ /* Make any display relative to this one use absolute position */
+ for (other = gpu->displays; other; other = other->next) {
+
+ if (other == display) continue;
+ if (other->screen != screen) continue;
+
+ for (mode = other->modes; mode; mode = mode->next) {
+ if (mode->relative_to == display) {
+ mode->position_type = CONF_ADJ_ABSOLUTE;
+ mode->relative_to = NULL;
+ }
+ }
+ }
+
+ /* Remove the display from the screen */
+ screen->displays_mask &= ~(display->device_mask);
+ screen->num_displays--;
+
+ /* Clean up old references to the screen in the display */
+ remove_modes_from_display(display);
+ display->screen = NULL;
+ }
+
+} /* remove_display_from_screen() */
+
+
+
+/** remove_displays_from_screen() ************************************
+ *
+ * Removes all displays currently pointing at this screen, also
+ * freeing any memory used.
+ *
+ **/
+
+void remove_displays_from_screen(nvScreenPtr screen)
+{
+ nvGpuPtr gpu;
+ nvDisplayPtr display;
+
+ if (screen && screen->gpu) {
+ gpu = screen->gpu;
+
+ for (display = gpu->displays; display; display = display->next) {
+
+ if (display->screen != screen) continue;
+
+ remove_display_from_screen(display);
+ }
+ }
+
+} /* remove_displays_from_screen() */
+
+
+
+/** free_screen() ****************************************************
+ *
+ * Frees memory used by a screen structure
+ *
+ */
+static void free_screen(nvScreenPtr screen)
+{
+ if (screen) {
+
+ remove_metamodes_from_screen(screen);
+ remove_displays_from_screen(screen);
+
+ if (screen->handle) {
+ NvCtrlAttributeClose(screen->handle);
+ }
+
+ free(screen);
+ }
+
+} /* free_screens() */
+
+
+
+/** add_screen_to_gpu() **********************************************
+ *
+ * Adds screen 'screen_id' that is connected to the gpu.
+ *
+ */
+static int add_screen_to_gpu(nvGpuPtr gpu, int screen_id, gchar **err_str)
+{
+ Display *display;
+ nvScreenPtr screen;
+ int val;
+ ReturnStatus ret;
+
+
+ /* Create the screen structure */
+ screen = (nvScreenPtr)calloc(1, sizeof(nvScreen));
+ if (!screen) goto fail;
+
+ screen->gpu = gpu;
+ screen->scrnum = screen_id;
+
+
+ /* Make an NV-CONTROL handle to talk to the screen */
+ display = NvCtrlGetDisplayPtr(gpu->handle);
+ screen->handle =
+ NvCtrlAttributeInit(display,
+ NV_CTRL_TARGET_TYPE_X_SCREEN,
+ screen_id,
+ NV_CTRL_ATTRIBUTES_NV_CONTROL_SUBSYSTEM |
+ NV_CTRL_ATTRIBUTES_XRANDR_SUBSYSTEM);
+ if (!screen->handle) {
+ *err_str = g_strdup_printf("Failed to create NV-CONTROL handle for\n"
+ "screen %d (on GPU-%d).",
+ screen_id, NvCtrlGetTargetId(gpu->handle));
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+
+ /* Make sure this screen supports dynamic twinview */
+ ret = NvCtrlGetAttribute(screen->handle, NV_CTRL_DYNAMIC_TWINVIEW,
+ &val);
+ if (ret != NvCtrlSuccess || !val) {
+ *err_str = g_strdup_printf("Dynamic TwinView is disabled on "
+ "screen %d.",
+ screen_id);
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+
+ /* The display owner GPU gets the screen(s) */
+ ret = NvCtrlGetAttribute(screen->handle, NV_CTRL_MULTIGPU_DISPLAY_OWNER,
+ &val);
+ if (ret != NvCtrlSuccess || val != NvCtrlGetTargetId(gpu->handle)) {
+ free_screen(screen);
+ return TRUE;
+ }
+
+
+ /* Listen to NV-CONTROL events on this screen handle */
+ screen->ctk_event = CTK_EVENT(ctk_event_new(screen->handle));
+
+
+ /* Query the depth of the screen */
+ screen->depth = NvCtrlGetScreenPlanes(screen->handle);
+
+
+ /* Parse the screen's metamodes (ties displays on the gpu to the screen) */
+ if (!add_metamodes_to_screen(screen, err_str)) {
+ nv_warning_msg("Failed to add metamodes to screen %d (on GPU-%d).",
+ screen_id, NvCtrlGetTargetId(gpu->handle));
+ goto fail;
+ }
+
+
+ /* Add the screen at the end of the gpu's screen list */
+ gpu->screens =
+ (nvScreenPtr)xconfigAddListItem((GenericListPtr)gpu->screens,
+ (GenericListPtr)screen);
+ gpu->num_screens++;
+ return TRUE;
+
+
+ fail:
+ free_screen(screen);
+ return FALSE;
+
+} /* add_screen_to_gpu() */
+
+
+
+/** remove_screen_from_gpu() *****************************************
+ *
+ * Removes a screen from a gpu.
+ *
+ */
+static void remove_screen_from_gpu(nvScreenPtr screen)
+{
+ nvGpuPtr gpu;
+ nvScreenPtr other;
+
+ if (!screen || !screen->gpu) return;
+
+ /* Remove the screen from the GPU */
+ gpu = screen->gpu;
+
+ gpu->screens =
+ (nvScreenPtr)xconfigRemoveListItem((GenericListPtr)gpu->screens,
+ (GenericListPtr)screen);
+ gpu->num_screens--;
+
+ /* Make sure other screens in the layout aren't relative
+ * to this screen
+ */
+ for (gpu = screen->gpu->layout->gpus; gpu; gpu = gpu->next) {
+ for (other = gpu->screens; other; other = other->next) {
+ if (other->relative_to == screen) {
+ other->position_type = CONF_ADJ_ABSOLUTE;
+ other->relative_to = NULL;
+ }
+ }
+ }
+
+ screen->gpu = NULL;
+
+ /* XXX May want to remove metamodes here */
+ /* XXX May want to remove displays here */
+
+} /* remove_screen_from_gpu() */
+
+
+
+/** remove_screens_from_gpu() ****************************************
+ *
+ * Removes all screens from a gpu.
+ *
+ */
+static void remove_screens_from_gpu(nvGpuPtr gpu)
+{
+ nvScreenPtr screen;
+
+ if (gpu) {
+ while (gpu->screens) {
+ screen = gpu->screens;
+ gpu->screens = screen->next;
+ free_screen(screen);
+ }
+ gpu->num_screens = 0;
+ }
+
+} /* remove_screens_from_gpu() */
+
+
+
+/** add_screens_to_gpu() *********************************************
+ *
+ * Queries the list of screens on the gpu.
+ *
+ */
+static Bool add_screens_to_gpu(nvGpuPtr gpu, gchar **err_str)
+{
+ ReturnStatus ret;
+ int *pData;
+ int len;
+ int i;
+
+
+ /* Clean up the GPU list */
+ remove_screens_from_gpu(gpu);
+
+
+ /* Query the list of X Screens this GPU is driving */
+ ret = NvCtrlGetBinaryAttribute(gpu->handle, 0,
+ NV_CTRL_BINARY_DATA_XSCREENS_USING_GPU,
+ (unsigned char **)(&pData), &len);
+ if (ret != NvCtrlSuccess) {
+ *err_str = g_strdup_printf("Failed to query list of screens driven\n"
+ "by GPU-%d '%s'.",
+ NvCtrlGetTargetId(gpu->handle), gpu->name);
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+
+ /* Add each X Screen */
+ for (i = 1; i <= pData[0]; i++) {
+ if (!add_screen_to_gpu(gpu, pData[i], err_str)) {
+ nv_warning_msg("Failed to add screen %d to GPU-%d '%s'.",
+ pData[i], NvCtrlGetTargetId(gpu->handle),
+ gpu->name);
+ goto fail;
+ }
+ }
+
+ return TRUE;
+
+
+ /* Failure case */
+ fail:
+ remove_screens_from_gpu(gpu);
+ return FALSE;
+
+} /* add_screens_to_gpu() */
+
+
+
+/* Display device functions ******************************************/
+
+
+/** remove_modelines_from_display() **********************************
+ *
+ * Clears the display device's modeline list.
+ *
+ **/
+
+static void remove_modelines_from_display(nvDisplayPtr display)
+{
+ nvModeLinePtr modeline;
+
+ if (display) {
+ while (display->modelines) {
+ modeline = display->modelines;
+ display->modelines = display->modelines->next;
+ free(modeline);
+ }
+ display->num_modelines = 0;
+ }
+
+} /* remove_modelines_from_display() */
+
+
+
+/** add_modelines_to_display() ***************************************
+ *
+ * Queries the display's current modepool (modelines list).
+ *
+ **/
+
+static Bool add_modelines_to_display(nvDisplayPtr display, gchar **err_str)
+{
+ nvModeLinePtr modeline;
+ char *modeline_strs = NULL;
+ char *str;
+ int len;
+ ReturnStatus ret;
+
+
+ /* Free any old mode lines */
+ remove_modelines_from_display(display);
+
+
+ /* Get the validated modelines for the display */
+ ret = NvCtrlGetBinaryAttribute(display->gpu->handle,
+ display->device_mask,
+ NV_CTRL_BINARY_DATA_MODELINES,
+ (unsigned char **)&modeline_strs, &len);
+ if (ret != NvCtrlSuccess) {
+ *err_str = g_strdup_printf("Failed to query modelines of display "
+ "device 0x%08x '%s'\nconnected to "
+ "GPU-%d '%s'.",
+ display->device_mask, display->name,
+ NvCtrlGetTargetId(display->gpu->handle),
+ display->gpu->name);
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+
+ /* Parse each modeline */
+ str = modeline_strs;
+ while (strlen(str)) {
+
+ modeline = parse_modeline(str);
+ if (!modeline) {
+ *err_str = g_strdup_printf("Failed to parse the following "
+ "modeline of display device\n"
+ "0x%08x '%s' connected to GPU-%d "
+ "'%s':\n\n%s",
+ display->device_mask,
+ display->name,
+ NvCtrlGetTargetId(display->gpu->handle),
+ display->gpu->name,
+ str);
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+ /* Add the modeline at the end of the display's modeline list */
+ display->modelines = (nvModeLinePtr)xconfigAddListItem
+ ((GenericListPtr)display->modelines, (GenericListPtr)modeline);
+ display->num_modelines++;
+
+ /* Get next modeline string */
+ str += strlen(str) +1;
+ }
+
+ XFree(modeline_strs);
+ return TRUE;
+
+
+ /* Handle the failure case */
+ fail:
+ remove_modelines_from_display(display);
+ XFree(modeline_strs);
+ return FALSE;
+
+} /* add_modelines_to_display() */
+
+
+
+/** free_display() ***************************************************
+ *
+ * Frees memory used by a display
+ *
+ */
+static void free_display(nvDisplayPtr display)
+{
+ if (display) {
+ remove_modes_from_display(display);
+ remove_modelines_from_display(display);
+ XFree(display->name);
+ free(display);
+ }
+
+} /* free_display(display) */
+
+
+
+/** add_display_to_gpu() *********************************************
+ *
+ * Adds the display with the device mask given to the GPU structure.
+ *
+ */
+static nvDisplayPtr add_display_to_gpu(nvGpuPtr gpu, unsigned int device_mask,
+ gchar **err_str)
+{
+ ReturnStatus ret;
+ nvDisplayPtr display = NULL;
+
+
+ /* Create the display structure */
+ display = (nvDisplayPtr)calloc(1, sizeof(nvDisplay));
+ if (!display) goto fail;
+
+
+ /* Init the display structure */
+ display->gpu = gpu;
+ display->device_mask = device_mask;
+
+
+ /* Query the display information */
+ ret = NvCtrlGetStringDisplayAttribute(gpu->handle,
+ device_mask,
+ NV_CTRL_STRING_DISPLAY_DEVICE_NAME,
+ &(display->name));
+ if (ret != NvCtrlSuccess) {
+ *err_str = g_strdup_printf("Failed to query name of display device\n"
+ "0x%08x connected to GPU-%d '%s'.",
+ device_mask, NvCtrlGetTargetId(gpu->handle),
+ gpu->name);
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+
+ /* Query the modelines for the display device */
+ if (!add_modelines_to_display(display, err_str)) {
+ nv_warning_msg("Failed to add modelines to display device 0x%08x "
+ "'%s'\nconnected to GPU-%d '%s'.",
+ device_mask, display->name,
+ NvCtrlGetTargetId(gpu->handle), gpu->name);
+ goto fail;
+ }
+
+
+ /* Add the display at the end of gpu's display list */
+ gpu->displays =
+ (nvDisplayPtr)xconfigAddListItem((GenericListPtr)gpu->displays,
+ (GenericListPtr)display);
+ gpu->connected_displays |= device_mask;
+ gpu->num_displays++;
+ return display;
+
+
+ /* Failure case */
+ fail:
+ free_display(display);
+ return NULL;
+
+} /* add_display_to_gpu() */
+
+
+
+/** remove_display_from_gpu() ****************************************
+ *
+ * Removes a display from the gpu
+ *
+ */
+static void remove_display_from_gpu(nvDisplayPtr display)
+{
+ nvGpuPtr gpu;
+ nvScreenPtr screen;
+
+
+ if (display && display->gpu) {
+ gpu = display->gpu;
+ screen = display->screen;
+
+ /* Remove the display from the screen it may be in */
+ if (screen) {
+ remove_display_from_screen(display);
+
+ /* If the screen is empty, remove it too */
+ if (!screen->num_displays) {
+ remove_screen_from_gpu(screen);
+ free_screen(screen);
+ }
+ }
+
+ /* Remove the display from the gpu */
+ gpu->displays =
+ (nvDisplayPtr)xconfigRemoveListItem((GenericListPtr)gpu->displays,
+ (GenericListPtr)display);
+ gpu->connected_displays &= ~(display->device_mask);
+ gpu->num_displays--;
+ }
+
+} /* remove_display_from_gpu() */
+
+
+
+/** remove_displays_from_gpu() ***************************************
+ *
+ * Removes all displays from the gpu
+ *
+ */
+static void remove_displays_from_gpu(nvGpuPtr gpu)
+{
+ nvDisplayPtr display;
+
+ if (gpu) {
+ while (gpu->displays) {
+ display = gpu->displays;
+ remove_display_from_screen(display);
+ gpu->displays = display->next;
+ free_display(display);
+ }
+ gpu->num_displays = 0;
+ }
+
+} /* remove_displays_from_gpu() */
+
+
+
+/** add_displays_to_gpu() ********************************************
+ *
+ * Adds the display devices connected on the GPU to the GPU structure
+ *
+ */
+static Bool add_displays_to_gpu(nvGpuPtr gpu, gchar **err_str)
+{
+ unsigned int mask;
+
+
+ /* Clean up the GPU list */
+ remove_displays_from_gpu(gpu);
+
+
+ /* Add each connected display */
+ for (mask = 1; mask; mask <<= 1) {
+
+ if (!(mask & (gpu->connected_displays))) continue;
+
+ if (!add_display_to_gpu(gpu, mask, err_str)) {
+ nv_warning_msg("Failed to add display device 0x%08x to GPU-%d "
+ "'%s'.",
+ mask, NvCtrlGetTargetId(gpu->handle), gpu->name);
+ goto fail;
+ }
+ }
+
+ return TRUE;
+
+
+ /* Failure case */
+ fail:
+ remove_displays_from_gpu(gpu);
+ return FALSE;
+
+} /* add_displays_to_gpu() */
+
+
+
+/* GPU functions *****************************************************/
+
+
+/** add_screenless_modes_to_displays() *******************************
+ *
+ * Adds fake modes to display devices that have no screens so we
+ * can show them on the layout page.
+ *
+ */
+static Bool add_screenless_modes_to_displays(nvGpuPtr gpu)
+{
+ nvDisplayPtr display;
+ nvModePtr mode;
+
+ for (display = gpu->displays; display; display = display->next) {
+ if (display->screen) continue;
+
+ /* Create a fake mode */
+ mode = (nvModePtr)calloc(1, sizeof(nvMode));
+ if (!mode) return FALSE;
+
+ mode->display = display;
+ mode->dummy = 1;
+
+ mode->dim[W] = 800;
+ mode->dim[H] = 600;
+ mode->pan[W] = mode->dim[W];
+ mode->pan[H] = mode->dim[H];
+
+ /* Add the mode to the display */
+ display->modes = mode;
+ display->cur_mode = mode;
+ display->num_modes = 1;
+ }
+
+ return TRUE;
+
+} /* add_screenless_modes_to_displays() */
+
+
+
+/** free_gpu() *******************************************************
+ *
+ * Frees memory used by the gpu.
+ *
+ **/
+static void free_gpu(nvGpuPtr gpu)
+{
+ if (gpu) {
+ remove_screens_from_gpu(gpu);
+ remove_displays_from_gpu(gpu);
+ XFree(gpu->name);
+ if (gpu->handle) {
+ NvCtrlAttributeClose(gpu->handle);
+ }
+ free(gpu);
+ }
+
+} /* free_gpu() */
+
+
+
+/** add_gpu_to_layout() **********************************************
+ *
+ * Adds a GPU to the layout structure.
+ *
+ **/
+static Bool add_gpu_to_layout(nvLayoutPtr layout, unsigned int gpu_id,
+ gchar **err_str)
+{
+ ReturnStatus ret;
+ Display *dpy;
+ nvGpuPtr gpu = NULL;
+
+
+ /* Create the GPU structure */
+ gpu = (nvGpuPtr)calloc(1, sizeof(nvGpu));
+ if (!gpu) goto fail;
+
+
+ /* Make an NV-CONTROL handle to talk to the GPU */
+ dpy = NvCtrlGetDisplayPtr(layout->handle);
+ gpu->layout = layout;
+ gpu->handle = NvCtrlAttributeInit(dpy, NV_CTRL_TARGET_TYPE_GPU, gpu_id,
+ NV_CTRL_ATTRIBUTES_NV_CONTROL_SUBSYSTEM);
+ if (!gpu->handle) {
+ *err_str = g_strdup_printf("Failed to create NV-CONTROL handle for "
+ "GPU-%d.", gpu_id);
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+ gpu->ctk_event = CTK_EVENT(ctk_event_new(gpu->handle));
+
+
+ /* Query the GPU information */
+ ret = NvCtrlGetStringAttribute(gpu->handle, NV_CTRL_STRING_PRODUCT_NAME,
+ &gpu->name);
+ if (ret != NvCtrlSuccess) {
+ *err_str = g_strdup_printf("Failed to query GPU name of GPU-%d.",
+ gpu_id);
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+ ret = NvCtrlGetAttribute(gpu->handle, NV_CTRL_CONNECTED_DISPLAYS,
+ (int *)&(gpu->connected_displays));
+ if (ret != NvCtrlSuccess) {
+ *err_str = g_strdup_printf("Failed to query connected display "
+ "devices on GPU-%d '%s'.",
+ gpu_id, gpu->name);
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+ ret = NvCtrlGetAttribute(gpu->handle, NV_CTRL_PCI_BUS,
+ (int *)&(gpu->pci_bus));
+ if (ret != NvCtrlSuccess) {
+ *err_str = g_strdup_printf("Failed to query PCI BUS on GPU-%d '%s'.",
+ gpu_id, gpu->name);
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+ ret = NvCtrlGetAttribute(gpu->handle, NV_CTRL_PCI_DEVICE,
+ (int *)&(gpu->pci_device));
+ if (ret != NvCtrlSuccess) {
+ *err_str = g_strdup_printf("Failed to query PCI DEVICE on "
+ "GPU-%d '%s'.", gpu_id, gpu->name);
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+ ret = NvCtrlGetAttribute(gpu->handle, NV_CTRL_PCI_FUNCTION,
+ (int *)&(gpu->pci_func));
+ if (ret != NvCtrlSuccess) {
+ *err_str = g_strdup_printf("Failed to query PCI FUNCTION on "
+ "GPU-%d '%s'.", gpu_id, gpu->name);
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+ ret = NvCtrlGetAttribute(gpu->handle, NV_CTRL_MAX_SCREEN_WIDTH,
+ (int *)&(gpu->max_width));
+ if (ret != NvCtrlSuccess) {
+ *err_str = g_strdup_printf("Failed to query MAX SCREEN WIDTH on "
+ "GPU-%d '%s'.", gpu_id, gpu->name);
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+ ret = NvCtrlGetAttribute(gpu->handle, NV_CTRL_MAX_SCREEN_HEIGHT,
+ (int *)&(gpu->max_height));
+ if (ret != NvCtrlSuccess) {
+ *err_str = g_strdup_printf("Failed to query MAX SCREEN HEIGHT on "
+ "GPU-%d '%s'.", gpu_id, gpu->name);
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+ ret = NvCtrlGetAttribute(gpu->handle, NV_CTRL_MAX_DISPLAYS,
+ (int *)&(gpu->max_displays));
+ if (ret != NvCtrlSuccess) {
+ *err_str = g_strdup_printf("Failed to query MAX DISPLAYS on "
+ "GPU-%d '%s'.", gpu_id, gpu->name);
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+
+ /* Add the display devices to the GPU */
+ if (!add_displays_to_gpu(gpu, err_str)) {
+ nv_warning_msg("Failed to add displays to GPU-%d '%s'.",
+ gpu_id, gpu->name);
+ goto fail;
+ }
+
+
+ /* Add the X Screens to the GPU */
+ if (!add_screens_to_gpu(gpu, err_str)) {
+ nv_warning_msg("Failed to add screens to GPU-%d '%s'.",
+ gpu_id, gpu->name);
+ goto fail;
+ }
+
+
+ /* Add fake modes to screenless display devices */
+ if (!add_screenless_modes_to_displays(gpu)) {
+ nv_warning_msg("Failed to add screenless modes to GPU-%d '%s'.",
+ gpu_id, gpu->name);
+ goto fail;
+ }
+
+
+ /* Add the GPU at the end of the layout's GPU list */
+ layout->gpus = (nvGpuPtr)xconfigAddListItem((GenericListPtr)layout->gpus,
+ (GenericListPtr)gpu);
+ layout->num_gpus++;
+ return TRUE;
+
+
+ /* Failure case */
+ fail:
+ free_gpu(gpu);
+ return FALSE;
+
+} /* add_gpu_to_layout() */
+
+
+
+/** remove_gpus_from_layout() ****************************************
+ *
+ * Removes all GPUs from the layout structure.
+ *
+ **/
+static void remove_gpus_from_layout(nvLayoutPtr layout)
+{
+ nvGpuPtr gpu;
+
+ if (layout) {
+ while (layout->gpus) {
+ gpu = layout->gpus;
+ layout->gpus = gpu->next;
+ free_gpu(gpu);
+ }
+ layout->num_gpus = 0;
+ }
+
+} /* remove_gpus_from_layout() */
+
+
+
+/** add_gpus_to_layout() *********************************************
+ *
+ * Adds the GPUs found on the server to the layout structure.
+ *
+ **/
+
+static int add_gpus_to_layout(nvLayoutPtr layout, gchar **err_str)
+{
+ ReturnStatus ret;
+ int ngpus;
+ int i;
+
+
+ /* Clean up the GPU list */
+ remove_gpus_from_layout(layout);
+
+
+ /* Query the number of GPUs on the server */
+ ret = NvCtrlQueryTargetCount(layout->handle, NV_CTRL_TARGET_TYPE_GPU,
+ &ngpus);
+ if (ret != NvCtrlSuccess || !ngpus) {
+ *err_str = g_strdup("Failed to query number of GPUs (or no GPUs "
+ "found) in the system.");
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+
+ /* Add each GPU */
+ for (i = 0; i < ngpus; i++) {
+ if (!add_gpu_to_layout(layout, i, err_str)) {
+ nv_warning_msg("Failed to add GPU-%d to layout.", i);
+ goto fail;
+ }
+ }
+
+ return layout->num_gpus;
+
+
+ /* Failure case */
+ fail:
+ remove_gpus_from_layout(layout);
+ return 0;
+
+} /* add_gpus_to_layout() */
+
+
+
+/* Layout functions **************************************************/
+
+
+/** assign_screen_positions() ****************************************
+ *
+ * Assign the initial position of the X Screens.
+ *
+ * - If Xinerama is enabled, query the XINERAMA_SCREEN_INFO.
+ *
+ * - If Xinerama is disabled, assume "right-of" orientation. (bleh!)
+ *
+ **/
+
+static void assign_screen_positions(CtkDisplayConfig *ctk_object)
+{
+ nvGpuPtr gpu;
+ nvScreenPtr prev_screen = NULL;
+ nvScreenPtr screen;
+ int xinerama;
+ int initialize = 0;
+
+ char *screen_info;
+ ScreenInfo screen_parsed_info;
+ ReturnStatus ret;
+
+
+ /* If xinerama is enabled, we can get the screen size! */
+ ret = NvCtrlGetAttribute(ctk_object->handle, NV_CTRL_XINERAMA, &xinerama);
+ if (ret != NvCtrlSuccess) {
+ initialize = 1; /* Fallback to right-of positioning */
+ }
+
+
+ /* Setup screen positions */
+ for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) {
+ for (screen = gpu->screens; screen; screen = screen->next) {
+
+ screen_info = NULL;
+ if (screen->handle && !initialize) {
+ ret = NvCtrlGetStringAttribute
+ (screen->handle,
+ NV_CTRL_STRING_XINERAMA_SCREEN_INFO,
+ &screen_info);
+
+ if (ret != NvCtrlSuccess) {
+ screen_info = NULL;
+ }
+ }
+
+ if (screen_info) {
+
+ /* Parse the positioning information */
+
+ screen_parsed_info.x = -1;
+ screen_parsed_info.y = -1;
+ screen_parsed_info.width = -1;
+ screen_parsed_info.height = -1;
+
+ parse_tokens(screen_info, apply_screen_info_token,
+ &screen_parsed_info);
+
+ if (screen_parsed_info.x >= 0 &&
+ screen_parsed_info.y >= 0 &&
+ screen_parsed_info.width >= 0 &&
+ screen_parsed_info.height) {
+
+ ctk_display_layout_set_screen_position
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ screen, CONF_ADJ_ABSOLUTE, NULL,
+ screen_parsed_info.x,
+ screen_parsed_info.y);
+ }
+ XFree(screen_info);
+
+ } else if (prev_screen) {
+ /* Set this screen right of the previous */
+ ctk_display_layout_set_screen_position
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ screen, CONF_ADJ_RIGHTOF, prev_screen, 0, 0);
+ }
+
+ prev_screen = screen;
+ }
+ }
+
+} /* assign_screen_positions() */
+
+
+
+/** load_server_layout() *********************************************
+ *
+ * Loads layout information from the X server.
+ *
+ **/
+
+nvLayoutPtr load_server_layout(NvCtrlAttributeHandle *handle, gchar **err_str)
+{
+ nvLayoutPtr layout;
+ ReturnStatus ret;
+
+
+ /* Allocate the layout structure */
+ layout = (nvLayoutPtr)calloc(1, sizeof(nvLayout));
+ if (!layout) goto fail;
+
+
+ /* Cache the handle for talking to the X Server */
+ layout->handle = handle;
+
+
+ /* Is Xinerma enabled? */
+ ret = NvCtrlGetAttribute(handle, NV_CTRL_XINERAMA,
+ &layout->xinerama_enabled);
+ if (ret != NvCtrlSuccess) {
+ *err_str = g_strdup("Failed to query status of Xinerama.");
+ nv_error_msg(*err_str);
+ goto fail;
+ }
+
+
+ /* Add GPUs to the layout */
+ if (!add_gpus_to_layout(layout, err_str)) {
+ nv_warning_msg("Failed to add GPU(s) to layout for display "
+ "configuration page.");
+ goto fail;
+ }
+
+ return layout;
+
+
+ /* Failure case */
+ fail:
+ if (layout) {
+ remove_gpus_from_layout(layout);
+ free(layout);
+ }
+ return NULL;
+
+} /* load_server_layout() */
+
+
+
+/* Widget creation functions *****************************************/
+
+
+/** ctk_display_config_get_type() ************************************
+ *
+ * Returns the display configuration type.
+ *
+ **/
+
+GType ctk_display_config_get_type(void)
+{
+ static GType ctk_display_config_type = 0;
+
+ if (!ctk_display_config_type) {
+ static const GTypeInfo ctk_display_config_info = {
+ sizeof (CtkDisplayConfigClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof(CtkDisplayConfig),
+ 0, /* n_preallocs */
+ NULL, /* instance_init */
+ };
+
+ ctk_display_config_type = g_type_register_static
+ (GTK_TYPE_VBOX, "CtkDisplayConfig", &ctk_display_config_info, 0);
+ }
+
+ return ctk_display_config_type;
+
+} /* ctk_display_config_get_type() */
+
+
+
+/** create_validation_dialog() ***************************************
+ *
+ * Creates the Validation Information dialog widget.
+ *
+ **/
+
+GtkWidget * create_validation_dialog(CtkDisplayConfig *ctk_object)
+{
+ GtkWidget *dialog;
+ GtkWidget *image;
+ GtkWidget *hbox;
+ GtkWidget *vbox;
+ GtkWidget *label;
+ GtkWidget *button;
+ GtkWidget *scrolled_window;
+ GtkWidget *textview;
+ GtkTextBuffer *buffer;
+
+
+ /* Display validation override confirmation dialog */
+ dialog = gtk_dialog_new_with_buttons
+ ("Layout Inconsistencie(s)",
+ GTK_WINDOW(gtk_widget_get_parent(GTK_WIDGET(ctk_object))),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ NULL);
+
+ /* Main horizontal box */
+ hbox = gtk_hbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+ hbox, TRUE, TRUE, 5);
+
+ /* Pack the information icon */
+ image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_INFO,
+ GTK_ICON_SIZE_DIALOG);
+ gtk_misc_set_alignment(GTK_MISC(image), 0.0f, 0.0f);
+ gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 5);
+
+ /* Main vertical box */
+ vbox = gtk_vbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 5);
+
+ /* Pack the main message */
+ label = gtk_label_new("The current layout has some inconsistencies.");
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.0f);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+
+ /* Details button */
+ button = gtk_button_new();
+ hbox = gtk_hbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ g_signal_connect(G_OBJECT(button), "clicked",
+ G_CALLBACK(validation_details_clicked),
+ (gpointer) ctk_object);
+ ctk_object->btn_validation_override_show = button;
+
+ /* Text view */
+ textview = gtk_text_view_new();
+ gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(textview), FALSE);
+ gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), FALSE);
+ gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(textview), GTK_WRAP_WORD);
+ gtk_text_view_set_left_margin(GTK_TEXT_VIEW(textview), 5);
+ gtk_text_view_set_pixels_above_lines(GTK_TEXT_VIEW(textview), 5);
+
+ buffer = gtk_text_buffer_new(NULL);
+ gtk_text_view_set_buffer(GTK_TEXT_VIEW(textview),
+ GTK_TEXT_BUFFER(buffer));
+
+ ctk_object->buf_validation_override = buffer;
+
+ scrolled_window = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_shadow_type
+ (GTK_SCROLLED_WINDOW(scrolled_window), GTK_SHADOW_IN);
+ gtk_container_add(GTK_CONTAINER(scrolled_window), textview);
+
+ /* Pack the scrolled window */
+ hbox = gtk_hbox_new(TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), scrolled_window, TRUE, TRUE, 5);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
+ ctk_object->box_validation_override_details = hbox;
+
+ /* Action Buttons */
+ gtk_dialog_add_button(GTK_DIALOG(dialog), "Auto Fix", GTK_RESPONSE_APPLY);
+ gtk_dialog_add_button(GTK_DIALOG(dialog), "Ignore", GTK_RESPONSE_ACCEPT);
+ /* Keep track of the cancel button so we can set focus on it */
+ button = gtk_dialog_add_button(GTK_DIALOG(dialog), "Cancel",
+ GTK_RESPONSE_REJECT);
+ ctk_object->btn_validation_override_cancel = button;
+
+ gtk_widget_show_all(GTK_DIALOG(dialog)->vbox);
+
+ return dialog;
+
+} /* create_validation_dialog() */
+
+
+
+/** create_validation_apply_dialog() *********************************
+ *
+ * Creates the Validation Apply Information dialog widget.
+ *
+ **/
+
+GtkWidget * create_validation_apply_dialog(CtkDisplayConfig *ctk_object)
+{
+ GtkWidget *dialog;
+ GtkWidget *image;
+ GtkWidget *hbox;
+ GtkWidget *vbox;
+ GtkWidget *label;
+ gchar bullet[8]; // UTF8 Bullet string
+ int len;
+ gchar *str;
+
+
+ /* Convert the Unicode "Bullet" Character into a UTF8 string */
+ len = g_unichar_to_utf8(0x2022, bullet);
+ bullet[len] = '\0';
+
+ /* Display validation override confirmation dialog */
+ dialog = gtk_dialog_new_with_buttons
+ ("Cannot Apply",
+ GTK_WINDOW(gtk_widget_get_parent(GTK_WIDGET(ctk_object))),
+ GTK_DIALOG_MODAL |
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ NULL);
+ ctk_object->dlg_validation_apply = dialog;
+
+ /* Main horizontal box */
+ hbox = gtk_hbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+ hbox, TRUE, TRUE, 5);
+
+ /* Pack the information icon */
+ image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_INFO,
+ GTK_ICON_SIZE_DIALOG);
+ gtk_misc_set_alignment(GTK_MISC(image), 0.0f, 0.0f);
+ gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 5);
+
+ /* Main vertical box */
+ vbox = gtk_vbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 5);
+
+ /* Pack the main message */
+ str = g_strdup_printf("The current settings cannot be completely applied\n"
+ "due to one or more of the following reasons:\n"
+ "\n"
+ "%s The location an X Screens has changed.\n"
+ "%s The location type of an X Screens has changed.\n"
+ "%s The color depth of an X Screen has changed.\n"
+ "%s An X Screen has been added or removed.\n"
+ "%s Xinerama is being enabled/disabled.\n"
+ "\n"
+ "For all the requested settings to take effect,\n"
+ "you must save the configuration to the X Config\n"
+ "file and restart the X Server.",
+ bullet, bullet, bullet, bullet, bullet);
+ label = gtk_label_new(str);
+ g_free(str);
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.0f);
+ gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
+
+ /* Action Buttons */
+ gtk_dialog_add_button(GTK_DIALOG(dialog), "Apply What Is Possible",
+ GTK_RESPONSE_ACCEPT);
+ gtk_dialog_add_button(GTK_DIALOG(dialog), "Cancel", GTK_RESPONSE_REJECT);
+
+ gtk_widget_show_all(GTK_DIALOG(dialog)->vbox);
+
+ return dialog;
+
+} /* create_validation_apply_dialog() */
+
+
+
+/** ctk_display_config_new() *****************************************
+ *
+ * Display Configuration widget creation.
+ *
+ **/
+
+GtkWidget* ctk_display_config_new(NvCtrlAttributeHandle *handle,
+ CtkConfig *ctk_config)
+{
+ GObject *object;
+ CtkDisplayConfig *ctk_object;
+
+ GtkWidget *banner;
+ GtkWidget *frame;
+ GtkWidget *hbox;
+ GtkWidget *hbox2;
+ GtkWidget *vbox;
+ GtkWidget *label;
+
+ GtkRequisition req;
+
+ GtkWidget *vpanel;
+ GtkWidget *scrolled_window;
+ GtkWidget *viewport;
+
+ GtkWidget *menu;
+ GtkWidget *menu_item;
+
+ gchar *err_str = NULL;
+
+
+ /*
+ * Create the ctk object
+ *
+ */
+
+ object = g_object_new(CTK_TYPE_DISPLAY_CONFIG, NULL);
+ ctk_object = CTK_DISPLAY_CONFIG(object);
+
+ ctk_object->handle = handle;
+ ctk_object->ctk_config = ctk_config;
+
+ ctk_object->apply_possible = TRUE;
+ ctk_object->advanced_mode = FALSE;
+
+ /* Set container properties of the object & pack the banner */
+ gtk_box_set_spacing(GTK_BOX(ctk_object), 5);
+
+ banner = ctk_banner_image_new(&blank_banner_image);
+ gtk_box_pack_start(GTK_BOX(object), banner, FALSE, FALSE, 0);
+
+
+
+ /*
+ * Create the display configuration widgets
+ *
+ */
+
+ /* Load the layout structure from the X server */
+ ctk_object->layout = load_server_layout(handle, &err_str);
+
+ /* If we failed to load, tell the user why */
+ if (err_str || !ctk_object->layout) {
+ gchar *str;
+
+ if (!err_str) {
+ str = g_strdup("Failed to load X Server Display Configuration.");
+ } else {
+ str = g_strdup_printf("Error while loading X Server Display "
+ "Configuration:\n\n%s", err_str);
+ g_free(err_str);
+ }
+
+ label = gtk_label_new(str);
+ g_free(str);
+ gtk_label_set_selectable(GTK_LABEL(label), TRUE);
+ gtk_container_add(GTK_CONTAINER(object), label);
+
+ /* Show the GUI */
+ gtk_widget_show_all(GTK_WIDGET(ctk_object));
+
+ return GTK_WIDGET(ctk_object);
+ }
+
+ /* Create the layout widget */
+ ctk_object->obj_layout = ctk_display_layout_new(handle, ctk_config,
+ ctk_object->layout,
+ 300, /* min width */
+ 225, /* min height */
+ layout_selected_callback,
+ (void *)ctk_object,
+ layout_modified_callback,
+ (void *)ctk_object);
+
+ /* Make sure we have some kind of positioning */
+ assign_screen_positions(ctk_object);
+
+ /* Grab the current screen position for "apply possible" tracking */
+ get_cur_screen_pos(ctk_object);
+
+
+ /*
+ * Create the widgets
+ *
+ */
+
+ /* Xinerama button */
+
+ ctk_object->chk_xinerama_enabled =
+ gtk_check_button_new_with_label("Enable Xinerama");
+ ctk_config_set_tooltip(ctk_config, ctk_object->chk_xinerama_enabled,
+ __layout_xinerama_button_help);
+ g_signal_connect(G_OBJECT(ctk_object->chk_xinerama_enabled), "toggled",
+ G_CALLBACK(xinerama_state_toggled),
+ (gpointer) ctk_object);
+
+
+ /* Display model name */
+ ctk_object->txt_display_model = gtk_label_new("");
+ gtk_label_set_selectable(GTK_LABEL(ctk_object->txt_display_model), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(ctk_object->txt_display_model), 0.0f, 0.5f);
+
+ /* Display configuration (Disabled, TwinView, Separate X Screen */
+ ctk_object->btn_display_config =
+ gtk_button_new_with_label("Configure...");
+ g_signal_connect(G_OBJECT(ctk_object->btn_display_config), "clicked",
+ G_CALLBACK(display_config_clicked),
+ (gpointer) ctk_object);
+ ctk_object->txt_display_config = gtk_label_new("Disabled");
+ gtk_misc_set_alignment(GTK_MISC(ctk_object->txt_display_config), 0.0f, 0.5f);
+
+
+ /* Display configuration dialog */
+ ctk_object->dlg_display_config = gtk_dialog_new_with_buttons
+ ("Configure Display Device",
+ GTK_WINDOW(gtk_widget_get_parent(GTK_WIDGET(ctk_object))),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT
+ | GTK_DIALOG_NO_SEPARATOR,
+ GTK_STOCK_OK,
+ GTK_RESPONSE_ACCEPT,
+ NULL);
+ ctk_object->btn_display_config_cancel =
+ gtk_dialog_add_button(GTK_DIALOG(ctk_object->dlg_display_config),
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL);
+ ctk_object->rad_display_config_disabled =
+ gtk_radio_button_new_with_label(NULL, "Disabled");
+ ctk_object->rad_display_config_xscreen =
+ gtk_radio_button_new_with_label_from_widget
+ (GTK_RADIO_BUTTON(ctk_object->rad_display_config_disabled),
+ "Separate X Screen");
+ ctk_object->rad_display_config_twinview =
+ gtk_radio_button_new_with_label_from_widget
+ (GTK_RADIO_BUTTON(ctk_object->rad_display_config_disabled),
+ "TwinView");
+ gtk_window_set_resizable(GTK_WINDOW(ctk_object->dlg_display_config),
+ FALSE);
+
+ /* Display disable dialog */
+ ctk_object->txt_display_disable = gtk_label_new("");
+ ctk_object->dlg_display_disable = gtk_dialog_new_with_buttons
+ ("Disable Display Device",
+ GTK_WINDOW(gtk_widget_get_parent(GTK_WIDGET(ctk_object))),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT
+ | GTK_DIALOG_NO_SEPARATOR,
+ NULL);
+ ctk_object->btn_display_disable_off =
+ gtk_dialog_add_button(GTK_DIALOG(ctk_object->dlg_display_disable),
+ "Remove",
+ GTK_RESPONSE_ACCEPT);
+ ctk_object->btn_display_disable_cancel =
+ gtk_dialog_add_button(GTK_DIALOG(ctk_object->dlg_display_disable),
+ "Ignore",
+ GTK_RESPONSE_CANCEL);
+ gtk_window_set_resizable(GTK_WINDOW(ctk_object->dlg_display_disable),
+ FALSE);
+
+
+ /* Display resolution */
+ ctk_object->mnu_display_resolution = gtk_option_menu_new();
+ ctk_config_set_tooltip(ctk_config, ctk_object->mnu_display_resolution,
+ __dpy_resolution_mnu_help);
+ g_signal_connect(G_OBJECT(ctk_object->mnu_display_resolution), "changed",
+ G_CALLBACK(display_resolution_changed),
+ (gpointer) ctk_object);
+
+
+ /* Display refresh */
+ ctk_object->mnu_display_refresh = gtk_option_menu_new();
+ ctk_config_set_tooltip(ctk_config, ctk_object->mnu_display_refresh,
+ __dpy_refresh_mnu_help);
+ g_signal_connect(G_OBJECT(ctk_object->mnu_display_refresh), "changed",
+ G_CALLBACK(display_refresh_changed),
+ (gpointer) ctk_object);
+
+ /* Display modeline modename */
+ ctk_object->txt_display_modename = gtk_label_new("");
+
+ /* Display Position Type (Absolute/Relative Menu) */
+ ctk_object->mnu_display_position_type = gtk_option_menu_new();
+ menu = gtk_menu_new();
+ menu_item = gtk_menu_item_new_with_label("Absolute");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ menu_item = gtk_menu_item_new_with_label("Right of");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ menu_item = gtk_menu_item_new_with_label("Left of");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ menu_item = gtk_menu_item_new_with_label("Above");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ menu_item = gtk_menu_item_new_with_label("Below");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ menu_item = gtk_menu_item_new_with_label("Clones");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ gtk_option_menu_set_menu
+ (GTK_OPTION_MENU(ctk_object->mnu_display_position_type), menu);
+ ctk_config_set_tooltip(ctk_config, ctk_object->mnu_display_position_type,
+ __dpy_position_type_help);
+ g_signal_connect(G_OBJECT(ctk_object->mnu_display_position_type),
+ "changed", G_CALLBACK(display_position_type_changed),
+ (gpointer) ctk_object);
+
+ /* Display Position Relative (Display device to be relative to) */
+ ctk_object->mnu_display_position_relative = gtk_option_menu_new();
+ ctk_config_set_tooltip(ctk_config,
+ ctk_object->mnu_display_position_relative,
+ __dpy_position_relative_help);
+ g_signal_connect(G_OBJECT(ctk_object->mnu_display_position_relative),
+ "changed",
+ G_CALLBACK(display_position_relative_changed),
+ (gpointer) ctk_object);
+
+ /* Display Position Offset (Absolute position) */
+ ctk_object->txt_display_position_offset = gtk_entry_new();
+ ctk_config_set_tooltip(ctk_config, ctk_object->txt_display_position_offset,
+ __dpy_position_offset_help);
+ g_signal_connect(G_OBJECT(ctk_object->txt_display_position_offset),
+ "activate", G_CALLBACK(display_position_offset_activate),
+ (gpointer) ctk_object);
+
+ /* Display Panning */
+ ctk_object->txt_display_panning = gtk_entry_new();
+ ctk_config_set_tooltip(ctk_config, ctk_object->txt_display_panning,
+ __dpy_panning_help);
+ g_signal_connect(G_OBJECT(ctk_object->txt_display_panning), "activate",
+ G_CALLBACK(display_panning_activate),
+ (gpointer) ctk_object);
+
+
+ /* X Screen number */
+ ctk_object->txt_screen_num = gtk_label_new("");
+ gtk_label_set_selectable(GTK_LABEL(ctk_object->txt_screen_num), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(ctk_object->txt_screen_num), 0.0f, 0.5f);
+
+ /* X Screen depth */
+ ctk_object->mnu_screen_depth = gtk_option_menu_new();
+ ctk_config_set_tooltip(ctk_config, ctk_object->mnu_screen_depth,
+ __screen_depth_help);
+ g_signal_connect(G_OBJECT(ctk_object->mnu_screen_depth), "changed",
+ G_CALLBACK(screen_depth_changed),
+ (gpointer) ctk_object);
+
+ /* Screen Position Type (Absolute/Relative Menu) */
+ ctk_object->mnu_screen_position_type = gtk_option_menu_new();
+ menu = gtk_menu_new();
+ menu_item = gtk_menu_item_new_with_label("Absolute");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ menu_item = gtk_menu_item_new_with_label("Right of");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ menu_item = gtk_menu_item_new_with_label("Left of");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ menu_item = gtk_menu_item_new_with_label("Above");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ menu_item = gtk_menu_item_new_with_label("Below");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ // XXX Add better support for this later.
+ //menu_item = gtk_menu_item_new_with_label("Relative to");
+ //gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ gtk_option_menu_set_menu
+ (GTK_OPTION_MENU(ctk_object->mnu_screen_position_type), menu);
+ ctk_config_set_tooltip(ctk_config, ctk_object->mnu_screen_position_type,
+ __screen_position_type_help);
+ g_signal_connect(G_OBJECT(ctk_object->mnu_screen_position_type),
+ "changed", G_CALLBACK(screen_position_type_changed),
+ (gpointer) ctk_object);
+
+ /* Screen Position Relative (Screen to be relative to) */
+ ctk_object->mnu_screen_position_relative = gtk_option_menu_new();
+ ctk_config_set_tooltip(ctk_config,
+ ctk_object->mnu_screen_position_relative,
+ __screen_position_relative_help);
+ g_signal_connect(G_OBJECT(ctk_object->mnu_screen_position_relative),
+ "changed",
+ G_CALLBACK(screen_position_relative_changed),
+ (gpointer) ctk_object);
+
+ /* Screen Position Offset (Absolute position) */
+ ctk_object->txt_screen_position_offset = gtk_entry_new();
+ ctk_config_set_tooltip(ctk_config, ctk_object->txt_screen_position_offset,
+ __screen_position_offset_help);
+ g_signal_connect(G_OBJECT(ctk_object->txt_screen_position_offset),
+ "activate", G_CALLBACK(screen_position_offset_activate),
+ (gpointer) ctk_object);
+
+ /* X Screen metamode */
+ ctk_object->btn_screen_metamode = gtk_button_new();
+ ctk_config_set_tooltip(ctk_config, ctk_object->btn_screen_metamode,
+ __screen_metamode_help);
+ g_signal_connect(G_OBJECT(ctk_object->btn_screen_metamode), "clicked",
+ G_CALLBACK(screen_metamode_clicked),
+ (gpointer) ctk_object);
+
+ ctk_object->btn_screen_metamode_add = gtk_button_new_with_label("Add");
+ ctk_config_set_tooltip(ctk_config, ctk_object->btn_screen_metamode_add,
+ __screen_metamode_add_button_help);
+ g_signal_connect(G_OBJECT(ctk_object->btn_screen_metamode_add), "clicked",
+ G_CALLBACK(screen_metamode_add_clicked),
+ (gpointer) ctk_object);
+
+ ctk_object->btn_screen_metamode_delete =
+ gtk_button_new_with_label("Delete");
+ ctk_config_set_tooltip(ctk_config, ctk_object->btn_screen_metamode_delete,
+ __screen_metamode_delete_button_help);
+ g_signal_connect(G_OBJECT(ctk_object->btn_screen_metamode_delete),
+ "clicked",
+ G_CALLBACK(screen_metamode_delete_clicked),
+ (gpointer) ctk_object);
+
+
+ /* Create the Validation dialog */
+ ctk_object->dlg_validation_override = create_validation_dialog(ctk_object);
+
+
+ /* Create the Apply Validation dialog */
+ ctk_object->dlg_validation_apply =
+ create_validation_apply_dialog(ctk_object);
+ gtk_window_set_resizable(GTK_WINDOW(ctk_object->dlg_validation_apply),
+ FALSE);
+
+
+ /* Reset confirmation dialog */
+ ctk_object->dlg_reset_confirm = gtk_dialog_new_with_buttons
+ ("Confirm Reset",
+ GTK_WINDOW(gtk_widget_get_parent(GTK_WIDGET(ctk_object))),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT
+ | GTK_DIALOG_NO_SEPARATOR,
+ GTK_STOCK_OK,
+ GTK_RESPONSE_ACCEPT,
+ NULL);
+ ctk_object->btn_reset_cancel =
+ gtk_dialog_add_button(GTK_DIALOG(ctk_object->dlg_reset_confirm),
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_REJECT);
+ gtk_window_set_resizable(GTK_WINDOW(ctk_object->dlg_reset_confirm),
+ FALSE);
+
+
+ /* Display ModeSwitch confirmation dialog */
+ ctk_object->dlg_display_confirm = gtk_dialog_new_with_buttons
+ ("Confirm ModeSwitch",
+ GTK_WINDOW(gtk_widget_get_parent(GTK_WIDGET(ctk_object))),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT
+ | GTK_DIALOG_NO_SEPARATOR,
+ GTK_STOCK_OK,
+ GTK_RESPONSE_ACCEPT,
+ NULL);
+ ctk_object->btn_display_apply_cancel =
+ gtk_dialog_add_button(GTK_DIALOG(ctk_object->dlg_display_confirm),
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_REJECT);
+ gtk_window_set_resizable(GTK_WINDOW(ctk_object->dlg_display_confirm),
+ FALSE);
+
+
+ /* Display confirm dialog text (Dynamically generated) */
+ ctk_object->txt_display_confirm = gtk_label_new("");
+
+
+ /* X config save dialog */
+ ctk_object->dlg_xconfig_save = gtk_dialog_new_with_buttons
+ ("Save X Configuration",
+ GTK_WINDOW(gtk_widget_get_parent(GTK_WIDGET(ctk_object))),
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT |
+ GTK_DIALOG_NO_SEPARATOR,
+ GTK_STOCK_SAVE,
+ GTK_RESPONSE_ACCEPT,
+ GTK_STOCK_CANCEL,
+ GTK_RESPONSE_REJECT,
+ NULL);
+ gtk_dialog_set_default_response(GTK_DIALOG(ctk_object->dlg_xconfig_save),
+ GTK_RESPONSE_REJECT);
+
+ ctk_object->btn_xconfig_preview = gtk_button_new();
+ g_signal_connect(G_OBJECT(ctk_object->btn_xconfig_preview), "clicked",
+ G_CALLBACK(xconfig_preview_clicked),
+ (gpointer) ctk_object);
+
+ ctk_object->txt_xconfig_save = gtk_text_view_new();
+ gtk_text_view_set_left_margin
+ (GTK_TEXT_VIEW(ctk_object->txt_xconfig_save), 5);
+
+ ctk_object->buf_xconfig_save = gtk_text_buffer_new(NULL);
+ gtk_text_view_set_buffer(GTK_TEXT_VIEW(ctk_object->txt_xconfig_save),
+ GTK_TEXT_BUFFER(ctk_object->buf_xconfig_save));
+
+ ctk_object->scr_xconfig_save = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_shadow_type
+ (GTK_SCROLLED_WINDOW(ctk_object->scr_xconfig_save), GTK_SHADOW_IN);
+
+ ctk_object->txt_xconfig_file = gtk_entry_new();
+ gtk_widget_set_size_request(ctk_object->txt_xconfig_file, 300, -1);
+
+ ctk_object->btn_xconfig_file = gtk_button_new_with_label("Browse...");
+ g_signal_connect(G_OBJECT(ctk_object->btn_xconfig_file), "clicked",
+ G_CALLBACK(xconfig_file_clicked),
+ (gpointer) ctk_object);
+ ctk_object->dlg_xconfig_file = gtk_file_selection_new
+ ("Please select the X configuration file");
+
+
+
+ /* Apply button */
+ ctk_object->btn_apply = gtk_button_new_with_label("Apply");
+ gtk_widget_set_sensitive(ctk_object->btn_apply, False);
+ ctk_config_set_tooltip(ctk_config, ctk_object->btn_apply,
+ __apply_button_help);
+ g_signal_connect(G_OBJECT(ctk_object->btn_apply), "clicked",
+ G_CALLBACK(apply_clicked),
+ (gpointer) ctk_object);
+
+
+ /* Probe button */
+ ctk_object->btn_probe = gtk_button_new_with_label("Detect Displays");
+ ctk_config_set_tooltip(ctk_config, ctk_object->btn_probe,
+ __probe_button_help);
+ g_signal_connect(G_OBJECT(ctk_object->btn_probe), "clicked",
+ G_CALLBACK(probe_clicked),
+ (gpointer) ctk_object);
+
+
+ /* Advanced button */
+ ctk_object->btn_advanced = gtk_button_new_with_label("Advanced...");
+ ctk_config_set_tooltip(ctk_config, ctk_object->btn_advanced,
+ __advanced_button_help);
+ g_signal_connect(G_OBJECT(ctk_object->btn_advanced), "clicked",
+ G_CALLBACK(advanced_clicked),
+ (gpointer) ctk_object);
+
+
+ /* Reset button */
+ ctk_object->btn_reset = gtk_button_new_with_label("Reset");
+ ctk_config_set_tooltip(ctk_config, ctk_object->btn_reset,
+ __reset_button_help);
+ g_signal_connect(G_OBJECT(ctk_object->btn_reset), "clicked",
+ G_CALLBACK(reset_clicked),
+ (gpointer) ctk_object);
+
+
+ /* Save button */
+ ctk_object->btn_save = gtk_button_new_with_label
+ ("Save to X Configuration File");
+ ctk_config_set_tooltip(ctk_config, ctk_object->btn_save,
+ __save_button_help);
+ g_signal_connect(G_OBJECT(ctk_object->btn_save), "clicked",
+ G_CALLBACK(save_clicked),
+ (gpointer) ctk_object);
+
+
+
+ /****
+ *
+ * Pack the widgets
+ *
+ ***/
+
+ { /* Layout section */
+
+ frame = gtk_frame_new("Layout");
+ hbox = gtk_hbox_new(FALSE, 5); /* main panel */
+ vbox = gtk_vbox_new(FALSE, 5); /* layout panel */
+ gtk_box_pack_start(GTK_BOX(ctk_object), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
+
+ hbox = gtk_hbox_new(FALSE, 5); /* layout panel */
+ gtk_container_set_border_width(GTK_CONTAINER(hbox), 5);
+ vbox = gtk_vbox_new(FALSE, 5);
+ gtk_container_add(GTK_CONTAINER(frame), hbox);
+ gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 5);
+
+ /* Pack the layout widget */
+ gtk_box_pack_start(GTK_BOX(vbox), ctk_object->obj_layout,
+ FALSE, FALSE, 0);
+
+ /* Xinerama checkbox */
+ gtk_box_pack_start(GTK_BOX(vbox), ctk_object->chk_xinerama_enabled,
+ FALSE, FALSE, 0);
+ }
+
+
+ /* Scrolled window */
+ scrolled_window = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
+ GTK_POLICY_NEVER,
+ GTK_POLICY_AUTOMATIC);
+ gtk_box_pack_start(GTK_BOX(ctk_object), scrolled_window, TRUE, TRUE, 0);
+ gtk_widget_set_size_request(scrolled_window, -1, 200);
+
+ viewport = gtk_viewport_new(NULL, NULL);
+ gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
+ gtk_container_add(GTK_CONTAINER(scrolled_window), viewport);
+
+
+ /* Panel for the display/screen sections */
+ vpanel = gtk_vbox_new(FALSE, 0);
+ gtk_container_add(GTK_CONTAINER(viewport), vpanel);
+
+
+ { /* Display section */
+ GtkWidget *longest_hbox;
+
+ /* Create the display frame */
+ frame = gtk_frame_new("Display");
+ ctk_object->display_frame = frame;
+ hbox = gtk_hbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(vpanel), hbox, FALSE, FALSE, 0);
+
+ /* Generate the major vbox for the display section */
+ vbox = gtk_vbox_new(FALSE, 5);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
+ gtk_container_add(GTK_CONTAINER(frame), vbox);
+
+ /* Display Configuration */
+ hbox = gtk_hbox_new(FALSE, 5);
+ /* XXX Pack widget later. Create it here so we can get its size */
+ longest_hbox = hbox;
+ label = gtk_label_new("Configuration:");
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
+ gtk_widget_size_request(label, &req);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 5);
+ gtk_box_pack_start(GTK_BOX(hbox), ctk_object->txt_display_config,
+ FALSE, FALSE, 0);
+ gtk_box_pack_end(GTK_BOX(hbox), ctk_object->btn_display_config,
+ FALSE, FALSE, 0);
+
+ /* Display model name */
+ hbox = gtk_hbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ label = gtk_label_new("Model:");
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
+ gtk_widget_set_size_request(label, req.width, -1);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 5);
+ gtk_box_pack_start(GTK_BOX(hbox), ctk_object->txt_display_model,
+ TRUE, TRUE, 0);
+
+ /* Pack the display configuration line */
+ gtk_box_pack_start(GTK_BOX(vbox), longest_hbox, FALSE, TRUE, 0);
+
+ /* Display resolution and refresh dropdowns */
+ hbox = gtk_hbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
+ label = gtk_label_new("Resolution:");
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
+ gtk_widget_set_size_request(label, req.width, -1);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 5);
+ gtk_box_pack_start(GTK_BOX(hbox), ctk_object->mnu_display_resolution,
+ TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), ctk_object->mnu_display_refresh,
+ TRUE, TRUE, 0);
+ ctk_object->box_display_resolution = hbox;
+
+ /* Modeline modename info */
+ hbox = gtk_hbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ label = gtk_label_new("Mode Name:");
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
+ gtk_widget_set_size_request(label, req.width, -1);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 5);
+ gtk_box_pack_start(GTK_BOX(hbox), ctk_object->txt_display_modename,
+ FALSE, FALSE, 0);
+ ctk_object->box_display_modename = hbox;
+
+ /* Display positioning */
+ label = gtk_label_new("Position:");
+ hbox = gtk_hbox_new(FALSE, 5);
+
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
+ gtk_widget_set_size_request(label, req.width, -1);
+
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 5);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ ctk_object->mnu_display_position_type,
+ TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ ctk_object->mnu_display_position_relative,
+ TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ ctk_object->txt_display_position_offset,
+ TRUE, TRUE, 0);
+ ctk_object->box_display_position = hbox;
+
+ /* Display panning text entry */
+ label = gtk_label_new("Panning:");
+ hbox = gtk_hbox_new(FALSE, 5);
+
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
+ gtk_widget_set_size_request(label, req.width, -1);
+
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 5);
+ gtk_box_pack_start(GTK_BOX(hbox), ctk_object->txt_display_panning,
+ TRUE, TRUE, 0);
+ ctk_object->box_display_panning = hbox;
+
+ } /* Display sub-section */
+
+
+ { /* X Screen */
+
+ /* Create the X screen frame */
+ frame = gtk_frame_new("X Screen");
+ ctk_object->screen_frame = frame;
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(vpanel), hbox, FALSE, FALSE, 5);
+
+ /* Generate the major vbox for the display section */
+ vbox = gtk_vbox_new(FALSE, 5);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), 5);
+ gtk_container_add(GTK_CONTAINER(frame), vbox);
+
+ /* X Screen number */
+ hbox = gtk_hbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ label = gtk_label_new("Screen Number:");
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
+ gtk_widget_size_request(label, &req);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 5);
+ gtk_box_pack_start(GTK_BOX(hbox), ctk_object->txt_screen_num,
+ TRUE, TRUE, 0);
+
+ /* X Screen depth dropdown */
+ hbox = gtk_hbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ label = gtk_label_new("Color Depth:");
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
+ gtk_widget_set_size_request(label, req.width, -1);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 5);
+ gtk_box_pack_start(GTK_BOX(hbox), ctk_object->mnu_screen_depth,
+ TRUE, TRUE, 0);
+ ctk_object->box_screen_depth = hbox;
+
+ /* X Screen positioning */
+ hbox = gtk_hbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ label = gtk_label_new("Position:");
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
+ gtk_widget_set_size_request(label, req.width, -1);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 5);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ ctk_object->mnu_screen_position_type,
+ TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ ctk_object->mnu_screen_position_relative,
+ TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ ctk_object->txt_screen_position_offset,
+ TRUE, TRUE, 0);
+ ctk_object->box_screen_position = hbox;
+
+ /* X Screen metamode drop down & buttons */
+ hbox = gtk_hbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+ label = gtk_label_new("MetaMode:");
+ gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
+ gtk_widget_set_size_request(label, req.width, -1);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, TRUE, 5);
+ gtk_box_pack_start(GTK_BOX(hbox), ctk_object->btn_screen_metamode,
+ TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), ctk_object->btn_screen_metamode_add,
+ TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), ctk_object->btn_screen_metamode_delete,
+ TRUE, TRUE, 0);
+ ctk_object->box_screen_metamode = hbox;
+
+ } /* X Screen sub-section */
+
+
+ { /* Buttons */
+ hbox = gtk_hbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(ctk_object), hbox, FALSE, FALSE, 0);
+
+ gtk_box_pack_end(GTK_BOX(hbox), ctk_object->btn_reset,
+ FALSE, FALSE, 0);
+ gtk_box_pack_end(GTK_BOX(hbox), ctk_object->btn_advanced,
+ FALSE, FALSE, 0);
+ gtk_box_pack_end(GTK_BOX(hbox), ctk_object->btn_probe,
+ FALSE, FALSE, 0);
+ gtk_box_pack_end(GTK_BOX(hbox), ctk_object->btn_apply,
+ FALSE, FALSE, 0);
+
+ hbox = gtk_hbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(ctk_object), hbox, FALSE, FALSE, 0);
+
+ gtk_box_pack_end(GTK_BOX(hbox), ctk_object->btn_save,
+ FALSE, FALSE, 0);
+ }
+
+
+ { /* Dialogs */
+
+ /* Display Configuration Dialog */
+ label = gtk_label_new("How should this display device be configured?");
+ hbox = gtk_hbox_new(TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 20);
+ gtk_box_pack_start
+ (GTK_BOX(GTK_DIALOG(ctk_object->dlg_display_config)->vbox),
+ hbox, TRUE, TRUE, 20);
+ gtk_box_pack_start
+ (GTK_BOX(GTK_DIALOG(ctk_object->dlg_display_config)->vbox),
+ ctk_object->rad_display_config_disabled, FALSE, FALSE, 0);
+ gtk_box_pack_start
+ (GTK_BOX(GTK_DIALOG(ctk_object->dlg_display_config)->vbox),
+ ctk_object->rad_display_config_xscreen, FALSE, FALSE, 0);
+ gtk_box_pack_start
+ (GTK_BOX(GTK_DIALOG(ctk_object->dlg_display_config)->vbox),
+ ctk_object->rad_display_config_twinview, FALSE, FALSE, 0);
+ gtk_widget_show_all(GTK_DIALOG(ctk_object->dlg_display_config)->vbox);
+
+ /* Display Disable Dialog */
+ hbox = gtk_hbox_new(TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), ctk_object->txt_display_disable,
+ FALSE, FALSE, 20);
+ gtk_box_pack_start
+ (GTK_BOX(GTK_DIALOG(ctk_object->dlg_display_disable)->vbox),
+ hbox, TRUE, TRUE, 20);
+ gtk_widget_show_all(GTK_DIALOG(ctk_object->dlg_display_disable)->vbox);
+
+ /* Reset Confirm Dialog */
+ label = gtk_label_new("Do you really want to reset the "
+ "configuration?");
+ hbox = gtk_hbox_new(TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 20);
+ gtk_box_pack_start
+ (GTK_BOX(GTK_DIALOG(ctk_object->dlg_reset_confirm)->vbox),
+ hbox, TRUE, TRUE, 20);
+ gtk_widget_show_all(GTK_DIALOG(ctk_object->dlg_reset_confirm)->vbox);
+
+ /* Apply Confirm Dialog */
+ hbox = gtk_hbox_new(TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), ctk_object->txt_display_confirm,
+ TRUE, TRUE, 20);
+ gtk_box_pack_start
+ (GTK_BOX(GTK_DIALOG(ctk_object->dlg_display_confirm)->vbox),
+ hbox, TRUE, TRUE, 20);
+ gtk_widget_show_all(GTK_DIALOG(ctk_object->dlg_display_confirm)->vbox);
+
+ /* X Config Save Dialog */
+ gtk_dialog_set_has_separator(GTK_DIALOG(ctk_object->dlg_xconfig_save),
+ TRUE);
+
+ /* Preview button */
+ hbox = gtk_hbox_new(FALSE, 0);
+ hbox2 = gtk_hbox_new(FALSE, 0);
+
+ gtk_box_pack_start(GTK_BOX(hbox), ctk_object->btn_xconfig_preview,
+ FALSE, FALSE, 5);
+ gtk_box_pack_start
+ (GTK_BOX(GTK_DIALOG(ctk_object->dlg_xconfig_save)->vbox),
+ hbox, FALSE, FALSE, 5);
+
+ /* Preview window */
+ hbox = gtk_hbox_new(TRUE, 0);
+
+ gtk_container_add(GTK_CONTAINER(ctk_object->scr_xconfig_save),
+ ctk_object->txt_xconfig_save);
+ gtk_box_pack_start(GTK_BOX(hbox),
+ ctk_object->scr_xconfig_save,
+ TRUE, TRUE, 5);
+ gtk_box_pack_start
+ (GTK_BOX(GTK_DIALOG(ctk_object->dlg_xconfig_save)->vbox),
+ hbox,
+ TRUE, TRUE, 0);
+ ctk_object->box_xconfig_save = hbox;
+
+ /* Filename */
+ hbox = gtk_hbox_new(FALSE, 0);
+ hbox2 = gtk_hbox_new(FALSE, 5);
+
+ gtk_box_pack_end(GTK_BOX(hbox2), ctk_object->btn_xconfig_file,
+ FALSE, FALSE, 0);
+ gtk_box_pack_end(GTK_BOX(hbox2), ctk_object->txt_xconfig_file,
+ TRUE, TRUE, 0);
+ gtk_box_pack_end(GTK_BOX(hbox), hbox2,
+ TRUE, TRUE, 5);
+ gtk_box_pack_start
+ (GTK_BOX(GTK_DIALOG(ctk_object->dlg_xconfig_save)->vbox),
+ hbox,
+ FALSE, FALSE, 5);
+
+ gtk_widget_show_all(GTK_DIALOG(ctk_object->dlg_xconfig_save)->vbox);
+ }
+
+
+ /* Show the GUI */
+ gtk_widget_show_all(GTK_WIDGET(ctk_object));
+
+
+ /* Setup the GUI */
+ setup_layout_frame(ctk_object);
+ setup_display_frame(ctk_object);
+ setup_screen_frame(ctk_object);
+
+
+ return GTK_WIDGET(ctk_object);
+
+} /* ctk_display_config_new() */
+
+
+
+/** ctk_display_config_create_help() *********************************
+ *
+ * Creates the Display Configuration help page.
+ *
+ **/
+
+GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *table,
+ CtkDisplayConfig *ctk_object)
+{
+ GtkTextIter i;
+ GtkTextBuffer *b;
+
+
+ b = gtk_text_buffer_new(table);
+
+ gtk_text_buffer_get_iter_at_offset(b, &i, 0);
+
+ ctk_help_title(b, &i, "Display Configuration Help");
+ ctk_help_para(b, &i, "This page gives access to configuration of "
+ "the X Server's display devices.");
+
+ ctk_help_para(b, &i, "");
+ ctk_help_heading(b, &i, "Layout Section");
+ ctk_help_para(b, &i, "This section shows information and configuration "
+ "settings for the X server layout.");
+ ctk_help_heading(b, &i, "Layout Image");
+ ctk_help_para(b, &i, "The layout image shows the geomertic relationship "
+ "that display devices and X screens have to each other. "
+ "You may drag display devices around to reposition them. "
+ "When in advanced view, the display's panning domain may "
+ "be resized by holding shift while dragging.");
+ ctk_help_heading(b, &i, "Enable Xinerama");
+ ctk_help_para(b, &i, "%s. This setting is only available when multiple "
+ "X screens are present.", __layout_xinerama_button_help);
+
+
+ ctk_help_para(b, &i, "");
+ ctk_help_heading(b, &i, "Display Section");
+ ctk_help_para(b, &i, "This section shows information and configuration "
+ "settings for the currently selected display device.");
+ ctk_help_heading(b, &i, "Model");
+ ctk_help_para(b, &i, "The Model name is the name of the display device.");
+ ctk_help_heading(b, &i, "Resolution");
+ ctk_help_para(b, &i, __dpy_resolution_mnu_help);
+ ctk_help_heading(b, &i, "Refresh");
+ ctk_help_para(b, &i, "The Refresh drop-down is to the right of the "
+ "Resolution drop-down. %s", __dpy_refresh_mnu_help);
+ ctk_help_heading(b, &i, "Mode Name");
+ ctk_help_para(b, &i, "The Mode name is the name of the modeline that is "
+ "currently chosen for the selected display device. "
+ "(Advanced view only)");
+ ctk_help_heading(b, &i, "Position Type");
+ ctk_help_para(b, &i, __dpy_position_type_help);
+ ctk_help_heading(b, &i, "Position Relative");
+ ctk_help_para(b, &i, __dpy_position_relative_help);
+ ctk_help_heading(b, &i, "Position Offset");
+ ctk_help_para(b, &i, __dpy_position_offset_help);
+ ctk_help_heading(b, &i, "Panning");
+ ctk_help_para(b, &i, "%s. (Advanced view only)", __dpy_panning_help);
+
+
+ ctk_help_para(b, &i, "");
+ ctk_help_heading(b, &i, "Screen Section");
+ ctk_help_para(b, &i, "This section shows information and configuration "
+ "settings for the currently selected X Screen.");
+ ctk_help_heading(b, &i, "Screen Depth");
+ ctk_help_para(b, &i, __screen_depth_help);
+ ctk_help_heading(b, &i, "Position Type");
+ ctk_help_para(b, &i, __screen_position_type_help);
+ ctk_help_heading(b, &i, "Position Relative");
+ ctk_help_para(b, &i, __screen_position_relative_help);
+ ctk_help_heading(b, &i, "Position Offset");
+ ctk_help_para(b, &i, __screen_position_offset_help);
+ ctk_help_heading(b, &i, "MetaMode Selection");
+ ctk_help_para(b, &i, "%s. (Advanced view only)", __screen_metamode_help);
+ ctk_help_heading(b, &i, "Add Metamode");
+ ctk_help_para(b, &i, "%s. (Advanced view only)",
+ __screen_metamode_add_button_help);
+ ctk_help_heading(b, &i, "Delete Metamode");
+ ctk_help_para(b, &i, "%s. (Advanced view only)",
+ __screen_metamode_delete_button_help);
+
+
+ ctk_help_para(b, &i, "");
+ ctk_help_heading(b, &i, "Buttons");
+ ctk_help_heading(b, &i, "Probe");
+ ctk_help_para(b, &i, __apply_button_help);
+ ctk_help_heading(b, &i, "Detect Displays");
+ ctk_help_para(b, &i, __probe_button_help);
+ ctk_help_heading(b, &i, "Advanced/Basic...");
+ ctk_help_para(b, &i, "%s. The Basic view modifies the currently active "
+ "MetaMode for an X screen, while the Advanced view exposes "
+ "all the MetaModes available on an X screen, and lets you "
+ "modify each of them", __advanced_button_help);
+ ctk_help_heading(b, &i, "Reset");
+ ctk_help_para(b, &i, __reset_button_help);
+ ctk_help_heading(b, &i, "Save to X Configuration File");
+ ctk_help_para(b, &i, __save_button_help);
+
+ ctk_help_finish(b);
+
+ return b;
+
+} /* ctk_display_config_create_help() */
+
+
+
+/* Widget setup & helper functions ***********************************/
+
+
+/** setup_layout_frame() *********************************************
+ *
+ * Sets up the layout frame to reflect the currently selected layout.
+ *
+ **/
+
+static void setup_layout_frame(CtkDisplayConfig *ctk_object)
+{
+ nvLayoutPtr layout = ctk_object->layout;
+ nvGpuPtr gpu;
+ int num_screens;
+
+
+ /* Only allow Xinerama when there are multiple X Screens */
+ num_screens = 0;
+ for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+ num_screens += gpu->num_screens;
+ }
+
+ /* Unselect Xinerama if only one (or no) X Screen */
+ if (num_screens <= 1) {
+ layout->xinerama_enabled = 0;
+ gtk_widget_hide(ctk_object->chk_xinerama_enabled);
+ return;
+ }
+ gtk_widget_show(ctk_object->chk_xinerama_enabled);
+
+ g_signal_handlers_block_by_func
+ (G_OBJECT(ctk_object->chk_xinerama_enabled),
+ G_CALLBACK(xinerama_state_toggled), (gpointer) ctk_object);
+
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON(ctk_object->chk_xinerama_enabled),
+ layout->xinerama_enabled);
+
+ g_signal_handlers_unblock_by_func
+ (G_OBJECT(ctk_object->chk_xinerama_enabled),
+ G_CALLBACK(xinerama_state_toggled), (gpointer) ctk_object);
+
+} /* setup_layout_frame() */
+
+
+
+/** setup_display_modename() *****************************************
+ *
+ * Updates the modeline modename of the selected display
+ *
+ **/
+
+static void setup_display_modename(CtkDisplayConfig *ctk_object)
+{
+ nvDisplayPtr display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+
+ if (!display || !display->screen || !ctk_object->advanced_mode) {
+ gtk_widget_hide(ctk_object->box_display_modename);
+ return;
+ }
+ gtk_widget_show(ctk_object->box_display_modename);
+
+
+ if (!display->cur_mode || !display->cur_mode->modeline) {
+ gtk_label_set(GTK_LABEL(ctk_object->txt_display_modename), "");
+ gtk_widget_set_sensitive(ctk_object->box_display_modename, FALSE);
+ return;
+ }
+ gtk_widget_set_sensitive(ctk_object->box_display_modename, TRUE);
+
+
+ gtk_label_set(GTK_LABEL(ctk_object->txt_display_modename),
+ display->cur_mode->modeline->data.identifier);
+
+} /* setup_display_modename() */
+
+
+
+/** setup_display_config() *******************************************
+ *
+ * Updates the text of the configure button to reflect the current
+ * setting of the selected display.
+ *
+ **/
+
+static void setup_display_config(CtkDisplayConfig *ctk_object)
+{
+ nvDisplayPtr display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+ if (!display) return;
+
+ if (!display->screen) {
+ gtk_label_set_text(GTK_LABEL(ctk_object->txt_display_config),
+ "Disabled");
+ } else if (display->screen->num_displays == 1) {
+ gtk_label_set_text(GTK_LABEL(ctk_object->txt_display_config),
+ "Separate X Screen");
+ } else {
+ gtk_label_set_text(GTK_LABEL(ctk_object->txt_display_config),
+ "TwinView");
+ }
+
+} /* setup_display_config() */
+
+
+
+/** setup_display_refresh_dropdwon() *********************************
+ *
+ * Generates the refresh rate dropdown based on the currently selected
+ * display.
+ *
+ **/
+
+static void setup_display_refresh_dropdown(CtkDisplayConfig *ctk_object)
+{
+ GtkWidget *menu;
+ GtkWidget *menu_item;
+ nvModeLinePtr modeline;
+ nvModeLinePtr auto_modeline;
+ nvModeLinePtr modelines;
+ nvModeLinePtr cur_modeline;
+ float cur_rate; /* Refresh Rate */
+ int cur_idx = 0; /* Currently selected modeline */
+
+ gchar *name; /* Modeline's label for the dropdown menu */
+
+ nvDisplayPtr display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+
+
+ /* Get selection information */
+ if (!display ||
+ !display->cur_mode ||
+ !display->cur_mode->modeline) {
+ goto fail;
+ }
+ modelines = display->modelines;
+ cur_modeline = display->cur_mode->modeline;
+ cur_rate = GET_MODELINE_REFRESH_RATE(cur_modeline);
+
+
+ /* Create the menu index -> modeline pointer lookup table */
+ if (ctk_object->refresh_table) {
+ free(ctk_object->refresh_table);
+ ctk_object->refresh_table_len = 0;
+ }
+ ctk_object->refresh_table =
+ (nvModeLinePtr *)calloc(1, display->num_modelines
+ * sizeof(nvModeLinePtr));
+ if (!ctk_object->refresh_table) {
+ goto fail;
+ }
+
+
+ /* Generate the refresh dropdown */
+ menu = gtk_menu_new();
+
+
+ /* Special case the 'nvidia-auto-select' mode. */
+ if (IS_NVIDIA_DEFAULT_MODE(cur_modeline)) {
+ menu_item = gtk_menu_item_new_with_label("Auto");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ gtk_widget_show(menu_item);
+ ctk_object->refresh_table[ctk_object->refresh_table_len++] =
+ cur_modeline;
+ modelines = NULL; /* Skip building rest of refresh dropdown */
+ }
+
+ /* Generate the refresh rate dropdown from the modelines list */
+ auto_modeline = NULL;
+ for (modeline = modelines; modeline; modeline = modeline->next) {
+
+ float modeline_rate;
+ nvModeLinePtr m;
+ int count_ref; /* # modelines with similar refresh rates */
+ int num_ref; /* Modeline # in a group of similar refresh rates */
+ int is_doublescan;
+ int is_interlaced;
+
+
+ /* Ignore modelines of different resolution */
+ if (modeline->data.hdisplay != cur_modeline->data.hdisplay ||
+ modeline->data.vdisplay != cur_modeline->data.vdisplay) {
+ continue;
+ }
+
+ /* Ignore special modes */
+ if (IS_NVIDIA_DEFAULT_MODE(modeline)) {
+ continue;
+ }
+
+ modeline_rate = GET_MODELINE_REFRESH_RATE(modeline);
+ is_doublescan = (modeline->data.flags & V_DBLSCAN);
+ is_interlaced = (modeline->data.flags & V_INTERLACE);
+
+ name = g_strdup_printf("%.0f Hz", modeline_rate);
+
+
+ /* Get a unique number for this modeline */
+ count_ref = 0; /* # modelines with similar refresh rates */
+ num_ref = 0; /* Modeline # in a group of similar refresh rates */
+ for (m = modelines; m; m = m->next) {
+ float m_rate = GET_MODELINE_REFRESH_RATE(m);
+ gchar *tmp = g_strdup_printf("%.0f Hz", m_rate);
+
+ if (!IS_NVIDIA_DEFAULT_MODE(m) &&
+ m->data.hdisplay == modeline->data.hdisplay &&
+ m->data.vdisplay == modeline->data.vdisplay &&
+ !g_ascii_strcasecmp(tmp, name) &&
+ m != auto_modeline) {
+
+ count_ref++;
+ /* Modelines with similar refresh rates get a unique # (num_ref) */
+ if (m == modeline) {
+ num_ref = count_ref; /* This modeline's # */
+ }
+ }
+ g_free(tmp);
+ }
+
+ /* Is default refresh rate for resolution */
+ if (!ctk_object->refresh_table_len) {
+ auto_modeline = modeline;
+ g_free(name);
+ name = g_strdup("Auto");
+
+ /* In advanced mode, all modelines are selectable */
+ } else if (count_ref > 1 && ctk_object->advanced_mode) {
+ gchar *tmp;
+ tmp = g_strdup_printf("%s (%d)", name, num_ref);
+ g_free(name);
+ name = tmp;
+
+ /* in simple mode only show one refresh rate */
+ } else if (num_ref > 1 && !ctk_object->advanced_mode) {
+ continue;
+ }
+
+
+ /* Add "DoubleScan" and "Interlace" information */
+ if (g_ascii_strcasecmp(name, "Auto")) {
+ gchar *extra = NULL;
+ gchar *tmp;
+
+ if (modeline->data.flags & V_DBLSCAN) {
+ extra = g_strdup_printf("DoubleScan");
+ }
+
+ if (modeline->data.flags & V_INTERLACE) {
+ if (extra) {
+ tmp = g_strdup_printf("%s, Interlace", extra);
+ g_free(extra);
+ extra = tmp;
+ } else {
+ extra = g_strdup_printf("Interlace");
+ }
+ }
+
+ if (extra) {
+ tmp = g_strdup_printf("%s (%s)", name, extra);
+ g_free(extra);
+ g_free(name);
+ name = tmp;
+ }
+ }
+
+
+ /* Keep track of the selected modeline */
+ if (cur_modeline == modeline) {
+ cur_idx = ctk_object->refresh_table_len;
+
+ /* Find a close match to the selected modeline */
+ } else if (ctk_object->refresh_table_len &&
+ ctk_object->refresh_table[cur_idx] != cur_modeline) {
+
+ /* Found a better resolution */
+ if (modeline->data.hdisplay == cur_modeline->data.hdisplay &&
+ modeline->data.vdisplay == cur_modeline->data.vdisplay) {
+
+ float prev_rate = GET_MODELINE_REFRESH_RATE(ctk_object->refresh_table[cur_idx]);
+ float rate = GET_MODELINE_REFRESH_RATE(modeline);
+
+ if (ctk_object->refresh_table[cur_idx]->data.hdisplay != cur_modeline->data.hdisplay ||
+ ctk_object->refresh_table[cur_idx]->data.vdisplay != cur_modeline->data.vdisplay) {
+ cur_idx = ctk_object->refresh_table_len;
+ }
+
+ /* Found a better refresh rate */
+ if (rate == cur_rate && prev_rate != cur_rate) {
+ cur_idx = ctk_object->refresh_table_len;
+ }
+ }
+ }
+
+
+ /* Add the modeline entry to the dropdown */
+ menu_item = gtk_menu_item_new_with_label(name);
+ g_free(name);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ gtk_widget_show(menu_item);
+ ctk_object->refresh_table[ctk_object->refresh_table_len++] = modeline;
+ }
+
+
+
+
+ /* Setup the menu and select the current modeline */
+ g_signal_handlers_block_by_func(G_OBJECT(ctk_object->mnu_display_refresh),
+ G_CALLBACK(display_refresh_changed),
+ (gpointer) ctk_object);
+ gtk_option_menu_set_menu
+ (GTK_OPTION_MENU(ctk_object->mnu_display_refresh), menu);
+ gtk_option_menu_set_history(GTK_OPTION_MENU(ctk_object->mnu_display_refresh), cur_idx);
+ gtk_widget_set_sensitive(ctk_object->mnu_display_refresh, True);
+
+ g_signal_handlers_unblock_by_func(G_OBJECT(ctk_object->mnu_display_refresh),
+ G_CALLBACK(display_refresh_changed),
+ (gpointer) ctk_object);
+
+
+ /* If dropdown only has one item, disable it */
+ if (ctk_object->refresh_table_len > 1) {
+ gtk_widget_set_sensitive(ctk_object->mnu_display_refresh, True);
+ } else {
+ gtk_widget_set_sensitive(ctk_object->mnu_display_refresh, False);
+ }
+
+
+ /* Update the nodename label */
+ setup_display_modename(ctk_object);
+ return;
+
+
+ /* Handle failures */
+ fail:
+ gtk_widget_set_sensitive(ctk_object->mnu_display_refresh, False);
+
+ setup_display_modename(ctk_object);
+
+} /* setup_display_refresh_dropdown() */
+
+
+
+/** setup_display_resolution_dropdwon() ******************************
+ *
+ * Generates the resolution dropdown based on the currently selected
+ * display.
+ *
+ **/
+
+static void setup_display_resolution_dropdown(CtkDisplayConfig *ctk_object)
+{
+ GtkWidget *menu;
+ GtkWidget *menu_item;
+
+ nvDisplayPtr display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+ nvModeLinePtr modeline;
+ nvModeLinePtr modelines;
+ nvModeLinePtr cur_modeline;
+
+ int cur_idx = 0; /* Currently selected modeline (resolution) */
+
+
+
+ /* Get selection information */
+ if (!display || !display->screen || !display->cur_mode) {
+ gtk_widget_hide(ctk_object->box_display_resolution);
+ return;
+ }
+ gtk_widget_show(ctk_object->box_display_resolution);
+ gtk_widget_set_sensitive(ctk_object->box_display_resolution, TRUE);
+
+
+ cur_modeline = display->cur_mode->modeline;
+
+
+ /* Create the modeline lookup table for the dropdown */
+ if (ctk_object->resolution_table) {
+ free(ctk_object->resolution_table);
+ ctk_object->resolution_table_len = 0;
+ }
+ ctk_object->resolution_table =
+ (nvModeLinePtr *)calloc(1, (display->num_modelines +1)
+ *sizeof(nvModeLinePtr));
+ if (!ctk_object->resolution_table) {
+ goto fail;
+ }
+
+
+ /* Start the menu generation */
+ menu = gtk_menu_new();
+
+
+ /* Add the off mode */
+ menu_item = gtk_menu_item_new_with_label("Off");
+ if (display->screen->num_displays <= 1) {
+ gtk_widget_set_sensitive(menu_item, False);
+ }
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ gtk_widget_show(menu_item);
+ ctk_object->resolution_table[ctk_object->resolution_table_len++] = NULL;
+
+
+ /* Add the 'nvidia-auto-select' modeline */
+ modelines = display->modelines;
+ if (IS_NVIDIA_DEFAULT_MODE(modelines)) {
+ menu_item = gtk_menu_item_new_with_label("Auto");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ gtk_widget_show(menu_item);
+ ctk_object->resolution_table[ctk_object->resolution_table_len++] =
+ modelines;
+ modelines = modelines->next;
+ }
+
+ /* Set the selected modeline index */
+ if (cur_modeline) {
+ cur_idx = 1; /* Modeline is set, start off as 'nvidia-auto-select' */
+ } else {
+ cur_idx = 0; /* Modeline not set, start off as 'off'. */
+ }
+
+
+ /* Generate the resolution menu */
+ modeline = modelines;
+ while (modeline) {
+ nvModeLinePtr m;
+ gchar *name;
+
+ /* Find the first resolution that matches the current res W & H */
+ m = modelines;
+ while (m != modeline) {
+ if (modeline->data.hdisplay == m->data.hdisplay &&
+ modeline->data.vdisplay == m->data.vdisplay) {
+ break;
+ }
+ m = m->next;
+ }
+
+ /* Add resolution if it is the first of its kind */
+ if (m == modeline) {
+
+ /* Set the current modeline idx if not already set by default */
+ if (cur_modeline) {
+ if (!IS_NVIDIA_DEFAULT_MODE(cur_modeline) &&
+ cur_modeline->data.hdisplay == modeline->data.hdisplay &&
+ cur_modeline->data.vdisplay == modeline->data.vdisplay) {
+ cur_idx = ctk_object->resolution_table_len;
+ }
+ }
+
+ name = g_strdup_printf("%dx%d", modeline->data.hdisplay,
+ modeline->data.vdisplay);
+ menu_item = gtk_menu_item_new_with_label(name);
+ g_free(name);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ gtk_widget_show(menu_item);
+ ctk_object->resolution_table[ctk_object->resolution_table_len++] =
+ modeline;
+ }
+ modeline = modeline->next;
+ }
+
+
+ /* Setup the menu and select the current mode */
+ g_signal_handlers_block_by_func
+ (G_OBJECT(ctk_object->mnu_display_resolution),
+ G_CALLBACK(display_resolution_changed), (gpointer) ctk_object);
+
+ gtk_option_menu_set_menu
+ (GTK_OPTION_MENU(ctk_object->mnu_display_resolution), menu);
+
+ gtk_option_menu_set_history
+ (GTK_OPTION_MENU(ctk_object->mnu_display_resolution), cur_idx);
+
+ /* If dropdown has only one item, disable menu selection */
+ if (ctk_object->resolution_table_len > 1) {
+ gtk_widget_set_sensitive(ctk_object->mnu_display_resolution, True);
+ } else {
+ gtk_widget_set_sensitive(ctk_object->mnu_display_resolution, False);
+ }
+
+ g_signal_handlers_unblock_by_func
+ (G_OBJECT(ctk_object->mnu_display_resolution),
+ G_CALLBACK(display_resolution_changed), (gpointer) ctk_object);
+
+ /* Update refresh dropdown */
+ setup_display_refresh_dropdown(ctk_object);
+ return;
+
+
+
+ /* Handle failures */
+ fail:
+
+ gtk_option_menu_remove_menu
+ (GTK_OPTION_MENU(ctk_object->mnu_display_resolution));
+
+ gtk_widget_set_sensitive(ctk_object->mnu_display_resolution, False);
+
+ setup_display_refresh_dropdown(ctk_object);
+
+} /* setup_display_resolution_dropdown() */
+
+
+
+/** setup_display_position_type() ************************************
+ *
+ * Sets up the display position type dropdown to reflect the position
+ * settings for the currently selected display (absolute/relative/
+ * none).
+ *
+ **/
+
+static void setup_display_position_type(CtkDisplayConfig *ctk_object)
+{
+ nvDisplayPtr display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+
+ /* Handle cases where the position type should be hidden */
+ if (!display || !display->screen || !display->cur_mode) {
+ gtk_widget_hide(ctk_object->mnu_display_position_type);
+ return;
+ }
+ gtk_widget_show(ctk_object->mnu_display_position_type);
+
+
+ /* Set absolute/relative positioning */
+ g_signal_handlers_block_by_func
+ (G_OBJECT(ctk_object->mnu_display_position_type),
+ G_CALLBACK(display_position_type_changed), (gpointer) ctk_object);
+
+ gtk_option_menu_set_history
+ (GTK_OPTION_MENU(ctk_object->mnu_display_position_type),
+ display->cur_mode->position_type);
+
+ g_signal_handlers_unblock_by_func
+ (G_OBJECT(ctk_object->mnu_display_position_type),
+ G_CALLBACK(display_position_type_changed), (gpointer) ctk_object);
+
+} /* setup_display_position_type() */
+
+
+
+/** setup_display_position_relative() ********************************
+ *
+ * Setup which display the selected display is relative to.
+ *
+ **/
+
+static void setup_display_position_relative(CtkDisplayConfig *ctk_object)
+{
+ nvDisplayPtr display;
+ nvDisplayPtr relative_to;
+ int idx;
+ int selected_idx;
+ GtkWidget *menu;
+ GtkWidget *menu_item;
+
+ display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+ if (!display || !display->screen || !display->cur_mode || !display->gpu) {
+ return;
+ }
+
+
+ /* Allocate the display lookup table for the dropdown */
+ if (ctk_object->display_position_table) {
+ free(ctk_object->display_position_table);
+ }
+
+ ctk_object->display_position_table_len =
+ display->screen->num_displays -1;
+
+ ctk_object->display_position_table =
+ (nvDisplayPtr *)calloc(1, ctk_object->display_position_table_len *
+ sizeof(nvDisplayPtr));
+
+ if (!ctk_object->display_position_table) {
+ ctk_object->display_position_table_len = 0;
+ gtk_widget_hide(ctk_object->mnu_display_position_relative);
+ return;
+ }
+
+
+ /* Generate the lookup table and display dropdown */
+ idx = 0;
+ selected_idx = 0;
+ menu = gtk_menu_new();
+ for (relative_to = display->gpu->displays;
+ relative_to;
+ relative_to = relative_to->next) {
+
+ if (relative_to == display || relative_to->screen != display->screen) {
+ continue;
+ }
+
+ if (relative_to == display->cur_mode->relative_to) {
+ selected_idx = idx;
+ }
+
+ ctk_object->display_position_table[idx] = relative_to;
+
+ menu_item = gtk_menu_item_new_with_label(relative_to->name);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ gtk_widget_show(menu_item);
+ idx++;
+ }
+
+
+ /* Set the menu and the selected display */
+ g_signal_handlers_block_by_func
+ (G_OBJECT(ctk_object->mnu_display_position_relative),
+ G_CALLBACK(display_position_relative_changed), (gpointer) ctk_object);
+
+ gtk_option_menu_set_menu
+ (GTK_OPTION_MENU(ctk_object->mnu_display_position_relative), menu);
+
+ gtk_option_menu_set_history
+ (GTK_OPTION_MENU(ctk_object->mnu_display_position_relative),
+ selected_idx);
+
+ g_signal_handlers_unblock_by_func
+ (G_OBJECT(ctk_object->mnu_display_position_relative),
+ G_CALLBACK(display_position_relative_changed), (gpointer) ctk_object);
+
+
+ /* Disable the widget if there is only one possibility */
+ gtk_widget_set_sensitive
+ (ctk_object->mnu_display_position_relative,
+ (idx > 1));
+
+
+ /* Handle cases where the position relative dropdown should be hidden */
+ if (display->cur_mode->position_type == CONF_ADJ_ABSOLUTE) {
+ gtk_widget_hide(ctk_object->mnu_display_position_relative);
+ return;
+ }
+ gtk_widget_show(ctk_object->mnu_display_position_relative);
+
+} /* setup_display_position_relative() */
+
+
+
+/** setup_display_position_offset() **********************************
+ *
+ * Sets up the display position offset text entry to reflect the
+ * currently selected display device.
+ *
+ **/
+
+static void setup_display_position_offset(CtkDisplayConfig *ctk_object)
+{
+ char *tmp_str;
+ nvDisplayPtr display;
+ nvModePtr mode;
+
+ display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+
+ /* Handle cases where the position offset should be hidden */
+ if (!display || !display->screen || !display->cur_mode ||
+ !display->cur_mode->modeline ||
+ display->cur_mode->position_type != CONF_ADJ_ABSOLUTE) {
+ gtk_widget_hide(ctk_object->txt_display_position_offset);
+ return;
+ }
+ gtk_widget_show(ctk_object->txt_display_position_offset);
+
+
+ /* Update the position text */
+ mode = display->cur_mode;
+
+ tmp_str = g_strdup_printf("%+d%+d",
+ mode->dim[X] - mode->metamode->edim[X],
+ mode->dim[Y] - mode->metamode->edim[Y]);
+
+ gtk_entry_set_text(GTK_ENTRY(ctk_object->txt_display_position_offset),
+ tmp_str);
+
+ g_free(tmp_str);
+
+} /* setup_display_position_offset() */
+
+
+
+/** setup_display_position() *****************************************
+ *
+ * Sets up the display position section to reflect the position
+ * settings for the currently selected display (absolute/relative/
+ * none).
+ *
+ **/
+
+static void setup_display_position(CtkDisplayConfig *ctk_object)
+{
+ nvDisplayPtr display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+
+ /* Hide the position box if this screen only has one display */
+ if (!display || !display->screen || display->screen->num_displays <= 1) {
+ gtk_widget_hide(ctk_object->box_display_position);
+ return;
+ }
+ gtk_widget_show(ctk_object->box_display_position);
+
+
+ /* If the display is off, disable the position widgets */
+ if (!display->cur_mode || !display->cur_mode->modeline) {
+ gtk_widget_set_sensitive(ctk_object->box_display_position, FALSE);
+ return;
+ }
+ gtk_widget_set_sensitive(ctk_object->box_display_position, TRUE);
+
+
+ /* Setup the display position widgets */
+ setup_display_position_type(ctk_object);
+
+ setup_display_position_relative(ctk_object);
+
+ setup_display_position_offset(ctk_object);
+
+} /* setup_display_position */
+
+
+
+/** setup_display_panning() ******************************************
+ *
+ * Sets up the display panning text entry to reflect the currently
+ * selected display.
+ *
+ **/
+
+static void setup_display_panning(CtkDisplayConfig *ctk_object)
+{
+ char *tmp_str;
+ nvDisplayPtr display;
+ nvModePtr mode;
+
+ display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+
+ if (!display || !display->screen || !ctk_object->advanced_mode) {
+ gtk_widget_hide(ctk_object->box_display_panning);
+ return;
+ }
+ gtk_widget_show(ctk_object->box_display_panning);
+
+
+ if (!display->cur_mode || !display->cur_mode->modeline) {
+ gtk_widget_set_sensitive(ctk_object->box_display_panning, FALSE);
+ return;
+ }
+ gtk_widget_set_sensitive(ctk_object->box_display_panning, TRUE);
+
+
+ /* Update the panning text */
+ mode = display->cur_mode;
+ tmp_str = g_strdup_printf("%dx%d", mode->pan[W], mode->pan[H]);
+
+ gtk_entry_set_text(GTK_ENTRY(ctk_object->txt_display_panning),
+ tmp_str);
+ g_free(tmp_str);
+
+} /* setup_display_panning */
+
+
+
+/** setup_display_frame() ********************************************
+ *
+ * Sets up the display frame to reflect the currently selected
+ * display.
+ *
+ **/
+
+static void setup_display_frame(CtkDisplayConfig *ctk_object)
+{
+ nvDisplayPtr display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+ gchar *type;
+ gchar *str;
+
+
+
+ /* If no display is selected or there is no screen, hide the frame */
+ if (!display) {
+ gtk_widget_set_sensitive(ctk_object->display_frame, False);
+ gtk_widget_hide(ctk_object->display_frame);
+ return;
+ }
+
+
+ /* Enable display widgets and setup widget information */
+ gtk_widget_set_sensitive(ctk_object->display_frame, True);
+
+
+ /* Setup the display name */
+ type = get_display_type_str(display->device_mask, 0);
+ str = g_strdup_printf("%s (%s)", display->name, type);
+ g_free(type);
+ gtk_label_set_text(GTK_LABEL(ctk_object->txt_display_model), str);
+ g_free(str);
+
+
+ /* Setp the seleted mode modename */
+ setup_display_config(ctk_object);
+
+
+ /* Setp the seleted mode modename */
+ setup_display_modename(ctk_object);
+
+
+ /* Setup display resolution menu */
+ setup_display_resolution_dropdown(ctk_object);
+
+
+ /* Setup position */
+ setup_display_position(ctk_object);
+
+
+ /* Setup panning */
+ setup_display_panning(ctk_object);
+
+
+ gtk_widget_show(ctk_object->display_frame);
+
+} /* setup_display_frame() */
+
+
+
+/** setup_screen_depth_dropdown() ************************************
+ *
+ * Generates the color depth dropdown based on the currently selected
+ * display device.
+ *
+ **/
+
+static void setup_screen_depth_dropdown(CtkDisplayConfig *ctk_object)
+{
+ GtkWidget *menu;
+ GtkWidget *menu_item;
+ nvDisplayPtr display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+ if (!display || !display->screen) {
+ gtk_widget_hide(ctk_object->box_screen_depth);
+ return;
+ }
+
+
+ menu = gtk_menu_new();
+ menu_item = gtk_menu_item_new_with_label("Millions of Colors (32 bpp)");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ gtk_widget_show(menu_item);
+ menu_item = gtk_menu_item_new_with_label("Thousands of Colors (16 bpp)");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ gtk_widget_show(menu_item);
+ menu_item = gtk_menu_item_new_with_label("256 Colors (8 bpp)");
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ gtk_widget_show(menu_item);
+
+ g_signal_handlers_block_by_func(G_OBJECT(ctk_object->mnu_screen_depth),
+ G_CALLBACK(screen_depth_changed),
+ (gpointer) ctk_object);
+
+ gtk_option_menu_set_menu
+ (GTK_OPTION_MENU(ctk_object->mnu_screen_depth), menu);
+
+ if (display->screen->depth == 24) {
+ gtk_option_menu_set_history
+ (GTK_OPTION_MENU(ctk_object->mnu_screen_depth), 0);
+ } else if (display->screen->depth == 16) {
+ gtk_option_menu_set_history
+ (GTK_OPTION_MENU(ctk_object->mnu_screen_depth), 1);
+ } else {
+ gtk_option_menu_set_history
+ (GTK_OPTION_MENU(ctk_object->mnu_screen_depth), 2);
+ }
+
+ g_signal_handlers_unblock_by_func(G_OBJECT(ctk_object->mnu_screen_depth),
+ G_CALLBACK(screen_depth_changed),
+ (gpointer) ctk_object);
+
+ gtk_widget_show(ctk_object->box_screen_depth);
+
+ return;
+
+} /* setup_screen_depth_dropdown() */
+
+
+
+/** setup_screen_position_type() *************************************
+ *
+ * Configures the screen position type dropdown to reflect the
+ * position setting for the currently selected screen.
+ *
+ **/
+
+static void setup_screen_position_type(CtkDisplayConfig *ctk_object)
+{
+ nvDisplayPtr display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+
+ /* Handle cases where the position type should be hidden */
+ if (!display || !display->screen) {
+ gtk_widget_hide(ctk_object->mnu_screen_position_type);
+ return;
+ }
+ gtk_widget_show(ctk_object->mnu_screen_position_type);
+
+
+ /* Set the selected positioning type */
+ g_signal_handlers_block_by_func
+ (G_OBJECT(ctk_object->mnu_screen_position_type),
+ G_CALLBACK(screen_position_type_changed), (gpointer) ctk_object);
+
+ gtk_option_menu_set_history
+ (GTK_OPTION_MENU(ctk_object->mnu_screen_position_type),
+ display->screen->position_type);
+
+ g_signal_handlers_unblock_by_func
+ (G_OBJECT(ctk_object->mnu_screen_position_type),
+ G_CALLBACK(screen_position_type_changed), (gpointer) ctk_object);
+
+} /* setup_screen_position_type() */
+
+
+
+/** setup_screen_position_relative() *********************************
+ *
+ * Setup which screen the selected screen is relative to.
+ *
+ **/
+
+static void setup_screen_position_relative(CtkDisplayConfig *ctk_object)
+{
+ nvDisplayPtr display;
+ nvScreenPtr screen;
+ nvScreenPtr relative_to;
+ nvGpuPtr gpu;
+ int idx;
+ int selected_idx;
+ GtkWidget *menu;
+ GtkWidget *menu_item;
+
+ display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+ if (!display || !display->cur_mode || !display->gpu || !display->screen) {
+ return;
+ }
+
+ screen = display->screen;
+
+
+ /* Allocate the screen lookup table for the dropdown */
+ if (ctk_object->screen_position_table) {
+ free(ctk_object->screen_position_table);
+ }
+
+ /* Count the number of screens */
+ ctk_object->screen_position_table_len = 0;
+ for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) {
+ ctk_object->screen_position_table_len += gpu->num_screens;
+ }
+
+ /* Don't count the current screen */
+ if (ctk_object->screen_position_table_len >= 1) {
+ ctk_object->screen_position_table_len--;
+ }
+
+ ctk_object->screen_position_table =
+ (nvScreenPtr *)calloc(1, ctk_object->screen_position_table_len *
+ sizeof(nvScreenPtr));
+
+ if (!ctk_object->screen_position_table) {
+ ctk_object->screen_position_table_len = 0;
+ gtk_widget_hide(ctk_object->mnu_screen_position_relative);
+ return;
+ }
+
+
+ /* Generate the lookup table and screen dropdown */
+ idx = 0;
+ selected_idx = 0;
+ menu = gtk_menu_new();
+ for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) {
+ for (relative_to = gpu->screens;
+ relative_to;
+ relative_to = relative_to->next) {
+
+ gchar *tmp_str;
+
+ if (relative_to == screen) continue;
+
+ if (relative_to == screen->relative_to) {
+ selected_idx = idx;
+ }
+
+ ctk_object->screen_position_table[idx] = relative_to;
+
+ tmp_str = g_strdup_printf("X Screen %d",
+ relative_to->scrnum);
+ menu_item = gtk_menu_item_new_with_label(tmp_str);
+ g_free(tmp_str);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ gtk_widget_show(menu_item);
+ idx++;
+ }
+ }
+
+
+ /* Set the menu and the selected display */
+ g_signal_handlers_block_by_func
+ (G_OBJECT(ctk_object->mnu_screen_position_relative),
+ G_CALLBACK(screen_position_relative_changed), (gpointer) ctk_object);
+
+ gtk_option_menu_set_menu
+ (GTK_OPTION_MENU(ctk_object->mnu_screen_position_relative), menu);
+
+ gtk_option_menu_set_history
+ (GTK_OPTION_MENU(ctk_object->mnu_screen_position_relative),
+ selected_idx);
+
+ g_signal_handlers_unblock_by_func
+ (G_OBJECT(ctk_object->mnu_screen_position_relative),
+ G_CALLBACK(screen_position_relative_changed), (gpointer) ctk_object);
+
+
+ /* Disable the widget if there is only one possibility */
+ gtk_widget_set_sensitive
+ (ctk_object->mnu_screen_position_relative,
+ (idx > 1));
+
+
+ /* Handle cases where the position relative dropdown should be hidden */
+ if (display->screen->position_type == CONF_ADJ_ABSOLUTE) {
+ gtk_widget_hide(ctk_object->mnu_screen_position_relative);
+ return;
+ }
+ gtk_widget_show(ctk_object->mnu_screen_position_relative);
+
+} /* setup_screen_position_relative() */
+
+
+
+/** setup_screen_position_offset() ***********************************
+ *
+ * Sets up the screen position offset text entry to reflect the
+ * currently selected screen.
+ *
+ **/
+
+static void setup_screen_position_offset(CtkDisplayConfig *ctk_object)
+{
+ char *tmp_str;
+ nvDisplayPtr display;
+ nvScreenPtr screen;
+
+ display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+
+ /* Handle cases where the position offset should be hidden */
+ if (!display || !display->screen ||
+ (display->screen->position_type != CONF_ADJ_ABSOLUTE &&
+ display->screen->position_type != CONF_ADJ_RELATIVE)) {
+ gtk_widget_hide(ctk_object->txt_screen_position_offset);
+ return;
+ }
+ gtk_widget_show(ctk_object->txt_screen_position_offset);
+
+
+ /* Update the position text */
+ screen = display->screen;
+
+ tmp_str = g_strdup_printf("%+d%+d", screen->dim[X], screen->dim[Y]);
+
+ gtk_entry_set_text(GTK_ENTRY(ctk_object->txt_screen_position_offset),
+ tmp_str);
+
+ g_free(tmp_str);
+
+} /* setup_screen_position_offset() */
+
+
+
+/** setup_screen_position() ******************************************
+ *
+ * Sets up the the screen position section to reflect the position
+ * settings for the currently selected screen.
+ *
+ **/
+
+static void setup_screen_position(CtkDisplayConfig *ctk_object)
+{
+ nvGpuPtr gpu;
+ nvDisplayPtr display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+ int num_screens;
+
+
+ /* Count the number of screens */
+ num_screens = 0;
+ for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) {
+ num_screens += gpu->num_screens;
+ }
+
+
+ /* Hide the position box if there is only one screen */
+ if (!display || !display->screen || num_screens <= 1) {
+ gtk_widget_hide(ctk_object->box_screen_position);
+ return;
+ }
+ gtk_widget_show(ctk_object->box_screen_position);
+
+
+ /* Setup the screen position widgets */
+ setup_screen_position_type(ctk_object);
+
+ setup_screen_position_relative(ctk_object);
+
+ setup_screen_position_offset(ctk_object);
+
+} /* setup_screen_position() */
+
+
+
+/** setup_screen_metamode() ******************************************
+ *
+ * Generates the metamode dropdown for the selected screen
+ *
+ **/
+
+static void setup_screen_metamode(CtkDisplayConfig *ctk_object)
+{
+ nvScreenPtr screen = ctk_display_layout_get_selected_screen
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+ gchar *str;
+
+
+ if (!screen || !ctk_object->advanced_mode) {
+ gtk_widget_hide(ctk_object->box_screen_metamode);
+ return;
+ }
+
+
+ /* Update the meatamode selector button */
+ str = g_strdup_printf("%d - ...", screen->cur_metamode_idx +1);
+ gtk_button_set_label(GTK_BUTTON(ctk_object->btn_screen_metamode), str);
+ g_free(str);
+
+ /* Only allow deletes if there are more than 1 metamodes */
+ gtk_widget_set_sensitive(ctk_object->btn_screen_metamode_delete,
+ ((screen->num_metamodes > 1) ? True : False));
+
+ gtk_widget_show(ctk_object->box_screen_metamode);
+
+} /* setup_screen_metamode() */
+
+
+
+/** setup_screen_frame() *********************************************
+ *
+ * Sets up the screen frame to reflect the currently selected screen.
+ *
+ **/
+
+static void setup_screen_frame(CtkDisplayConfig *ctk_object)
+{
+ nvDisplayPtr display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+ gchar *tmp;
+
+
+ /* If there is no display or no screen selected, hide the frame */
+ if (!display || !display->screen) {
+ gtk_widget_set_sensitive(ctk_object->screen_frame, False);
+ gtk_widget_hide(ctk_object->screen_frame);
+ return;
+ }
+
+
+ /* Enable display widgets and setup widget information */
+ gtk_widget_set_sensitive(ctk_object->screen_frame, True);
+
+
+ /* Setup the screen number */
+ tmp = g_strdup_printf("%d", display->screen->scrnum);
+ gtk_label_set_text(GTK_LABEL(ctk_object->txt_screen_num), tmp);
+ g_free(tmp);
+
+
+ /* Setup depth menu */
+ setup_screen_depth_dropdown(ctk_object);
+
+
+ /* Setup position */
+ setup_screen_position(ctk_object);
+
+
+ /* Setup metamode menu */
+ setup_screen_metamode(ctk_object);
+
+
+ gtk_widget_show(ctk_object->screen_frame);
+
+} /* setup_screen_frame() */
+
+
+
+/** validation_fix_crowded_metamodes() *******************************
+ *
+ * Goes through each screen's metamodes and ensures that at most
+ * two display devices are active (have a modeline set) per metamode.
+ * This function also checks to make sure that there is at least
+ * one display device active for each metamode.
+ *
+ **/
+
+static gint validation_fix_crowded_metamodes(CtkDisplayConfig *ctk_object,
+ nvScreenPtr screen)
+{
+ nvDisplayPtr display;
+ nvModePtr first_mode = NULL;
+ nvModePtr mode;
+ int num;
+ int i, j;
+
+
+ /* Verify each metamode with the metamodes that come before it */
+ for (i = 0; i < screen->num_metamodes; i++) {
+
+ /* Keep track of the first mode in case we need to assign
+ * a default resolution
+ */
+ first_mode = NULL;
+
+ /* Count the number of display devices that have a mode
+ * set for this metamode. NULL out the modes of extra
+ * display devices once we've counted 2 display devices
+ * that have a (non NULL) mode set.
+ */
+ num = 0;
+ for (display = screen->gpu->displays;
+ display;
+ display = display->next) {
+
+ if (display->screen != screen) continue;
+
+ /* Check the mode that corresponds with the metamode */
+ mode = display->modes;
+ for (j = 0; j < i; j++) {
+ mode = mode->next;
+ }
+
+ if (!first_mode) {
+ first_mode = mode;
+ }
+
+ if (mode->modeline) {
+ num++;
+ }
+
+ /* Disable extra modes */
+ if (num > 2) {
+ ctk_display_layout_set_mode_modeline
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ mode, NULL);
+
+ nv_info_msg(TAB, "Setting display device '%s' as Off "
+ "for MetaMode %d on Screen %d. (There are "
+ "already two active display devices for this "
+ "MetaMode.", display->name, i, screen->scrnum);
+ }
+ }
+
+ /* Handle the case where a metamode has no active display device */
+ if (!num) {
+
+ /* There are other modelines, so we can safely delete this one */
+ if (screen->num_metamodes > 1) {
+
+ /* Delete the metamode */
+ ctk_display_layout_delete_screen_metamode
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), screen, i);
+
+ nv_info_msg(TAB, "Removed MetaMode %d on Screen %d (No "
+ "active display devices)\n", i,
+ screen->scrnum);
+
+ /* Since we just deleted the current metamode, we
+ * need to check the i'th metamode "again" since this
+ * is effectively the next metamode.
+ */
+ i--;
+
+ /* This is the only modeline, activate the first display */
+ } else if (first_mode) {
+
+ /* Select the first modeline in the modepool */
+ ctk_display_layout_set_mode_modeline
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ first_mode,
+ first_mode->display->modelines);
+
+ nv_info_msg(TAB, "Activating display device '%s' for MetaMode "
+ "%d on Screen %d. (Minimally, a Screen must have "
+ "one MetaMode with at least one active display "
+ "device.)",
+ first_mode->display->name, i, screen->scrnum);
+ }
+ }
+ }
+
+ return 1;
+
+} /* validation_fix_crowded_metamodes() */
+
+
+
+/** validation_fix_crowded_metamodes() *******************************
+ *
+ * Goes through each screen's metamodes and ensures that each
+ * metamode string is unique. If a metamode string is not unique,
+ * the duplicate metamode is removed.
+ *
+ **/
+
+static gint validation_remove_dupe_metamodes(CtkDisplayConfig *ctk_object,
+ nvScreenPtr screen)
+{
+ int i, j;
+ char *metamode_str;
+
+ /* Verify each metamode with the metamodes that come before it */
+ for (i = 1; i < screen->num_metamodes; i++) {
+
+ metamode_str = get_screen_metamode_str(screen, i, 0);
+ for (j = 0; j < i; j++) {
+ char *tmp;
+ tmp = get_screen_metamode_str(screen, j, 0);
+
+ /* Remove duplicates */
+ if (!strcmp(metamode_str, tmp)) {
+
+ /* Delete the metamode */
+ ctk_display_layout_delete_screen_metamode
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), screen, i);
+
+ nv_info_msg(TAB, "Removed MetaMode %d on Screen %d (Is "
+ "Duplicate of MetaMode %d)\n", i+1, screen->scrnum,
+ j+1);
+ g_free(tmp);
+ i--; /* Check the new metamode in i'th position */
+ break;
+ }
+ g_free(tmp);
+ }
+ g_free(metamode_str);
+ }
+
+ return 1;
+
+} /* validation_remove_dupe_metamodes() */
+
+
+
+/** validation_auto_fix_screen() *************************************
+ *
+ * Do what we can to make this screen conform to validation.
+ *
+ **/
+
+static gint validation_auto_fix_screen(CtkDisplayConfig *ctk_object,
+ nvScreenPtr screen)
+{
+ gint status = 1;
+
+ status &= validation_fix_crowded_metamodes(ctk_object, screen);
+ status &= validation_remove_dupe_metamodes(ctk_object, screen);
+
+ return status;
+
+} /* validation_auto_fix_screen() */
+
+
+
+/** validation_auto_fix() ********************************************
+ *
+ * Attempts to fix any problems found in the layout. Returns 1 if
+ * the layout is in a valid state when done. Returns 0 if there
+ * was a problem and the layout validation error could not be fixed
+ * by this function.
+ *
+ **/
+
+static gint validation_auto_fix(CtkDisplayConfig *ctk_object)
+{
+ nvLayoutPtr layout = ctk_object->layout;
+ nvGpuPtr gpu;
+ nvScreenPtr screen;
+ gint success = 1;
+
+
+ /* Auto fix each screen */
+ for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+ for (screen = gpu->screens; screen; screen = screen->next) {
+ if (!validation_auto_fix_screen(ctk_object, screen)) {
+ success = 0;
+ break;
+ }
+ }
+ }
+
+ if (!success) {
+ nv_warning_msg("Failed to auto fix X configuration.");
+ /* XXX We should pop up a dialog box to let the user know
+ * there are still problems.
+ */
+ }
+
+ return success;
+
+} /* validation_auto_fix() */
+
+
+
+/** validate_screen() ************************************************
+ *
+ * This function returns NULL if the screen is found to be in a
+ * valid state. To be in a valid state the screen's metamodes must
+ * adhear to the following:
+ *
+ * - Have at least 1 display device activated for all metamodes.
+ *
+ * - Have at most 2 display devices activated for all metamodes.
+ *
+ * - All metamodes must be unique.
+ *
+ * - All metamodes must have a coherent offset (The top left corner
+ * of the bounding box of all the metamodes must be the same.)
+ *
+ * If the screen is found to be in an invalid state, a string
+ * describing the problem is returned. This string should be freed
+ * by the user when done with it.
+ *
+ **/
+
+static gchar * validate_screen(nvScreenPtr screen)
+{
+ nvDisplayPtr display;
+ nvModePtr mode;
+ int i, j;
+ int num_displays;
+ char *metamode_str;
+ gchar *err_str = NULL;
+ gchar *tmp;
+ gchar *tmp2;
+
+ gchar bullet[8]; // UTF8 Bullet string
+ int len;
+
+
+
+ /* Convert the Unicode "Bullet" Character into a UTF8 string */
+ len = g_unichar_to_utf8(0x2022, bullet);
+ bullet[len] = '\0';
+
+
+ for (i = 0; i < screen->num_metamodes; i++) {
+
+ /* Count the number of display devices used in the metamode */
+ num_displays = 0;
+ for (display = screen->gpu->displays;
+ display;
+ display = display->next) {
+
+ if (display->screen != screen) continue;
+
+ mode = display->modes;
+ for (j = 0; j < i; j++) {
+ mode = mode->next;
+ }
+ if (mode->modeline) {
+ num_displays++;
+ }
+ }
+
+
+ /* There must be at least one display active in the metamode. */
+ if (!num_displays) {
+ tmp = g_strdup_printf("%s MetaMode %d of Screen %d does not have "
+ "an active display devices.\n\n",
+ bullet, i+1, screen->scrnum);
+ tmp2 = g_strconcat((err_str ? err_str : ""), tmp, NULL);
+ g_free(err_str);
+ g_free(tmp);
+ err_str = tmp2;
+ }
+
+
+ /* There can be at most two displays active in the metamode. */
+ if (num_displays > 2) {
+ tmp = g_strdup_printf("%s MetaMode %d of Screen %d has more than "
+ "two active display devices.\n\n",
+ bullet, i+1, screen->scrnum);
+ tmp2 = g_strconcat((err_str ? err_str : ""), tmp, NULL);
+ g_free(err_str);
+ g_free(tmp);
+ err_str = tmp2;
+ }
+
+
+ /* Verify that the metamode is unique */
+ metamode_str = get_screen_metamode_str(screen, i, 0);
+ for (j = 0; j < i; j++) {
+ char *tmp = get_screen_metamode_str(screen, j, 0);
+
+ /* Make sure the metamode is unique */
+ if (!strcmp(metamode_str, tmp)) {
+ g_free(tmp);
+ tmp = g_strdup_printf("%s MetaMode %d of Screen %d is the "
+ "same as MetaMode %d. All MetaModes "
+ "must be unique.\n\n",
+ bullet, i+1, screen->scrnum, j+1);
+ tmp2 = g_strconcat((err_str ? err_str : ""), tmp, NULL);
+ g_free(err_str);
+ err_str = tmp2;
+ g_free(tmp);
+ break;
+ }
+ g_free(tmp);
+ }
+ g_free(metamode_str);
+ }
+
+ return err_str;
+
+} /* validate_screen() */
+
+
+
+/** validate_layout() ************************************************
+ *
+ * Makes sure that the layout is ready for applying/saving.
+ *
+ * If the layout is found to be invalid the user is prompted to
+ * cancel the operation or to ignore and continue despite the
+ * errors.
+ *
+ **/
+
+static int validate_layout(CtkDisplayConfig *ctk_object)
+{
+ nvLayoutPtr layout = ctk_object->layout;
+ nvGpuPtr gpu;
+ nvScreenPtr screen;
+ gchar *err_strs = NULL;
+ gchar *err_str;
+ gchar *tmp;
+ gint result;
+
+
+ /* Validate each screen */
+ for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+ for (screen = gpu->screens; screen; screen = screen->next) {
+ err_str = validate_screen(screen);
+ if (err_str) {
+ tmp = g_strconcat((err_strs ? err_strs : ""), err_str, NULL);
+ g_free(err_strs);
+ g_free(err_str);
+ err_strs = tmp;
+ }
+ }
+ }
+
+ /* Layout is valid */
+ if (!err_strs) {
+ return 1;
+ }
+
+ /* Layout is not valid, ask the user what we should do */
+ gtk_text_buffer_set_text
+ (GTK_TEXT_BUFFER(ctk_object->buf_validation_override), err_strs, -1);
+ g_free(err_strs);
+
+ gtk_widget_hide(ctk_object->box_validation_override_details);
+ gtk_window_resize(GTK_WINDOW(ctk_object->dlg_validation_override),
+ 350, 1);
+ gtk_window_set_resizable(GTK_WINDOW(ctk_object->dlg_validation_override),
+ FALSE);
+ gtk_button_set_label(GTK_BUTTON(ctk_object->btn_validation_override_show),
+ "Show Details...");
+
+ /* Show the confirm dialog */
+ gtk_window_set_transient_for
+ (GTK_WINDOW(ctk_object->dlg_validation_override),
+ GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(ctk_object))));
+ gtk_widget_grab_focus(ctk_object->btn_validation_override_cancel);
+ gtk_widget_show(ctk_object->dlg_validation_override);
+ result = gtk_dialog_run(GTK_DIALOG(ctk_object->dlg_validation_override));
+ gtk_widget_hide(ctk_object->dlg_validation_override);
+
+ switch (result)
+ {
+ case GTK_RESPONSE_ACCEPT:
+ /* User wants to ignore the validation warnings */
+ return 1;
+
+ case GTK_RESPONSE_APPLY:
+ /* User wants to auto fix the warnings */
+ result = validation_auto_fix(ctk_object);
+
+ /* Update the GUI to reflect any updates made by auto fix */
+ setup_display_frame(ctk_object);
+ setup_screen_frame(ctk_object);
+ return result;
+
+ case GTK_RESPONSE_REJECT:
+ default:
+ /* User wants to heed the validation warnings */
+ return 0;
+ }
+
+ return 0;
+
+} /* validate_layout() */
+
+
+
+/** validate_apply() *************************************************
+ *
+ * Informs the user if we can't apply for whatever reason. This
+ * function returns FALSE if we should not continue the apply or
+ * TRUE if we should continue the apply operation(s).
+ *
+ **/
+
+static gboolean validate_apply(CtkDisplayConfig *ctk_object)
+{
+ gint result;
+
+ if (ctk_object->apply_possible) {
+ return TRUE;
+ }
+
+ /* Show the "can't apply" dialog */
+
+ /* If we can't apply, let the user know.
+ *
+ * XXX - Show more details as to why exactly we can't apply.
+ */
+
+ gtk_window_set_transient_for
+ (GTK_WINDOW(ctk_object->dlg_validation_apply),
+ GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(ctk_object))));
+ gtk_widget_show(ctk_object->dlg_validation_apply);
+ result = gtk_dialog_run(GTK_DIALOG(ctk_object->dlg_validation_apply));
+ gtk_widget_hide(ctk_object->dlg_validation_apply);
+
+
+ switch (result) {
+ case GTK_RESPONSE_ACCEPT:
+ /* User wants to ignore the validation warnings */
+ return TRUE;
+
+ case GTK_RESPONSE_REJECT:
+ default:
+ return FALSE;
+ }
+
+
+ return FALSE;
+
+} /* validate_apply() */
+
+
+
+/* Callback handlers *************************************************/
+
+
+/** layout_selected_callback() ***************************************
+ *
+ * Called every time the user selects a new display from the layout
+ * image.
+ *
+ **/
+
+void layout_selected_callback(nvLayoutPtr layout, void *data)
+{
+ CtkDisplayConfig *ctk_object = (CtkDisplayConfig *)data;
+
+
+ /* Reconfigure GUI to display information about the selected screen. */
+ setup_display_frame(ctk_object);
+ setup_screen_frame(ctk_object);
+
+ get_cur_screen_pos(ctk_object);
+
+} /* layout_selected_callback() */
+
+
+
+/** layout_modified_callback() ***************************************
+ *
+ * Called every time the user moves a screen/display in the layout
+ * image.
+ *
+ **/
+
+void layout_modified_callback(nvLayoutPtr layout, void *data)
+{
+ CtkDisplayConfig *ctk_object = (CtkDisplayConfig *)data;
+
+
+ /* Sync the information displayed by the GUI to match the settings
+ * of the currently selected display device.
+ */
+
+ /* Setup position */
+ setup_display_position(ctk_object);
+
+
+ /* Setup panning */
+ setup_display_panning(ctk_object);
+
+ setup_screen_position(ctk_object);
+
+ /* If the positioning of the X Screen changes, we cannot apply */
+ check_screen_pos_changed(ctk_object);
+
+ gtk_widget_set_sensitive(ctk_object->btn_apply, True);
+
+} /* layout_modified_callback() */
+
+
+
+/* Widget signal handlers ********************************************/
+
+
+/** do_enable_display_for_xscreen() **********************************
+ *
+ * Adds the display device to a separate X Screen in the layout.
+ *
+ **/
+
+void do_enable_display_for_xscreen(CtkDisplayConfig *ctk_object,
+ nvDisplayPtr display)
+{
+ nvLayoutPtr layout = ctk_object->layout;
+ nvGpuPtr gpu;
+ nvScreenPtr screen;
+ nvMetaModePtr metamode;
+ nvModePtr mode;
+ int scrnum;
+
+
+ /* Get the next available screen number */
+ scrnum = 0;
+ for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+ for (screen = gpu->screens; screen; screen = screen->next) {
+ scrnum++;
+ }
+ }
+
+
+ /* Get resources */
+ screen = (nvScreenPtr)calloc(1, sizeof(nvScreen));
+ metamode = (nvMetaModePtr)calloc(1, sizeof(nvMetaMode));
+ if (!screen) return;
+ if (!metamode) {
+ free(screen);
+ return;
+ }
+
+
+ /* Setup the display */
+ display->screen = screen;
+
+
+ /* Setup the mode */
+ mode = display->modes;
+
+ mode->modeline = display->modelines;
+ mode->metamode = metamode;
+
+ /* XXX Hopefully display->modelines is 'nvidia-auto-select' */
+ mode->dim[W] = display->modelines->data.hdisplay;
+ mode->dim[H] = display->modelines->data.vdisplay;
+ mode->pan[W] = mode->dim[W];
+ mode->pan[H] = mode->dim[H];
+ mode->position_type = CONF_ADJ_ABSOLUTE;
+
+
+ /* Setup the initial metamode */
+ metamode->id = -1;
+ metamode->source = METAMODE_SOURCE_NVCONTROL;
+ metamode->switchable = True;
+
+
+ /* Setup the screen */
+ screen->scrnum = scrnum;
+ screen->gpu = display->gpu;
+ screen->depth = 24;
+ screen->displays_mask = display->device_mask;
+ screen->num_displays = 1;
+ screen->metamodes = metamode;
+ screen->num_metamodes = 1;
+ screen->cur_metamode = metamode;
+ screen->cur_metamode_idx = 0;
+
+ /* XXX Should we position it "RightOf" the right-most screen by default? */
+ screen->dim[X] = mode->dim[X];
+ screen->dim[Y] = mode->dim[Y];
+ screen->position_type = CONF_ADJ_ABSOLUTE;
+
+
+ /* Add the screen at the end of the gpu's screen list */
+ gpu = display->gpu;
+ gpu->screens =
+ (nvScreenPtr)xconfigAddListItem((GenericListPtr)gpu->screens,
+ (GenericListPtr)screen);
+ gpu->num_screens++;
+
+
+ /* We can't dynamically add new X Screens */
+ ctk_object->apply_possible = FALSE;
+
+} /* do_enable_display_for_xscreen() */
+
+
+
+/** do_enable_display_for_twinview() *********************************
+ *
+ * Adds the display device to the TwinView setup that already exists
+ * on the GPU.
+ *
+ **/
+
+static void do_enable_display_for_twinview(CtkDisplayConfig *ctk_object,
+ nvDisplayPtr display)
+{
+ nvGpuPtr gpu;
+ nvScreenPtr screen;
+ nvMetaModePtr metamode;
+ nvModePtr mode;
+ guint new_mask;
+
+
+ /* Make sure a screen exists */
+ gpu = display->gpu;
+ screen = gpu->screens;
+
+ if (!screen) return;
+
+
+ /* Associate the display device with the screen */
+ new_mask = screen->displays_mask | display->device_mask;
+ if (screen->handle) {
+ ReturnStatus ret;
+ ret = NvCtrlSetAttribute(screen->handle,
+ NV_CTRL_ASSOCIATED_DISPLAY_DEVICES,
+ new_mask);
+ if (ret != NvCtrlSuccess) {
+ nv_error_msg("Failed to associate display device '%s' with "
+ "X Screen %d!", display->name, screen->scrnum);
+ } else {
+ /* Make sure other parts of nvidia-settings get updated */
+ ctk_event_emit(screen->ctk_event, 0,
+ NV_CTRL_ASSOCIATED_DISPLAY_DEVICES, new_mask);
+ }
+ }
+
+
+ /* Fix up the display's metamode list */
+ remove_modes_from_display(display);
+
+ for (metamode = screen->metamodes; metamode; metamode = metamode->next) {
+
+ /* Create the nvidia-auto-select mode fo the display */
+ mode = parse_mode(display, "nvidia-auto-select");
+ mode->metamode = metamode;
+
+ /* Set the currently selected mode */
+ if (metamode == screen->cur_metamode) {
+ display->cur_mode = mode;
+ }
+
+ /* Position the new mode at the top right of the metamode */
+ mode->position_type = CONF_ADJ_ABSOLUTE;
+ mode->dim[X] = metamode->dim[X] + metamode->dim[W];
+ mode->dim[Y] = metamode->dim[Y];
+ mode->pan[X] = mode->dim[X];
+ mode->pan[Y] = mode->dim[Y];
+
+ /* Add the mode at the end of the display's mode list */
+ display->modes =
+ (nvModePtr)xconfigAddListItem((GenericListPtr)display->modes,
+ (GenericListPtr)mode);
+ display->num_modes++;
+ }
+
+
+ /* Link the screen and display together */
+ screen->displays_mask = new_mask;
+ screen->num_displays++;
+ display->screen = screen;
+
+} /* do_enable_display_for_twinview() */
+
+
+
+/** do_configure_display_for_xscreen() *******************************
+ *
+ * Configures the display's GPU for Multiple X Screens
+ *
+ **/
+
+static void do_configure_display_for_xscreen(CtkDisplayConfig *ctk_object,
+ nvDisplayPtr display)
+{
+ nvLayoutPtr layout = ctk_object->layout;
+ nvGpuPtr gpu;
+ nvScreenPtr screen;
+ nvMetaModePtr metamode;
+ nvModePtr mode;
+ int scrnum = 0;
+
+
+ if (!display || !display->gpu) return;
+
+
+ /* Get the next available screen number */
+ scrnum = 0;
+ for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+ for (screen = gpu->screens; screen; screen = screen->next) {
+ scrnum++;
+ }
+ }
+
+ gpu = display->gpu;
+
+
+ /* Make sure there is just one display device per X Screen */
+ for (display = gpu->displays; display; display = display->next) {
+
+ nvScreenPtr new_screen;
+
+ screen = display->screen;
+ if (!screen || screen->num_displays == 1) continue;
+
+ /* Create a new X Screen for this display */
+ new_screen = (nvScreenPtr)calloc(1, sizeof(nvScreen));
+ if (!new_screen) continue; /* XXX Fail */
+
+ new_screen->gpu = gpu;
+ new_screen->scrnum = scrnum++;
+
+ new_screen->depth = screen->depth;
+
+ new_screen->displays_mask = display->device_mask;
+ new_screen->num_displays = 1;
+
+ /* Create a metamode for each mode on the display */
+ new_screen->num_metamodes = 0;
+ for (mode = display->modes; mode; mode = mode->next) {
+
+ /* Create the metamode */
+ metamode = (nvMetaModePtr)calloc(1, sizeof(nvMetaMode));
+ if (!metamode) continue; /* XXX Fail ! */
+
+ metamode->source = METAMODE_SOURCE_NVCONTROL;
+
+ /* Make the mode point to the new metamode */
+ mode->metamode = metamode;
+
+ /* Set the current metamode if this is the current mode */
+ if (display->cur_mode == mode) {
+ new_screen->cur_metamode = metamode;
+ new_screen->cur_metamode_idx = new_screen->num_metamodes;
+ }
+
+ /* Append the metamode */
+ new_screen->metamodes =
+ (nvMetaModePtr)xconfigAddListItem((GenericListPtr)new_screen->metamodes,
+ (GenericListPtr)metamode);
+ new_screen->num_metamodes++;
+ }
+
+ /* Move the display to the new screen */
+ screen->num_displays--;
+ screen->displays_mask &= ~(display->device_mask);
+
+ display->screen = new_screen;
+
+ /* Append the screen to the gpu */
+ gpu->screens =
+ (nvScreenPtr)xconfigAddListItem((GenericListPtr)gpu->screens,
+ (GenericListPtr)new_screen);
+ gpu->num_screens++;
+
+ /* Earlier display devices get first dibs on low screen numbers */
+ new_screen->handle = screen->handle;
+ new_screen->ctk_event = screen->ctk_event;
+ new_screen->scrnum = screen->scrnum;
+ screen->handle = NULL;
+ screen->ctk_event = NULL;
+ screen->scrnum = scrnum -1;
+
+ /* Can't apply creation of new screens */
+ ctk_object->apply_possible = FALSE;
+ }
+
+
+ /* Translate mode positional relationships to screen relationships */
+ for (display = gpu->displays; display; display = display->next) {
+
+ if (!display->screen) continue;
+
+ for (mode = display->modes; mode; mode = mode->next) {
+ if (mode->relative_to &&
+ (mode->relative_to->gpu == mode->display->gpu)) {
+ display->screen->position_type = mode->position_type;
+ display->screen->relative_to = mode->relative_to->screen;
+ }
+ mode->position_type = CONF_ADJ_ABSOLUTE;
+ mode->relative_to = NULL;
+ }
+ }
+
+} /* do_configure_display_for_xscreen() */
+
+
+
+/** do_configure_display_for_twinview() ******************************
+ *
+ * Configures the display's GPU for TwinView
+ *
+ **/
+
+static void do_configure_display_for_twinview(CtkDisplayConfig *ctk_object,
+ nvDisplayPtr display)
+{
+ nvScreenPtr screen;
+ nvMetaModePtr metamode;
+ nvModePtr mode;
+ nvModePtr last_mode;
+ nvGpuPtr gpu = display->gpu;
+ int m;
+
+
+ /* We need at least one screen to activate TwinView */
+ if (!gpu || !gpu->screens) return;
+
+
+ /* Make sure the screen has enough metamodes */
+ screen = gpu->screens;
+ for (display = gpu->displays; display; display = display->next) {
+
+ /* Only add enabled displays to TwinView setup */
+ if (!display->screen) continue;
+
+ /* Make sure the screen has enough metamodes */
+ for (m = display->num_modes - screen->num_metamodes; m > 0; m--) {
+
+ metamode = (nvMetaModePtr)calloc(1, sizeof(nvMetaMode));
+ if (!metamode) break; // XXX Sigh.
+
+ metamode->source = METAMODE_SOURCE_NVCONTROL;
+
+ /* Add the metamode at the end of the screen's metamode list */
+ screen->metamodes =
+ (nvMetaModePtr)xconfigAddListItem((GenericListPtr)screen->metamodes,
+ (GenericListPtr)metamode);
+ screen->num_metamodes++;
+ }
+ }
+
+
+ /* Make sure each display has the right number of modes and that
+ * the modes point to the right metamode in the screen.
+ */
+ for (display = gpu->displays; display; display = display->next) {
+
+ /* Only add enabled displays to TwinView setup */
+ if (!display->screen) continue;
+
+ /* Make the display mode point to the right metamode */
+ metamode = screen->metamodes;
+ mode = display->modes;
+ last_mode = NULL;
+ while (metamode && mode) {
+
+ if (metamode == screen->cur_metamode) {
+ display->cur_mode = mode;
+ }
+
+ /* Keep the relationship between displays if possible. If
+ * this display's screen is relative to another screen
+ * on the same gpu, translate the relationship to the
+ * display's mode.
+ */
+ if (display->screen->relative_to &&
+ (display->screen->relative_to->gpu == gpu)) {
+
+ nvDisplayPtr other;
+
+ /* Make the display relative to the other display */
+ for (other = gpu->displays; other; other = other->next) {
+ if (other->screen == display->screen->relative_to) {
+ mode->position_type = display->screen->position_type;
+ mode->relative_to = other;
+ break;
+ }
+ }
+ }
+ mode->metamode = metamode;
+
+ if (mode && !mode->next) {
+ last_mode = mode;
+ }
+ metamode = metamode->next;
+ mode = mode->next;
+ }
+
+ /* Add dummy modes */
+ while (metamode) {
+
+ mode = parse_mode(display, "NULL");
+ mode->dummy = 1;
+ mode->metamode = metamode;
+
+ if (metamode == screen->cur_metamode) {
+ display->cur_mode = mode;
+ }
+
+ /* Duplicate position information of the last mode */
+ if (last_mode) {
+ mode->dim[X] = last_mode->dim[X];
+ mode->dim[Y] = last_mode->dim[Y];
+ mode->pan[X] = last_mode->pan[X];
+ mode->pan[Y] = last_mode->pan[Y];
+ mode->position_type = last_mode->position_type;
+ mode->relative_to = last_mode->relative_to;
+ }
+
+ /* Add the mode at the end of display's mode list */
+ display->modes =
+ (nvModePtr)xconfigAddListItem((GenericListPtr)display->modes,
+ (GenericListPtr)mode);
+ display->num_modes++;
+ metamode = metamode->next;
+ }
+ }
+
+
+ /* Make the displays part of the screen */
+ for (display = gpu->displays; display; display = display->next) {
+
+ /* Only add enabled displays to TwinView setup */
+ if (!display->screen) continue;
+
+ if (display->screen != screen) {
+ display->screen = screen;
+ screen->displays_mask |= display->device_mask;
+ screen->num_displays++;
+ }
+ }
+
+
+ /* Delete extra screens on the GPU */
+ while (gpu->screens->next) {
+ nvScreenPtr other;
+
+ /* Delete screens that come before 'screen' */
+ if (gpu->screens != screen) {
+ other = gpu->screens;
+ gpu->screens = other->next;
+
+ /* Delete screens that comes after 'screen' */
+ } else {
+ other = gpu->screens->next;
+ gpu->screens->next = other->next;
+ }
+
+ /* Handle positional relationships going away */
+ if (screen->relative_to == other) {
+ screen->position_type = CONF_ADJ_ABSOLUTE;
+ screen->relative_to = NULL;
+ }
+
+ /* Clean up memory used by the screen */
+ while (other->metamodes) {
+ nvMetaModePtr metamode = other->metamodes;
+ other->metamodes = metamode->next;
+ free(metamode);
+ }
+
+ /* Keep the lowest screen number */
+ if (other->scrnum < screen->scrnum) {
+ if (screen->handle) {
+ NvCtrlAttributeClose(screen->handle);
+ }
+ screen->scrnum = other->scrnum;
+ screen->handle = other->handle;
+ } else {
+ if (other->handle) {
+ NvCtrlAttributeClose(other->handle);
+ }
+ }
+
+ free(other);
+ gpu->num_screens--;
+ }
+
+} /* do_configure_display_for_twinview() */
+
+
+
+/** do_query_remove_display() ****************************************
+ *
+ * Asks the user about removing a display device from the layout.
+ *
+ **/
+
+static gboolean do_query_remove_display(CtkDisplayConfig *ctk_object,
+ nvDisplayPtr display)
+{
+ gint result;
+
+
+ /* Show the display disable dialog */
+ gtk_window_set_transient_for
+ (GTK_WINDOW(ctk_object->dlg_display_disable),
+ GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(ctk_object))));
+ gtk_widget_show_all(ctk_object->dlg_display_disable);
+ gtk_widget_grab_focus(ctk_object->btn_display_disable_cancel);
+ result = gtk_dialog_run(GTK_DIALOG(ctk_object->dlg_display_disable));
+ gtk_widget_hide(ctk_object->dlg_display_disable);
+
+ switch (result)
+ {
+ case GTK_RESPONSE_ACCEPT:
+ return True;
+
+ case GTK_RESPONSE_CANCEL:
+ default:
+ /* Cancel */
+ return False;
+ }
+
+ return False;
+
+} /* do_query_remove_display() */
+
+
+
+/** do_disable_display() *********************************************
+ *
+ * Confirms disabling of the display device.
+ *
+ **/
+
+void do_disable_display(CtkDisplayConfig *ctk_object, nvDisplayPtr display)
+{
+ nvGpuPtr gpu = display->gpu;
+ nvScreenPtr screen = display->screen;
+ gchar *str;
+ gchar *type = get_display_type_str(display->device_mask, 0);
+
+
+ /* Setup the remove display dialog */
+ if (ctk_object->advanced_mode) {
+ str = g_strdup_printf("Disable the display device %s (%s) "
+ "on GPU-%d (%s)?",
+ display->name, type,
+ NvCtrlGetTargetId(gpu->handle), gpu->name);
+ } else {
+ str = g_strdup_printf("Disable the display device %s (%s)?",
+ display->name, type);
+ }
+ g_free(type);
+
+ gtk_label_set_text
+ (GTK_LABEL(ctk_object->txt_display_disable), str);
+ g_free(str);
+
+ gtk_button_set_label(GTK_BUTTON(ctk_object->btn_display_disable_off),
+ "Disable");
+ gtk_button_set_label(GTK_BUTTON(ctk_object->btn_display_disable_cancel),
+ "Cancel");
+
+
+ /* Ask user what to do */
+ if (do_query_remove_display(ctk_object, display)) {
+
+ /* Remove display from the X Screen */
+ remove_display_from_screen(display);
+
+ /* If the screen is empty, remove it */
+ if (!screen->num_displays) {
+ remove_screen_from_gpu(screen);
+ free_screen(screen);
+ }
+
+ /* Add the fake mode to the display */
+ add_screenless_modes_to_displays(display->gpu);
+ }
+
+} /* do_disable_display() */
+
+
+
+/** display_config_clicked() *****************************************
+ *
+ * Called when user clicks on the display configuration button.
+ *
+ **/
+
+static void display_config_clicked(GtkWidget *widget, gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ nvDisplayPtr display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+ gint result;
+ gboolean update = FALSE;
+ nvGpuPtr gpu;
+ int num_screens;
+
+
+ if (!display) return;
+
+
+ /* Don't allow disabling the last display device */
+ num_screens = 0;
+ for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) {
+ num_screens += gpu->num_screens;
+ }
+ if (num_screens == 1 && display->screen &&
+ display->screen->num_displays == 1) {
+ gtk_widget_set_sensitive(ctk_object->rad_display_config_disabled,
+ FALSE);
+ } else {
+ gtk_widget_set_sensitive(ctk_object->rad_display_config_disabled,
+ TRUE);
+ }
+
+
+ /* We can only enable as many X Screens as the GPU supports */
+ if (!display->screen &&
+ (display->gpu->num_screens >= display->gpu->max_displays)) {
+ gtk_widget_set_sensitive(ctk_object->rad_display_config_xscreen,
+ FALSE);
+ } else {
+ gtk_widget_set_sensitive(ctk_object->rad_display_config_xscreen,
+ TRUE);
+ }
+
+
+ /* We can't setup TwinView if there is only one display connected,
+ * there are no existing X Screens on the GPU, or this display is
+ * the only enabled device on the GPU.
+ */
+ if (display->gpu->num_displays == 1 || !display->gpu->num_screens ||
+ (display->gpu->num_screens == 1 &&
+ display->gpu->screens->num_displays == 1 &&
+ display->screen == display->gpu->screens)) {
+ gtk_widget_set_sensitive(ctk_object->rad_display_config_twinview,
+ FALSE);
+ } else {
+ gtk_widget_set_sensitive(ctk_object->rad_display_config_twinview,
+ TRUE);
+ }
+
+
+ /* Setup the button state */
+ if (!display->screen) {
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_disabled),
+ TRUE);
+ gtk_button_set_label
+ (GTK_BUTTON(ctk_object->rad_display_config_disabled),
+ "Disabled");
+ gtk_button_set_label
+ (GTK_BUTTON(ctk_object->rad_display_config_xscreen),
+ "Separate X Screen (Requires X restart)");
+ gtk_button_set_label
+ (GTK_BUTTON(ctk_object->rad_display_config_twinview),
+ "TwinView");
+
+ } else if (display->screen->num_displays > 1) {
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_twinview),
+ TRUE);
+ gtk_button_set_label
+ (GTK_BUTTON(ctk_object->rad_display_config_disabled),
+ "Disabled");
+ gtk_button_set_label
+ (GTK_BUTTON(ctk_object->rad_display_config_xscreen),
+ "Separate X Screen (Requires X restart)");
+ gtk_button_set_label
+ (GTK_BUTTON(ctk_object->rad_display_config_twinview),
+ "TwinView");
+
+ } else {
+ gtk_toggle_button_set_active
+ (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_xscreen),
+ TRUE);
+ gtk_button_set_label
+ (GTK_BUTTON(ctk_object->rad_display_config_disabled),
+ "Disabled (Requires X restart)");
+ gtk_button_set_label
+ (GTK_BUTTON(ctk_object->rad_display_config_xscreen),
+ "Separate X Screen");
+ gtk_button_set_label
+ (GTK_BUTTON(ctk_object->rad_display_config_twinview),
+ "TwinView (Requires X restart)");
+ }
+
+
+ /* Show the display config dialog */
+ gtk_window_set_transient_for
+ (GTK_WINDOW(ctk_object->dlg_display_config),
+ GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(ctk_object))));
+ gtk_widget_show_all(ctk_object->dlg_display_config);
+ gtk_widget_grab_focus(ctk_object->btn_display_config_cancel);
+ result = gtk_dialog_run(GTK_DIALOG(ctk_object->dlg_display_config));
+ gtk_widget_hide(ctk_object->dlg_display_config);
+
+ switch (result)
+ {
+ case GTK_RESPONSE_ACCEPT:
+ /* OK */
+ break;
+
+ case GTK_RESPONSE_CANCEL:
+ default:
+ /* Cancel */
+ return;
+ }
+
+
+
+ if (gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_disabled))) {
+ if (display->screen) {
+ do_disable_display(ctk_object, display);
+ update = TRUE;
+ }
+ } else {
+
+ /* Make sure the display has modelines */
+ if (!display->modelines) {
+ char *tokens;
+ gchar *err_str = NULL;
+ NvCtrlStringOperation(display->gpu->handle, display->device_mask,
+ NV_CTRL_STRING_OPERATION_BUILD_MODEPOOL,
+ "", &tokens);
+ update = TRUE;
+ if (!add_modelines_to_display(display, &err_str)) {
+ nv_warning_msg(err_str);
+ g_free(err_str);
+ return;
+ }
+ }
+ if (!display->modelines) return;
+
+ if (!display->screen) {
+
+ /* Enable display as a separate X Screen */
+ if (gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_xscreen))) {
+ do_enable_display_for_xscreen(ctk_object, display);
+ update = TRUE;
+ }
+
+ /* Enable display in TwinView with an existing screen */
+ if (gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_twinview))) {
+ do_enable_display_for_twinview(ctk_object, display);
+ update = TRUE;
+ }
+
+ } else {
+
+ /* Move display to a new X Screen */
+ if (display->screen->num_displays > 1 &&
+ gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_xscreen))) {
+ do_configure_display_for_xscreen(ctk_object, display);
+ update = TRUE;
+ }
+
+ /* Setup TwinView on the first X Screen */
+ if (display->screen->num_displays == 1 &&
+ gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON(ctk_object->rad_display_config_twinview))) {
+ do_configure_display_for_twinview(ctk_object, display);
+ update = TRUE;
+ }
+ }
+ }
+
+
+ /* Sync the GUI */
+ if (update) {
+
+ /* Recaltulate */
+ ctk_display_layout_redraw(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+ /* Auto fix all screens on the gpu */
+ {
+ nvGpuPtr gpu = display->gpu;
+ nvScreenPtr screen;
+
+ for (screen = gpu->screens; screen; screen = screen->next) {
+ validation_auto_fix_screen(ctk_object, screen);
+ }
+ }
+
+ /* Redraw */
+ ctk_display_layout_redraw(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+ /* Update GUI */
+ setup_layout_frame(ctk_object);
+ setup_display_frame(ctk_object);
+ setup_screen_frame(ctk_object);
+
+ gtk_widget_set_sensitive(ctk_object->btn_apply, True);
+ }
+
+} /* display_config_clicked() */
+
+
+
+/** display_refresh_changed() ****************************************
+ *
+ * Called when user selects a new refresh rate for a display.
+ *
+ **/
+
+static void display_refresh_changed(GtkWidget *widget, gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ gint idx;
+ nvModeLinePtr modeline;
+ nvDisplayPtr display;
+
+
+ /* Get the modeline and display to set */
+ idx = gtk_option_menu_get_history(GTK_OPTION_MENU(widget));
+ modeline = ctk_object->refresh_table[idx];
+ display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+
+ /* In Basic view, we assume the user most likely wants
+ * to change which metamode is being used.
+ */
+ if (!ctk_object->advanced_mode && (display->screen->num_displays == 1)) {
+ int metamode_idx = find_closest_mode_with_modeline(display, modeline);
+
+ /* Select the new metamode */
+ if (metamode_idx >= 0) {
+ ctk_display_layout_set_screen_metamode
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ display->screen, metamode_idx);
+ }
+ }
+
+
+ /* Update the display's currently selected mode */
+ ctk_display_layout_set_mode_modeline
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ display->cur_mode, modeline);
+
+
+ /* Update the modename */
+ setup_display_modename(ctk_object);
+
+ gtk_widget_set_sensitive(ctk_object->btn_apply, True);
+
+} /* display_refresh_changed() */
+
+
+
+/** display_resolution_changed() *************************************
+ *
+ * Called when user selects a new resolution for a display device.
+ *
+ **/
+
+static void display_resolution_changed(GtkWidget *widget, gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ gint idx;
+ nvModeLinePtr modeline;
+ nvDisplayPtr display;
+
+
+ /* Get the modeline and display to set */
+ idx = gtk_option_menu_get_history(GTK_OPTION_MENU(widget));
+ modeline = ctk_object->resolution_table[idx];
+ display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+
+ /* Ignore selecting same resolution */
+ if (display->cur_mode->modeline == modeline) {
+ return;
+ }
+
+
+ /* In Basic view, we assume the user most likely wants
+ * to change which metamode is being used.
+ */
+ if (!ctk_object->advanced_mode && (display->screen->num_displays == 1)) {
+ int metamode_idx = find_closest_mode_with_modeline(display, modeline);
+
+ /* Select the new metamode */
+ if (metamode_idx >= 0) {
+ ctk_display_layout_set_screen_metamode
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ display->screen, metamode_idx);
+ }
+ }
+
+
+ /* Select the new modeline for its resolution */
+ ctk_display_layout_set_mode_modeline
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ display->cur_mode, modeline);
+
+
+ /* Regenerate the refresh menu */
+ setup_display_refresh_dropdown(ctk_object);
+
+
+ /* Sync the display position */
+ setup_display_position(ctk_object);
+
+
+ /* Sync the panning domain */
+ setup_display_panning(ctk_object);
+
+
+ gtk_widget_set_sensitive(ctk_object->btn_apply, True);
+
+} /* display_resolution_changed() */
+
+
+
+/** display_position_type_changed() **********************************
+ *
+ * Called when user selects a new display position method (relative/
+ * absolute)
+ *
+ **/
+
+static void display_position_type_changed(GtkWidget *widget,
+ gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ nvDisplayPtr display;
+ gint position_idx;
+ int position_type;
+ gint relative_to_idx;
+ nvDisplayPtr relative_to;
+
+
+ display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+ /* Get the new position type */
+ position_idx =
+ gtk_option_menu_get_history
+ (GTK_OPTION_MENU(ctk_object->mnu_display_position_type));
+
+ position_type = __position_table[position_idx];
+
+ relative_to_idx =
+ gtk_option_menu_get_history
+ (GTK_OPTION_MENU(ctk_object->mnu_display_position_relative));
+
+ if (relative_to_idx >= 0 &&
+ relative_to_idx < ctk_object->display_position_table_len) {
+
+ relative_to =
+ ctk_object->display_position_table[relative_to_idx];
+
+ /* Update the layout */
+ ctk_display_layout_set_display_position
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ display, position_type, relative_to,
+ display->cur_mode->dim[X],
+ display->cur_mode->dim[Y]);
+ }
+
+
+ /* Cannot apply if the screen position changed */
+ check_screen_pos_changed(ctk_object);
+
+
+ /* Update GUI */
+ setup_display_position_relative(ctk_object);
+
+ setup_display_position_offset(ctk_object);
+
+ gtk_widget_set_sensitive(ctk_object->btn_apply, True);
+
+} /* display_position_type_changed() */
+
+
+
+/** display_position_relative_changed() ******************************
+ *
+ * Called when user selects a new display to be positioned relative
+ * to.
+ *
+ **/
+
+static void display_position_relative_changed(GtkWidget *widget,
+ gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ nvDisplayPtr display;
+ gint position_idx;
+ gint relative_to_idx;
+ int position_type;
+ nvDisplayPtr relative_to;
+
+ display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+ /* Get the new display to be relative to */
+ position_idx = gtk_option_menu_get_history
+ (GTK_OPTION_MENU(ctk_object->mnu_display_position_type));
+
+ position_type = __position_table[position_idx];
+
+ relative_to_idx = gtk_option_menu_get_history
+ (GTK_OPTION_MENU(ctk_object->mnu_display_position_relative));
+
+ if (relative_to_idx >= 0 &&
+ relative_to_idx < ctk_object->display_position_table_len) {
+
+ relative_to = ctk_object->display_position_table[relative_to_idx];
+
+ /* Update the relative position */
+ ctk_display_layout_set_display_position
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ display, position_type, relative_to, 0, 0);
+ }
+
+
+ /* Cannot apply if we change the relative position */
+ check_screen_pos_changed(ctk_object);
+
+
+ /* Update the GUI */
+ setup_display_position_offset(ctk_object);
+
+ gtk_widget_set_sensitive(ctk_object->btn_apply, True);
+
+} /* display_position_relative_changed() */
+
+
+
+/** display_position_offset_activate() *******************************
+ *
+ * Called when user modifies the display position offset text entry.
+ *
+ **/
+
+static void display_position_offset_activate(GtkWidget *widget,
+ gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ const gchar *str = gtk_entry_get_text(GTK_ENTRY(widget));
+ int x, y;
+ nvDisplayPtr display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+
+ if (!display) return;
+
+ /* Parse user input */
+ str = read_pair(str, 0, &x, &y);
+ if (!str) {
+ /* Reset the display position */
+ setup_display_position_offset(ctk_object);
+ return;
+ }
+
+ /* Make coordinates relative to top left of Screen */
+ x += display->cur_mode->metamode->edim[X];
+ y += display->cur_mode->metamode->edim[Y];
+
+
+ /* Update the absolute position */
+ ctk_display_layout_set_display_position
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ display, CONF_ADJ_ABSOLUTE, NULL, x, y);
+
+ gtk_widget_set_sensitive(ctk_object->btn_apply, True);
+
+} /* display_position_offset_activate() */
+
+
+
+/** display_panning_activate() ***************************************
+ *
+ * Called when user modifies the display position text entry.
+ *
+ **/
+
+static void display_panning_activate(GtkWidget *widget, gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ const gchar *str = gtk_entry_get_text(GTK_ENTRY(widget));
+ int x, y;
+ nvDisplayPtr display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+
+ if (!display) {
+ return;
+ }
+
+ str = read_pair(str, 'x', &x, &y);
+ if (!str) {
+ /* Reset the display panning */
+ setup_display_panning(ctk_object);
+ return;
+ }
+
+ ctk_display_layout_set_display_panning
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), display, x, y);
+
+} /* display_panning_activate() */
+
+
+
+/** screen_depth_changed() *******************************************
+ *
+ * Called when user selects a new color depth for a screen.
+ *
+ **/
+
+static void screen_depth_changed(GtkWidget *widget, gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ gint idx = gtk_option_menu_get_history(GTK_OPTION_MENU(widget));
+ int depth = 8;
+ nvScreenPtr screen = ctk_display_layout_get_selected_screen
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+ if (!screen) return;
+
+ /* Set the new default depth of the screen */
+ if (idx == 0) {
+ depth = 24;
+ } else if (idx == 1) {
+ depth = 16;
+ }
+ ctk_display_layout_set_screen_depth
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), screen, depth);
+
+ /* Can't apply screen depth changes */
+ ctk_object->apply_possible = FALSE;
+
+ gtk_widget_set_sensitive(ctk_object->btn_apply, True);
+
+} /* screen_depth_changed() */
+
+
+
+/** screen_position_type_changed() ***********************************
+ *
+ * Called when user selects a new screen position method (relative/
+ * absolute)
+ *
+ **/
+
+static void screen_position_type_changed(GtkWidget *widget,
+ gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ nvScreenPtr screen = ctk_display_layout_get_selected_screen
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+ gint position_idx;
+ int position_type;
+ gint relative_to_idx;
+ nvScreenPtr relative_to;
+
+ if (!screen) return;
+
+ /* Get the new position type */
+ position_idx =
+ gtk_option_menu_get_history
+ (GTK_OPTION_MENU(ctk_object->mnu_screen_position_type));
+
+ position_type = __position_table[position_idx];
+
+ relative_to_idx =
+ gtk_option_menu_get_history
+ (GTK_OPTION_MENU(ctk_object->mnu_screen_position_relative));
+
+ if (relative_to_idx >= 0 &&
+ relative_to_idx < ctk_object->screen_position_table_len) {
+
+ relative_to =
+ ctk_object->screen_position_table[relative_to_idx];
+
+ /* Update the layout */
+ ctk_display_layout_set_screen_position
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ screen, position_type, relative_to,
+ screen->dim[X],
+ screen->dim[Y]);
+ }
+
+
+ /* Cannot apply changes to screen positioning */
+ ctk_object->apply_possible = FALSE;
+
+
+ /* Update the GUI */
+ setup_screen_position_relative(ctk_object);
+
+ setup_screen_position_offset(ctk_object);
+
+ gtk_widget_set_sensitive(ctk_object->btn_apply, True);
+
+} /* screen_position_type_changed() */
+
+
+
+/** screen_position_relative_changed() *******************************
+ *
+ * Called when user selects a new screen to be positioned relative
+ * to.
+ *
+ **/
+
+static void screen_position_relative_changed(GtkWidget *widget,
+ gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ nvScreenPtr screen = ctk_display_layout_get_selected_screen
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+ gint position_idx;
+ gint relative_to_idx;
+ int position_type;
+ nvScreenPtr relative_to;
+
+ if (!screen) return;
+
+ /* Get the new X Screen to be relative to */
+ position_idx = gtk_option_menu_get_history
+ (GTK_OPTION_MENU(ctk_object->mnu_screen_position_type));
+
+ position_type = __position_table[position_idx];
+
+ relative_to_idx = gtk_option_menu_get_history
+ (GTK_OPTION_MENU(ctk_object->mnu_screen_position_relative));
+
+ if (relative_to_idx >= 0 &&
+ relative_to_idx < ctk_object->screen_position_table_len) {
+
+ relative_to = ctk_object->screen_position_table[relative_to_idx];
+
+ /* Update the relative position */
+ ctk_display_layout_set_screen_position
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ screen, position_type, relative_to, 0, 0);
+ }
+
+
+ /* Cannot apply changes to screen positioning */
+ ctk_object->apply_possible = FALSE;
+
+
+ /* Update the GUI */
+ setup_screen_position_offset(ctk_object);
+
+ gtk_widget_set_sensitive(ctk_object->btn_apply, True);
+
+} /* screen_position_relative_changed() */
+
+
+
+/** screen_position_offset_activate() ********************************
+ *
+ * Called when user modifies the screen position offset text entry.
+ *
+ **/
+
+static void screen_position_offset_activate(GtkWidget *widget,
+ gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ const gchar *str = gtk_entry_get_text(GTK_ENTRY(widget));
+ int x, y;
+ nvScreenPtr screen = ctk_display_layout_get_selected_screen
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+ if (!screen) return;
+
+
+ /* Parse user input */
+ str = read_pair(str, 0, &x, &y);
+ if (!str) {
+ /* Reset the display position */
+ setup_screen_position_offset(ctk_object);
+ return;
+ }
+
+
+ /* Cannot apply changes to screen positioning */
+ ctk_object->apply_possible = FALSE;
+
+
+ /* Update the absolute position */
+ ctk_display_layout_set_screen_position
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ screen, screen->position_type, screen->relative_to, x, y);
+
+ gtk_widget_set_sensitive(ctk_object->btn_apply, True);
+
+} /* screen_position_offset_activate() */
+
+
+
+/** screen_metamode_clicked() ****************************************
+ *
+ * Called when user selects a new metamode for the selected screen
+ *
+ **/
+
+static void screen_metamode_clicked(GtkWidget *widget, gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ GtkWidget *menu;
+ GtkWidget *menu_item;
+ int i;
+ gchar *str;
+ gchar *tmp;
+ nvScreenPtr screen = ctk_display_layout_get_selected_screen
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+ if (!screen) return;
+
+ /* Generate the popup menu */
+ menu = gtk_menu_new();
+ for (i = 0; i < screen->num_metamodes; i++) {
+
+ /* Setup the menu item text */
+ tmp = get_screen_metamode_str(screen, i, 1);
+ str = g_strdup_printf("%d - \"%s\"", i+1, tmp);
+ menu_item = gtk_menu_item_new_with_label(str);
+ g_free(str);
+ g_free(tmp);
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
+ gtk_widget_show(menu_item);
+ g_signal_connect(G_OBJECT(menu_item),
+ "activate",
+ G_CALLBACK(screen_metamode_activate),
+ (gpointer) ctk_object);
+ }
+
+ /* Show the popup menu */
+ gtk_menu_popup(GTK_MENU(menu),
+ NULL, NULL, NULL, NULL,
+ 1, gtk_get_current_event_time());
+
+} /* screen_metamode_clicked() */
+
+
+
+/** screen_metamode_activate() ***************************************
+ *
+ * Called when user selects a new metamode for the selected screen
+ *
+ **/
+
+static void screen_metamode_activate(GtkWidget *widget, gpointer user_data)
+{
+ GtkMenuItem *item = (GtkMenuItem *) widget;
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+
+ nvScreenPtr screen = ctk_display_layout_get_selected_screen
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+ const gchar *str =
+ gtk_label_get_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(item))));
+ int idx;
+ gchar *name;
+
+ if (!screen || !str) return;
+
+ idx = atoi(str) -1;
+
+ name = g_strdup_printf("%d - ...", idx+1);
+ gtk_button_set_label(GTK_BUTTON(ctk_object->btn_screen_metamode), name);
+ g_free(name);
+
+
+ ctk_display_layout_set_screen_metamode
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), screen, idx);
+
+
+ /* Sync the display frame */
+ setup_display_frame(ctk_object);
+
+ gtk_widget_set_sensitive(ctk_object->btn_apply, True);
+
+} /* screen_metamode_activate() */
+
+
+
+/** screen_metamode_add_clicked() ************************************
+ *
+ * Called when user clicks on the display's "Add" metamode button.
+ *
+ **/
+
+static void screen_metamode_add_clicked(GtkWidget *widget, gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ nvScreenPtr screen = ctk_display_layout_get_selected_screen
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+ if (!screen) return;
+
+
+ /* Add a new metamode to the screen */
+ ctk_display_layout_add_screen_metamode
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), screen);
+
+
+ /* Update the GUI */
+ setup_display_frame(ctk_object);
+ setup_screen_frame(ctk_object);
+
+ gtk_widget_set_sensitive(ctk_object->btn_apply, True);
+
+} /* screen_metamode_add_clicked() */
+
+
+
+/** screen_metamode_delete_clicked() *********************************
+ *
+ * Called when user clicks on the display's "Delete" metamode button.
+ *
+ **/
+
+static void screen_metamode_delete_clicked(GtkWidget *widget,
+ gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ nvScreenPtr screen = ctk_display_layout_get_selected_screen
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+ if (!screen) return;
+
+
+ ctk_display_layout_delete_screen_metamode
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ screen, screen->cur_metamode_idx);
+
+ /* Update the GUI */
+ setup_display_frame(ctk_object);
+ setup_screen_frame(ctk_object);
+
+ gtk_widget_set_sensitive(ctk_object->btn_apply, True);
+
+} /* screen_metamode_delete_clicked() */
+
+
+
+/** xinerama_state_toggled() *****************************************
+ *
+ * Called when user toggles the state of the "Enable Xinerama"
+ * button.
+ *
+ **/
+
+static void xinerama_state_toggled(GtkWidget *widget, gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+
+ ctk_object->layout->xinerama_enabled =
+ gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+
+ /* Can't dynamically enable Xinerama */
+ ctk_object->apply_possible = FALSE;
+
+ /* Make the apply button sensitive to user input */
+ gtk_widget_set_sensitive(ctk_object->btn_apply, True);
+
+} /* xinerama_state_toggled() */
+
+
+
+/** update_display_confirm_text() ************************************
+ *
+ * Generates the text used in the confirmation dialog.
+ *
+ **/
+
+static void update_display_confirm_text(CtkDisplayConfig *ctk_object,
+ int screen)
+{
+ gchar *str;
+ str = g_strdup_printf("The Mode on X Screen %d has been set.\n"
+ "Would you like to keep the current settings?\n\n"
+ "Reverting in %d seconds...",
+ screen, ctk_object->display_confirm_countdown);
+ gtk_label_set_text(GTK_LABEL(ctk_object->txt_display_confirm), str);
+ g_free(str);
+
+} /* update_display_confirm_text() */
+
+
+
+/** do_display_confirm_countdown() ***********************************
+ *
+ * timeout callback for reverting a modeline setting.
+ *
+ **/
+
+static gboolean do_display_confirm_countdown(gpointer data)
+{
+ SwitchModeCallbackInfo *info = (SwitchModeCallbackInfo *) data;
+ CtkDisplayConfig *ctk_object = info->ctk_object;
+ int screen = info->screen;
+
+ ctk_object->display_confirm_countdown--;
+ if (ctk_object->display_confirm_countdown > 0) {
+ update_display_confirm_text(ctk_object, screen);
+ return True;
+ }
+
+ /* Force dialog to cancel */
+ gtk_dialog_response(GTK_DIALOG(ctk_object->dlg_display_confirm),
+ GTK_RESPONSE_REJECT);
+
+ return False;
+
+} /* do_display_confirm_countdown() */
+
+
+
+/** switch_to_current_metamode() *************************************
+ *
+ * Switches to the current screen metamode using XRandR
+ *
+ **/
+
+static Bool switch_to_current_metamode(CtkDisplayConfig *ctk_object,
+ nvScreenPtr screen)
+{
+ ReturnStatus ret;
+ gint result;
+ nvMetaModePtr metamode;
+ int new_width;
+ int new_height;
+ int new_rate;
+ int old_width;
+ int old_height;
+ int old_rate;
+ static SwitchModeCallbackInfo info;
+ GtkWidget *dlg;
+ GtkWidget *parent;
+ gchar *msg;
+
+
+ if (!screen->handle || !screen->cur_metamode) goto fail;
+
+ metamode = screen->cur_metamode;
+
+ new_width = metamode->edim[W];
+ new_height = metamode->edim[H];
+ new_rate = metamode->id;
+
+
+ /* Find the parent window for displaying dialogs */
+
+ parent = gtk_widget_get_parent(GTK_WIDGET(ctk_object));
+ while (!GTK_IS_WINDOW(parent)) {
+ GtkWidget *old = parent;
+ parent = gtk_widget_get_parent(GTK_WIDGET(old));
+ if (!parent || old == parent) {
+ /* GTK Error, can't find parent window! */
+ goto fail;
+ }
+ }
+
+
+ /* XRandR must be available to do mode switching */
+
+ if (!NvCtrlGetXrandrEventBase(screen->handle)) {
+ dlg = gtk_message_dialog_new
+ (GTK_WINDOW(parent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_CLOSE,
+ "The XRandR X extension was not found. This extension must "
+ "be supported by the X server and enabled for display "
+ "configuration settings to be dynamically applicable.");
+
+ gtk_dialog_run(GTK_DIALOG(dlg));
+ gtk_widget_destroy(dlg);
+
+ nv_warning_msg("XRandR X extension not enabled, "
+ "cannot apply settings!");
+ goto fail;
+ }
+
+
+ /* Get the current mode so we can fall back on that if the
+ * mode switch fails, or the user does not confirm.
+ */
+
+ ret = NvCtrlXrandrGetScreenMode(screen->handle, &old_width, &old_height,
+ &old_rate);
+ if (ret != NvCtrlSuccess) {
+ nv_warning_msg("Failed to get current (fallback) mode for "
+ "display device!");
+ goto fail;
+ }
+
+ nv_info_msg(TAB, "Current mode: %dx%d (id: %d)",
+ old_width, old_height, old_rate);
+
+
+ /* Switch to the new mode */
+
+ nv_info_msg(TAB, "Switching to mode: %dx%d (id: %d)...",
+ new_width, new_height, new_rate);
+
+ ret = NvCtrlXrandrSetScreenMode(screen->handle, new_width, new_height,
+ new_rate);
+ if (ret != NvCtrlSuccess) {
+
+ nv_warning_msg("Failed to set MetaMode (%d) '%s' "
+ "(mode: %dx%d, id: %d) on X Screen %d!",
+ screen->cur_metamode_idx+1, metamode->string, new_width,
+ new_height, new_rate,
+ NvCtrlGetTargetId(screen->handle));
+
+ if (screen->num_metamodes > 1) {
+ msg = g_strdup_printf("Failed to set MetaMode (%d) '%s' "
+ "(Mode %dx%d, id: %d) on X Screen %d\n\n"
+ "Would you like to remove this MetaMode?",
+ screen->cur_metamode_idx+1, metamode->string,
+ new_width, new_height, new_rate,
+ NvCtrlGetTargetId(screen->handle));
+ dlg = gtk_message_dialog_new
+ (GTK_WINDOW(parent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_YES_NO,
+ msg);
+ } else {
+ msg = g_strdup_printf("Failed to set MetaMode (%d) '%s' "
+ "(Mode %dx%d, id: %d) on X Screen %d.",
+ screen->cur_metamode_idx+1, metamode->string,
+ new_width, new_height, new_rate,
+ NvCtrlGetTargetId(screen->handle));
+ dlg = gtk_message_dialog_new
+ (GTK_WINDOW(parent),
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_OK,
+ msg);
+ }
+
+ result = gtk_dialog_run(GTK_DIALOG(dlg));
+
+ switch (result) {
+ case GTK_RESPONSE_YES:
+ ctk_display_layout_delete_screen_metamode
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ screen, screen->cur_metamode_idx);
+
+ nv_info_msg(TAB, "Removed MetaMode %d on Screen %d.\n",
+ screen->cur_metamode_idx+1,
+ NvCtrlGetTargetId(screen));
+
+ /* Update the GUI */
+ setup_display_frame(ctk_object);
+ setup_screen_frame(ctk_object);
+ break;
+ case GTK_RESPONSE_OK:
+ /* Nothing to do with last metamode */
+ default:
+ /* Ignore the bad metamode */
+ break;
+ }
+
+ g_free(msg);
+ gtk_widget_destroy(dlg);
+ goto fail;
+ }
+
+
+ /* Setup the counter callback data */
+ info.ctk_object = ctk_object;
+ info.screen = NvCtrlGetTargetId(screen->handle);
+
+ /* Start the countdown timer */
+ ctk_object->display_confirm_countdown = DEFAULT_SWITCH_MODE_TIMEOUT;
+ update_display_confirm_text(ctk_object, info.screen);
+ ctk_object->display_confirm_timer =
+ g_timeout_add(1000,
+ (GSourceFunc)do_display_confirm_countdown,
+ (gpointer)(&info));
+
+ /* Show the confirm dialog */
+ gtk_window_set_transient_for
+ (GTK_WINDOW(ctk_object->dlg_display_confirm),
+ GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(ctk_object))));
+ gtk_widget_show_all(ctk_object->dlg_display_confirm);
+ gtk_widget_grab_focus(ctk_object->btn_display_apply_cancel);
+ result = gtk_dialog_run(GTK_DIALOG(ctk_object->dlg_display_confirm));
+ gtk_widget_hide(ctk_object->dlg_display_confirm);
+
+ switch (result)
+ {
+ case GTK_RESPONSE_ACCEPT:
+ /* Kill the timer */
+ g_source_remove(ctk_object->display_confirm_timer);
+ break;
+
+ case GTK_RESPONSE_REJECT:
+ default:
+ /* Fall back to previous settings */
+ nv_info_msg(TAB, "Switching back to mode: %dx%d (id: %d)...",
+ old_width, old_height, old_rate);
+
+ NvCtrlXrandrSetScreenMode(screen->handle, old_width, old_height,
+ old_rate);
+ /* Good luck! */
+ goto fail;
+ }
+
+ return TRUE;
+
+ fail:
+ return FALSE;
+
+} /* switch_to_current_metamode() */
+
+
+
+/** find_metamode_string() *******************************************
+ *
+ * Finds "metamode_str" in the list of strings in metamode_strs.
+ * If metamode_str is found, a pointer to the full metamode string
+ * is returned (including tokens, if any.)
+ *
+ * if "metamode_str" is not found in "metamode_strs", NULL is
+ * returned.
+ *
+ **/
+
+static char *find_metamode_string(char *metamode_str, char *metamode_strs)
+{
+ char *m;
+ char *str;
+
+ for (m = metamode_strs; m && strlen(m); m += strlen(m) +1) {
+
+ /* Skip tokens if any */
+ str = strstr(m, "::");
+ if (str) {
+ str = (char *)skip_whitespace(str +2);
+ } else {
+ str = m;
+ }
+
+ /* See if metamode strings match */
+ if (!strcmp(str, metamode_str)) return m;
+ }
+
+ return NULL;
+
+} /* find_metamode_string() */
+
+
+
+/** preprocess_metamodes() *******************************************
+ *
+ * Does preprocess work to the metamode strings:
+ *
+ * - Generates the metamode strings for the screen's metamodes
+ * that will be used for creating the metamode list on the X
+ * Server.
+ *
+ * - Whites out each string in the metamode_strs list that should
+ * not be deleted (it has a matching metamode in "screen".)
+ *
+ * - Adds new metamodes to the X Server screen that are specified
+ * in "screen".
+ *
+ **/
+
+static void preprocess_metamodes(nvScreenPtr screen, char *metamode_strs)
+{
+ nvMetaModePtr metamode;
+ ReturnStatus ret;
+ char *str = NULL;
+ char *tokens;
+ int metamode_idx;
+
+
+ for (metamode = screen->metamodes, metamode_idx = 0;
+ metamode;
+ metamode = metamode->next, metamode_idx++) {
+
+ /* Generate the metamore's string */
+ free(metamode->string);
+ metamode->string = get_screen_metamode_str(screen, metamode_idx, 0);
+ if (!metamode->string) continue;
+
+ /* Look for the metamode string in metamode_strs */
+ str = find_metamode_string(metamode->string, metamode_strs);
+ if (str) {
+
+ /* Grab the metamode id from the tokens */
+ tokens = strdup(str);
+ if (tokens) {
+ char *tmp = strstr(tokens, "::");
+ if (tmp) {
+ *tmp = '\0';
+ parse_tokens(tokens, apply_metamode_token, metamode);
+ }
+ free(tokens);
+ }
+
+ /* The metamode was found, white out the metamode string
+ * so it does not get deleted and continue.
+ */
+ while (*str) {
+ *str = ' ';
+ str++;
+ }
+ continue;
+ }
+
+ /* The metamode was not found, so add it to the X Screen's list */
+ tokens = NULL;
+ ret = NvCtrlStringOperation(screen->handle, 0,
+ NV_CTRL_STRING_OPERATION_ADD_METAMODE,
+ metamode->string, &tokens);
+
+ /* Grab the metamode ID from the returned tokens */
+ if (ret == NvCtrlSuccess) {
+ if (tokens) {
+ parse_tokens(tokens, apply_metamode_token, metamode);
+ free(tokens);
+ }
+ nv_info_msg(TAB, "Added > %s", metamode->string);
+ }
+ }
+
+} /* preprocess_metamodes() */
+
+
+
+/** order_metamodes() ************************************************
+ *
+ * Makes sure the metamodes are ordered properly by moving each
+ * metamode to its correct location in the server's metamode list.
+ *
+ **/
+
+static void order_metamodes(nvScreenPtr screen)
+{
+ nvMetaModePtr metamode;
+ int metamode_idx;
+ char *metamode_str;
+ char *update_str;
+ int len;
+ ReturnStatus ret;
+
+
+ for (metamode = screen->metamodes, metamode_idx = 0;
+ metamode;
+ metamode = metamode->next, metamode_idx++) {
+
+ metamode_str = get_screen_metamode_str(screen, metamode_idx,
+ 0);
+ if (!metamode_str) continue;
+
+ /* Append the index we want */
+ len = 24 + strlen(metamode_str);
+ update_str = malloc(len);
+ snprintf(update_str, len, "index=%d :: %s", metamode_idx,
+ metamode_str);
+
+ ret = NvCtrlSetStringAttribute(screen->handle,
+ NV_CTRL_STRING_MOVE_METAMODE,
+ update_str, NULL);
+ if (ret == NvCtrlSuccess) {
+ nv_info_msg(TAB, "Moved > %s", metamode_str);
+ }
+ free(metamode_str);
+ }
+
+} /* order_metamodes() */
+
+
+
+/** postprocess_metamodes() ******************************************
+ *
+ * Does post processing work on the metamode list:
+ *
+ * - Deletes any metamode left in the metamode_strs
+ *
+ **/
+
+static void postprocess_metamodes(nvScreenPtr screen, char *metamode_strs)
+{
+ char *metamode_str;
+ char *str;
+ ReturnStatus ret;
+
+
+ /* Delete metamodes that were not cleared out from the metamode_strs */
+ for (metamode_str = metamode_strs;
+ metamode_str && strlen(metamode_str);
+ metamode_str += strlen(metamode_str) +1) {
+
+ /* Skip tokens */
+ str = strstr(metamode_str, "::");
+ if (!str) continue;
+
+ str = (char *)skip_whitespace(str +2);
+
+
+ /* Delete the metamode */
+ ret = NvCtrlSetStringAttribute(screen->handle,
+ NV_CTRL_STRING_DELETE_METAMODE,
+ str, NULL);
+ if (ret == NvCtrlSuccess) {
+ nv_info_msg(TAB, "Removed > %s", str);
+ }
+ }
+
+ /* Reorder the list of metamodes */
+ order_metamodes(screen);
+
+} /* postprocess_metamodes() */
+
+
+
+/** update_screen_metamodes() ****************************************
+ *
+ * Updates the screen's metamode list.
+ *
+ **/
+
+static int update_screen_metamodes(CtkDisplayConfig *ctk_object,
+ nvScreenPtr screen)
+{
+ char *metamode_strs = NULL;
+ char *cur_metamode_str = NULL;
+ char *metamode_str;
+ int len;
+
+ int clear_apply = 0; /* Set if we should clear the apply button */
+ ReturnStatus ret;
+
+
+ /* Make sure the screen has a valid handle to make the updates */
+ if (!screen->handle) {
+ return 1;
+ }
+
+ nv_info_msg("", "Updating Screen %d's MetaModes:",
+ NvCtrlGetTargetId(screen->handle));
+
+ /* To update the metamode list of the screen:
+ *
+ * (preprocess)
+ * - Get the current list of metamodes for this screen
+ * - Add all the new metamodes at the end of the list
+ *
+ * (mode switch)
+ * - Do a modeswitch, if we need to
+ *
+ * (postprocess)
+ * - Delete any unused mode
+ * - Move metamodes to the correct location
+ **/
+
+ /* Get the list of the current metamodes */
+
+ ret = NvCtrlGetBinaryAttribute(screen->handle,
+ 0,
+ NV_CTRL_BINARY_DATA_METAMODES,
+ (unsigned char **)&metamode_strs,
+ &len);
+ if (ret != NvCtrlSuccess) goto done;
+
+ /* Get the current metamode for the screen */
+
+ ret = NvCtrlGetStringAttribute(screen->handle,
+ NV_CTRL_STRING_CURRENT_METAMODE,
+ &cur_metamode_str);
+ if (ret != NvCtrlSuccess) goto done;
+
+ /* Skip tokens */
+ metamode_str = strstr(cur_metamode_str, "::");
+ if (metamode_str) {
+ metamode_str = (char *)skip_whitespace(metamode_str +2);
+ } else {
+ metamode_str = cur_metamode_str;
+ }
+
+ /* Preprocess the new metamodes list */
+
+ preprocess_metamodes(screen, metamode_strs);
+
+ /* If we need to switch metamodes, do so now */
+
+ if (strcmp(screen->cur_metamode->string, metamode_str)) {
+ if (switch_to_current_metamode(ctk_object, screen)) {
+ ctk_config_statusbar_message(ctk_object->ctk_config,
+ "Switched to mode %dx%d "
+ "@ %d Hz.",
+ screen->cur_metamode->edim[W],
+ screen->cur_metamode->edim[H],
+ screen->cur_metamode->id);
+
+ nv_info_msg(TAB, "Using > %s", screen->cur_metamode->string);
+
+ clear_apply = 1;
+ }
+ }
+
+ /* Post process the metamodes list */
+
+ postprocess_metamodes(screen, metamode_strs);
+
+ done:
+
+ XFree(metamode_strs);
+ XFree(cur_metamode_str);
+
+ return clear_apply;
+
+} /* update_screen_metamodes() */
+
+
+
+/** apply_clicked() **************************************************
+ *
+ * Called when user clicks on the "Apply" button.
+ *
+ **/
+
+static void apply_clicked(GtkWidget *widget, gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ nvGpuPtr gpu;
+ int clear_apply = 1;
+
+
+ /* Make sure we can apply */
+ if (!validate_apply(ctk_object)) {
+ return;
+ }
+
+ /* Make sure the layout is ready to be applied */
+ if (!validate_layout(ctk_object)) {
+ return;
+ }
+
+ /* Update all GPUs */
+ for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) {
+ nvScreenPtr screen;
+
+ /* Update all X Screens */
+ for (screen = gpu->screens; screen; screen = screen->next) {
+
+ if (!screen->handle) continue;
+
+ if (!update_screen_metamodes(ctk_object, screen)) {
+ clear_apply = FALSE;
+ } else {
+ ReturnStatus ret;
+ ret = NvCtrlSetAttribute(screen->handle,
+ NV_CTRL_ASSOCIATED_DISPLAY_DEVICES,
+ screen->displays_mask);
+ if (ret != NvCtrlSuccess) {
+ nv_error_msg("Failed to set screen %d's association mask "
+ "to: 0x%08x",
+ screen->scrnum, screen->displays_mask);
+ } else {
+ /* Make sure other parts of nvidia-settings get updated */
+ ctk_event_emit(screen->ctk_event, 0,
+ NV_CTRL_ASSOCIATED_DISPLAY_DEVICES,
+ screen->displays_mask);
+ }
+ }
+ }
+ }
+
+ /* Clear the apply button if all went well */
+ if (clear_apply) {
+ gtk_widget_set_sensitive(widget, False);
+ }
+
+} /* apply_clicked() */
+
+
+
+/** xconfig_file_clicked() *******************************************
+ *
+ * Called when the user clicks on the "Browse..." button of the
+ * X Config save dialog.
+ *
+ **/
+
+static void xconfig_file_clicked(GtkWidget *widget, gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ const gchar *filename =
+ gtk_entry_get_text(GTK_ENTRY(ctk_object->txt_xconfig_file));
+ gint result;
+
+
+ /* Ask user for a filename */
+ gtk_window_set_transient_for
+ (GTK_WINDOW(ctk_object->dlg_xconfig_file),
+ GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(ctk_object))));
+
+ gtk_file_selection_set_filename
+ (GTK_FILE_SELECTION(ctk_object->dlg_xconfig_file), filename);
+
+ result = gtk_dialog_run(GTK_DIALOG(ctk_object->dlg_xconfig_file));
+ gtk_widget_hide(ctk_object->dlg_xconfig_file);
+
+ switch (result) {
+ case GTK_RESPONSE_ACCEPT:
+ case GTK_RESPONSE_OK:
+
+ filename = gtk_file_selection_get_filename
+ (GTK_FILE_SELECTION(ctk_object->dlg_xconfig_file));
+
+ gtk_entry_set_text(GTK_ENTRY(ctk_object->txt_xconfig_file),
+ filename);
+ break;
+ default:
+ return;
+ }
+
+} /* xconfig_file_clicked() */
+
+
+
+/** xconfig_preview_clicked() ****************************************
+ *
+ * Called when the user clicks on the "Preview" button of the
+ * X Config save dialog.
+ *
+ **/
+
+static void xconfig_preview_clicked(GtkWidget *widget, gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ gboolean show = !GTK_WIDGET_VISIBLE(ctk_object->box_xconfig_save);
+
+ if (show) {
+ gtk_widget_show_all(ctk_object->box_xconfig_save);
+ gtk_window_set_resizable(GTK_WINDOW(ctk_object->dlg_xconfig_save),
+ TRUE);
+ gtk_widget_set_size_request(ctk_object->txt_xconfig_save, 450, 350);
+ gtk_button_set_label(GTK_BUTTON(ctk_object->btn_xconfig_preview),
+ "Hide Preview...");
+ } else {
+ gtk_widget_hide(ctk_object->box_xconfig_save);
+ gtk_window_set_resizable(GTK_WINDOW(ctk_object->dlg_xconfig_save),
+ FALSE);
+ gtk_button_set_label(GTK_BUTTON(ctk_object->btn_xconfig_preview),
+ "Show Preview...");
+ }
+
+} /* xconfig_preview_clicked() */
+
+
+
+/** makeXConfigModeline() ********************************************
+ *
+ * Returns a copy of an XF86Config-parser modeline structure.
+ *
+ */
+
+static XConfigModeLinePtr makeXConfigModeline(nvModeLinePtr modeline)
+{
+ XConfigModeLinePtr xconf_modeline;
+
+ if (!modeline) return NULL;
+
+ xconf_modeline = (XConfigModeLinePtr) malloc(sizeof(XConfigModeLineRec));
+ if (!xconf_modeline) return NULL;
+
+ *xconf_modeline = modeline->data;
+
+ if (modeline->xconfig_name) {
+ xconf_modeline->identifier = strdup(modeline->xconfig_name);
+ } else if (modeline->data.identifier) {
+ xconf_modeline->identifier = strdup(modeline->data.identifier);
+ }
+
+ if (modeline->data.comment) {
+ xconf_modeline->comment = strdup(modeline->data.comment);
+ }
+
+ return xconf_modeline;
+
+} /* makeXConfigModeline() */
+
+
+
+/*
+ * add_modelines_to_monitor() - Given a list of modes "modes", this
+ * function adds all the user-specified modelines in use to the
+ * X config monitor "monitor"'s modeline list.
+ */
+
+static Bool add_modelines_to_monitor(XConfigMonitorPtr monitor,
+ nvModePtr modes)
+{
+ XConfigModeLinePtr modeline;
+ nvModePtr mode;
+
+ /* Add modelines from the list of modes given */
+ for (mode = modes; mode; mode = mode->next) {
+ if (!mode->modeline) continue;
+
+ /* Only add modelines that originated from the X Config
+ * or that were added through NV-CONTROL.
+ */
+ if (!(mode->modeline->source & MODELINE_SOURCE_USER)) continue;
+
+ /* Don't add the same modeline twice */
+ if ((mode->modeline->source & MODELINE_SOURCE_XCONFIG)) {
+ if (xconfigFindModeLine(mode->modeline->xconfig_name,
+ monitor->modelines)) continue;
+ } else {
+ if (xconfigFindModeLine(mode->modeline->data.identifier,
+ monitor->modelines)) continue;
+ }
+
+ /* Dupe the modeline and add it to the monitor section */
+ modeline = makeXConfigModeline(mode->modeline);
+ if (!modeline) continue;
+
+ /* Append to the end of the modeline list */
+ monitor->modelines =
+ (XConfigModeLinePtr)xconfigAddListItem((GenericListPtr)monitor->modelines,
+ (GenericListPtr)modeline);
+ }
+
+ return TRUE;
+
+} /* add_modelines_to_monitor() */
+
+
+
+/*
+ * add_monitor_to_xconfig() - Adds the given display device's information
+ * to the X configuration structure.
+ */
+
+static Bool add_monitor_to_xconfig(nvDisplayPtr display, XConfigPtr config,
+ int monitor_id)
+{
+ XConfigMonitorPtr monitor;
+ XConfigOptionPtr opt = NULL;
+ ReturnStatus ret;
+ char *range_str = NULL;
+ char *tmp;
+ char *v_source = NULL;
+ char *h_source = NULL;
+ float min, max;
+
+ monitor = (XConfigMonitorPtr)calloc(1, sizeof(XConfigMonitorRec));
+ if (!monitor) goto fail;
+
+ monitor->identifier = (char *)malloc(32);
+ snprintf(monitor->identifier, 32, "Monitor%d", monitor_id);
+ monitor->vendor = xconfigStrdup("Unknown"); /* XXX */
+ monitor->modelname = xconfigStrdup(display->name);
+
+ /* Get the Horizontal Sync ranges from nv-control */
+
+ ret = NvCtrlGetStringDisplayAttribute
+ (display->gpu->handle,
+ display->device_mask,
+ NV_CTRL_STRING_VALID_HORIZ_SYNC_RANGES,
+ &range_str);
+ if (ret != NvCtrlSuccess) {
+ nv_error_msg("Unable to determine valid horizontal sync ranges "
+ "for display device '%s' (GPU: %s)!",
+ display->name, display->gpu->name);
+ goto fail;
+ }
+
+ /* Skip tokens */
+ tmp = strstr(range_str, "::");
+ if (tmp) {
+ *tmp = '\0';
+ tmp += 2;
+ }
+
+ if (!read_float_range(tmp, &min, &max)) {
+ nv_error_msg("Unable to determine valid horizontal sync ranges "
+ "for display device '%s' (GPU: %s)!",
+ display->name, display->gpu->name);
+ goto fail;
+ }
+
+ monitor->n_hsync = 1;
+ monitor->hsync[0].lo = min;
+ monitor->hsync[0].hi = max;
+
+ parse_tokens(range_str, apply_monitor_token, (void *)(&h_source));
+ free(range_str);
+ range_str = NULL;
+
+ /* Get the Horizontal Sync ranges from nv-control */
+
+ ret = NvCtrlGetStringDisplayAttribute
+ (display->gpu->handle,
+ display->device_mask,
+ NV_CTRL_STRING_VALID_VERT_REFRESH_RANGES,
+ &range_str);
+ if (ret != NvCtrlSuccess) {
+ nv_error_msg("Unable to determine valid vertical refresh ranges "
+ "for display device '%s' (GPU: %s)!",
+ display->name, display->gpu->name);
+ goto fail;
+ }
+
+ /* Skip tokens */
+ tmp = strstr(range_str, "::");
+ if (tmp) {
+ *tmp = '\0';
+ tmp += 2;
+ }
+
+ if (!read_float_range(tmp, &min, &max)) {
+ nv_error_msg("Unable to determine valid vertical refresh ranges "
+ "for display device '%s' (GPU: %s)!",
+ display->name, display->gpu->name);
+ goto fail;
+ }
+
+ monitor->n_vrefresh = 1;
+ monitor->vrefresh[0].lo = min;
+ monitor->vrefresh[0].hi = max;
+
+ parse_tokens(range_str, apply_monitor_token, (void *)(&v_source));
+ free(range_str);
+ range_str = NULL;
+
+ if (h_source && v_source) {
+ monitor->comment =
+ g_strdup_printf(" # HorizSync source: %s, "
+ "VertRefresh source: %s\n",
+ h_source, v_source);
+ }
+ free(h_source);
+ free(v_source);
+
+ /* Add other options */
+
+ opt = xconfigAddNewOption(opt, xconfigStrdup("DPMS"), NULL);
+ monitor->options = opt;
+
+ /* Add modelines used by this display */
+
+ add_modelines_to_monitor(monitor, display->modes);
+
+ /* Append the monitor to the end of the monitor list */
+
+ config->monitors =
+ (XConfigMonitorPtr)xconfigAddListItem((GenericListPtr)config->monitors,
+ (GenericListPtr)monitor);
+
+ display->conf_monitor = monitor;
+ return TRUE;
+
+
+ fail:
+ free(range_str);
+ free(h_source);
+ free(v_source);
+ if (monitor) {
+ xconfigFreeMonitorList(monitor);
+ }
+ return FALSE;
+
+} /* add_monitor_to_xconfig() */
+
+
+
+/*
+ * add_device_to_xconfig() - Adds the given device (GPU)'s information
+ * to the X configuration file. If a valid screen order number is given,
+ * it is also included (This is required for having separate X screens
+ * driven by a single GPU.)
+ */
+
+static XConfigDevicePtr add_device_to_xconfig(nvGpuPtr gpu, XConfigPtr config,
+ int device_id, int screen_id,
+ int print_bus_id)
+{
+ XConfigDevicePtr device;
+
+ device = (XConfigDevicePtr)calloc(1, sizeof(XConfigDeviceRec));
+ if (!device) goto fail;
+
+
+ /* Fill out the device information */
+ device->identifier = (char *)malloc(32);
+ snprintf(device->identifier, 32, "Videocard%d", device_id);
+
+ device->driver = xconfigStrdup("nvidia");
+ device->vendor = xconfigStrdup("NVIDIA Corporation");
+ device->board = xconfigStrdup(gpu->name);
+
+ if (print_bus_id) {
+ device->busid = (char *)malloc(32);
+ snprintf(device->busid, 32, "PCI:%d:%d:0",
+ gpu->pci_bus, gpu->pci_device);
+ }
+
+ device->chipid = -1;
+ device->chiprev = -1;
+ device->irq = -1;
+ device->screen = screen_id;
+
+
+ /* Append to the end of the device list */
+ config->devices =
+ (XConfigDevicePtr)xconfigAddListItem((GenericListPtr)config->devices,
+ (GenericListPtr)device);
+
+ return device;
+
+ fail:
+ if (device) {
+ xconfigFreeDeviceList(device);
+ }
+ return NULL;
+
+} /* add_device_to_xconfig() */
+
+
+
+/*
+ * add_display_to_screen() - Sets up the display subsection of
+ * the X config screen structure with information from the given
+ * screen.
+ */
+
+static Bool add_display_to_screen(nvScreenPtr screen,
+ XConfigScreenPtr conf_screen)
+{
+ /* Clear the display list */
+ xconfigFreeDisplayList(conf_screen->displays);
+ conf_screen->displays = NULL;
+
+
+ /* Add a single display subsection for the default depth */
+ conf_screen->displays = xconfigAddDisplay(NULL, conf_screen->defaultdepth);
+ if (!conf_screen->displays) goto fail;
+
+
+ /* XXX Don't do any further tweaking to the display subsection.
+ * All mode configuration should be done through the 'MetaModes"
+ * X Option. The modes generated by xconfigAddDisplay() will
+ * be used as a fallack.
+ */
+
+ return TRUE;
+
+ fail:
+ xconfigFreeDisplayList(conf_screen->displays);
+ conf_screen->displays = NULL;
+
+ return FALSE;
+
+} /* add_display_to_screen() */
+
+
+
+/*
+ * add_screen_to_xconfig() - Adds the given X Screen's information
+ * to the X configuration structure.
+ */
+
+static Bool add_screen_to_xconfig(CtkDisplayConfig *ctk_object,
+ nvScreenPtr screen, XConfigPtr config,
+ int screen_id)
+{
+ XConfigScreenPtr conf_screen;
+ nvDisplayPtr display;
+ nvDisplayPtr other;
+ char *metamode_strs;
+
+ conf_screen = (XConfigScreenPtr)calloc(1, sizeof(XConfigScreenRec));
+ if (!conf_screen) goto fail;
+
+
+ /* Fill out the screen information */
+ conf_screen->identifier = (char *)malloc(32);
+ snprintf(conf_screen->identifier, 32, "Screen%d", screen_id);
+
+
+ /* Tie the screen to its device section */
+ conf_screen->device_name =
+ xconfigStrdup(screen->conf_device->identifier);
+ conf_screen->device = screen->conf_device;
+
+
+ /* Find the first display on the screen */
+ for (display = screen->gpu->displays; display; display = display->next) {
+ if (display->screen == screen) {
+ break;
+ }
+ }
+ if (!display) {
+ nv_error_msg("Unable to find a display device for screen %d!",
+ screen->scrnum);
+ goto fail;
+ }
+
+
+ /* Create the screen's only Monitor section from the first display */
+ if (!add_monitor_to_xconfig(display, config, screen_id)) {
+ nv_error_msg("Failed to add display device '%s' to screen %d!",
+ display->name, screen->scrnum);
+ goto fail;
+ }
+
+
+ /* Tie the screen to the monitor section */
+ conf_screen->monitor_name =
+ xconfigStrdup(display->conf_monitor->identifier);
+ conf_screen->monitor = display->conf_monitor;
+
+
+ /* Add the modelines of all other connected displays to the monitor */
+ for (other = screen->gpu->displays; other; other = other->next) {
+ if (other->screen != screen) continue;
+ if (other == display) continue;
+
+ /* Add modelines used by this display */
+ add_modelines_to_monitor(display->conf_monitor, other->modes);
+ }
+
+ /* Add the TwinView option for multi monitor setups */
+ if (screen->num_displays > 1) {
+ conf_screen->options =
+ xconfigAddNewOption(conf_screen->options,
+ xconfigStrdup("TwinView"),
+ xconfigStrdup("1"));
+ }
+
+ /* XXX Setup any other twinview options ... */
+
+ /* Setup the metamode section.
+ *
+ * In basic view, always specify the currently selected
+ * metamode first in the list so the X server starts
+ * in this mode.
+ */
+ metamode_strs = get_screen_metamode_strs(screen, 1,
+ !ctk_object->advanced_mode);
+
+ /* If no user specified metamodes were found, add
+ * whatever the currently selected metamode is
+ */
+ if (!metamode_strs) {
+ metamode_strs = get_screen_metamode_str(screen,
+ screen->cur_metamode_idx, 1);
+ }
+
+ if (metamode_strs) {
+ conf_screen->options =
+ xconfigAddNewOption(conf_screen->options,
+ xconfigStrdup("metamodes"),
+ metamode_strs);
+ }
+
+
+ /* Setup the display section */
+ conf_screen->defaultdepth = screen->depth;
+
+
+ /* Setup the display subsection of the screen */
+ if (!add_display_to_screen(screen, conf_screen)) {
+ nv_error_msg("Failed to add Display section for screen %d!",
+ screen->scrnum);
+ goto fail;
+ }
+
+
+ /* Append to the end of the screen list */
+ config->screens =
+ (XConfigScreenPtr)xconfigAddListItem((GenericListPtr)config->screens,
+ (GenericListPtr)conf_screen);
+
+ screen->conf_screen = conf_screen;
+ return TRUE;
+
+ fail:
+ if (conf_screen) {
+ xconfigFreeScreenList(conf_screen);
+ }
+ return FALSE;
+
+} /* add_screen_to_xconfig() */
+
+
+
+/*
+ * add_screens_to_xconfig() - Adds all the X Screens in the given
+ * layout to the X configuration structure.
+ */
+
+static Bool add_screens_to_xconfig(CtkDisplayConfig *ctk_object,
+ nvLayoutPtr layout, XConfigPtr config)
+{
+ nvGpuPtr gpu;
+ nvScreenPtr screen;
+ int device_id, screen_id;
+ int print_bus_ids;
+
+
+ /* Clear the screen list */
+ xconfigFreeMonitorList(config->monitors);
+ config->monitors = NULL;
+ xconfigFreeDeviceList(config->devices);
+ config->devices = NULL;
+ xconfigFreeScreenList(config->screens);
+ config->screens = NULL;
+
+ /* Don't print the bus ID in the case where we have a single
+ * GPU driving a single X Screen
+ */
+ if (layout->num_gpus == 1 &&
+ layout->gpus->num_screens == 1) {
+ print_bus_ids = 0;
+ } else {
+ print_bus_ids = 1;
+ }
+
+ /* Generate the Device sections and Screen sections */
+
+ device_id = 0;
+ screen_id = 0;
+
+ for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+ int device_screen_id = -1;
+
+ for (screen = gpu->screens; screen; screen = screen->next) {
+
+ /* Only print a screen number if more than 1 screen on gpu */
+ if (gpu->num_screens > 1) {
+ device_screen_id++;
+ }
+
+ /* Each screen needs a unique device section */
+ screen->conf_device = add_device_to_xconfig(gpu, config,
+ device_id,
+ device_screen_id,
+ print_bus_ids);
+ if (!screen->conf_device) {
+ nv_error_msg("Failed to add Device '%s' to X Config.",
+ gpu->name);
+ goto fail;
+ }
+
+ if (!add_screen_to_xconfig(ctk_object, screen,
+ config, screen_id)) {
+ nv_error_msg("Failed to add X Screen %d to X Config.",
+ screen->scrnum);
+ goto fail;
+ }
+
+ device_id++;
+ screen_id++;
+ }
+ }
+ return TRUE;
+
+ fail:
+ xconfigFreeMonitorList(config->monitors);
+ config->monitors = NULL;
+ xconfigFreeDeviceList(config->devices);
+ config->devices = NULL;
+ xconfigFreeScreenList(config->screens);
+ config->screens = NULL;
+ return FALSE;
+
+} /* add_screens_to_xconfig() */
+
+
+
+/*
+ * add_adjacency_to_xconfig() - Adds the given X screen's positioning
+ * information to an X config structure.
+ */
+
+static Bool add_adjacency_to_xconfig(nvScreenPtr screen, XConfigPtr config,
+ int scrnum)
+{
+ XConfigAdjacencyPtr adj;
+ XConfigLayoutPtr conf_layout = config->layouts;
+
+
+ adj = (XConfigAdjacencyPtr) calloc(1, sizeof(XConfigAdjacencyRec));
+ if (!adj) return FALSE;
+
+ adj->scrnum = scrnum;
+ adj->screen = screen->conf_screen;
+ adj->screen_name = xconfigStrdup(screen->conf_screen->identifier);
+
+ /* Position the X Screen */
+ if (screen->position_type == CONF_ADJ_ABSOLUTE) {
+ adj->x = screen->dim[X];
+ adj->y = screen->dim[Y];
+ } else {
+ adj->where = screen->position_type;
+ adj->refscreen =
+ xconfigStrdup(screen->relative_to->conf_screen->identifier);
+ adj->x = screen->x_offset;
+ adj->y = screen->y_offset;
+ }
+
+ /* Append to the end of the screen list */
+ conf_layout->adjacencies =
+ (XConfigAdjacencyPtr)xconfigAddListItem((GenericListPtr)conf_layout->adjacencies,
+ (GenericListPtr)adj);
+
+ return TRUE;
+
+} /* add_adjacency_to_xconfig() */
+
+
+
+/*
+ * add_layout_to_xconfig() - Adds layout (adjacency/X Screen
+ * positioning) information to the X config structure based
+ * in the layout given.
+ */
+
+static Bool add_layout_to_xconfig(nvLayoutPtr layout, XConfigPtr config)
+{
+ XConfigLayoutPtr conf_layout;
+ nvGpuPtr gpu;
+ nvScreenPtr screen;
+ int scrnum;
+
+
+ /* Just modify the first layout */
+ conf_layout = config->layouts;
+ if (!conf_layout) {
+ nv_error_msg("Unable to generate initial layout!");
+ goto fail;
+ }
+
+
+ /* Clean up the adjacencies */
+ xconfigFreeAdjacencyList(conf_layout->adjacencies);
+ conf_layout->adjacencies = NULL;
+
+
+ /* Assign the adjacencies */
+ scrnum = 0;
+ for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+ for (screen = gpu->screens; screen; screen = screen->next) {
+ if (!add_adjacency_to_xconfig(screen, config, scrnum)) goto fail;
+ scrnum++;
+ }
+ }
+
+
+ /* Setup for Xinerama */
+ if (!config->flags) {
+ config->flags = (XConfigFlagsPtr) calloc(1, sizeof(XConfigFlagsRec));
+ if (!config->flags) goto fail;
+ }
+ config->flags->options =
+ xconfigAddNewOption(config->flags->options,
+ xconfigStrdup("Xinerama"),
+ xconfigStrdup(layout->xinerama_enabled?"1":"0"));
+
+ layout->conf_layout = conf_layout;
+ return TRUE;
+
+ fail:
+ return FALSE;
+
+} /* add_layout_to_xconfig() */
+
+
+
+/*
+ * get_default_project_root() - scan some common directories for the X
+ * project root
+ *
+ * Users of this information should be careful to account for the
+ * modular layout.
+ */
+
+char *get_default_project_root(void)
+{
+ char *paths[] = { "/usr/X11R6", "/usr/X11", NULL };
+ struct stat stat_buf;
+ int i;
+
+ for (i = 0; paths[i]; i++) {
+
+ if (stat(paths[i], &stat_buf) == -1) {
+ continue;
+ }
+
+ if (S_ISDIR(stat_buf.st_mode)) {
+ return paths[i];
+ }
+ }
+
+ /* default to "/usr/X11R6", I guess */
+
+ return paths[0];
+
+} /* get_default_project_root() */
+
+
+
+/*
+ * generateXConfig() - Generates an X config structure based
+ * on the layout given.
+ */
+
+static XConfigPtr generateXConfig(CtkDisplayConfig *ctk_object)
+{
+ nvLayoutPtr layout = ctk_object->layout;
+ XConfigPtr config = NULL;
+ GenerateOptions go;
+ char *server_vendor;
+
+
+ /* Query server Xorg/XFree86 */
+ server_vendor = NvCtrlGetServerVendor(layout->handle);
+ if (server_vendor && g_strrstr(server_vendor, "X.Org")) {
+ go.xserver = X_IS_XORG;
+ } else {
+ go.xserver = X_IS_XF86;
+ }
+
+
+ /* XXX Assume we are creating an X config file for the local system */
+ go.x_project_root = get_default_project_root();
+ go.keyboard = NULL;
+ go.mouse = NULL;
+ go.keyboard_driver = NULL;
+
+
+ /* Generate the basic layout */
+ config = xconfigGenerate(&go);
+
+
+ /* Repopulate the X config file with the right information */
+ if (!add_screens_to_xconfig(ctk_object, layout, config)) {
+ nv_error_msg("Failed to add X Screens to X Config.");
+ goto fail;
+ }
+ if (!add_layout_to_xconfig(layout, config)) {
+ nv_error_msg("Failed to add Server Layout to X Config.");
+ goto fail;
+ }
+
+ return config;
+
+ fail:
+ if (config) {
+ xconfigFreeConfig(config);
+ }
+ return NULL;
+
+} /* generateXConfig() */
+
+
+
+/*
+ * tilde_expansion() - do tilde expansion on the given path name;
+ * based loosely on code snippets found in the comp.unix.programmer
+ * FAQ. The tilde expansion rule is: if a tilde ('~') is alone or
+ * followed by a '/', then substitute the current user's home
+ * directory; if followed by the name of a user, then substitute that
+ * user's home directory.
+ *
+ * Code adapted from nvidia-xconfig
+ */
+
+char *tilde_expansion(char *str)
+{
+ char *prefix = NULL;
+ char *replace, *user, *ret;
+ struct passwd *pw;
+ int len;
+
+ if ((!str) || (str[0] != '~')) return str;
+
+ if ((str[1] == '/') || (str[1] == '\0')) {
+
+ /* expand to the current user's home directory */
+
+ prefix = getenv("HOME");
+ if (!prefix) {
+
+ /* $HOME isn't set; get the home directory from /etc/passwd */
+
+ pw = getpwuid(getuid());
+ if (pw) prefix = pw->pw_dir;
+ }
+
+ replace = str + 1;
+
+ } else {
+
+ /* expand to the specified user's home directory */
+
+ replace = strchr(str, '/');
+ if (!replace) replace = str + strlen(str);
+
+ len = replace - str;
+ user = malloc(len + 1);
+ strncpy(user, str+1, len-1);
+ user[len] = '\0';
+ pw = getpwnam(user);
+ if (pw) prefix = pw->pw_dir;
+ free (user);
+ }
+
+ if (!prefix) return str;
+
+ ret = malloc(strlen(prefix) + strlen(replace) + 1);
+ strcpy(ret, prefix);
+ strcat(ret, replace);
+
+ return ret;
+
+} /* tilde_expansion() */
+
+
+
+/*
+ * update_banner() - add our banner at the top of the config, but
+ * first we need to remove any lines that already include our prefix
+ * (because presumably they are a banner from an earlier run of
+ * nvidia-settings)
+ *
+ * Code adapted from nvidia-xconfig
+ */
+
+extern const char *pNV_ID;
+
+static void update_banner(XConfigPtr config)
+{
+ static const char *banner =
+ "X configuration file generated by nvidia-settings\n";
+ static const char *prefix =
+ "# nvidia-settings: ";
+
+ char *s = config->comment;
+ char *line, *eol, *tmp;
+
+ /* remove all lines that begin with the prefix */
+
+ while (s && (line = strstr(s, prefix))) {
+
+ eol = strchr(line, '\n'); /* find the end of the line */
+
+ if (eol) {
+ eol++;
+ if (*eol == '\0') eol = NULL;
+ }
+
+ if (line == s) { /* the line with the prefix is at the start */
+ if (eol) { /* there is more after the prefix line */
+ tmp = g_strdup(eol);
+ g_free(s);
+ s = tmp;
+ } else { /* the prefix line is the only line */
+ g_free(s);
+ s = NULL;
+ }
+ } else { /* prefix line is in the middle or end */
+ *line = '\0';
+ tmp = g_strconcat(s, eol, NULL);
+ g_free(s);
+ s = tmp;
+ }
+ }
+
+ /* add our prefix lines at the start of the comment */
+ config->comment = g_strconcat(prefix, banner,
+ "# ", pNV_ID, "\n",
+ (s ? s : ""),
+ NULL);
+ if (s) g_free(s);
+
+} /* update_banner() */
+
+
+
+/** save_xconfig_file() **********************************************
+ *
+ * Saves the X config file text from buf into a file called
+ * filename. If filename already exists, a backup file named
+ * 'filename.backup' is created.
+ *
+ **/
+
+static int save_xconfig_file(gchar *filename, char *buf, mode_t mode)
+{
+ gchar *backup_filename = NULL;
+ FILE *fp = NULL;
+ size_t size;
+
+ int ret = 0;
+
+
+ if (!buf || !filename) goto done;
+
+ size = strlen(buf) ;
+
+ /* Backup any existing file */
+ if ((access(filename, F_OK) == 0)) {
+
+ backup_filename = g_strdup_printf("%s.backup", filename);
+ nv_info_msg("", "X configuration file '%s' already exists, "
+ "backing up file as '%s'", filename,
+ backup_filename);
+
+ /* Delete any existing backup file */
+ if (access(backup_filename, F_OK) == 0) {
+
+ if (unlink(backup_filename) != 0) {
+ nv_error_msg("Unable to create backup file '%s'.",
+ backup_filename);
+ goto done;
+ }
+ }
+
+ /* Make the current x config file the backup */
+ if (rename(filename, backup_filename)) {
+ nv_error_msg("Unable to create backup file '%s'.",
+ backup_filename);
+ goto done;
+ }
+ }
+
+ /* Write out the X Config file */
+ fp = fopen(filename, "w");
+ if (!fp) {
+ nv_error_msg("Unable to open file '%s' for writing.",
+ filename);
+ goto done;
+ }
+ fprintf(fp, "%s", buf);
+
+ ret = 1;
+
+ done:
+
+ if (fp) fclose(fp);
+ g_free(backup_filename);
+ return ret;
+
+} /* save_xconfig_file() */
+
+
+
+/** save_clicked() ***************************************************
+ *
+ * Called when the user clicks on the "Save" button.
+ *
+ **/
+
+static void save_clicked(GtkWidget *widget, gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ gint result;
+
+ gchar *filename;
+ XConfigPtr config = NULL;
+
+ char *tmp_filename;
+ int tmp_fd;
+ struct stat st;
+ void *buf;
+ GtkTextIter buf_start, buf_end;
+
+
+ /* Make sure the layout is ready to be saved */
+ if (!validate_layout(ctk_object)) {
+ return;
+ }
+
+
+ /* Setup the default X config filename */
+ if (!ctk_object->layout->filename) {
+ filename = (gchar *) xconfigOpenConfigFile(NULL, NULL);
+ if (filename) {
+ ctk_object->layout->filename = g_strdup(filename);
+ xconfigCloseConfigFile();
+ filename = NULL;
+ } else {
+ ctk_object->layout->filename = g_strdup("");
+ }
+ }
+ gtk_entry_set_text(GTK_ENTRY(ctk_object->txt_xconfig_file),
+ ctk_object->layout->filename);
+
+
+ /* Generate an X Config file from the layout */
+ config = generateXConfig(ctk_object);
+ if (!config) {
+ nv_error_msg("Failed to generate an X config file!");
+ return;
+ }
+
+ /* Update the X Config banner */
+ update_banner(config);
+
+ /* Setup the X config file preview buffer by writing to a temp file */
+ tmp_filename = g_strdup_printf("/tmp/.xconfig.tmp.XXXXXX");
+ tmp_fd = mkstemp(tmp_filename);
+ if (!tmp_fd) {
+ nv_error_msg("Failed to create temp file for displaying X config!");
+ g_free(tmp_filename);
+ return;
+ }
+ xconfigWriteConfigFile(tmp_filename, config);
+ xconfigFreeConfig(config);
+
+ lseek(tmp_fd, 0, SEEK_SET);
+ fstat(tmp_fd, &st);
+ buf = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, tmp_fd, 0);
+ gtk_text_buffer_set_text(GTK_TEXT_BUFFER(ctk_object->buf_xconfig_save),
+ buf, st.st_size);
+ munmap(buf, st.st_size);
+ close(tmp_fd);
+ remove(tmp_filename);
+ g_free(tmp_filename);
+
+
+ /* Confirm the save */
+ gtk_window_set_transient_for
+ (GTK_WINDOW(ctk_object->dlg_xconfig_save),
+ GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(ctk_object))));
+ gtk_widget_hide(ctk_object->box_xconfig_save);
+ gtk_window_resize(GTK_WINDOW(ctk_object->dlg_xconfig_save), 350, 1);
+ gtk_window_set_resizable(GTK_WINDOW(ctk_object->dlg_xconfig_save),
+ FALSE);
+ gtk_button_set_label(GTK_BUTTON(ctk_object->btn_xconfig_preview),
+ "Show preview...");
+ gtk_widget_show(ctk_object->dlg_xconfig_save);
+ result = gtk_dialog_run(GTK_DIALOG(ctk_object->dlg_xconfig_save));
+ gtk_widget_hide(ctk_object->dlg_xconfig_save);
+
+
+ /* Handle user's response */
+ switch (result)
+ {
+ case GTK_RESPONSE_ACCEPT:
+
+ /* Get the filename to write to */
+ filename =
+ (gchar *) gtk_entry_get_text(GTK_ENTRY(ctk_object->txt_xconfig_file));
+
+ g_free(ctk_object->layout->filename);
+ ctk_object->layout->filename = tilde_expansion(filename);
+ if (ctk_object->layout->filename == filename) {
+ ctk_object->layout->filename = g_strdup(filename);
+ }
+ filename = ctk_object->layout->filename;
+
+
+ /* Get the buffer to write */
+ gtk_text_buffer_get_bounds
+ (GTK_TEXT_BUFFER(ctk_object->buf_xconfig_save), &buf_start,
+ &buf_end);
+ buf = (void *) gtk_text_buffer_get_text
+ (GTK_TEXT_BUFFER(ctk_object->buf_xconfig_save), &buf_start,
+ &buf_end, FALSE);
+ if (!buf) {
+ nv_error_msg("Failed to read X configuration buffer!");
+ break;
+ }
+
+ /* Save the X config file */
+ nv_info_msg("", "Writing X Config file '%s'", filename);
+ save_xconfig_file(filename, (char *)buf, 0644);
+ g_free(buf);
+ break;
+
+ case GTK_RESPONSE_REJECT:
+ default:
+ /* do nothing. */
+ break;
+ }
+
+} /* save_clicked() */
+
+
+
+/** advanced_clicked() ***********************************************
+ *
+ * Called when user clicks on the "Advanced..." button.
+ *
+ **/
+
+static void advanced_clicked(GtkWidget *widget, gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+
+
+ /* Toggle advanced options for the display */
+ ctk_object->advanced_mode = !(ctk_object->advanced_mode);
+
+
+ /* Show advanced display options */
+ if (ctk_object->advanced_mode) {
+ gtk_button_set_label(GTK_BUTTON(widget), "Basic...");
+ ctk_display_layout_set_advanced_mode(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ 1);
+
+ /* Show basic display options */
+ } else {
+ gtk_button_set_label(GTK_BUTTON(widget), "Advanced...");
+ ctk_display_layout_set_advanced_mode(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ 0);
+ }
+
+
+ /* Update the GUI to show the right widgets */
+ setup_display_frame(ctk_object);
+ setup_screen_frame(ctk_object);
+
+} /* advanced_clicked() */
+
+
+
+/** probe_clicked() **************************************************
+ *
+ * Called when user clicks on the "Probe" button.
+ *
+ **/
+
+static void probe_clicked(GtkWidget *widget, gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ unsigned int probed_displays;
+ unsigned int mask;
+ nvGpuPtr gpu;
+ nvDisplayPtr display;
+ nvDisplayPtr selected_display = ctk_display_layout_get_selected_display
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+ ReturnStatus ret;
+ gchar *type;
+ gchar *str;
+
+
+ /* Probe each GPU for display changes */
+ for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) {
+ if (!gpu->handle) continue;
+
+
+ /* Do the probe */
+ ret = NvCtrlGetAttribute(gpu->handle, NV_CTRL_PROBE_DISPLAYS,
+ (int *)&probed_displays);
+ if (ret != NvCtrlSuccess) {
+ nv_error_msg("Failed to probe for display devices on GPU-%d '%s'.",
+ NvCtrlGetTargetId(gpu->handle), gpu->name);
+ continue;
+ }
+
+ /* Make sure other parts of nvidia-settings get updated */
+ ctk_event_emit(gpu->ctk_event, 0,
+ NV_CTRL_PROBE_DISPLAYS, probed_displays);
+
+ /* Go through the probed displays */
+ for (mask = 1; mask; mask <<= 1) {
+
+ /* Ask users about removing old displays */
+ if ((gpu->connected_displays & mask) &&
+ !(probed_displays & mask)) {
+
+ display = get_display_from_gpu(gpu, mask);
+ if (!display) continue; /* XXX ack. */
+
+ /* The selected display is being removed */
+ if (display == selected_display) {
+ selected_display = NULL;
+ }
+
+ /* Setup the remove display dialog */
+ type = get_display_type_str(display->device_mask, 0);
+ str = g_strdup_printf("The display device %s (%s) on GPU-%d "
+ "(%s) has been\nunplugged. Would you "
+ "like to remove this display from the "
+ "layout?",
+ display->name, type,
+ NvCtrlGetTargetId(gpu->handle),
+ gpu->name);
+ g_free(type);
+ gtk_label_set_text(GTK_LABEL(ctk_object->txt_display_disable),
+ str);
+ g_free(str);
+
+ gtk_button_set_label
+ (GTK_BUTTON(ctk_object->btn_display_disable_off),
+ "Remove");
+
+ gtk_button_set_label
+ (GTK_BUTTON(ctk_object->btn_display_disable_cancel),
+ "Ignore");
+
+ /* Ask the user if they want to remove the display */
+ if (do_query_remove_display(ctk_object, display)) {
+
+ /* Remove display from the GPU */
+ remove_display_from_gpu(display);
+ free_display(display);
+
+ /* Let display layout widget know about change */
+ ctk_display_layout_update_display_count
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout), NULL);
+
+ /* Activate the apply button */
+ gtk_widget_set_sensitive(ctk_object->btn_apply, True);
+ }
+
+ /* Add new displays as 'disabled' */
+ } else if (!(gpu->connected_displays & mask) &&
+ (probed_displays & mask)) {
+ gchar *err_str = NULL;
+ display = add_display_to_gpu(gpu, mask, &err_str);
+ if (err_str) {
+ nv_warning_msg(err_str);
+ g_free(err_str);
+ }
+ add_screenless_modes_to_displays(gpu);
+ ctk_display_layout_update_display_count
+ (CTK_DISPLAY_LAYOUT(ctk_object->obj_layout),
+ selected_display);
+ }
+ }
+ }
+
+
+ /* Sync the GUI */
+ ctk_display_layout_redraw(CTK_DISPLAY_LAYOUT(ctk_object->obj_layout));
+
+ setup_display_frame(ctk_object);
+
+ setup_screen_frame(ctk_object);
+
+} /* probe_clicked() */
+
+
+
+/** reset_clicked() **************************************************
+ *
+ * Called when user clicks on the "Reset" button.
+ *
+ **/
+
+static void reset_clicked(GtkWidget *widget, gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ nvLayoutPtr layout;
+ gint result;
+ gchar *err_str = NULL;
+
+
+ /* Show the confirm dialog */
+ gtk_window_set_transient_for
+ (GTK_WINDOW(ctk_object->dlg_reset_confirm),
+ GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(ctk_object))));
+ gtk_widget_grab_focus(ctk_object->btn_reset_cancel);
+ gtk_widget_show(ctk_object->dlg_reset_confirm);
+ result = gtk_dialog_run(GTK_DIALOG(ctk_object->dlg_reset_confirm));
+ gtk_widget_hide(ctk_object->dlg_reset_confirm);
+
+ switch (result)
+ {
+ case GTK_RESPONSE_ACCEPT:
+ /* User wants to reset the configuration */
+ break;
+
+ case GTK_RESPONSE_REJECT:
+ default:
+ /* User doesn't want to reset the configuration */
+ return;
+ }
+
+
+ /* Load the current layout */
+ layout = load_server_layout(ctk_object->handle, &err_str);
+
+
+ /* Handle errors loading the new layout */
+ if (!layout || err_str) {
+ nv_error_msg(err_str);
+ g_free(err_str);
+ return;
+ }
+
+
+ /* Free the existing layout */
+ if (ctk_object->layout) {
+ remove_gpus_from_layout(ctk_object->layout);
+ free(ctk_object->layout);
+ }
+
+
+ /* Setup the new layout */
+ ctk_object->layout = layout;
+ ctk_display_layout_set_layout((CtkDisplayLayout *)(ctk_object->obj_layout),
+ ctk_object->layout);
+
+
+ /* Make sure X Screens have some kind of position */
+ assign_screen_positions(ctk_object);
+
+
+ /* Setup the GUI */
+ setup_layout_frame(ctk_object);
+ setup_display_frame(ctk_object);
+ setup_screen_frame(ctk_object);
+
+ /* Get new position */
+ get_cur_screen_pos(ctk_object);
+
+ /* Clear the apply button */
+ ctk_object->apply_possible = TRUE;
+ gtk_widget_set_sensitive(ctk_object->btn_apply, FALSE);
+
+} /* reset_clicked() */
+
+
+
+/** validation_details_clicked() *************************************
+ *
+ * Callback for when the user clicks on the "Show/Hide Details"
+ * button in the validation confirmation dialog.
+ *
+ **/
+
+static void validation_details_clicked(GtkWidget *widget, gpointer user_data)
+{
+ CtkDisplayConfig *ctk_object = CTK_DISPLAY_CONFIG(user_data);
+ gboolean show =
+ !(GTK_WIDGET_VISIBLE(ctk_object->box_validation_override_details));
+
+ if (show) {
+ gtk_widget_show_all(ctk_object->box_validation_override_details);
+ gtk_window_set_resizable
+ (GTK_WINDOW(ctk_object->dlg_validation_override), TRUE);
+ gtk_widget_set_size_request
+ (ctk_object->box_validation_override_details, 450, 150);
+ gtk_button_set_label
+ (GTK_BUTTON(ctk_object->btn_validation_override_show),
+ "Hide Details...");
+ } else {
+ gtk_widget_hide(ctk_object->box_validation_override_details);
+ gtk_window_set_resizable
+ (GTK_WINDOW(ctk_object->dlg_validation_override), FALSE);
+ gtk_button_set_label
+ (GTK_BUTTON(ctk_object->btn_validation_override_show),
+ "Show Details...");
+ }
+
+} /* validation_details_clicked() */
diff --git a/src/gtk+-2.x/ctkdisplayconfig.h b/src/gtk+-2.x/ctkdisplayconfig.h
new file mode 100644
index 0000000..75a96c1
--- /dev/null
+++ b/src/gtk+-2.x/ctkdisplayconfig.h
@@ -0,0 +1,197 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
+ * of the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+#ifndef __CTK_DISPLAYCONFIG_H__
+#define __CTK_DISPLAYCONFIG_H__
+
+#include "ctkevent.h"
+#include "ctkconfig.h"
+#include "ctkdisplaylayout.h"
+
+
+G_BEGIN_DECLS
+
+#define CTK_TYPE_DISPLAY_CONFIG (ctk_display_config_get_type())
+
+#define CTK_DISPLAY_CONFIG(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), CTK_TYPE_DISPLAY_CONFIG, \
+ CtkDisplayConfig))
+
+#define CTK_DISPLAY_CONFIG_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), CTK_TYPE_DISPLAY_CONFIG, \
+ CtkDisplayConfigClass))
+
+#define CTK_IS_DISPLAY_CONFIG(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CTK_TYPE_DISPLAY_CONFIG))
+
+#define CTK_IS_DISPLAY_CONFIG_CLASS(class) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), CTK_TYPE_DISPLAY_CONFIG))
+
+#define CTK_DISPLAY_CONFIG_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_DISPLAY_CONFIG, \
+ CtkDisplayConfigClass))
+
+
+typedef struct _CtkDisplayConfig
+{
+ GtkVBox parent;
+
+ NvCtrlAttributeHandle *handle;
+ CtkConfig *ctk_config;
+
+
+ /* Layout */
+ nvLayoutPtr layout;
+ GtkWidget *obj_layout;
+
+ GtkWidget *chk_xinerama_enabled;
+
+
+ /* Display - Info */
+ GtkWidget *display_frame;
+
+ GtkWidget *txt_display_model;
+ GtkWidget *txt_display_gpu;
+
+ GtkWidget *btn_display_config;
+ GtkWidget *txt_display_config;
+
+ /* Display - Settings */
+ GtkWidget *box_display_resolution;
+ GtkWidget *mnu_display_resolution;
+ nvModeLinePtr *resolution_table;
+ int resolution_table_len;
+
+ GtkWidget *mnu_display_refresh;
+ nvModeLinePtr *refresh_table; /* Lookup table for refresh menu */
+ int refresh_table_len;
+
+ GtkWidget *box_display_modename;
+ GtkWidget *txt_display_modename;
+
+ GtkWidget *box_display_position;
+ GtkWidget *mnu_display_position_type; /* Absolute, Right of... */
+ GtkWidget *mnu_display_position_relative; /* List of available devices */
+ nvDisplayPtr *display_position_table; /* Lookup table for relative display position */
+ int display_position_table_len;
+ GtkWidget *txt_display_position_offset; /* Absolute: +0+0 */
+
+ GtkWidget *box_display_panning;
+ GtkWidget *txt_display_panning;
+
+
+ /* X Screen - Info */
+ GtkWidget *screen_frame;
+
+ GtkWidget *txt_screen_num;
+
+ /* X Screen - Settings */
+ GtkWidget *box_screen_depth;
+ GtkWidget *mnu_screen_depth;
+
+ GtkWidget *box_screen_position;
+ GtkWidget *mnu_screen_position_type; /* Absolute, Right of... */
+ GtkWidget *mnu_screen_position_relative; /* List of available devices */
+ nvScreenPtr *screen_position_table;
+ int screen_position_table_len;
+ GtkWidget *txt_screen_position_offset; /* Absolute: +0+0 */
+
+ GtkWidget *box_screen_metamode;
+ GtkWidget *btn_screen_metamode;
+ GtkWidget *btn_screen_metamode_add;
+ GtkWidget *btn_screen_metamode_delete;
+
+
+ /* Dialogs */
+ GtkWidget *dlg_display_config;
+ GtkWidget *rad_display_config_disabled;
+ GtkWidget *rad_display_config_xscreen;
+ GtkWidget *rad_display_config_twinview;
+ GtkWidget *btn_display_config_cancel;
+
+ GtkWidget *dlg_display_disable;
+ GtkWidget *txt_display_disable;
+ GtkWidget *btn_display_disable_off;
+ GtkWidget *btn_display_disable_cancel;
+
+ GtkWidget *dlg_validation_override;
+ GtkTextBuffer *buf_validation_override;
+ GtkWidget *btn_validation_override_cancel;
+ GtkWidget *box_validation_override_details;
+ GtkWidget *btn_validation_override_show; /* Show details */
+
+ GtkWidget *dlg_validation_apply;
+
+ GtkWidget *dlg_reset_confirm;
+ GtkWidget *btn_reset_cancel;
+
+ GtkWidget *dlg_display_confirm;
+ GtkWidget *txt_display_confirm;
+ GtkWidget *btn_display_apply_cancel;
+ guint display_confirm_timer;
+ int display_confirm_countdown; /* Timeout to reset display config */
+
+ GtkWidget *dlg_xconfig_save; /* Save X config dialog */
+ GtkWidget *scr_xconfig_save;
+ GtkWidget *txt_xconfig_save; /* Text file... */
+ GtkTextBuffer *buf_xconfig_save; /* Text file... */
+ GtkWidget *btn_xconfig_preview; /* Show/Hide button */
+ GtkWidget *box_xconfig_save; /* Show/Hide this box */
+
+ GtkWidget *dlg_xconfig_file; /* File save dialog */
+ GtkWidget *btn_xconfig_file;
+ GtkWidget *txt_xconfig_file;
+
+
+ /* Buttons */
+ GtkWidget *btn_apply;
+ gboolean apply_possible; /* True if all modifications are applicable */
+ int cur_screen_pos[2]; /* Keep track of the selected X Screen's position */
+
+ GtkWidget *btn_save;
+ GtkWidget *btn_probe;
+
+ GtkWidget *btn_advanced;
+ gboolean advanced_mode; /* True if we are in advanced mode */
+
+ GtkWidget *btn_reset;
+
+} CtkDisplayConfig;
+
+typedef struct _CtkDisplayConfigClass
+{
+ GtkVBoxClass parent_class;
+} CtkDisplayConfigClass;
+
+
+GType ctk_display_config_get_type (void) G_GNUC_CONST;
+GtkWidget* ctk_display_config_new (NvCtrlAttributeHandle *,
+ CtkConfig *);
+
+GtkTextBuffer *ctk_display_config_create_help(GtkTextTagTable *,
+ CtkDisplayConfig *);
+
+G_END_DECLS
+
+#endif /* __CTK_DISPLAYCONFIG_H__ */
diff --git a/src/gtk+-2.x/ctkdisplaydevice-crt.c b/src/gtk+-2.x/ctkdisplaydevice-crt.c
index 06e1a22..cbf3583 100644
--- a/src/gtk+-2.x/ctkdisplaydevice-crt.c
+++ b/src/gtk+-2.x/ctkdisplaydevice-crt.c
@@ -36,8 +36,16 @@
#include "ctkhelp.h"
+static void ctk_display_device_crt_class_init(CtkDisplayDeviceCrtClass *);
+static void ctk_display_device_crt_finalize(GObject *);
+
static void reset_button_clicked(GtkButton *button, gpointer user_data);
+static void ctk_display_device_crt_setup(CtkDisplayDeviceCrt
+ *ctk_display_device_crt);
+
+static void enabled_displays_received(GtkObject *object, gpointer arg1,
+ gpointer user_data);
GType ctk_display_device_crt_get_type(void)
{
@@ -48,7 +56,7 @@ GType ctk_display_device_crt_get_type(void)
sizeof (CtkDisplayDeviceCrtClass),
NULL, /* base_init */
NULL, /* base_finalize */
- NULL, /* class_init, */
+ (GClassInitFunc) ctk_display_device_crt_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (CtkDisplayDeviceCrt),
@@ -63,6 +71,26 @@ GType ctk_display_device_crt_get_type(void)
return ctk_display_device_crt_type;
}
+static void ctk_display_device_crt_class_init(
+ CtkDisplayDeviceCrtClass *ctk_display_device_crt_class
+)
+{
+ GObjectClass *gobject_class = (GObjectClass *)ctk_display_device_crt_class;
+ gobject_class->finalize = ctk_display_device_crt_finalize;
+}
+
+static void ctk_display_device_crt_finalize(
+ GObject *object
+)
+{
+ CtkDisplayDeviceCrt *ctk_display_device_crt = CTK_DISPLAY_DEVICE_CRT(object);
+ g_free(ctk_display_device_crt->name);
+}
+
+/*
+ * ctk_display_device_crt_new() - constructor for the CRT display
+ * device page.
+ */
GtkWidget* ctk_display_device_crt_new(NvCtrlAttributeHandle *handle,
CtkConfig *ctk_config,
@@ -74,19 +102,16 @@ GtkWidget* ctk_display_device_crt_new(NvCtrlAttributeHandle *handle,
CtkDisplayDeviceCrt *ctk_display_device_crt;
GtkWidget *banner;
GtkWidget *hbox;
- GtkWidget *label;
GtkWidget *alignment;
- GtkWidget *edid;
-
- char *s;
object = g_object_new(CTK_TYPE_DISPLAY_DEVICE_CRT, NULL);
ctk_display_device_crt = CTK_DISPLAY_DEVICE_CRT(object);
ctk_display_device_crt->handle = handle;
ctk_display_device_crt->ctk_config = ctk_config;
+ ctk_display_device_crt->ctk_event = ctk_event;
ctk_display_device_crt->display_device_mask = display_device_mask;
- ctk_display_device_crt->name = name;
+ ctk_display_device_crt->name = g_strdup(name);
gtk_box_set_spacing(GTK_BOX(object), 10);
@@ -101,13 +126,8 @@ GtkWidget* ctk_display_device_crt_new(NvCtrlAttributeHandle *handle,
* sensitivity), though we pack it at the bottom of the page
*/
- label = gtk_label_new("Reset Hardware Defaults");
- hbox = gtk_hbox_new(FALSE, 0);
- ctk_display_device_crt->reset_button = gtk_button_new();
-
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 15);
- gtk_container_add(GTK_CONTAINER(ctk_display_device_crt->reset_button),
- hbox);
+ ctk_display_device_crt->reset_button =
+ gtk_button_new_with_label("Reset Hardware Defaults");
alignment = gtk_alignment_new(1, 1, 0, 0);
gtk_container_add(GTK_CONTAINER(alignment),
@@ -132,33 +152,29 @@ GtkWidget* ctk_display_device_crt_new(NvCtrlAttributeHandle *handle,
gtk_box_pack_start(GTK_BOX(object),
ctk_display_device_crt->image_sliders,
FALSE, FALSE, 0);
- } else {
- s = g_strconcat("There are no configurable options available for ",
- ctk_display_device_crt->name, ".", NULL);
-
- label = gtk_label_new(s);
-
- g_free(s);
-
- gtk_box_pack_start(GTK_BOX(object), label, FALSE, FALSE, 0);
}
/* pack the EDID button */
- edid = ctk_edid_new(handle, ctk_config, ctk_event,
- ctk_display_device_crt->reset_button,
- display_device_mask, name);
- if (edid) {
- gtk_box_pack_start(GTK_BOX(object), edid, FALSE, FALSE, 0);
- ctk_display_device_crt->edid_available = TRUE;
- } else {
- ctk_display_device_crt->edid_available = FALSE;
- }
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, 0);
+ ctk_display_device_crt->edid_box = hbox;
/* show the page */
gtk_widget_show_all(GTK_WIDGET(object));
+ /* Update the GUI */
+
+ ctk_display_device_crt_setup(ctk_display_device_crt);
+
+ /* handle enable/disable events on the display device */
+
+ g_signal_connect(G_OBJECT(ctk_event),
+ CTK_EVENT_NAME(NV_CTRL_ENABLED_DISPLAYS),
+ G_CALLBACK(enabled_displays_received),
+ (gpointer) ctk_display_device_crt);
+
return GTK_WIDGET(object);
}
@@ -170,7 +186,6 @@ GtkTextBuffer *ctk_display_device_crt_create_help(GtkTextTagTable *table,
{
GtkTextIter i;
GtkTextBuffer *b;
- gboolean ret;
b = gtk_text_buffer_new(table);
@@ -178,22 +193,13 @@ GtkTextBuffer *ctk_display_device_crt_create_help(GtkTextTagTable *table,
ctk_help_title(b, &i, "%s Help", ctk_display_device_crt->name);
- if (ctk_display_device_crt->image_sliders) {
- ret = add_image_sliders_help
- (CTK_IMAGE_SLIDERS(ctk_display_device_crt->image_sliders), b, &i);
- } else {
- ret = FALSE;
- }
+ add_image_sliders_help
+ (CTK_IMAGE_SLIDERS(ctk_display_device_crt->image_sliders), b, &i);
- if (ctk_display_device_crt->edid_available) {
+ if (ctk_display_device_crt->edid) {
add_acquire_edid_help(b, &i);
}
- if (!ret) {
- ctk_help_para(b, &i, "There are no configurable options available "
- "for %s.", ctk_display_device_crt->name);
- }
-
ctk_help_finish(b);
return b;
@@ -210,13 +216,94 @@ static void reset_button_clicked(GtkButton *button, gpointer user_data)
CtkDisplayDeviceCrt *ctk_display_device_crt =
CTK_DISPLAY_DEVICE_CRT(user_data);
- if (ctk_display_device_crt->image_sliders) {
- ctk_image_sliders_reset
- (CTK_IMAGE_SLIDERS(ctk_display_device_crt->image_sliders));
- }
+ ctk_image_sliders_reset
+ (CTK_IMAGE_SLIDERS(ctk_display_device_crt->image_sliders));
+
+ gtk_widget_set_sensitive(ctk_display_device_crt->reset_button, FALSE);
ctk_config_statusbar_message(ctk_display_device_crt->ctk_config,
"Reset hardware defaults for %s.",
ctk_display_device_crt->name);
} /* reset_button_clicked() */
+
+
+
+/*
+ * Updates the display device page to reflect the current
+ * configuration of the display device.
+ */
+static void ctk_display_device_crt_setup(CtkDisplayDeviceCrt
+ *ctk_display_device_crt)
+{
+ ReturnStatus ret;
+ unsigned int enabled_displays;
+
+
+ /* Is display enabled? */
+
+ ret = NvCtrlGetAttribute(ctk_display_device_crt->handle,
+ NV_CTRL_ENABLED_DISPLAYS,
+ (int *)&enabled_displays);
+
+ ctk_display_device_crt->display_enabled =
+ (ret == NvCtrlSuccess &&
+ (enabled_displays & (ctk_display_device_crt->display_device_mask)));
+
+
+ /* Update the image sliders */
+
+ ctk_image_sliders_setup
+ (CTK_IMAGE_SLIDERS(ctk_display_device_crt->image_sliders));
+
+
+ /* update acquire EDID button */
+
+ if (ctk_display_device_crt->edid) {
+ GList *list;
+
+ list = gtk_container_get_children
+ (GTK_CONTAINER(ctk_display_device_crt->edid_box));
+ if (list) {
+ gtk_container_remove
+ (GTK_CONTAINER(ctk_display_device_crt->edid_box),
+ (GtkWidget *)(list->data));
+ g_list_free(list);
+ }
+ }
+
+ ctk_display_device_crt->edid =
+ ctk_edid_new(ctk_display_device_crt->handle,
+ ctk_display_device_crt->ctk_config,
+ ctk_display_device_crt->ctk_event,
+ ctk_display_device_crt->reset_button,
+ ctk_display_device_crt->display_device_mask,
+ ctk_display_device_crt->name);
+
+ if (ctk_display_device_crt->edid) {
+ gtk_box_pack_start(GTK_BOX(ctk_display_device_crt->edid_box),
+ ctk_display_device_crt->edid, TRUE, TRUE, 0);
+ }
+
+
+ /* update the reset button */
+
+ gtk_widget_set_sensitive(ctk_display_device_crt->reset_button, FALSE);
+
+} /* ctk_display_device_crt_setup() */
+
+
+
+/*
+ * When the list of enabled displays on the GPU changes,
+ * this page should disable/enable access based on whether
+ * or not the display device is enabled.
+ */
+static void enabled_displays_received(GtkObject *object, gpointer arg1,
+ gpointer user_data)
+{
+ CtkDisplayDeviceCrt *ctk_object = CTK_DISPLAY_DEVICE_CRT(user_data);
+
+ ctk_display_device_crt_setup(ctk_object);
+
+} /* enabled_displays_received() */
diff --git a/src/gtk+-2.x/ctkdisplaydevice-crt.h b/src/gtk+-2.x/ctkdisplaydevice-crt.h
index f31632a..56180d3 100644
--- a/src/gtk+-2.x/ctkdisplaydevice-crt.h
+++ b/src/gtk+-2.x/ctkdisplaydevice-crt.h
@@ -60,12 +60,15 @@ struct _CtkDisplayDeviceCrt
NvCtrlAttributeHandle *handle;
CtkConfig *ctk_config;
+ CtkEvent *ctk_event;
GtkWidget *image_sliders;
GtkWidget *reset_button;
+
+ GtkWidget *edid_box;
+ GtkWidget *edid;
unsigned int display_device_mask;
- unsigned int active_attributes;
- gboolean edid_available;
+ gboolean display_enabled;
char *name;
};
diff --git a/src/gtk+-2.x/ctkdisplaydevice-dfp.c b/src/gtk+-2.x/ctkdisplaydevice-dfp.c
index f5fdcf6..ead85c3 100644
--- a/src/gtk+-2.x/ctkdisplaydevice-dfp.c
+++ b/src/gtk+-2.x/ctkdisplaydevice-dfp.c
@@ -37,6 +37,9 @@
#include "ctkutils.h"
+static void ctk_display_device_dfp_class_init(CtkDisplayDeviceDfpClass *);
+static void ctk_display_device_dfp_finalize(GObject *);
+
static GtkWidget *make_scaling_radio_button(CtkDisplayDeviceDfp
*ctk_display_device_dfp,
GtkWidget *vbox,
@@ -69,12 +72,23 @@ dfp_dithering_update_radio_buttons(CtkDisplayDeviceDfp *ctk_display_device_dfp,
static void dfp_update_received(GtkObject *object, gpointer arg1,
gpointer user_data);
+static void dfp_info_setup(CtkDisplayDeviceDfp *ctk_display_device_dfp);
+
+static void dfp_scaling_setup(CtkDisplayDeviceDfp *ctk_display_device_dfp);
+
+static void dfp_dithering_setup(CtkDisplayDeviceDfp *ctk_display_device_dfp);
+
+static void ctk_display_device_dfp_setup(CtkDisplayDeviceDfp
+ *ctk_display_device_dfp);
+
+static void enabled_displays_received(GtkObject *object, gpointer arg1,
+ gpointer user_data);
+
#define FRAME_PADDING 5
#define __SCALING (1<<0)
#define __DITHERING (1<<1)
-#define __INFO (1<<2)
static const char *__scaling_help =
@@ -103,8 +117,8 @@ GType ctk_display_device_dfp_get_type(void)
sizeof (CtkDisplayDeviceDfpClass),
NULL, /* base_init */
NULL, /* base_finalize */
- NULL, /* class_init, */
- NULL, /* class_finalize */
+ (GClassInitFunc) ctk_display_device_dfp_class_init,
+ NULL, /* class_finalize, */
NULL, /* class_data */
sizeof (CtkDisplayDeviceDfp),
0, /* n_preallocs */
@@ -118,11 +132,26 @@ GType ctk_display_device_dfp_get_type(void)
return ctk_display_device_dfp_type;
}
+static void ctk_display_device_dfp_class_init(
+ CtkDisplayDeviceDfpClass *ctk_display_device_dfp_class
+)
+{
+ GObjectClass *gobject_class = (GObjectClass *)ctk_display_device_dfp_class;
+ gobject_class->finalize = ctk_display_device_dfp_finalize;
+}
+
+static void ctk_display_device_dfp_finalize(
+ GObject *object
+)
+{
+ CtkDisplayDeviceDfp *ctk_display_device_dfp = CTK_DISPLAY_DEVICE_DFP(object);
+ g_free(ctk_display_device_dfp->name);
+}
/*
* ctk_display_device_dfp_new() - constructor for the DFP display
- * device page
+ * device page.
*/
GtkWidget* ctk_display_device_dfp_new(NvCtrlAttributeHandle *handle,
@@ -136,7 +165,6 @@ GtkWidget* ctk_display_device_dfp_new(NvCtrlAttributeHandle *handle,
GtkWidget *banner;
GtkWidget *frame;
GtkWidget *hbox, *vbox, *tmpbox;
- GtkWidget *label;
GtkWidget *eventbox;
GtkWidget *radio0;
@@ -144,13 +172,8 @@ GtkWidget* ctk_display_device_dfp_new(NvCtrlAttributeHandle *handle,
GtkWidget *radio2;
GtkWidget *radio3;
GtkWidget *alignment;
- GtkWidget *edid;
GtkWidget *table;
-
- ReturnStatus ret;
-
- gint val, i;
object = g_object_new(CTK_TYPE_DISPLAY_DEVICE_DFP, NULL);
@@ -158,7 +181,7 @@ GtkWidget* ctk_display_device_dfp_new(NvCtrlAttributeHandle *handle,
ctk_display_device_dfp->handle = handle;
ctk_display_device_dfp->ctk_config = ctk_config;
ctk_display_device_dfp->display_device_mask = display_device_mask;
- ctk_display_device_dfp->name = name;
+ ctk_display_device_dfp->name = g_strdup(name);
gtk_box_set_spacing(GTK_BOX(object), 10);
@@ -173,13 +196,8 @@ GtkWidget* ctk_display_device_dfp_new(NvCtrlAttributeHandle *handle,
* sensitivity), though we pack it at the bottom of the page
*/
- label = gtk_label_new("Reset Hardware Defaults");
- hbox = gtk_hbox_new(FALSE, 0);
- ctk_display_device_dfp->reset_button = gtk_button_new();
-
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 15);
- gtk_container_add(GTK_CONTAINER(ctk_display_device_dfp->reset_button),
- hbox);
+ ctk_display_device_dfp->reset_button =
+ gtk_button_new_with_label("Reset Hardware Defaults");
alignment = gtk_alignment_new(1, 1, 0, 0);
gtk_container_add(GTK_CONTAINER(alignment),
@@ -200,176 +218,116 @@ GtkWidget* ctk_display_device_dfp_new(NvCtrlAttributeHandle *handle,
gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, FRAME_PADDING);
/* DFP info */
- ret = NvCtrlGetDisplayAttribute(handle, display_device_mask,
- NV_CTRL_FLATPANEL_CHIP_LOCATION, &val);
- if (ret == NvCtrlSuccess) {
- char *chip_location, *link, *signal;
- gint tmp;
-
- /* NV_CTRL_FLATPANEL_CHIP_LOCATION */
- ret = NvCtrlGetDisplayAttribute(handle, display_device_mask,
- NV_CTRL_FLATPANEL_CHIP_LOCATION, &tmp);
- chip_location = NULL;
- if (ret == NvCtrlSuccess) {
- if (tmp == NV_CTRL_FLATPANEL_CHIP_LOCATION_INTERNAL) chip_location = "Internal";
- if (tmp == NV_CTRL_FLATPANEL_CHIP_LOCATION_EXTERNAL) chip_location = "External";
- }
-
- ret = NvCtrlGetDisplayAttribute(handle, display_device_mask,
- NV_CTRL_FLATPANEL_LINK, &tmp);
- link = NULL;
- if (ret == NvCtrlSuccess) {
- if (tmp == NV_CTRL_FLATPANEL_LINK_SINGLE) link = "Single";
- if (tmp == NV_CTRL_FLATPANEL_LINK_DUAL) link = "Dual";
- }
-
- ret = NvCtrlGetDisplayAttribute(handle, display_device_mask,
- NV_CTRL_FLATPANEL_SIGNAL, &tmp);
- signal = NULL;
- if (ret == NvCtrlSuccess) {
- if (tmp == NV_CTRL_FLATPANEL_SIGNAL_LVDS) signal = "LVDS";
- if (tmp == NV_CTRL_FLATPANEL_SIGNAL_TMDS) signal = "TMDS";
- }
-
- frame = gtk_frame_new("Flat Panel Information");
- gtk_box_pack_start(GTK_BOX(hbox), frame, FALSE, FALSE, 0);
-
- table = gtk_table_new(3, 2, FALSE);
-
- /*
- * insert a vbox between the frame and the table, so that the
- * table doesn't expand to fill all of the space within the
- * frame
- */
-
- tmpbox = gtk_vbox_new(FALSE, 0);
- gtk_box_pack_start(GTK_BOX(tmpbox), table, FALSE, FALSE, 0);
-
- gtk_container_add(GTK_CONTAINER(frame), tmpbox);
-
- gtk_table_set_row_spacings(GTK_TABLE(table), 3);
- gtk_table_set_col_spacings(GTK_TABLE(table), 15);
-
- gtk_container_set_border_width(GTK_CONTAINER(table), 5);
+ frame = gtk_frame_new("Flat Panel Information");
+ gtk_box_pack_start(GTK_BOX(hbox), frame, FALSE, FALSE, 0);
- add_table_row(table, 0, 0, "Chip location:", chip_location);
- add_table_row(table, 1, 0, "DVI connection link:", link);
- add_table_row(table, 2, 0, "Signal:", signal);
-
- ctk_display_device_dfp->active_attributes |= __INFO;
- }
- else
- ctk_display_device_dfp->active_attributes &= ~__INFO;
+ table = gtk_table_new(3, 2, FALSE);
+
+ /*
+ * insert a vbox between the frame and the table, so that the
+ * table doesn't expand to fill all of the space within the
+ * frame
+ */
+
+ tmpbox = gtk_vbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(tmpbox), table, FALSE, FALSE, 0);
+
+ gtk_container_add(GTK_CONTAINER(frame), tmpbox);
+
+ gtk_table_set_row_spacings(GTK_TABLE(table), 3);
+ gtk_table_set_col_spacings(GTK_TABLE(table), 15);
+
+ gtk_container_set_border_width(GTK_CONTAINER(table), 5);
+
+ ctk_display_device_dfp->txt_chip_location =
+ add_table_row(table, 0,
+ 0, 0.5, "Chip location:",
+ 0, 0.5, "");
+
+ ctk_display_device_dfp->txt_link =
+ add_table_row(table, 1,
+ 0, 0.5, "DVI connection link:",
+ 0, 0.5, "");
+
+ ctk_display_device_dfp->txt_signal =
+ add_table_row(table, 2,
+ 0, 0.5, "Signal:",
+ 0, 0.5, "");
/* FlatPanel Scaling */
- ret = NvCtrlGetDisplayAttribute(handle, display_device_mask,
- NV_CTRL_FLATPANEL_SCALING, &val);
-
- if (ret == NvCtrlSuccess) {
- frame = gtk_frame_new("FlatPanel Scaling");
- eventbox = gtk_event_box_new();
- gtk_container_add(GTK_CONTAINER(eventbox), frame);
- gtk_box_pack_start(GTK_BOX(hbox), eventbox, FALSE, FALSE, 0);
+ frame = gtk_frame_new("FlatPanel Scaling");
+ eventbox = gtk_event_box_new();
+ gtk_container_add(GTK_CONTAINER(eventbox), frame);
+ gtk_box_pack_start(GTK_BOX(hbox), eventbox, FALSE, FALSE, 0);
+ ctk_display_device_dfp->scaling_frame = frame;
- ctk_config_set_tooltip(ctk_config, eventbox, __scaling_help);
-
- vbox = gtk_vbox_new(FALSE, FRAME_PADDING);
- gtk_container_set_border_width(GTK_CONTAINER(vbox), FRAME_PADDING);
- gtk_container_add(GTK_CONTAINER(frame), vbox);
-
-
- radio0 = make_scaling_radio_button
- (ctk_display_device_dfp, vbox, NULL, "Default",
- NV_CTRL_FLATPANEL_SCALING_DEFAULT);
-
- radio1 = make_scaling_radio_button
- (ctk_display_device_dfp, vbox, radio0, "Scaled",
- NV_CTRL_FLATPANEL_SCALING_SCALED);
-
- radio2 = make_scaling_radio_button
- (ctk_display_device_dfp, vbox, radio1, "Centered",
- NV_CTRL_FLATPANEL_SCALING_CENTERED);
-
- radio3 = make_scaling_radio_button
- (ctk_display_device_dfp, vbox, radio2, "Fixed Aspect Ratio Scaled",
- NV_CTRL_FLATPANEL_SCALING_ASPECT_SCALED);
-
- /*
- * XXX TODO: determine when we should advertise Monitor
- * Scaling (aka "Native" scaling)
- */
-
- ctk_display_device_dfp->scaling_buttons
- [NV_CTRL_FLATPANEL_SCALING_NATIVE] = NULL;
-
-
- dfp_scaling_update_radio_buttons(ctk_display_device_dfp, val);
-
- g_signal_connect(G_OBJECT(ctk_event),
- CTK_EVENT_NAME(NV_CTRL_FLATPANEL_SCALING),
- G_CALLBACK(dfp_update_received),
- (gpointer) ctk_display_device_dfp);
-
- ctk_display_device_dfp->active_attributes |= __SCALING;
-
- } else {
-
- for (i = 0; i < NV_CTRL_FLATPANEL_SCALING_ASPECT_SCALED+1; i++) {
- ctk_display_device_dfp->scaling_buttons[i] = NULL;
- }
-
- ctk_display_device_dfp->active_attributes &= ~__SCALING;
- }
+ ctk_config_set_tooltip(ctk_config, eventbox, __scaling_help);
+
+ vbox = gtk_vbox_new(FALSE, FRAME_PADDING);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), FRAME_PADDING);
+ gtk_container_add(GTK_CONTAINER(frame), vbox);
+
+ radio0 = make_scaling_radio_button
+ (ctk_display_device_dfp, vbox, NULL, "Default",
+ NV_CTRL_FLATPANEL_SCALING_DEFAULT);
+
+ radio1 = make_scaling_radio_button
+ (ctk_display_device_dfp, vbox, radio0, "Scaled",
+ NV_CTRL_FLATPANEL_SCALING_SCALED);
+
+ radio2 = make_scaling_radio_button
+ (ctk_display_device_dfp, vbox, radio1, "Centered",
+ NV_CTRL_FLATPANEL_SCALING_CENTERED);
+
+ radio3 = make_scaling_radio_button
+ (ctk_display_device_dfp, vbox, radio2, "Fixed Aspect Ratio Scaled",
+ NV_CTRL_FLATPANEL_SCALING_ASPECT_SCALED);
+
+ /*
+ * XXX TODO: determine when we should advertise Monitor
+ * Scaling (aka "Native" scaling)
+ */
+
+ ctk_display_device_dfp->scaling_buttons
+ [NV_CTRL_FLATPANEL_SCALING_NATIVE] = NULL;
+
+ g_signal_connect(G_OBJECT(ctk_event),
+ CTK_EVENT_NAME(NV_CTRL_FLATPANEL_SCALING),
+ G_CALLBACK(dfp_update_received),
+ (gpointer) ctk_display_device_dfp);
/* FlatPanel Dithering */
- ret = NvCtrlGetDisplayAttribute(handle, display_device_mask,
- NV_CTRL_FLATPANEL_DITHERING, &val);
-
- if (ret == NvCtrlSuccess) {
- frame = gtk_frame_new("FlatPanel Dithering");
- eventbox = gtk_event_box_new();
- gtk_container_add(GTK_CONTAINER(eventbox), frame);
- gtk_box_pack_start(GTK_BOX(hbox), eventbox, TRUE, TRUE, 0);
+ frame = gtk_frame_new("FlatPanel Dithering");
+ eventbox = gtk_event_box_new();
+ gtk_container_add(GTK_CONTAINER(eventbox), frame);
+ gtk_box_pack_start(GTK_BOX(hbox), eventbox, TRUE, TRUE, 0);
+ ctk_display_device_dfp->dithering_frame = frame;
- ctk_config_set_tooltip(ctk_config, eventbox, __dithering_help);
-
- vbox = gtk_vbox_new(FALSE, FRAME_PADDING);
- gtk_container_set_border_width(GTK_CONTAINER(vbox), FRAME_PADDING);
- gtk_container_add(GTK_CONTAINER(frame), vbox);
+ ctk_config_set_tooltip(ctk_config, eventbox, __dithering_help);
+ vbox = gtk_vbox_new(FALSE, FRAME_PADDING);
+ gtk_container_set_border_width(GTK_CONTAINER(vbox), FRAME_PADDING);
+ gtk_container_add(GTK_CONTAINER(frame), vbox);
- radio0 = make_dithering_radio_button
- (ctk_display_device_dfp, vbox, NULL, "Default",
- NV_CTRL_FLATPANEL_DITHERING_DEFAULT);
-
- radio1 = make_dithering_radio_button
- (ctk_display_device_dfp, vbox, radio0, "Enabled",
- NV_CTRL_FLATPANEL_DITHERING_ENABLED);
-
- radio2 = make_dithering_radio_button
- (ctk_display_device_dfp, vbox, radio1, "Disabled",
- NV_CTRL_FLATPANEL_DITHERING_DISABLED);
-
- dfp_dithering_update_radio_buttons(ctk_display_device_dfp, val);
-
- g_signal_connect(G_OBJECT(ctk_event),
- CTK_EVENT_NAME(NV_CTRL_FLATPANEL_DITHERING),
- G_CALLBACK(dfp_update_received),
- (gpointer) ctk_display_device_dfp);
-
- ctk_display_device_dfp->active_attributes |= __DITHERING;
-
- } else {
-
- for (i = 0; i < NV_CTRL_FLATPANEL_DITHERING_DISABLED+1; i++) {
- ctk_display_device_dfp->dithering_buttons[i] = NULL;
- }
-
- ctk_display_device_dfp->active_attributes &= ~__DITHERING;
- }
+ radio0 = make_dithering_radio_button
+ (ctk_display_device_dfp, vbox, NULL, "Default",
+ NV_CTRL_FLATPANEL_DITHERING_DEFAULT);
+
+ radio1 = make_dithering_radio_button
+ (ctk_display_device_dfp, vbox, radio0, "Enabled",
+ NV_CTRL_FLATPANEL_DITHERING_ENABLED);
+
+ radio2 = make_dithering_radio_button
+ (ctk_display_device_dfp, vbox, radio1, "Disabled",
+ NV_CTRL_FLATPANEL_DITHERING_DISABLED);
+
+ g_signal_connect(G_OBJECT(ctk_event),
+ CTK_EVENT_NAME(NV_CTRL_FLATPANEL_DITHERING),
+ G_CALLBACK(dfp_update_received),
+ (gpointer) ctk_display_device_dfp);
/* pack the image sliders */
@@ -385,20 +343,25 @@ GtkWidget* ctk_display_device_dfp_new(NvCtrlAttributeHandle *handle,
/* pack the EDID button */
- edid = ctk_edid_new(handle, ctk_config, ctk_event,
- ctk_display_device_dfp->reset_button,
- display_device_mask, name);
- if (edid) {
- gtk_box_pack_start(GTK_BOX(object), edid, FALSE, FALSE, 0);
- ctk_display_device_dfp->edid_available = TRUE;
- } else {
- ctk_display_device_dfp->edid_available = FALSE;
- }
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, 0);
+ ctk_display_device_dfp->edid_box = hbox;
/* show the page */
gtk_widget_show_all(GTK_WIDGET(object));
+ /* Update the GUI */
+
+ ctk_display_device_dfp_setup(ctk_display_device_dfp);
+
+ /* handle enable/disable events on the display device */
+
+ g_signal_connect(G_OBJECT(ctk_event),
+ CTK_EVENT_NAME(NV_CTRL_ENABLED_DISPLAYS),
+ G_CALLBACK(enabled_displays_received),
+ (gpointer) ctk_display_device_dfp);
+
return GTK_WIDGET(object);
} /* ctk_display_device_dfp_new() */
@@ -613,10 +576,8 @@ static void reset_button_clicked(GtkButton *button, gpointer user_data)
gint value;
- if (ctk_display_device_dfp->image_sliders) {
- ctk_image_sliders_reset
- (CTK_IMAGE_SLIDERS(ctk_display_device_dfp->image_sliders));
- }
+ ctk_image_sliders_reset
+ (CTK_IMAGE_SLIDERS(ctk_display_device_dfp->image_sliders));
/*
* if scaling is active, send the default scaling value to the
@@ -650,6 +611,10 @@ static void reset_button_clicked(GtkButton *button, gpointer user_data)
dfp_dithering_update_radio_buttons(ctk_display_device_dfp, value);
}
+ /* Update the reset button */
+
+ gtk_widget_set_sensitive(ctk_display_device_dfp->reset_button, FALSE);
+
/* status bar message */
ctk_config_statusbar_message(ctk_display_device_dfp->ctk_config,
@@ -758,7 +723,7 @@ dfp_dithering_update_radio_buttons(CtkDisplayDeviceDfp *ctk_display_device_dfp,
/*
- * dfp_dithering_update_received() - callback function for changed DFP
+ * dfp_update_received() - callback function for changed DFP
* settings; this is called when we receive an event indicating that
* another NV-CONTROL client changed any of the settings that we care
* about.
@@ -794,7 +759,7 @@ static void dfp_update_received(GtkObject *object, gpointer arg1,
break;
}
-} /* dfp_dithering_update_received() */
+} /* dfp_update_received() */
@@ -809,7 +774,6 @@ GtkTextBuffer *ctk_display_device_dfp_create_help(GtkTextTagTable *table,
{
GtkTextIter i;
GtkTextBuffer *b;
- gboolean ret = FALSE;
b = gtk_text_buffer_new(table);
@@ -817,82 +781,275 @@ GtkTextBuffer *ctk_display_device_dfp_create_help(GtkTextTagTable *table,
ctk_help_title(b, &i, "%s Help", ctk_display_device_dfp->name);
- if (ctk_display_device_dfp->active_attributes & __INFO) {
- ctk_help_heading(b, &i, "FlatPanel Information");
- ctk_help_para(b, &i, __info_help);
+ ctk_help_heading(b, &i, "FlatPanel Information");
+ ctk_help_para(b, &i, __info_help);
- ctk_help_term(b, &i, "Chip Location");
- ctk_help_para(b, &i, "Report whether the flatpanel is driven by "
- "the on-chip controller (internal), or a "
- " separate controller chip elsewhere on the "
- "graphics board (external)");
+ ctk_help_term(b, &i, "Chip Location");
+ ctk_help_para(b, &i, "Report whether the flatpanel is driven by "
+ "the on-chip controller (internal), or a "
+ " separate controller chip elsewhere on the "
+ "graphics board (external)");
- ctk_help_term(b, &i, "Link");
- ctk_help_para(b, &i, "Report whether the specified display device "
- "is driven by a single link or dual link DVI "
- "connection.");
-
- ctk_help_term(b, &i, "Signal");
- ctk_help_para(b, &i, "Report whether the flatpanel is driven by "
- "an LVDS or TMDS signal");
-
- ret = TRUE;
- }
+ ctk_help_term(b, &i, "Link");
+ ctk_help_para(b, &i, "Report whether the specified display device "
+ "is driven by a single link or dual link DVI "
+ "connection.");
- if (ctk_display_device_dfp->active_attributes & __SCALING) {
- ctk_help_heading(b, &i, "FlatPanel Scaling");
- ctk_help_para(b, &i, __scaling_help);
-
- ctk_help_term(b, &i, "Default");
- ctk_help_para(b, &i, "The driver will choose what scaling state is "
- "best.");
-
- ctk_help_term(b, &i, "Scaled");
- ctk_help_para(b, &i, "The image will be expanded to fit the entire "
- "FlatPanel.");
-
- ctk_help_term(b, &i, "Centered");
- ctk_help_para(b, &i, "The image will only occupy the number of pixels "
- "needed and be centered on the FlatPanel.");
-
- ctk_help_term(b, &i, "Fixed Aspect Ratio Scaled");
- ctk_help_para(b, &i, "The image will be expanded (like when Scaled), "
- "but the image will retain the original aspect ratio.");
- ret = TRUE;
- }
+ ctk_help_term(b, &i, "Signal");
+ ctk_help_para(b, &i, "Report whether the flatpanel is driven by "
+ "an LVDS or TMDS signal");
- if (ctk_display_device_dfp->active_attributes & __DITHERING) {
- ctk_help_heading(b, &i, "FlatPanel Dithering");
- ctk_help_para(b, &i, __dithering_help);
-
- ctk_help_term(b, &i, "Default");
- ctk_help_para(b, &i, "The driver will choose when to dither.");
-
- ctk_help_term(b, &i, "Enabled");
- ctk_help_para(b, &i, "Force dithering on.");
-
- ctk_help_term(b, &i, "Disabled");
- ctk_help_para(b, &i, "Force dithering off.");
-
- ret = TRUE;
- }
+ ctk_help_heading(b, &i, "FlatPanel Scaling");
+ ctk_help_para(b, &i, __scaling_help);
+
+ ctk_help_term(b, &i, "Default");
+ ctk_help_para(b, &i, "The driver will choose what scaling state is "
+ "best.");
+
+ ctk_help_term(b, &i, "Scaled");
+ ctk_help_para(b, &i, "The image will be expanded to fit the entire "
+ "FlatPanel.");
+
+ ctk_help_term(b, &i, "Centered");
+ ctk_help_para(b, &i, "The image will only occupy the number of pixels "
+ "needed and be centered on the FlatPanel.");
+
+ ctk_help_term(b, &i, "Fixed Aspect Ratio Scaled");
+ ctk_help_para(b, &i, "The image will be expanded (like when Scaled), "
+ "but the image will retain the original aspect ratio.");
+
+ ctk_help_heading(b, &i, "FlatPanel Dithering");
+ ctk_help_para(b, &i, __dithering_help);
+
+ ctk_help_term(b, &i, "Default");
+ ctk_help_para(b, &i, "The driver will choose when to dither.");
+
+ ctk_help_term(b, &i, "Enabled");
+ ctk_help_para(b, &i, "Force dithering on.");
+
+ ctk_help_term(b, &i, "Disabled");
+ ctk_help_para(b, &i, "Force dithering off.");
- if (ctk_display_device_dfp->image_sliders) {
- ret |= add_image_sliders_help
- (CTK_IMAGE_SLIDERS(ctk_display_device_dfp->image_sliders), b, &i);
- }
+ add_image_sliders_help
+ (CTK_IMAGE_SLIDERS(ctk_display_device_dfp->image_sliders), b, &i);
- if (ctk_display_device_dfp->edid_available) {
+ if (ctk_display_device_dfp->edid) {
add_acquire_edid_help(b, &i);
}
- if (!ret) {
- ctk_help_para(b, &i, "There are no configurable options available "
- "for %s.", ctk_display_device_dfp->name);
- }
-
ctk_help_finish(b);
return b;
} /* ctk_display_device_dfp_create_help() */
+
+
+
+/*
+ * dfp_info_setup() -
+ *
+ *
+ */
+static void dfp_info_setup(CtkDisplayDeviceDfp *ctk_display_device_dfp)
+{
+ ReturnStatus ret;
+ gint val;
+ char *chip_location, *link, *signal;
+
+ chip_location = link = signal = "Unknown";
+
+ /* Chip location */
+
+ ret =
+ NvCtrlGetDisplayAttribute(ctk_display_device_dfp->handle,
+ ctk_display_device_dfp->display_device_mask,
+ NV_CTRL_FLATPANEL_CHIP_LOCATION, &val);
+ if (ret == NvCtrlSuccess) {
+ if (val == NV_CTRL_FLATPANEL_CHIP_LOCATION_INTERNAL)
+ chip_location = "Internal";
+ if (val == NV_CTRL_FLATPANEL_CHIP_LOCATION_EXTERNAL)
+ chip_location = "External";
+ }
+ gtk_label_set_text
+ (GTK_LABEL(ctk_display_device_dfp->txt_chip_location), chip_location);
+
+ /* Link */
+
+ ret =
+ NvCtrlGetDisplayAttribute(ctk_display_device_dfp->handle,
+ ctk_display_device_dfp->display_device_mask,
+ NV_CTRL_FLATPANEL_LINK, &val);
+ if (ret == NvCtrlSuccess) {
+ if (val == NV_CTRL_FLATPANEL_LINK_SINGLE) link = "Single";
+ if (val == NV_CTRL_FLATPANEL_LINK_DUAL) link = "Dual";
+ }
+ gtk_label_set_text
+ (GTK_LABEL(ctk_display_device_dfp->txt_link), link);
+
+ /* Signal */
+
+ ret =
+ NvCtrlGetDisplayAttribute(ctk_display_device_dfp->handle,
+ ctk_display_device_dfp->display_device_mask,
+ NV_CTRL_FLATPANEL_SIGNAL, &val);
+ if (ret == NvCtrlSuccess) {
+ if (val == NV_CTRL_FLATPANEL_SIGNAL_LVDS) signal = "LVDS";
+ if (val == NV_CTRL_FLATPANEL_SIGNAL_TMDS) signal = "TMDS";
+ }
+ gtk_label_set_text
+ (GTK_LABEL(ctk_display_device_dfp->txt_signal), signal);
+
+} /* dfp_info_setup() */
+
+
+
+/*
+ * dfp_scaling_setup() - Update GUI to reflect X server settings of
+ * DFP Scaling.
+ */
+static void dfp_scaling_setup(CtkDisplayDeviceDfp *ctk_display_device_dfp)
+{
+ ReturnStatus ret;
+ int val;
+
+ ret =
+ NvCtrlGetDisplayAttribute(ctk_display_device_dfp->handle,
+ ctk_display_device_dfp->display_device_mask,
+ NV_CTRL_FLATPANEL_SCALING, &val);
+ if (ret != NvCtrlSuccess) {
+ gtk_widget_set_sensitive(ctk_display_device_dfp->scaling_frame, FALSE);
+ gtk_widget_hide(ctk_display_device_dfp->scaling_frame);
+ ctk_display_device_dfp->active_attributes &= ~__SCALING;
+ return;
+ }
+
+ gtk_widget_show(ctk_display_device_dfp->scaling_frame);
+ ctk_display_device_dfp->active_attributes |= __SCALING;
+
+ gtk_widget_set_sensitive(ctk_display_device_dfp->scaling_frame, TRUE);
+
+ dfp_scaling_update_radio_buttons(ctk_display_device_dfp, val);
+
+} /* dfp_scaling_setup() */
+
+
+
+/*
+ * dfp_dithering_setup() - Update GUI to reflect X server settings
+ * of DFP Dithering.
+ */
+static void dfp_dithering_setup(CtkDisplayDeviceDfp *ctk_display_device_dfp)
+{
+ ReturnStatus ret;
+ int val;
+
+ ret =
+ NvCtrlGetDisplayAttribute(ctk_display_device_dfp->handle,
+ ctk_display_device_dfp->display_device_mask,
+ NV_CTRL_FLATPANEL_DITHERING, &val);
+ if (ret != NvCtrlSuccess) {
+ gtk_widget_set_sensitive(ctk_display_device_dfp->dithering_frame,
+ FALSE);
+ gtk_widget_hide(ctk_display_device_dfp->dithering_frame);
+ ctk_display_device_dfp->active_attributes &= ~__DITHERING;
+ return;
+ }
+
+ gtk_widget_show(ctk_display_device_dfp->dithering_frame);
+ ctk_display_device_dfp->active_attributes |= __DITHERING;
+
+ gtk_widget_set_sensitive(ctk_display_device_dfp->dithering_frame, TRUE);
+
+ dfp_dithering_update_radio_buttons(ctk_display_device_dfp, val);
+
+} /* dfp_dithering_setup() */
+
+
+
+/*
+ * Updates the display device page to reflect the current
+ * configuration of the display device.
+ */
+static void ctk_display_device_dfp_setup(CtkDisplayDeviceDfp
+ *ctk_display_device_dfp)
+{
+ ReturnStatus ret;
+ unsigned int enabled_displays;
+
+
+ /* Is display enabled? */
+
+ ret = NvCtrlGetAttribute(ctk_display_device_dfp->handle,
+ NV_CTRL_ENABLED_DISPLAYS,
+ (int *)&enabled_displays);
+
+ ctk_display_device_dfp->display_enabled =
+ (ret == NvCtrlSuccess &&
+ (enabled_displays & (ctk_display_device_dfp->display_device_mask)));
+
+
+ /* Update DFP-specific settings */
+
+ dfp_info_setup(ctk_display_device_dfp);
+
+ dfp_scaling_setup(ctk_display_device_dfp);
+
+ dfp_dithering_setup(ctk_display_device_dfp);
+
+
+ /* Update the image sliders */
+
+ ctk_image_sliders_setup
+ (CTK_IMAGE_SLIDERS(ctk_display_device_dfp->image_sliders));
+
+
+ /* update acquire EDID button */
+
+ if (ctk_display_device_dfp->edid) {
+ GList *list;
+
+ list = gtk_container_get_children
+ (GTK_CONTAINER(ctk_display_device_dfp->edid_box));
+ if (list) {
+ gtk_container_remove
+ (GTK_CONTAINER(ctk_display_device_dfp->edid_box),
+ (GtkWidget *)(list->data));
+ g_list_free(list);
+ }
+ }
+
+ ctk_display_device_dfp->edid =
+ ctk_edid_new(ctk_display_device_dfp->handle,
+ ctk_display_device_dfp->ctk_config,
+ ctk_display_device_dfp->ctk_event,
+ ctk_display_device_dfp->reset_button,
+ ctk_display_device_dfp->display_device_mask,
+ ctk_display_device_dfp->name);
+
+ if (ctk_display_device_dfp->edid) {
+ gtk_box_pack_start(GTK_BOX(ctk_display_device_dfp->edid_box),
+ ctk_display_device_dfp->edid, TRUE, TRUE, 0);
+ }
+
+
+ /* update the reset button */
+
+ gtk_widget_set_sensitive(ctk_display_device_dfp->reset_button, FALSE);
+
+} /* ctk_display_device_dfp_setup() */
+
+
+
+/*
+ * When the list of enabled displays on the GPU changes,
+ * this page should disable/enable access based on whether
+ * or not the display device is enabled.
+ */
+static void enabled_displays_received(GtkObject *object, gpointer arg1,
+ gpointer user_data)
+{
+ CtkDisplayDeviceDfp *ctk_object = CTK_DISPLAY_DEVICE_DFP(user_data);
+
+ ctk_display_device_dfp_setup(ctk_object);
+
+} /* enabled_displays_received() */
diff --git a/src/gtk+-2.x/ctkdisplaydevice-dfp.h b/src/gtk+-2.x/ctkdisplaydevice-dfp.h
index b8c432a..ae1c578 100644
--- a/src/gtk+-2.x/ctkdisplaydevice-dfp.h
+++ b/src/gtk+-2.x/ctkdisplaydevice-dfp.h
@@ -60,15 +60,25 @@ struct _CtkDisplayDeviceDfp
NvCtrlAttributeHandle *handle;
CtkConfig *ctk_config;
+ CtkEvent *ctk_event;
GtkWidget *image_sliders;
GtkWidget *reset_button;
+ GtkWidget *edid_box;
+ GtkWidget *edid;
+ GtkWidget *txt_chip_location;
+ GtkWidget *txt_link;
+ GtkWidget *txt_signal;
+
+ GtkWidget *scaling_frame;
GtkWidget *scaling_buttons[NV_CTRL_FLATPANEL_SCALING_ASPECT_SCALED+1];
+
+ GtkWidget *dithering_frame;
GtkWidget *dithering_buttons[NV_CTRL_FLATPANEL_DITHERING_DISABLED+1];
unsigned int display_device_mask;
+ gboolean display_enabled;
unsigned int active_attributes;
- gboolean edid_available;
char *name;
};
diff --git a/src/gtk+-2.x/ctkdisplaydevice-tv.c b/src/gtk+-2.x/ctkdisplaydevice-tv.c
index e0b13f6..13c1110 100644
--- a/src/gtk+-2.x/ctkdisplaydevice-tv.c
+++ b/src/gtk+-2.x/ctkdisplaydevice-tv.c
@@ -24,15 +24,6 @@
/*
* The TV DisplayDevice widget provides a way to adjust TV settings.
- *
- * TODO:
- *
- * - make the reset button sensitive only when there is a value to
- * change
- *
- * - tooltips
- *
- * - online help
*/
#include <gtk/gtk.h>
@@ -73,30 +64,25 @@ static const char* __tv_saturation_help = "The TV Brightness slider adjusts "
/* local prototypes */
-static void add_adjustment(CtkDisplayDeviceTv *ctk_display_device_tv,
- int attribute, unsigned int attribute_bitmask,
- char *name, const char *help,
- GtkObject **adjustment);
+static void ctk_display_device_tv_class_init(CtkDisplayDeviceTvClass *);
+static void ctk_display_device_tv_finalize(GObject *);
+
+static GtkWidget * add_scale(CtkDisplayDeviceTv *ctk_display_device_tv,
+ int attribute, char *name, const char *help);
static void adjustment_value_changed(GtkAdjustment *adjustment,
gpointer user_data);
static void reset_defaults(GtkButton *button, gpointer user_data);
-static void value_changed(GtkObject *object, gpointer arg1,
- gpointer user_data);
+static void value_received(GtkObject *object, gpointer arg1,
+ gpointer user_data);
-/*
- * constants indicating which attributes are available (so that we
- * know which attributes to document) in the online Help
- */
+static void ctk_display_device_tv_setup(CtkDisplayDeviceTv
+ *ctk_display_device_tv);
-#define __OVERSCAN (1 << 0)
-#define __FLICKER_FILTER (1 << 1)
-#define __BRIGHTNESS (1 << 2)
-#define __HUE (1 << 3)
-#define __CONTRAST (1 << 4)
-#define __SATURATION (1 << 5)
+static void enabled_displays_received(GtkObject *object, gpointer arg1,
+ gpointer user_data);
GType ctk_display_device_tv_get_type(void)
@@ -108,7 +94,7 @@ GType ctk_display_device_tv_get_type(void)
sizeof (CtkDisplayDeviceTvClass),
NULL, /* base_init */
NULL, /* base_finalize */
- NULL, /* class_init, */
+ (GClassInitFunc) ctk_display_device_tv_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (CtkDisplayDeviceTv),
@@ -123,11 +109,26 @@ GType ctk_display_device_tv_get_type(void)
return ctk_display_device_tv_type;
}
+static void ctk_display_device_tv_class_init(
+ CtkDisplayDeviceTvClass *ctk_display_device_tv_class
+)
+{
+ GObjectClass *gobject_class = (GObjectClass *)ctk_display_device_tv_class;
+ gobject_class->finalize = ctk_display_device_tv_finalize;
+}
+
+static void ctk_display_device_tv_finalize(
+ GObject *object
+)
+{
+ CtkDisplayDeviceTv *ctk_display_device_tv = CTK_DISPLAY_DEVICE_TV(object);
+ g_free(ctk_display_device_tv->name);
+}
/*
- * ctk_display_device_tv_new() - constructor for the CtkDisplayDeviceTv
- * widget
+ * ctk_display_device_tv_new() - constructor for the TV display
+ * device page.
*/
GtkWidget* ctk_display_device_tv_new(NvCtrlAttributeHandle *handle,
@@ -143,19 +144,16 @@ GtkWidget* ctk_display_device_tv_new(NvCtrlAttributeHandle *handle,
GtkWidget *hbox;
GtkWidget *label;
GtkWidget *alignment;
- GtkWidget *edid;
-
- char *str;
- ReturnStatus ret;
+
object = g_object_new(CTK_TYPE_DISPLAY_DEVICE_TV, NULL);
ctk_display_device_tv = CTK_DISPLAY_DEVICE_TV(object);
ctk_display_device_tv->handle = handle;
ctk_display_device_tv->ctk_config = ctk_config;
+ ctk_display_device_tv->ctk_event = ctk_event;
ctk_display_device_tv->display_device_mask = display_device_mask;
- ctk_display_device_tv->name = name;
- ctk_display_device_tv->active_attributes = 0;
+ ctk_display_device_tv->name = g_strdup(name);
gtk_box_set_spacing(GTK_BOX(object), 10);
@@ -164,98 +162,100 @@ GtkWidget* ctk_display_device_tv_new(NvCtrlAttributeHandle *handle,
banner = ctk_banner_image_new(&tv_banner_image);
gtk_box_pack_start(GTK_BOX(object), banner, FALSE, FALSE, 0);
+ /* Information */
- /* NV_CTRL_STRING_TV_ENCODER_NAME */
+ frame = gtk_frame_new(NULL);
+ gtk_box_pack_start(GTK_BOX(object), frame, FALSE, FALSE, 0);
+ ctk_display_device_tv->info_frame = frame;
- ret = NvCtrlGetStringDisplayAttribute(handle, display_device_mask,
- NV_CTRL_STRING_TV_ENCODER_NAME,
- &str);
- if (ret == NvCtrlSuccess) {
- frame = gtk_frame_new(NULL);
- gtk_box_pack_start(GTK_BOX(object), frame, FALSE, FALSE, 0);
-
- hbox = gtk_hbox_new(FALSE, FRAME_PADDING);
- gtk_container_set_border_width(GTK_CONTAINER(hbox), FRAME_PADDING);
- gtk_container_add(GTK_CONTAINER(frame), hbox);
-
- label = gtk_label_new("TV Encoder: ");
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
-
- label = gtk_label_new(str);
- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
- }
+ hbox = gtk_hbox_new(FALSE, FRAME_PADDING);
+ gtk_container_set_border_width(GTK_CONTAINER(hbox), FRAME_PADDING);
+ gtk_container_add(GTK_CONTAINER(frame), hbox);
+
+ label = gtk_label_new("TV Encoder: ");
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ label = gtk_label_new("");
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+ ctk_display_device_tv->txt_encoder_name = label;
+
+
/* NV_CTRL_TV_OVERSCAN */
- add_adjustment(ctk_display_device_tv, NV_CTRL_TV_OVERSCAN,
- __OVERSCAN, "TV OverScan", __tv_overscan_help,
- &ctk_display_device_tv->overscan);
+ ctk_display_device_tv->overscan =
+ add_scale(ctk_display_device_tv, NV_CTRL_TV_OVERSCAN,
+ "TV OverScan", __tv_overscan_help);
g_signal_connect(G_OBJECT(ctk_event),
CTK_EVENT_NAME(NV_CTRL_TV_OVERSCAN),
- G_CALLBACK(value_changed),
+ G_CALLBACK(value_received),
(gpointer) ctk_display_device_tv);
/* NV_CTRL_TV_FLICKER_FILTER */
- add_adjustment(ctk_display_device_tv, NV_CTRL_TV_FLICKER_FILTER,
- __FLICKER_FILTER, "TV Flicker Filter",
- __tv_flicker_filter_help,
- &ctk_display_device_tv->flicker_filter);
+ ctk_display_device_tv->flicker_filter =
+ add_scale(ctk_display_device_tv, NV_CTRL_TV_FLICKER_FILTER,
+ "TV Flicker Filter", __tv_flicker_filter_help);
g_signal_connect(G_OBJECT(ctk_event),
CTK_EVENT_NAME(NV_CTRL_TV_FLICKER_FILTER),
- G_CALLBACK(value_changed),
+ G_CALLBACK(value_received),
(gpointer) ctk_display_device_tv);
/* NV_CTRL_TV_BRIGHTNESS */
-
- add_adjustment(ctk_display_device_tv, NV_CTRL_TV_BRIGHTNESS,
- __BRIGHTNESS, "TV Brightness", __tv_brightness_help,
- &ctk_display_device_tv->brightness);
+
+ ctk_display_device_tv->brightness =
+ add_scale(ctk_display_device_tv, NV_CTRL_TV_BRIGHTNESS,
+ "TV Brightness", __tv_brightness_help);
g_signal_connect(G_OBJECT(ctk_event),
CTK_EVENT_NAME(NV_CTRL_TV_BRIGHTNESS),
- G_CALLBACK(value_changed),
+ G_CALLBACK(value_received),
(gpointer) ctk_display_device_tv);
/* NV_CTRL_TV_HUE */
- add_adjustment(ctk_display_device_tv, NV_CTRL_TV_HUE,
- __HUE, "TV Hue", __tv_hue_help,
- &ctk_display_device_tv->hue);
+ ctk_display_device_tv->hue =
+ add_scale(ctk_display_device_tv, NV_CTRL_TV_HUE,
+ "TV Hue", __tv_hue_help);
g_signal_connect(G_OBJECT(ctk_event),
CTK_EVENT_NAME(NV_CTRL_TV_HUE),
- G_CALLBACK(value_changed),
+ G_CALLBACK(value_received),
(gpointer) ctk_display_device_tv);
/* NV_CTRL_TV_CONTRAST */
- add_adjustment(ctk_display_device_tv, NV_CTRL_TV_CONTRAST,
- __CONTRAST, "TV Contrast", __tv_contrast_help,
- &ctk_display_device_tv->contrast);
+ ctk_display_device_tv->contrast =
+ add_scale(ctk_display_device_tv, NV_CTRL_TV_CONTRAST,
+ "TV Contrast", __tv_contrast_help);
g_signal_connect(G_OBJECT(ctk_event),
CTK_EVENT_NAME(NV_CTRL_TV_CONTRAST),
- G_CALLBACK(value_changed),
+ G_CALLBACK(value_received),
(gpointer) ctk_display_device_tv);
/* NV_CTRL_TV_SATURATION */
- add_adjustment(ctk_display_device_tv, NV_CTRL_TV_SATURATION,
- __SATURATION, "TV Saturation", __tv_saturation_help,
- &ctk_display_device_tv->saturation);
+ ctk_display_device_tv->saturation =
+ add_scale(ctk_display_device_tv, NV_CTRL_TV_SATURATION,
+ "TV Saturation", __tv_saturation_help);
g_signal_connect(G_OBJECT(ctk_event),
CTK_EVENT_NAME(NV_CTRL_TV_SATURATION),
- G_CALLBACK(value_changed),
+ G_CALLBACK(value_received),
(gpointer) ctk_display_device_tv);
- /* pack the image sliders */
+ /* Create the reset button here so it can be used by the image sliders */
+
+ ctk_display_device_tv->reset_button =
+ gtk_button_new_with_label("Reset TV Hardware Defaults");
+
+ /* create and pack the image sliders */
ctk_display_device_tv->image_sliders =
- ctk_image_sliders_new(handle, ctk_config, ctk_event, NULL,
+ ctk_image_sliders_new(handle, ctk_config, ctk_event,
+ ctk_display_device_tv->reset_button,
display_device_mask, name);
if (ctk_display_device_tv->image_sliders) {
gtk_box_pack_start(GTK_BOX(object),
@@ -264,10 +264,7 @@ GtkWidget* ctk_display_device_tv_new(NvCtrlAttributeHandle *handle,
}
/* reset button */
-
- ctk_display_device_tv->reset_button =
- gtk_button_new_with_label("Reset TV Hardware Defaults");
-
+
g_signal_connect(G_OBJECT(ctk_display_device_tv->reset_button), "clicked",
G_CALLBACK(reset_defaults),
(gpointer) ctk_display_device_tv);
@@ -275,33 +272,38 @@ GtkWidget* ctk_display_device_tv_new(NvCtrlAttributeHandle *handle,
alignment = gtk_alignment_new(1, 1, 0, 0);
gtk_container_add(GTK_CONTAINER(alignment),
ctk_display_device_tv->reset_button);
- gtk_box_pack_start(GTK_BOX(object), alignment, TRUE, TRUE, 0);
+ gtk_box_pack_end(GTK_BOX(object), alignment, TRUE, TRUE, 0);
g_signal_connect(G_OBJECT(ctk_event),
CTK_EVENT_NAME(NV_CTRL_TV_RESET_SETTINGS),
- G_CALLBACK(value_changed),
+ G_CALLBACK(value_received),
(gpointer) ctk_display_device_tv);
ctk_config_set_tooltip(ctk_config, ctk_display_device_tv->reset_button,
"The Reset TV Hardware Defaults button restores "
"the TV settings to their default values.");
- /* pack the EDID button */
+ /* EDID button box */
+
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, 0);
+ ctk_display_device_tv->edid_box = hbox;
- edid = ctk_edid_new(handle, ctk_config, ctk_event,
- ctk_display_device_tv->reset_button,
- display_device_mask, name);
- if (edid) {
- gtk_box_pack_start(GTK_BOX(object), edid, FALSE, FALSE, 0);
- ctk_display_device_tv->edid_available = TRUE;
- } else {
- ctk_display_device_tv->edid_available = FALSE;
- }
-
/* finally, display the widget */
gtk_widget_show_all(GTK_WIDGET(object));
+ /* update the GUI */
+
+ ctk_display_device_tv_setup(ctk_display_device_tv);
+
+ /* handle enable/disable events on the display device */
+
+ g_signal_connect(G_OBJECT(ctk_event),
+ CTK_EVENT_NAME(NV_CTRL_ENABLED_DISPLAYS),
+ G_CALLBACK(enabled_displays_received),
+ (gpointer) ctk_display_device_tv);
+
return GTK_WIDGET(object);
} /* ctk_display_device_tv_new() */
@@ -309,68 +311,62 @@ GtkWidget* ctk_display_device_tv_new(NvCtrlAttributeHandle *handle,
/*
- * add_adjustment() - if the specified attribute exists and we can
- * query its valid values, create a new adjustment widget and pack it
+ * Returns whether or not the scale is active
+ */
+
+static gint get_scale_active(CtkScale *scale)
+{
+ GtkAdjustment *adj = scale->gtk_adjustment;
+
+ return
+ GPOINTER_TO_INT(g_object_get_data(G_OBJECT(adj), "attribute active"));
+
+} /* get_scale_active() */
+
+
+
+/*
+ * add_scale() - if the specified attribute exists and we can
+ * query its valid values, create a new scale widget and pack it
* in the ctk_display_device_tv
*/
-static void add_adjustment(CtkDisplayDeviceTv *ctk_display_device_tv,
- int attribute, unsigned int attribute_bitmask,
- char *name, const char *help,
- GtkObject **adjustment)
+static GtkWidget * add_scale(CtkDisplayDeviceTv *ctk_display_device_tv,
+ int attribute, char *name, const char *help)
{
- ReturnStatus ret0, ret1;
- NVCTRLAttributeValidValuesRec valid;
GtkObject *adj;
- NvCtrlAttributeHandle *handle = ctk_display_device_tv->handle;
- unsigned int mask = ctk_display_device_tv->display_device_mask;
- int val;
GtkWidget *scale;
-
- ret0 = NvCtrlGetValidDisplayAttributeValues(handle, mask,
- attribute, &valid);
-
- ret1 = NvCtrlGetDisplayAttribute(handle, mask, attribute, &val);
-
- if ((ret0 == NvCtrlSuccess) && (ret1 == NvCtrlSuccess) &&
- (valid.type == ATTRIBUTE_TYPE_RANGE)) {
-
- adj = gtk_adjustment_new(val, valid.u.range.min,
- valid.u.range.max, 1, 1, 0);
-
- gtk_adjustment_set_value(GTK_ADJUSTMENT(adj), val);
+
+
+ adj = gtk_adjustment_new(0, 0, 10, 1, 1, 0);
- g_object_set_data(G_OBJECT(adj), "attribute",
- GINT_TO_POINTER(attribute));
+ g_object_set_data(G_OBJECT(adj), "attribute",
+ GINT_TO_POINTER(attribute));
- g_object_set_data(G_OBJECT(adj), "attribute name", name);
+ g_object_set_data(G_OBJECT(adj), "attribute name", name);
- g_signal_connect(G_OBJECT(adj), "value_changed",
- G_CALLBACK(adjustment_value_changed),
- (gpointer) ctk_display_device_tv);
-
- scale = ctk_scale_new(GTK_ADJUSTMENT(adj), name,
- ctk_display_device_tv->ctk_config,
- G_TYPE_INT);
-
- if (help) {
- ctk_config_set_tooltip(ctk_display_device_tv->ctk_config,
- CTK_SCALE_TOOLTIP_WIDGET(scale), help);
- }
+ g_object_set_data(G_OBJECT(adj), "attribute active",
+ GINT_TO_POINTER(0));
- gtk_box_pack_start(GTK_BOX(ctk_display_device_tv), scale,
- FALSE, FALSE, 0);
-
- *adjustment = adj;
-
- ctk_display_device_tv->active_attributes |= attribute_bitmask;
+ g_signal_connect(G_OBJECT(adj), "value_changed",
+ G_CALLBACK(adjustment_value_changed),
+ (gpointer) ctk_display_device_tv);
- } else {
- *adjustment = NULL;
+ scale = ctk_scale_new(GTK_ADJUSTMENT(adj), name,
+ ctk_display_device_tv->ctk_config,
+ G_TYPE_INT);
- ctk_display_device_tv->active_attributes &= ~attribute_bitmask;
+ if (help) {
+ ctk_config_set_tooltip(ctk_display_device_tv->ctk_config,
+ CTK_SCALE_TOOLTIP_WIDGET(scale), help);
}
-} /* add_adjustment() */
+
+ gtk_box_pack_start(GTK_BOX(ctk_display_device_tv), scale,
+ FALSE, FALSE, 0);
+
+ return scale;
+
+} /* add_scale() */
@@ -388,6 +384,8 @@ static void post_adjustment_value_changed(GtkAdjustment *adjustment,
{
char *name = g_object_get_data(G_OBJECT(adjustment), "attribute name");
+ gtk_widget_set_sensitive(ctk_display_device_tv->reset_button, TRUE);
+
ctk_config_statusbar_message(ctk_display_device_tv->ctk_config,
"%s set to %d.", name, value);
@@ -433,17 +431,20 @@ static void adjustment_value_changed(GtkAdjustment *adjustment,
*/
static void reset_slider(CtkDisplayDeviceTv *ctk_display_device_tv,
- GtkObject *adj)
+ GtkWidget *scale)
{
+ GtkAdjustment *adj;
gint attribute;
- gpointer user_data;
ReturnStatus ret;
gint val;
+ adj = CTK_SCALE(scale)->gtk_adjustment;
+
if (!adj) return;
- user_data = g_object_get_data(G_OBJECT(adj), "attribute");
- attribute = GPOINTER_TO_INT(user_data);
+ if (!get_scale_active(CTK_SCALE(scale))) return;
+
+ attribute = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(adj), "attribute"));
ret = NvCtrlGetDisplayAttribute(ctk_display_device_tv->handle,
ctk_display_device_tv->display_device_mask,
@@ -478,7 +479,9 @@ static void reset_sliders(CtkDisplayDeviceTv *ctk_display_device_tv)
reset_slider(ctk_display_device_tv, ctk_display_device_tv->hue);
reset_slider(ctk_display_device_tv, ctk_display_device_tv->contrast);
reset_slider(ctk_display_device_tv, ctk_display_device_tv->saturation);
-
+
+ gtk_widget_set_sensitive(ctk_display_device_tv->reset_button, FALSE);
+
ctk_config_statusbar_message(ctk_display_device_tv->ctk_config,
"Reset TV Hardware defaults for %s.",
ctk_display_device_tv->name);
@@ -496,10 +499,23 @@ static void reset_defaults(GtkButton *button, gpointer user_data)
{
CtkDisplayDeviceTv *ctk_display_device_tv =
CTK_DISPLAY_DEVICE_TV(user_data);
-
- NvCtrlSetDisplayAttribute(ctk_display_device_tv->handle,
- ctk_display_device_tv->display_device_mask,
- NV_CTRL_TV_RESET_SETTINGS, 1);
+ gint active = 0;
+
+ /* Make sure something is active */
+
+ active =
+ (get_scale_active(CTK_SCALE(ctk_display_device_tv->overscan)) ||
+ get_scale_active(CTK_SCALE(ctk_display_device_tv->flicker_filter)) ||
+ get_scale_active(CTK_SCALE(ctk_display_device_tv->brightness)) ||
+ get_scale_active(CTK_SCALE(ctk_display_device_tv->hue)) ||
+ get_scale_active(CTK_SCALE(ctk_display_device_tv->contrast)) ||
+ get_scale_active(CTK_SCALE(ctk_display_device_tv->saturation)));
+
+ if (active) {
+ NvCtrlSetDisplayAttribute(ctk_display_device_tv->handle,
+ ctk_display_device_tv->display_device_mask,
+ NV_CTRL_TV_RESET_SETTINGS, 1);
+ }
if (ctk_display_device_tv->image_sliders) {
ctk_image_sliders_reset
@@ -507,46 +523,48 @@ static void reset_defaults(GtkButton *button, gpointer user_data)
}
reset_sliders(ctk_display_device_tv);
-
+
} /* reset_defaults() */
/*
- * value_changed() - callback function for changed TV settings; this
+ * value_received() - callback function for changed TV settings; this
* is called when we receive an event indicating that another
* NV-CONTROL client changed any of the settings that we care about.
*/
-static void value_changed(GtkObject *object, gpointer arg1, gpointer user_data)
+static void value_received(GtkObject *object, gpointer arg1,
+ gpointer user_data)
{
CtkEventStruct *event_struct;
CtkDisplayDeviceTv *ctk_display_device_tv =
CTK_DISPLAY_DEVICE_TV(user_data);
- GtkObject *adj;
+ GtkAdjustment *adj;
+ GtkWidget *scale;
gint val;
event_struct = (CtkEventStruct *) arg1;
switch (event_struct->attribute) {
case NV_CTRL_TV_OVERSCAN:
- adj = ctk_display_device_tv->overscan;
+ scale = ctk_display_device_tv->overscan;
break;
case NV_CTRL_TV_FLICKER_FILTER:
- adj = ctk_display_device_tv->flicker_filter;
+ scale = ctk_display_device_tv->flicker_filter;
break;
case NV_CTRL_TV_BRIGHTNESS:
- adj = ctk_display_device_tv->brightness;
+ scale = ctk_display_device_tv->brightness;
break;
case NV_CTRL_TV_HUE:
- adj = ctk_display_device_tv->hue;
+ scale = ctk_display_device_tv->hue;
break;
case NV_CTRL_TV_CONTRAST:
- adj = ctk_display_device_tv->contrast;
+ scale = ctk_display_device_tv->contrast;
break;
case NV_CTRL_TV_SATURATION:
- adj = ctk_display_device_tv->saturation;
+ scale = ctk_display_device_tv->saturation;
break;
case NV_CTRL_TV_RESET_SETTINGS:
reset_sliders(ctk_display_device_tv);
@@ -555,6 +573,7 @@ static void value_changed(GtkObject *object, gpointer arg1, gpointer user_data)
return;
}
+ adj = CTK_SCALE(scale)->gtk_adjustment;
val = gtk_adjustment_get_value(GTK_ADJUSTMENT(adj));
if (val != event_struct->value) {
@@ -572,7 +591,7 @@ static void value_changed(GtkObject *object, gpointer arg1, gpointer user_data)
g_signal_handlers_unblock_by_func(adj, adjustment_value_changed,
ctk_display_device_tv);
}
-} /* value_changed() */
+} /* value_received() */
@@ -587,7 +606,6 @@ GtkTextBuffer *ctk_display_device_tv_create_help(GtkTextTagTable *table,
{
GtkTextIter i;
GtkTextBuffer *b;
- gboolean ret = FALSE;
b = gtk_text_buffer_new(table);
@@ -595,58 +613,221 @@ GtkTextBuffer *ctk_display_device_tv_create_help(GtkTextTagTable *table,
ctk_help_title(b, &i, "%s Help", ctk_display_device_tv->name);
- if (ctk_display_device_tv->active_attributes & __OVERSCAN) {
- ctk_help_heading(b, &i, "TV Overscan");
- ctk_help_para(b, &i, __tv_overscan_help);
- ret = TRUE;
- }
+ ctk_help_heading(b, &i, "TV Overscan");
+ ctk_help_para(b, &i, __tv_overscan_help);
- if (ctk_display_device_tv->active_attributes & __FLICKER_FILTER) {
- ctk_help_heading(b, &i, "TV Flicker Filter");
- ctk_help_para(b, &i, __tv_flicker_filter_help);
- ret = TRUE;
- }
+ ctk_help_heading(b, &i, "TV Flicker Filter");
+ ctk_help_para(b, &i, __tv_flicker_filter_help);
- if (ctk_display_device_tv->active_attributes & __BRIGHTNESS) {
- ctk_help_heading(b, &i, "TV Brightness");
- ctk_help_para(b, &i, __tv_brightness_help);
- ret = TRUE;
- }
+ ctk_help_heading(b, &i, "TV Brightness");
+ ctk_help_para(b, &i, __tv_brightness_help);
- if (ctk_display_device_tv->active_attributes & __HUE) {
- ctk_help_heading(b, &i, "TV Hue");
- ctk_help_para(b, &i, __tv_hue_help);
- ret = TRUE;
- }
+ ctk_help_heading(b, &i, "TV Hue");
+ ctk_help_para(b, &i, __tv_hue_help);
- if (ctk_display_device_tv->active_attributes & __CONTRAST) {
- ctk_help_heading(b, &i, "TV Contrast");
- ctk_help_para(b, &i, __tv_contrast_help);
- ret = TRUE;
- }
+ ctk_help_heading(b, &i, "TV Contrast");
+ ctk_help_para(b, &i, __tv_contrast_help);
- if (ctk_display_device_tv->active_attributes & __SATURATION) {
- ctk_help_heading(b, &i, "TV Saturation");
- ctk_help_para(b, &i, __tv_saturation_help);
- ret = TRUE;
- }
+ ctk_help_heading(b, &i, "TV Saturation");
+ ctk_help_para(b, &i, __tv_saturation_help);
- if (ctk_display_device_tv->image_sliders) {
- ret |= add_image_sliders_help
- (CTK_IMAGE_SLIDERS(ctk_display_device_tv->image_sliders), b, &i);
- }
+ add_image_sliders_help
+ (CTK_IMAGE_SLIDERS(ctk_display_device_tv->image_sliders), b, &i);
- if (ctk_display_device_tv->edid_available) {
+ if (ctk_display_device_tv->edid) {
add_acquire_edid_help(b, &i);
}
- if (!ret) {
- ctk_help_para(b, &i, "There are no configurable options available "
- "for %s.", ctk_display_device_tv->name);
- }
-
ctk_help_finish(b);
return b;
} /* ctk_display_device_tv_create_help() */
+
+
+
+/* Update GUI state of the scale to reflect current settings
+ * on the X Driver.
+ */
+
+static void setup_scale(CtkDisplayDeviceTv *ctk_display_device_tv,
+ int attribute, GtkWidget *scale)
+{
+ ReturnStatus ret0, ret1;
+ NVCTRLAttributeValidValuesRec valid;
+ NvCtrlAttributeHandle *handle = ctk_display_device_tv->handle;
+ unsigned int mask = ctk_display_device_tv->display_device_mask;
+ int val;
+ GtkAdjustment *adj = CTK_SCALE(scale)->gtk_adjustment;
+
+
+ /* Read settings from X server */
+ ret0 = NvCtrlGetValidDisplayAttributeValues(handle, mask,
+ attribute, &valid);
+
+ ret1 = NvCtrlGetDisplayAttribute(handle, mask, attribute, &val);
+
+ if ((ret0 == NvCtrlSuccess) && (ret1 == NvCtrlSuccess) &&
+ (valid.type == ATTRIBUTE_TYPE_RANGE)) {
+
+ g_signal_handlers_block_by_func(adj, adjustment_value_changed,
+ ctk_display_device_tv);
+
+ adj->lower = valid.u.range.min;
+ adj->upper = valid.u.range.max;
+ gtk_adjustment_changed(GTK_ADJUSTMENT(adj));
+
+ gtk_adjustment_set_value(GTK_ADJUSTMENT(adj), val);
+
+ g_signal_handlers_unblock_by_func(adj, adjustment_value_changed,
+ ctk_display_device_tv);
+
+ g_object_set_data(G_OBJECT(adj), "attribute active",
+ GINT_TO_POINTER(1));
+
+ gtk_widget_set_sensitive(scale, TRUE);
+ gtk_widget_show(scale);
+ } else {
+
+ g_object_set_data(G_OBJECT(adj), "attribute active",
+ GINT_TO_POINTER(0));
+
+ gtk_widget_set_sensitive(scale, FALSE);
+ gtk_widget_hide(scale);
+ }
+
+
+} /* setup_scale() */
+
+
+
+/*
+ * Updates the display device TV page to reflect the current
+ * configuration of the display device.
+ */
+static void ctk_display_device_tv_setup(CtkDisplayDeviceTv
+ *ctk_display_device_tv)
+{
+ ReturnStatus ret;
+ char *str;
+ unsigned int enabled_displays;
+
+
+ /* Is display enabled? */
+
+ ret = NvCtrlGetAttribute(ctk_display_device_tv->handle,
+ NV_CTRL_ENABLED_DISPLAYS,
+ (int *)&enabled_displays);
+
+ ctk_display_device_tv->display_enabled =
+ (ret == NvCtrlSuccess &&
+ (enabled_displays & (ctk_display_device_tv->display_device_mask)));
+
+
+ /* Information Frame */
+
+ /* NV_CTRL_STRING_TV_ENCODER_NAME */
+
+ ret = NvCtrlGetStringDisplayAttribute
+ (ctk_display_device_tv->handle,
+ ctk_display_device_tv->display_device_mask,
+ NV_CTRL_STRING_TV_ENCODER_NAME,
+ &str);
+ if (ret == NvCtrlSuccess) {
+ gtk_label_set_text(GTK_LABEL(ctk_display_device_tv->txt_encoder_name),
+ str);
+ gtk_widget_show(ctk_display_device_tv->info_frame);
+ XFree(str);
+ } else {
+ gtk_widget_hide(ctk_display_device_tv->info_frame);
+ }
+
+
+ /* Update sliders */
+
+ /* NV_CTRL_TV_OVERSCAN */
+
+ setup_scale(ctk_display_device_tv, NV_CTRL_TV_OVERSCAN,
+ ctk_display_device_tv->overscan);
+
+ /* NV_CTRL_TV_FLICKER_FILTER */
+
+ setup_scale(ctk_display_device_tv, NV_CTRL_TV_FLICKER_FILTER,
+ ctk_display_device_tv->flicker_filter);
+
+ /* NV_CTRL_TV_BRIGHTNESS */
+
+ setup_scale(ctk_display_device_tv, NV_CTRL_TV_BRIGHTNESS,
+ ctk_display_device_tv->brightness);
+
+ /* NV_CTRL_TV_HUE */
+
+ setup_scale(ctk_display_device_tv, NV_CTRL_TV_HUE,
+ ctk_display_device_tv->hue);
+
+ /* NV_CTRL_TV_CONTRAST */
+
+ setup_scale(ctk_display_device_tv, NV_CTRL_TV_CONTRAST,
+ ctk_display_device_tv->contrast);
+
+ /* NV_CTRL_TV_SATURATION */
+
+ setup_scale(ctk_display_device_tv, NV_CTRL_TV_SATURATION,
+ ctk_display_device_tv->saturation);
+
+ /* Update the image sliders */
+
+ ctk_image_sliders_setup
+ (CTK_IMAGE_SLIDERS(ctk_display_device_tv->image_sliders));
+
+
+ /* update acquire EDID button */
+
+ if (ctk_display_device_tv->edid) {
+ GList *list;
+
+ list = gtk_container_get_children
+ (GTK_CONTAINER(ctk_display_device_tv->edid_box));
+ if (list) {
+ gtk_container_remove
+ (GTK_CONTAINER(ctk_display_device_tv->edid_box),
+ (GtkWidget *)(list->data));
+ g_list_free(list);
+ }
+ }
+
+ ctk_display_device_tv->edid =
+ ctk_edid_new(ctk_display_device_tv->handle,
+ ctk_display_device_tv->ctk_config,
+ ctk_display_device_tv->ctk_event,
+ ctk_display_device_tv->reset_button,
+ ctk_display_device_tv->display_device_mask,
+ ctk_display_device_tv->name);
+
+ if (ctk_display_device_tv->edid) {
+ gtk_box_pack_start(GTK_BOX(ctk_display_device_tv->edid_box),
+ ctk_display_device_tv->edid, TRUE, TRUE, 0);
+ }
+
+
+ /* update the reset button */
+
+ gtk_widget_set_sensitive(ctk_display_device_tv->reset_button, FALSE);
+
+} /* ctk_display_device_tv_setup() */
+
+
+
+/*
+ * When the list of enabled displays on the GPU changes,
+ * this page should disable/enable access based on whether
+ * or not the display device is enabled.
+ */
+static void enabled_displays_received(GtkObject *object, gpointer arg1,
+ gpointer user_data)
+{
+ CtkDisplayDeviceTv *ctk_object = CTK_DISPLAY_DEVICE_TV(user_data);
+
+ ctk_display_device_tv_setup(ctk_object);
+
+} /* enabled_displays_received() */
diff --git a/src/gtk+-2.x/ctkdisplaydevice-tv.h b/src/gtk+-2.x/ctkdisplaydevice-tv.h
index dbeafe2..d4597a8 100644
--- a/src/gtk+-2.x/ctkdisplaydevice-tv.h
+++ b/src/gtk+-2.x/ctkdisplaydevice-tv.h
@@ -57,25 +57,30 @@ typedef struct _CtkDisplayDeviceTvClass CtkDisplayDeviceTvClass;
struct _CtkDisplayDeviceTv
{
GtkVBox parent;
+ CtkConfig *ctk_config;
+ CtkEvent *ctk_event;
NvCtrlAttributeHandle *handle;
- CtkConfig *ctk_config;
- GtkWidget *image_sliders;
- GtkWidget *reset_button;
+ unsigned int display_device_mask;
+ gboolean display_enabled;
+ char *name;
- GtkObject *overscan;
- GtkObject *flicker_filter;
-
- GtkObject *brightness;
- GtkObject *hue;
- GtkObject *contrast;
- GtkObject *saturation;
+ GtkWidget *info_frame;
+ GtkWidget *txt_encoder_name;
+
+ GtkWidget *overscan;
+ GtkWidget *flicker_filter;
- unsigned int display_device_mask;
- unsigned int active_attributes;
- gboolean edid_available;
+ GtkWidget *brightness;
+ GtkWidget *hue;
+ GtkWidget *contrast;
+ GtkWidget *saturation;
+
+ GtkWidget *image_sliders;
- char *name;
+ GtkWidget *edid_box;
+ GtkWidget *edid;
+ GtkWidget *reset_button;
};
struct _CtkDisplayDeviceTvClass
diff --git a/src/gtk+-2.x/ctkdisplaydevice.c b/src/gtk+-2.x/ctkdisplaydevice.c
deleted file mode 100644
index a379f51..0000000
--- a/src/gtk+-2.x/ctkdisplaydevice.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
- * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
- * and Linux systems.
- *
- * Copyright (C) 2004 NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of Version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
- * of the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the:
- *
- * Free Software Foundation, Inc.
- * 59 Temple Place - Suite 330
- * Boston, MA 02111-1307, USA
- *
- */
-
-#include <gtk/gtk.h>
-#include <NvCtrlAttributes.h>
-
-#include "display_device_banner.h"
-#include "crt.h"
-#include "dfp.h"
-#include "tv.h"
-#include "ctkimage.h"
-
-#include "ctkdisplaydevice.h"
-
-#include "ctkconfig.h"
-#include "ctkhelp.h"
-
-
-GType ctk_display_device_get_type(void)
-{
- static GType ctk_display_device_type = 0;
-
- if (!ctk_display_device_type) {
- static const GTypeInfo ctk_display_device_info = {
- sizeof (CtkDisplayDeviceClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- NULL, /* class_init, */
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (CtkDisplayDevice),
- 0, /* n_preallocs */
- NULL, /* instance_init */
- };
-
- ctk_display_device_type = g_type_register_static (GTK_TYPE_VBOX,
- "CtkDisplayDevice", &ctk_display_device_info, 0);
- }
-
- return ctk_display_device_type;
-}
-
-
-GtkWidget* ctk_display_device_new(NvCtrlAttributeHandle *handle,
- CtkConfig *ctk_config, CtkEvent *ctk_event)
-{
- GObject *object;
- CtkDisplayDevice *ctk_display_device;
- GtkWidget *image;
- GtkWidget *banner;
- GtkWidget *frame;
- GtkWidget *hbox;
- GtkWidget *vbox;
- GtkWidget *label;
- GtkWidget *alignment;
- ReturnStatus ret;
-
- guint8 *image_buffer = NULL;
- const nv_image_t *img;
- int enabled, i, mask, n;
- char *name;
-
- object = g_object_new(CTK_TYPE_DISPLAY_DEVICE, NULL);
-
- ctk_display_device = CTK_DISPLAY_DEVICE(object);
- ctk_display_device->handle = handle;
- ctk_display_device->ctk_config = ctk_config;
- ctk_display_device->num_display_devices = 0;
-
- gtk_box_set_spacing(GTK_BOX(object), 10);
-
- /* banner */
-
- banner = ctk_banner_image_new(&display_device_banner_image);
- gtk_box_pack_start(GTK_BOX(object), banner, FALSE, FALSE, 0);
-
- /*
- * In the future: this page will be where things like TwinView
- * will be configured. In the meantime, just put place holders
- * for each display device present on this X screen.
- */
-
- ret = NvCtrlGetAttribute(handle, NV_CTRL_ENABLED_DISPLAYS, &enabled);
- if (ret != NvCtrlSuccess) {
- return NULL;
- }
-
- ctk_display_device->enabled_display_devices = enabled;
-
- /* create an alignment to center the placeholder */
-
- alignment = gtk_alignment_new(0.5, 0.5, 0.0, 0.0);
- gtk_box_pack_start(GTK_BOX(object), alignment, TRUE, FALSE, 0);
-
- /* create a frame to hold the whole placeholder */
-
- frame = gtk_frame_new(NULL);
- gtk_container_add(GTK_CONTAINER(alignment), frame);
-
- /* create an hbox to hold each display device */
-
- hbox = gtk_hbox_new(FALSE, 5);
- gtk_container_add(GTK_CONTAINER(frame), hbox);
-
- /* create a vbox with image and label for each display device */
-
- for (n = 0, i = 0; i < 24; i++) {
-
- mask = 1 << i;
- if (!(enabled & mask)) continue;
-
- /* get the name of the display device */
-
- ret =
- NvCtrlGetStringDisplayAttribute(handle, mask,
- NV_CTRL_STRING_DISPLAY_DEVICE_NAME,
- &name);
-
- if ((ret != NvCtrlSuccess) || (!name)) {
- name = g_strdup("Unknown");
- }
-
- /* get the correct image for each display device type */
-
- if (mask & CTK_DISPLAY_DEVICE_CRT_MASK) {
- img = &crt_image;
- } else if (mask & CTK_DISPLAY_DEVICE_TV_MASK) {
- img = &tv_image;
- } else if (mask & CTK_DISPLAY_DEVICE_DFP_MASK) {
- img = &dfp_image;
- } else {
- continue;
- }
-
- vbox = gtk_vbox_new(FALSE, 5);
- gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 5);
-
- frame = gtk_frame_new(NULL);
- gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 5);
-
- image_buffer = decompress_image_data(img);
-
- image = gtk_image_new_from_pixbuf
- (gdk_pixbuf_new_from_data(image_buffer, GDK_COLORSPACE_RGB,
- TRUE, 8, img->width, img->height,
- img->width * img->bytes_per_pixel,
- free_decompressed_image, NULL));
-
- gtk_container_add(GTK_CONTAINER(frame), image);
-
- label = gtk_label_new(name);
-
- gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
-
- /* save the display device name */
-
- ctk_display_device->display_device_names[n] = name;
-
- /* increment the display device count */
-
- n++;
- }
-
- ctk_display_device->num_display_devices = n;
-
- /* show the page */
-
- gtk_widget_show_all(GTK_WIDGET(object));
-
- return GTK_WIDGET(object);
-
-} /* ctk_display_device_new() */
-
-
-
-/*
- * ctk_display_device_create_help() - construct help page
- */
-
-GtkTextBuffer *ctk_display_device_create_help(GtkTextTagTable *table,
- CtkDisplayDevice
- *ctk_display_device)
-{
- GtkTextIter i;
- GtkTextBuffer *b;
- char *title, *page, *s, *tmp, *name;
- int n, num;
-
- num = ctk_display_device->num_display_devices;
-
- if (num == 1) {
- title = "Display Device Help";
- page = "page";
- } else {
- title = "Display Devices Help";
- page = "pages";
- }
-
- /* ugliness to build list of display device names */
-
- s = NULL;
- for (n = 0; n < num; n++) {
-
- name = ctk_display_device->display_device_names[n];
-
- if (s) {
- tmp = s;
- s = g_strconcat(s, " ", NULL);
- g_free(tmp);
- } else {
- s = g_strdup(" ");
- }
-
- tmp = s;
-
- if (n == (num - 1)) {
- s = g_strconcat(s, name, NULL);
- } else if (n == (num - 2)) {
- s = g_strconcat(s, name, " and", NULL);
- } else {
- s = g_strconcat(s, name, ",", NULL);
- }
-
- g_free(tmp);
- }
-
-
- b = gtk_text_buffer_new(table);
-
- gtk_text_buffer_get_iter_at_offset(b, &i, 0);
-
- ctk_help_title(b, &i, title);
-
- ctk_help_para(b, &i, "The %s page is a place holder until support "
- "for configuring TwinView is added.", title);
-
- ctk_help_para(b, &i, "Please see the %s for%s for per-display device "
- "configuration.", page, s);
-
- ctk_help_finish(b);
-
- return b;
-
-} /* ctk_display_device_create_help() */
diff --git a/src/gtk+-2.x/ctkdisplaydevice.h b/src/gtk+-2.x/ctkdisplaydevice.h
deleted file mode 100644
index 2036eb5..0000000
--- a/src/gtk+-2.x/ctkdisplaydevice.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
- * and Linux systems.
- *
- * Copyright (C) 2004 NVIDIA Corporation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of Version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
- * of the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the:
- *
- * Free Software Foundation, Inc.
- * 59 Temple Place - Suite 330
- * Boston, MA 02111-1307, USA
- *
- */
-
-#ifndef __CTK_DISPLAYDEVICE_H__
-#define __CTK_DISPLAYDEVICE_H__
-
-#include "ctkevent.h"
-#include "ctkconfig.h"
-
-G_BEGIN_DECLS
-
-#define CTK_TYPE_DISPLAY_DEVICE (ctk_display_device_get_type())
-
-#define CTK_DISPLAY_DEVICE(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), CTK_TYPE_DISPLAY_DEVICE, \
- CtkDisplayDevice))
-
-#define CTK_DISPLAY_DEVICE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), CTK_TYPE_DISPLAY_DEVICE, \
- CtkDisplayDeviceClass))
-
-#define CTK_IS_DISPLAY_DEVICE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CTK_TYPE_DISPLAY_DEVICE))
-
-#define CTK_IS_DISPLAY_DEVICE_CLASS(class) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), CTK_TYPE_DISPLAY_DEVICE))
-
-#define CTK_DISPLAY_DEVICE_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_DISPLAY_DEVICE, \
- CtkDisplayDeviceClass))
-
-
-#define CTK_DISPLAY_DEVICE_CRT_MASK 0x000000FF
-#define CTK_DISPLAY_DEVICE_TV_MASK 0x0000FF00
-#define CTK_DISPLAY_DEVICE_DFP_MASK 0x00FF0000
-
-
-typedef struct _CtkDisplayDevice CtkDisplayDevice;
-typedef struct _CtkDisplayDeviceClass CtkDisplayDeviceClass;
-
-struct _CtkDisplayDevice
-{
- GtkVBox parent;
-
- NvCtrlAttributeHandle *handle;
- CtkConfig *ctk_config;
-
- unsigned int enabled_display_devices;
-
- int num_display_devices;
- char *display_device_names[24];
-
-};
-
-struct _CtkDisplayDeviceClass
-{
- GtkVBoxClass parent_class;
-};
-
-GType ctk_display_device_get_type (void) G_GNUC_CONST;
-GtkWidget* ctk_display_device_new (NvCtrlAttributeHandle *,
- CtkConfig *, CtkEvent *);
-
-GtkTextBuffer *ctk_display_device_create_help(GtkTextTagTable *,
- CtkDisplayDevice *);
-
-G_END_DECLS
-
-#endif /* __CTK_DISPLAYDEVICE_H__ */
diff --git a/src/gtk+-2.x/ctkdisplaylayout.c b/src/gtk+-2.x/ctkdisplaylayout.c
new file mode 100644
index 0000000..2b851e1
--- /dev/null
+++ b/src/gtk+-2.x/ctkdisplaylayout.c
@@ -0,0 +1,3690 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
+ * of the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+#include <stdlib.h> /* malloc */
+#include <string.h> /* strlen */
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+
+#include "ctkevent.h"
+#include "ctkhelp.h"
+#include "ctkdisplaylayout.h"
+
+
+
+
+/* GUI look and feel */
+
+#define DEFAULT_SNAP_STRENGTH 100
+
+#define MAX_LAYOUT_WIDTH 0x00007FFF /* 16 bit signed int (32767) */
+#define MAX_LAYOUT_HEIGHT 0x00007FFF
+
+#define LAYOUT_IMG_OFFSET 2 /* Border + White trimming */
+#define LAYOUT_IMG_BORDER_PADDING 8
+
+#define LAYOUT_IMG_FG_COLOR "black"
+#define LAYOUT_IMG_BG_COLOR "#AAAAAA"
+#define LAYOUT_IMG_SELECT_COLOR "#FF8888"
+
+
+/* Device (GPU) Coloring */
+
+#define BG_SCR_ON 0 /* Screen viewing area (Has modeline set) */
+#define BG_PAN_ON 1 /* Screen panning area (Has modeline set) */
+#define BG_SCR_OFF 2 /* Screen viewing area (Off/Disabled) */
+#define BG_PAN_OFF 3 /* Screen panning area (Off/Disabled) */
+
+#define NUM_COLOR_PALETTES MAX_DEVICES /* One palette for each possible Device/GPU */
+#define NUM_COLORS_PER_PALETTE 4 /* Number of colors in a device's palette */
+#define NUM_COLORS ((NUM_COLOR_PALETTES) * (NUM_COLORS_PER_PALETTE))
+
+#if MAX_DEVICES != 8
+#warning "Each GPU needs a color palette!"
+#endif
+
+/* Each device will need a unique color palette */
+char *__palettes_color_names[NUM_COLORS] = {
+
+ /* Blue */
+ "#D9DBF4", /* View - Has modeline set */
+ "#C9CBE4", /* Panning - Has modeline set */
+ "#BABCD5", /* View - Off/Disabled */
+ "#A3A5BE", /* Panning - OFf/Disabled */
+
+ /* Orange */
+ "#FFDB94",
+ "#E8C47D",
+ "#C9A55E",
+ "#A6823B",
+
+ /* Purple */
+ "#E2D4F0",
+ "#CFC1DD",
+ "#B7A9C5",
+ "#9D8FAB",
+
+ /* Beige */
+ "#EAF1C9",
+ "#CBD2AA",
+ "#ADB48C",
+ "#838A62",
+
+ /* Green */
+ "#96E562",
+ "#70BF3C",
+ "#5BAA27",
+ "#3C8B08",
+
+ /* Pink */
+ "#FFD6E9",
+ "#E1B8CB",
+ "#C79EB1",
+ "#A87F92",
+
+ /* Yellow */
+ "#EEEE7E",
+ "#E0E070",
+ "#D5D565",
+ "#C4C454",
+
+ /* Teal */
+ "#C9EAF1",
+ "#A2C3CA",
+ "#8DAEB5",
+ "#76979E"
+ };
+
+
+
+
+/*** P R O T O T Y P E S *****************************************************/
+
+
+static gboolean expose_event_callback (GtkWidget *widget,
+ GdkEventExpose *event,
+ gpointer data);
+
+static gboolean configure_event_callback (GtkWidget *widget,
+ GdkEventConfigure *event,
+ gpointer data);
+
+static gboolean motion_event_callback (GtkWidget *widget,
+ GdkEventMotion *event,
+ gpointer data);
+
+static gboolean button_press_event_callback (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer data);
+
+static gboolean button_release_event_callback (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer data);
+
+
+static void calc_metamode(nvScreenPtr screen, nvMetaModePtr metamode);
+
+
+
+
+/*** F U N C T I O N S *******************************************************/
+
+
+/** zorder_layout() **************************************************
+ *
+ * In order to draw and allow selecting display devices, we need to
+ * keep them in a Z-ordered list. This function creates the initial
+ * Z-order list for the given layout based on the devices it has.
+ *
+ **/
+
+static void zorder_layout(CtkDisplayLayout *ctk_object)
+{
+ nvLayoutPtr layout = ctk_object->layout;
+ nvGpuPtr gpu;
+ int i;
+
+
+ /* Clear the list */
+ if (ctk_object->Zorder) {
+ free(ctk_object->Zorder);
+ ctk_object->Zorder = NULL;
+ }
+ ctk_object->Zcount = 0;
+ ctk_object->Zselected = 0;
+
+
+ /* Count the number of displays in the layout */
+ for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+ ctk_object->Zcount += gpu->num_displays;
+ }
+
+
+ /* If there are no displays, we're done */
+ if (!ctk_object->Zcount) {
+ return;
+ }
+
+
+ /* Create the Z order list buffer */
+ ctk_object->Zorder =
+ (nvDisplayPtr *)calloc(1, ctk_object->Zcount *sizeof(nvDisplayPtr));
+ if (!ctk_object->Zorder) {
+ ctk_object->Zcount = 0;
+ return;
+ }
+
+
+ /* Populate the Z order list */
+ i = 0;
+ for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+ nvDisplayPtr display;
+ for (display = gpu->displays; display; display = display->next) {
+ ctk_object->Zorder[i++] = display;
+ }
+ }
+
+} /* zorder_layout() */
+
+
+
+/** get_selected() ***************************************************
+ *
+ * Returns the currently selected display. The selected display
+ * device should always be at the top of the Z-order.
+ *
+ **/
+
+static nvDisplayPtr get_selected(CtkDisplayLayout *ctk_object)
+{
+ if (!(ctk_object->Zselected) || !(ctk_object->Zcount)) {
+ return NULL;
+ }
+
+ return ctk_object->Zorder[0];
+
+} /* get_selected() */
+
+
+
+/** get_metamode() ***************************************************
+ *
+ * Returns a screen's metamode_idx'th metamode, clamping to the last
+ * available metamode in the list.
+ *
+ **/
+
+static nvMetaModePtr get_metamode(nvScreenPtr screen, int metamode_idx)
+{
+ nvMetaModePtr metamode = screen->metamodes;
+
+ while (metamode && metamode->next && metamode_idx) {
+ metamode = metamode->next;
+ metamode_idx--;
+ }
+
+ return metamode;
+
+} /* get_metamode() */
+
+
+
+/** get_mode() *******************************************************
+ *
+ * Returns a display device's mode_idx'th mode.
+ *
+ **/
+
+static nvModePtr get_mode(nvDisplayPtr display, int mode_idx)
+{
+ nvModePtr mode = display->modes;
+
+ while (mode && mode->next && mode_idx) {
+ mode = mode->next;
+ mode_idx--;
+ }
+
+ return mode;
+
+} /* get_mode() */
+
+
+
+/** sync_modify() ****************************************************
+ *
+ * When the user is moving/panning a display device around, a
+ * temporary dimension buffer is used to allow for snapping to other
+ * displays.
+ *
+ * This function sets up the temporary buffer by copying the actual
+ * dimensions of the selected display device to the temporary buffer.
+ *
+ **/
+
+static void sync_modify(CtkDisplayLayout *ctk_object)
+{
+ nvDisplayPtr display = get_selected(ctk_object);
+
+ if (display && display->cur_mode) {
+ ctk_object->modify_dim[X] = display->cur_mode->pan[X];
+ ctk_object->modify_dim[Y] = display->cur_mode->pan[Y];
+ ctk_object->modify_dim[W] = display->cur_mode->pan[W];
+ ctk_object->modify_dim[H] = display->cur_mode->pan[H];
+ }
+
+} /* sync_modify() */
+
+
+
+/** sync_scaling() ***************************************************
+ *
+ * Computes the scaling required to display the layout image.
+ *
+ **/
+
+static void sync_scaling(CtkDisplayLayout *ctk_object)
+{
+ int *dim = ctk_object->layout->dim;
+ float wscale;
+ float hscale;
+
+ wscale = (float)(ctk_object->img_dim[W]) / (float)(dim[W]);
+ hscale = (float)(ctk_object->img_dim[H]) / (float)(dim[H]);
+
+ if (wscale * dim[H] > ctk_object->img_dim[H]) {
+ ctk_object->scale = hscale;
+ } else {
+ ctk_object->scale = wscale;
+ }
+
+} /* sync_scaling() */
+
+
+
+/** point_in_dim() ***************************************************
+ *
+ * Determines if a point lies within the given dimensions
+ *
+ **/
+
+static int point_in_dim(int *dim, int x, int y)
+{
+ if (x > dim[X] && x < (dim[X] + dim[W]) &&
+ y > dim[Y] && y < (dim[Y] + dim[H])) {
+ return 1;
+ }
+
+ return 0;
+
+} /* point_in_dim() */
+
+
+
+/** offset functions *************************************************
+ *
+ * Offsetting functions
+ *
+ * These functions do the dirty work of actually moving display
+ * devices around in the layout.
+ *
+ **/
+
+/* Offset a single mode */
+static void offset_mode(nvModePtr mode, int x, int y)
+{
+ mode->dim[X] += x;
+ mode->dim[Y] += y;
+ mode->pan[X] = mode->dim[X];
+ mode->pan[Y] = mode->dim[Y];
+}
+
+/* Offset a display by offsetting the current mode */
+static void offset_display(nvDisplayPtr display, int x, int y, int full)
+{
+ /* XXX For now, if there is only one display, offset all
+ * of its modes. Later, allow the user to override
+ * this behavior.
+ */
+ if ((display->screen && display->screen->num_displays == 1) || full) {
+ nvModePtr mode;
+ for (mode = display->modes; mode; mode = mode->next) {
+ offset_mode(mode, x, y);
+ }
+ } else if (display->cur_mode) {
+ offset_mode(display->cur_mode, x, y);
+ }
+}
+
+/* Offsets an X screen */
+static void offset_screen(nvScreenPtr screen, int x, int y)
+{
+ nvMetaModePtr metamode;
+
+ screen->dim[X] += x;
+ screen->dim[Y] += y;
+
+ for (metamode = screen->metamodes; metamode; metamode = metamode->next) {
+ metamode->dim[X] += x;
+ metamode->dim[Y] += y;
+ metamode->edim[X] += x;
+ metamode->edim[Y] += y;
+ }
+}
+
+/* Offsets the entire layout by offsetting its X screens and display devices */
+static void offset_layout(nvLayoutPtr layout, int x, int y, int full)
+{
+ nvGpuPtr gpu;
+ nvScreenPtr screen;
+ nvDisplayPtr display;
+
+ layout->dim[X] += x;
+ layout->dim[Y] += y;
+
+ for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+
+ /* Offset screens */
+ for (screen = gpu->screens; screen; screen = screen->next) {
+ offset_screen(screen, x, y);
+ }
+
+ /* Offset displays */
+ for (display = gpu->displays; display; display = display->next) {
+ offset_display(display, x, y, full);
+ }
+ }
+} /* offset functions */
+
+
+
+/** resolve_display() ************************************************
+ *
+ * Figures out where the current mode of the given display should be
+ * placed in relation to the layout.
+ *
+ * XXX This function assumes there are no relationship loops
+ *
+ **/
+
+static int resolve_display(nvDisplayPtr display, int pos[4])
+{
+ nvModePtr mode = display->cur_mode;
+ int relative_pos[4];
+
+ if (!mode) return 0;
+
+
+ /* Set the dimensions */
+ pos[W] = mode->pan[W];
+ pos[H] = mode->pan[H];
+
+
+ /* Find the position */
+ switch (mode->position_type) {
+ case CONF_ADJ_ABSOLUTE:
+ pos[X] = mode->pan[X];
+ pos[Y] = mode->pan[Y];
+ break;
+
+ case CONF_ADJ_RIGHTOF:
+ resolve_display(mode->relative_to, relative_pos);
+ pos[X] = relative_pos[X] + relative_pos[W];
+ pos[Y] = relative_pos[Y];
+ break;
+
+ case CONF_ADJ_LEFTOF:
+ resolve_display(mode->relative_to, relative_pos);
+ pos[X] = relative_pos[X] - pos[W];
+ pos[Y] = relative_pos[Y];
+ break;
+
+ case CONF_ADJ_BELOW:
+ resolve_display(mode->relative_to, relative_pos);
+ pos[X] = relative_pos[X];
+ pos[Y] = relative_pos[Y] + relative_pos[H];
+ break;
+
+ case CONF_ADJ_ABOVE:
+ resolve_display(mode->relative_to, relative_pos);
+ pos[X] = relative_pos[X];
+ pos[Y] = relative_pos[Y] - pos[H];
+ break;
+
+ case CONF_ADJ_RELATIVE: /* Clone */
+ resolve_display(mode->relative_to, relative_pos);
+ pos[X] = relative_pos[X];
+ pos[Y] = relative_pos[Y];
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+
+} /* resolve_display() */
+
+
+
+/** resolve_displays_in_screen() *************************************
+ *
+ * Resolves relative display positions into absolute positions for
+ * the currently selected metamode of the screen.
+ *
+ **/
+
+static void resolve_displays_in_screen(nvScreenPtr screen)
+{
+ nvDisplayPtr display;
+ int pos[4];
+
+ /* Resolve the current mode of each display in the screen */
+ for (display = screen->gpu->displays; display; display = display->next) {
+
+ if (display->screen != screen) continue;
+
+ if (resolve_display(display, pos)) {
+ display->cur_mode->dim[X] = pos[X];
+ display->cur_mode->dim[Y] = pos[Y];
+ display->cur_mode->pan[X] = pos[X];
+ display->cur_mode->pan[Y] = pos[Y];
+ }
+ }
+
+ /* Get the new position of the metamode */
+ calc_metamode(screen, screen->cur_metamode);
+
+} /* resolve_displays_in_screen() */
+
+
+
+/** resolve_screen() *************************************************
+ *
+ * Figures out where the current metamode of the given screen should be
+ * placed in relation to the layout.
+ *
+ * XXX This function assumes there are no relationship loops
+ *
+ **/
+
+static int resolve_screen(nvScreenPtr screen, int pos[4])
+{
+ nvMetaModePtr metamode = screen->cur_metamode;
+ int relative_pos[4];
+
+ if (!metamode) return 0;
+
+
+ /* Set the dimensions */
+ pos[W] = metamode->dim[W];
+ pos[H] = metamode->dim[H];
+
+
+ /* Find the position */
+ switch (screen->position_type) {
+ case CONF_ADJ_ABSOLUTE:
+ pos[X] = metamode->dim[X];
+ pos[Y] = metamode->dim[Y];
+ break;
+
+ case CONF_ADJ_RIGHTOF:
+ resolve_screen(screen->relative_to, relative_pos);
+ pos[X] = relative_pos[X] + relative_pos[W];
+ pos[Y] = relative_pos[Y];
+ break;
+
+ case CONF_ADJ_LEFTOF:
+ resolve_screen(screen->relative_to, relative_pos);
+ pos[X] = relative_pos[X] - pos[W];
+ pos[Y] = relative_pos[Y];
+ break;
+
+ case CONF_ADJ_BELOW:
+ resolve_screen(screen->relative_to, relative_pos);
+ pos[X] = relative_pos[X];
+ pos[Y] = relative_pos[Y] + relative_pos[H];
+ break;
+
+ case CONF_ADJ_ABOVE:
+ resolve_screen(screen->relative_to, relative_pos);
+ pos[X] = relative_pos[X];
+ pos[Y] = relative_pos[Y] - pos[H];
+ break;
+
+ case CONF_ADJ_RELATIVE: /* Clone */
+ resolve_screen(screen->relative_to, relative_pos);
+ pos[X] = relative_pos[X];
+ pos[Y] = relative_pos[Y];
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+
+} /* resolve_screen() */
+
+
+
+/* resolve_screen_in_layout() ***************************************
+ *
+ * Resolves relative screen positions into absolute positions for
+ * the currently selected metamode of the screen.
+ *
+ **/
+
+static void resolve_screen_in_layout(nvScreenPtr screen)
+{
+ nvDisplayPtr display;
+ int pos[4];
+ int x, y;
+
+
+ /* Resolve the current screen location */
+ if (resolve_screen(screen, pos)) {
+
+ /* Move the screen and the displays by offsetting */
+
+ x = pos[X] - screen->cur_metamode->dim[X];
+ y = pos[Y] - screen->cur_metamode->dim[Y];
+
+ offset_screen(screen, x, y);
+
+ for (display = screen->gpu->displays;
+ display;
+ display = display->next) {
+
+ if (display->screen != screen) continue;
+
+ offset_mode(display->cur_mode, x, y);
+ }
+ }
+
+} /* resolve_screen_in_layout() */
+
+
+
+/** resolve_layout() *************************************************
+ *
+ * Resolves relative positions into absolute positions for the
+ * the *current* layout.
+ *
+ **/
+
+static void resolve_layout(nvLayoutPtr layout)
+{
+ nvGpuPtr gpu;
+ nvScreenPtr screen;
+
+ /* First, resolve TwinView relationships */
+ for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+ for (screen = gpu->screens; screen; screen = screen->next) {
+ resolve_displays_in_screen(screen);
+ }
+ }
+
+ /* Next, resolve X Screen relationships */
+ for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+ for (screen = gpu->screens; screen; screen = screen->next) {
+ resolve_screen_in_layout(screen);
+ }
+ }
+
+} /* resolve_layout() */
+
+
+
+/** calc_metamode() **************************************************
+ *
+ * Calculates the dimensions of a metamode.
+ *
+ * - Calculates the smallest bounding box that can hold the given
+ * metamode of the X Screen.
+ *
+ **/
+
+static void calc_metamode(nvScreenPtr screen, nvMetaModePtr metamode)
+{
+ nvDisplayPtr display;
+ nvModePtr mode;
+ int init = 1;
+ int einit = 1;
+ int *dim; // Bounding box for all modes, including NULL modes.
+ int *edim; // Bounding box for non-NULL modes.
+
+
+ if (!screen || !metamode) {
+ return;
+ }
+
+ dim = metamode->dim;
+ edim = metamode->edim;
+
+ dim[X] = edim[X] = 0;
+ dim[Y] = edim[Y] = 0;
+ dim[W] = edim[W] = 0;
+ dim[H] = edim[H] = 0;
+
+ /* Calculate its dimensions */
+ for (display = screen->gpu->displays; display; display = display->next) {
+
+ if (display->screen != screen) continue;
+
+ /* Get the display's mode that is part of the metamode. */
+ for (mode = display->modes; mode; mode = mode->next) {
+ if (mode->metamode == metamode) break;
+ }
+ if (!mode) continue;
+
+ if (init) {
+ dim[X] = mode->pan[X];
+ dim[Y] = mode->pan[Y];
+ dim[W] = mode->pan[X] +mode->pan[W];
+ dim[H] = mode->pan[Y] +mode->pan[H];
+ init = 0;
+ } else {
+ dim[X] = MIN(dim[X], mode->dim[X]);
+ dim[Y] = MIN(dim[Y], mode->dim[Y]);
+ dim[W] = MAX(dim[W], mode->dim[X] +mode->pan[W]);
+ dim[H] = MAX(dim[H], mode->dim[Y] +mode->pan[H]);
+ }
+
+ /* Don't include NULL modes in the effective dimension calculation */
+ if (!mode->modeline) continue;
+
+ if (einit) {
+ edim[X] = mode->pan[X];
+ edim[Y] = mode->pan[Y];
+ edim[W] = mode->pan[X] +mode->pan[W];
+ edim[H] = mode->pan[Y] +mode->pan[H];
+ einit = 0;
+ } else {
+ edim[X] = MIN(edim[X], mode->dim[X]);
+ edim[Y] = MIN(edim[Y], mode->dim[Y]);
+ edim[W] = MAX(edim[W], mode->dim[X] +mode->pan[W]);
+ edim[H] = MAX(edim[H], mode->dim[Y] +mode->pan[H]);
+ }
+ }
+
+ dim[W] = dim[W] - dim[X];
+ dim[H] = dim[H] - dim[Y];
+
+ edim[W] = edim[W] - edim[X];
+ edim[H] = edim[H] - edim[Y];
+
+} /* calc_metamode() */
+
+
+
+/** calc_screen() ****************************************************
+ *
+ * Calculates the dimensions of an X Screen
+ *
+ * - Calculates the smallest bounding box that can hold all of the
+ * metamodes of the X Screen.
+ *
+ **/
+
+static void calc_screen(nvScreenPtr screen)
+{
+ nvMetaModePtr metamode;
+ int *dim;
+
+
+ if (!screen) return;
+
+ dim = screen->dim;
+ metamode = screen->metamodes;
+
+ if (!metamode) {
+ dim[X] = 0;
+ dim[Y] = 0;
+ dim[W] = 0;
+ dim[H] = 0;
+ return;
+ }
+
+ calc_metamode(screen, metamode);
+ dim[X] = metamode->dim[X];
+ dim[Y] = metamode->dim[Y];
+ dim[W] = metamode->dim[X] +metamode->dim[W];
+ dim[H] = metamode->dim[Y] +metamode->dim[H];
+
+ for (metamode = metamode->next;
+ metamode;
+ metamode = metamode->next) {
+
+ calc_metamode(screen, metamode);
+ dim[X] = MIN(dim[X], metamode->dim[X]);
+ dim[Y] = MIN(dim[Y], metamode->dim[Y]);
+ dim[W] = MAX(dim[W], metamode->dim[X] +metamode->dim[W]);
+ dim[H] = MAX(dim[H], metamode->dim[Y] +metamode->dim[H]);
+ }
+
+ dim[W] = dim[W] - dim[X];
+ dim[H] = dim[H] - dim[Y];
+
+} /* calc_screen() */
+
+
+
+/** calc_layout() ****************************************************
+ *
+ * Calculates the dimensions (width & height) of the layout. This is
+ * the smallest bounding box that holds all the gpu's X screen's
+ * display device's (current) modes in the layout. (Bounding box of
+ * all the current metamodes of all X Screens.)
+ *
+ * As a side effect, all other screen/metamode dimensions are
+ * calculated.
+ *
+ **/
+
+static void calc_layout(nvLayoutPtr layout)
+{
+ nvGpuPtr gpu;
+ nvScreenPtr screen;
+ nvDisplayPtr display;
+ int init = 1;
+ int *dim;
+ int x;
+
+
+ if (!layout) return;
+
+ resolve_layout(layout);
+
+ dim = layout->dim;
+ dim[X] = 0;
+ dim[Y] = 0;
+ dim[W] = 0;
+ dim[H] = 0;
+
+ for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+
+ for (screen = gpu->screens; screen; screen = screen->next) {
+ int *sdim;
+
+ calc_screen(screen);
+ sdim = screen->cur_metamode->dim;
+
+ if (init) {
+ dim[X] = sdim[X];
+ dim[Y] = sdim[Y];
+ dim[W] = sdim[X] +sdim[W];
+ dim[H] = sdim[Y] +sdim[H];
+ init = 0;
+ continue;
+ }
+
+ dim[X] = MIN(dim[X], sdim[X]);
+ dim[Y] = MIN(dim[Y], sdim[Y]);
+ dim[W] = MAX(dim[W], sdim[X] +sdim[W]);
+ dim[H] = MAX(dim[H], sdim[Y] +sdim[H]);
+ }
+ }
+
+ dim[W] = dim[W] - dim[X];
+ dim[H] = dim[H] - dim[Y];
+
+
+ /* Position disabled display devices off to the top right */
+ x = dim[W] + dim[X];
+ for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+ for (display = gpu->displays; display; display = display->next) {
+ if (display->screen) continue;
+
+ display->cur_mode->dim[X] = x;
+ display->cur_mode->pan[X] = x;
+ display->cur_mode->dim[Y] = 0;
+ display->cur_mode->pan[Y] = 0;
+
+ x += display->cur_mode->dim[W];
+ dim[W] += display->cur_mode->dim[W];
+ dim[H] = MAX(dim[H], display->cur_mode->dim[H]);
+ }
+ }
+
+} /* calc_layout() */
+
+
+
+/** set_screen_metamode() ********************************************
+ *
+ * Updates the layout structure to make the screen and each of its
+ * displays point to the correct metamode/mode.
+ *
+ **/
+
+static void set_screen_metamode(nvLayoutPtr layout, nvScreenPtr screen,
+ int new_metamode_idx)
+{
+ nvDisplayPtr display;
+
+
+ /* Set which metamode the screen is pointing to */
+ screen->cur_metamode_idx = new_metamode_idx;
+ screen->cur_metamode = get_metamode(screen, new_metamode_idx);
+
+ /* Make each display within the screen point to the new mode */
+ for (display = screen->gpu->displays; display; display = display->next) {
+
+ if (display->screen != screen) continue; /* Display not in screen */
+
+ display->cur_mode = get_mode(display, new_metamode_idx);
+ }
+
+ /* Recalculate the layout dimensions */
+ calc_layout(layout);
+ offset_layout(layout, -layout->dim[X], -layout->dim[Y], 1);
+
+} /* set_screen_metamode() */
+
+
+
+/** recenter_layout() ************************************************
+ *
+ * Recenters all metamodes of all screens in the layout. (Makes
+ * sure that the top left corner of each screen's metamode is (0,0)
+ * if possible.)
+ *
+ **/
+
+static void recenter_layout(nvLayoutPtr layout)
+{
+ nvGpuPtr gpu;
+ nvScreenPtr screen;
+ int real_metamode_idx;
+ int metamode_idx;
+
+ for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+
+ for (screen = gpu->screens; screen; screen = screen->next) {
+
+ real_metamode_idx = screen->cur_metamode_idx;
+
+ for (metamode_idx = 0;
+ metamode_idx < screen->num_metamodes;
+ metamode_idx++) {
+
+ if (metamode_idx == real_metamode_idx) continue;
+
+ set_screen_metamode(layout, screen, metamode_idx);
+ }
+
+ set_screen_metamode(layout, screen, real_metamode_idx);
+ }
+ }
+
+} /* recenter_layout() */
+
+
+
+/** snap_dim_to_dim() ***********************************************
+ *
+ * Snaps the sides of two rectangles together.
+ *
+ * Snaps the dimensions of "src" to those of "snap" if any part
+ * of the "src" rectangle is within "snap_strength" of the "snap"
+ * rectangle. The resulting, snapped, rectangle is returned in
+ * "dst", along with the deltas (how far we needed to jump in order
+ * to produce a snap) in the vertical and horizontal directions.
+ *
+ * No vertically snapping occurs if 'best_vert' is NULL.
+ * No horizontal snapping occurs if 'best_horz' is NULL.
+ *
+ **/
+
+static void snap_dim_to_dim(int *dst, int *src, int *snap, int snap_strength,
+ int *best_vert, int *best_horz)
+{
+ int dist;
+
+
+ /* Snap vertically */
+ if (best_vert) {
+
+ /* Snap top side to top side */
+ dist = abs(snap[Y] - src[Y]);
+ if (dist <= snap_strength && dist < *best_vert) {
+ dst[Y] = snap[Y];
+ *best_vert = dist;
+ }
+
+ /* Snap top side to bottom side */
+ dist = abs((snap[Y] + snap[H]) - src[Y]);
+ if (dist <= snap_strength && dist < *best_vert) {
+ dst[Y] = snap[Y] + snap[H];
+ *best_vert = dist;
+ }
+
+ /* Snap bottom side to top side */
+ dist = abs(snap[Y] - (src[Y] + src[H]));
+ if (dist <= snap_strength && dist < *best_vert) {
+ dst[Y] = snap[Y] - src[H];
+ *best_vert = dist;
+ }
+
+ /* Snap bottom side to bottom side */
+ dist = abs((snap[Y] + snap[H]) - (src[Y] + src[H]));
+ if (dist <= snap_strength && dist < *best_vert) {
+ dst[Y] = snap[Y] + snap[H] - src[H];
+ *best_vert = dist;
+ }
+
+ /* Snap midlines */
+ if (/* Top of 'src' is above bottom of 'snap' */
+ (src[Y] <= snap[Y] + snap[H] + snap_strength) &&
+ /* Bottom of 'src' is below top of 'snap' */
+ (src[Y] + src[H] >= snap[Y] - snap_strength)) {
+
+ /* Snap vertically */
+ dist = abs((snap[Y] + snap[H]/2) - (src[Y]+src[H]/2));
+ if (dist <= snap_strength && dist < *best_vert) {
+ dst[Y] = snap[Y] + snap[H]/2 - src[H]/2;
+ *best_vert = dist;
+ }
+ }
+ }
+
+
+ /* Snap horizontally */
+ if (best_horz) {
+
+ /* Snap left side to left side */
+ dist = abs(snap[X] - src[X]);
+ if (dist <= snap_strength && dist < *best_horz) {
+ dst[X] = snap[X];
+ *best_horz = dist;
+ }
+
+ /* Snap left side to right side */
+ dist = abs((snap[X] + snap[W]) - src[X]);
+ if (dist <= snap_strength && dist < *best_horz) {
+ dst[X] = snap[X] + snap[W];
+ *best_horz = dist;
+ }
+
+ /* Snap right side to left side */
+ dist = abs(snap[X] - (src[X] + src[W]));
+ if (dist <= snap_strength && dist < *best_horz) {
+ dst[X] = snap[X] - src[W];
+ *best_horz = dist;
+ }
+
+ /* Snap right side to right side */
+ dist = abs((snap[X] + snap[W]) - (src[X]+src[W]));
+ if (dist <= snap_strength && dist < *best_horz) {
+ dst[X] = snap[X] + snap[W] - src[W];
+ *best_horz = dist;
+ }
+
+ /* Snap midlines */
+ if (/* Left of 'src' is before right of 'snap' */
+ (src[X] <= snap[X] + snap[W] + snap_strength) &&
+ /* Right of 'src' is after left of 'snap' */
+ (src[X] + src[W] >= snap[X] - snap_strength)) {
+
+ /* Snap vertically */
+ dist = abs((snap[X] + snap[W]/2) - (src[X]+src[W]/2));
+ if (dist <= snap_strength && dist < *best_horz) {
+ dst[X] = snap[X] + snap[W]/2 - src[W]/2;
+ *best_horz = dist;
+ }
+ }
+ }
+
+} /* snap_dim_to_dim() */
+
+
+
+/** snap_side_to_dim() **********************************************
+ *
+ * Snaps the sides of src to snap and stores the result in dst
+ *
+ * Returns 1 if a snap occured.
+ *
+ **/
+
+static void snap_side_to_dim(int *dst, int *src, int *snap, int snap_strength,
+ int *best_vert, int *best_horz)
+{
+ int dist;
+
+
+ /* Snap vertically */
+ if (best_vert) {
+
+ /* Snap side to top side */
+ dist = abs(snap[Y] - (src[Y] + src[H]));
+ if (dist <= snap_strength && dist < *best_vert) {
+ dst[H] = snap[Y] - src[Y];
+ *best_vert = dist;
+ }
+
+ /* Snap side to bottom side */
+ dist = abs((snap[Y] + snap[H]) - (src[Y] + src[H]));
+ if (dist <= snap_strength && dist < *best_vert) {
+ dst[H] = snap[Y] + snap[H] - src[Y];
+ *best_vert = dist;
+ }
+ }
+
+
+ /* Snap horizontally */
+ if (best_horz) {
+
+ /* Snap side to left side */
+ dist = abs(snap[X] - (src[X] + src[W]));
+ if (dist <= snap_strength && dist < *best_horz) {
+ dst[W] = snap[X] - src[X];
+ *best_horz = dist;
+ }
+
+ /* Snap side to right side */
+ dist = abs((snap[X] + snap[W]) - (src[X] + src[W]));
+ if (dist <= snap_strength && dist < *best_horz) {
+ dst[W] = snap[X] + snap[W] - src[X];
+ *best_horz = dist;
+ }
+ }
+
+} /* snap_side_to_dim() */
+
+
+
+/** snap_move() *****************************************************
+ *
+ * Snaps the given dimensions 'dim' (viewport or panning domain of
+ * a dislay) to other display devices' viewport and/or panning
+ * domains in the layout due to a move.
+ *
+ * Returns 1 if a snap occured, 0 if not.
+ *
+ **/
+
+static int snap_move(CtkDisplayLayout *ctk_object, int *dim)
+{
+ int dim_orig[4];
+ int best_vert;
+ int best_horz;
+ int *bv;
+ int *bh;
+ int z;
+ int dist;
+ nvDisplayPtr display;
+ nvDisplayPtr other;
+ nvGpuPtr gpu;
+ nvScreenPtr screen;
+
+
+ display = get_selected(ctk_object);
+ gpu = display->gpu;
+ screen = display->screen;
+
+
+ /* We will know that a snap occured if
+ * 'best_xxxx' <= ctk_object->snap_strength, so we
+ * initialize both directions to not having snapped here.
+ */
+ best_vert = ctk_object->snap_strength +1;
+ best_horz = ctk_object->snap_strength +1;
+
+
+ /* Copy the original dimensions (Always snap from this reference) */
+ dim_orig[X] = dim[X];
+ dim_orig[Y] = dim[Y];
+ dim_orig[W] = dim[W];
+ dim_orig[H] = dim[H];
+
+
+ /* Snap to other display's modes */
+ for (z = 1; z < ctk_object->Zcount; z++) {
+
+ other = ctk_object->Zorder[z];
+
+ /* Other display must have a mode */
+ if (!other || !other->cur_mode || !other->screen) continue;
+
+
+ bv = &best_vert;
+ bh = &best_horz;
+
+ /* We shouldn't snap horizontally to the other display if
+ * we are in a right-of/left-of relative relationship with
+ * the other display/display's screen.
+ */
+ if (((other->cur_mode->position_type == CONF_ADJ_RIGHTOF) ||
+ (other->cur_mode->position_type == CONF_ADJ_LEFTOF)) &&
+ (other->cur_mode->relative_to == display)) {
+ bh = NULL;
+ }
+ if (((display->cur_mode->position_type == CONF_ADJ_RIGHTOF) ||
+ (display->cur_mode->position_type == CONF_ADJ_LEFTOF)) &&
+ (display->cur_mode->relative_to == other)) {
+ bh = NULL;
+ }
+ if (display->screen && other->screen &&
+ ((other->screen->position_type == CONF_ADJ_RIGHTOF) ||
+ (other->screen->position_type == CONF_ADJ_LEFTOF)) &&
+ (other->screen->relative_to == display->screen)) {
+ bh = NULL;
+ }
+ if (display->screen && other->screen &&
+ ((display->screen->position_type == CONF_ADJ_RIGHTOF) ||
+ (display->screen->position_type == CONF_ADJ_LEFTOF)) &&
+ (display->screen->relative_to == other->screen)) {
+ bh = NULL;
+ }
+
+ /* If we aren't snapping horizontally with the other display,
+ * we shouldn't snap vertically either if this is the top-most
+ * display in the screen.
+ */
+ if (!bh && display->cur_mode->dim[Y] == display->screen->dim[Y]) {
+ bv = NULL;
+ }
+
+
+ /* We shouldn't snap vertically to the other display if
+ * we are in a above/below relative relationship with
+ * the other display/display's screen.
+ */
+ if (((other->cur_mode->position_type == CONF_ADJ_ABOVE) ||
+ (other->cur_mode->position_type == CONF_ADJ_BELOW)) &&
+ (other->cur_mode->relative_to == display)) {
+ bv = NULL;
+ }
+ if (((display->cur_mode->position_type == CONF_ADJ_ABOVE) ||
+ (display->cur_mode->position_type == CONF_ADJ_BELOW)) &&
+ (display->cur_mode->relative_to == other)) {
+ bv = NULL;
+ }
+
+ if (display->screen && other->screen &&
+ ((other->screen->position_type == CONF_ADJ_ABOVE) ||
+ (other->screen->position_type == CONF_ADJ_BELOW)) &&
+ (other->screen->relative_to == display->screen)) {
+ bv = NULL;
+ }
+ if (display->screen && other->screen &&
+ ((display->screen->position_type == CONF_ADJ_ABOVE) ||
+ (display->screen->position_type == CONF_ADJ_BELOW)) &&
+ (display->screen->relative_to == other->screen)) {
+ bv = NULL;
+ }
+
+ /* If we aren't snapping vertically with the other display,
+ * we shouldn't snap horizontally either if this is the left-most
+ * display in the screen.
+ */
+ if (!bv && display->cur_mode->dim[X] == display->screen->dim[X]) {
+ bh = NULL;
+ }
+
+
+ /* Snap to other display's panning dimensions */
+ snap_dim_to_dim(dim,
+ dim_orig,
+ ctk_object->Zorder[z]->cur_mode->pan,
+ ctk_object->snap_strength,
+ bv, bh);
+
+ /* Snap to other display's dimensions */
+ snap_dim_to_dim(dim,
+ dim_orig,
+ ctk_object->Zorder[z]->cur_mode->dim,
+ ctk_object->snap_strength,
+ bv, bh);
+ }
+
+
+ /* Snap to the maximum screen dimensions */
+ dist = abs(screen->dim[X] + gpu->max_width - dim_orig[W] - dim_orig[X]);
+ if (dist <= ctk_object->snap_strength && dist < best_horz) {
+ dim[X] = screen->dim[X] + gpu->max_width - dim_orig[W];
+ best_horz = dist;
+ }
+ dist = abs(screen->dim[Y] + gpu->max_height - dim_orig[H] - dim_orig[Y]);
+ if (dist <= ctk_object->snap_strength && dist < best_vert) {
+ dim[Y] = screen->dim[Y] + gpu->max_height - dim_orig[H];
+ best_vert = dist;
+ }
+
+
+ return (best_vert <= ctk_object->snap_strength ||
+ best_horz <= ctk_object->snap_strength);
+
+} /* snap_move() */
+
+
+
+/** snap_pan() ******************************************************
+ *
+ * Snaps the bottom right of the panning domain given 'pan' of the
+ * currently selected display to other display devices' viewport
+ * and/or panning domains in the layout due to a panning domain
+ * resize.
+ *
+ * Returns 1 if a snap happened, 0 if not.
+ *
+ **/
+
+static int snap_pan(CtkDisplayLayout *ctk_object, int *pan, int *dim)
+{
+ int pan_orig[4];
+ int best_vert;
+ int best_horz;
+ int *bv;
+ int *bh;
+ int z;
+ int dist;
+ nvDisplayPtr display;
+ nvDisplayPtr other;
+ nvGpuPtr gpu;
+ nvScreenPtr screen;
+
+
+ display = get_selected(ctk_object);
+ gpu = display->gpu;
+ screen = display->screen;
+
+
+ /* We will know that a snap occured if
+ * 'best_xxxx' <= ctk_object->snap_strength, so we
+ * initialize both directions to not having snapped here.
+ */
+ best_vert = ctk_object->snap_strength +1;
+ best_horz = ctk_object->snap_strength +1;
+
+
+ /* Copy the original dimensions (Always snap from this reference) */
+ pan_orig[X] = pan[X];
+ pan_orig[Y] = pan[Y];
+ pan_orig[W] = pan[W];
+ pan_orig[H] = pan[H];
+
+
+ /* Snap to other display's modes */
+ for (z = 1; z < ctk_object->Zcount; z++) {
+
+ other = ctk_object->Zorder[z];
+
+ /* Other display must have a mode */
+ if (!other || !other->cur_mode || !other->screen) continue;
+
+ bv = &best_vert;
+ bh = &best_horz;
+
+
+ /* Don't snap to other displays that are positioned right of
+ * the display being panned.
+ */
+ if ((other->cur_mode->position_type == CONF_ADJ_RIGHTOF) &&
+ other->cur_mode->relative_to == display) {
+ bh = NULL;
+ }
+ if ((display->cur_mode->position_type == CONF_ADJ_LEFTOF) &&
+ display->cur_mode->relative_to == other) {
+ bh = NULL;
+ }
+ if (display->screen && other->screen &&
+ (other->screen->position_type == CONF_ADJ_RIGHTOF) &&
+ (other->screen->relative_to == display->screen)) {
+ bh = NULL;
+ }
+ if (display->screen && other->screen &&
+ (display->screen->position_type == CONF_ADJ_LEFTOF) &&
+ (display->screen->relative_to == other->screen)) {
+ bh = NULL;
+ }
+
+ /* Don't snap to other displays that are positioned below of
+ * the display being panned.
+ */
+ if ((other->cur_mode->position_type == CONF_ADJ_BELOW) &&
+ other->cur_mode->relative_to == display) {
+ bv = NULL;
+ }
+ if ((display->cur_mode->position_type == CONF_ADJ_ABOVE) &&
+ display->cur_mode->relative_to == other) {
+ bv = NULL;
+ }
+ if (display->screen && other->screen &&
+ (other->screen->position_type == CONF_ADJ_BELOW) &&
+ (other->screen->relative_to == display->screen)) {
+ bv = NULL;
+ }
+ if (display->screen && other->screen &&
+ (display->screen->position_type == CONF_ADJ_ABOVE) &&
+ (display->screen->relative_to == other->screen)) {
+ bv = NULL;
+ }
+
+ /* Snap to other screen panning dimensions */
+ snap_side_to_dim(pan,
+ pan_orig,
+ ctk_object->Zorder[z]->cur_mode->pan,
+ ctk_object->snap_strength,
+ bv, bh);
+
+ /* Snap to other screen dimensions */
+ snap_side_to_dim(pan,
+ pan_orig,
+ ctk_object->Zorder[z]->cur_mode->dim,
+ ctk_object->snap_strength,
+ bv, bh);
+ }
+
+
+ /* Snap to multiples of the display's dimensions */
+ dist = pan_orig[W] % dim[W];
+ if (dist <= ctk_object->snap_strength && dist < best_horz) {
+ pan[W] = dim[W] * (int)(pan_orig[W] / dim[W]);
+ best_horz = dist;
+ }
+ dist = dim[W] - (pan_orig[W] % dim[W]);
+ if (dist <= ctk_object->snap_strength && dist < best_horz) {
+ pan[W] = dim[W] * (1 + (int)(pan_orig[W] / dim[W]));
+ best_horz = dist;
+ }
+ dist = abs(pan_orig[H] % dim[H]);
+ if (dist <= ctk_object->snap_strength && dist < best_vert) {
+ pan[H] = dim[H] * (int)(pan_orig[H] / dim[H]);
+ best_vert = dist;
+ }
+ dist = dim[H] - (pan_orig[H] % dim[H]);
+ if (dist <= ctk_object->snap_strength && dist < best_vert) {
+ pan[H] = dim[H] * (1 + (int)(pan_orig[H] / dim[H]));
+ best_vert = dist;
+ }
+
+
+ /* Snap to the maximum screen dimensions */
+ dist = abs((screen->dim[X] + gpu->max_width)
+ -(pan_orig[X] + pan_orig[W]));
+ if (dist <= ctk_object->snap_strength && dist < best_horz) {
+ pan[W] = screen->dim[X] + gpu->max_width - pan_orig[X];
+ best_horz = dist;
+ }
+ dist = abs((screen->dim[Y] + gpu->max_height)
+ -(pan_orig[Y] + pan_orig[H]));
+ if (dist <= ctk_object->snap_strength && dist < best_vert) {
+ pan[H] = screen->dim[Y] + gpu->max_height - pan_orig[Y];
+ best_vert = dist;
+ }
+
+
+ return (best_vert <= ctk_object->snap_strength ||
+ best_horz <= ctk_object->snap_strength);
+
+} /* snap_pan() */
+
+
+
+/** move_selected() **************************************************
+ *
+ * Moves the selected display device by the given offset, optionally
+ * snapping to other displays.
+ *
+ * If something actually moved, this function returns 1. Otherwise
+ * 0 is returned.
+ *
+ **/
+
+static int move_selected(CtkDisplayLayout *ctk_object, int x, int y, int snap)
+{
+ nvLayoutPtr layout = ctk_object->layout;
+ nvDisplayPtr display;
+ nvGpuPtr gpu;
+ nvScreenPtr screen;
+ int *pan;
+ int *dim;
+ int orig_pos[2];
+ int post_snap_display_pos[2];
+ int orig_mm_pos[2];
+ int snap_dim[4];
+
+
+ /* Get the dimensions of the display to move */
+ display = get_selected(ctk_object);
+ if (!display ||
+ !display->screen ||
+ !display->cur_mode ||
+ display->cur_mode->position_type != CONF_ADJ_ABSOLUTE) {
+ return 0;
+ }
+ gpu = display->gpu;
+ screen = display->screen;
+ dim = display->cur_mode->dim;
+ pan = display->cur_mode->pan;
+ orig_pos[X] = dim[X];
+ orig_pos[Y] = dim[Y];
+ orig_mm_pos[X] = display->screen->cur_metamode->dim[X];
+ orig_mm_pos[Y] = display->screen->cur_metamode->dim[Y];
+
+
+ /* Move the display */
+ ctk_object->modify_dim[X] += x;
+ ctk_object->modify_dim[Y] += y;
+ snap_dim[X] = ctk_object->modify_dim[X]; /* Snap from move dim */
+ snap_dim[Y] = ctk_object->modify_dim[Y];
+ snap_dim[W] = dim[W];
+ snap_dim[H] = dim[H];
+
+
+ /* Snap */
+ if (snap && ctk_object->snap_strength) {
+
+ /* Snap our viewport to other screens */
+ snap_move(ctk_object, snap_dim);
+
+ /* Snap our panning domain to other screens */
+ snap_dim[W] = pan[W];
+ snap_dim[H] = pan[H];
+ snap_move(ctk_object, snap_dim);
+ }
+ dim[X] = snap_dim[X];
+ dim[Y] = snap_dim[Y];
+ pan[X] = dim[X];
+ pan[Y] = dim[Y];
+
+
+ /* Prevent layout from growing too big */
+ x = MAX_LAYOUT_WIDTH - pan[W];
+ if (dim[X] > x) {
+ ctk_object->modify_dim[X] += x - dim[X];
+ dim[X] = x;
+ }
+ y = MAX_LAYOUT_HEIGHT - pan[H];
+ if (dim[Y] > y) {
+ ctk_object->modify_dim[Y] += y - dim[Y];
+ dim[Y] = y;
+ }
+ x = layout->dim[W] - MAX_LAYOUT_WIDTH;
+ if (dim[X] < x) {
+ ctk_object->modify_dim[X] += x - dim[X];
+ dim[X] = x;
+ }
+ y = layout->dim[H] - MAX_LAYOUT_HEIGHT;
+ if (dim[Y] < y) {
+ ctk_object->modify_dim[Y] += y - dim[Y];
+ dim[Y] = y;
+ }
+
+
+ /* Prevent screen from growing too big */
+ x = screen->dim[X] + gpu->max_width - pan[W];
+ if (dim[X] > x) {
+ ctk_object->modify_dim[X] += x - dim[X];
+ dim[X] = x;
+ }
+ y = screen->dim[Y] + gpu->max_height -pan[H];
+ if (dim[Y] > y) {
+ ctk_object->modify_dim[Y] += y - dim[Y];
+ dim[Y] = y;
+ }
+ x = screen->dim[X] + screen->dim[W] - gpu->max_width;
+ if (dim[X] < x) {
+ ctk_object->modify_dim[X] += x - dim[X];
+ dim[X] = x;
+ }
+ y = screen->dim[Y] + screen->dim[H] - gpu->max_height;
+ if (dim[Y] < y) {
+ ctk_object->modify_dim[Y] += y - dim[Y];
+ dim[Y] = y;
+ }
+
+
+ /* Sync panning position */
+ pan[X] = dim[X];
+ pan[Y] = dim[Y];
+
+
+ /* Get the post-snap display position. If calculating the
+ * layout changes the display's position, the modify dim
+ * (used to mode the display) should be offset as well.
+ */
+ post_snap_display_pos[X] = dim[X];
+ post_snap_display_pos[Y] = dim[Y];
+
+
+ /* If the display's screen is using absolute positioning, we should
+ * check to see if the position of the metamode has changed and if
+ * so, offset other metamodes on the screen (hence moving the screen's
+ * position.)
+ *
+ * If the screen is using relative positioning, don't offset
+ * metamodes since the screen's position is based on another
+ * screen.
+ */
+ if (display->screen->position_type == CONF_ADJ_ABSOLUTE) {
+ resolve_displays_in_screen(display->screen);
+ calc_metamode(display->screen, display->screen->cur_metamode);
+ x = display->screen->cur_metamode->dim[X] - orig_mm_pos[X];
+ y = display->screen->cur_metamode->dim[Y] - orig_mm_pos[Y];
+
+ if (x || y) {
+ nvDisplayPtr other;
+ nvModePtr mode;
+
+ for (other = display->gpu->displays; other; other = other->next) {
+
+ /* Other display must be in the same screen */
+ if (other->screen != display->screen) continue;
+
+ for (mode = other->modes; mode; mode = mode->next) {
+
+ /* Only move non-current modes */
+ if (mode == other->cur_mode) continue;
+
+ /* Don't move modes that are relative */
+ if (mode->position_type != CONF_ADJ_ABSOLUTE) continue;
+
+ mode->dim[X] += x;
+ mode->dim[Y] += y;
+ mode->pan[X] = mode->dim[X];
+ mode->pan[Y] = mode->dim[Y];
+ }
+ }
+ }
+ }
+
+
+ /* Recalculate layout dimensions and scaling */
+ calc_layout(layout);
+ offset_layout(layout, -layout->dim[X], -layout->dim[Y], 1);
+ recenter_layout(layout);
+ sync_scaling(ctk_object);
+
+
+ /* Update the modify dim if the position of the selected display changed */
+ if ((post_snap_display_pos[X] != dim[X] ||
+ post_snap_display_pos[Y] != dim[Y])) {
+ ctk_object->modify_dim[X] += dim[X] - post_snap_display_pos[X];
+ ctk_object->modify_dim[Y] += dim[Y] - post_snap_display_pos[Y];
+ }
+
+
+ /* Did the actual position of the display device change? */
+ if ((orig_pos[X] != dim[X] || orig_pos[Y] != dim[Y])) {
+ return 1;
+ }
+
+ return 0;
+
+} /* move_selected() */
+
+
+
+/** pan_selected() ***************************************************
+ *
+ * Changes the size of the panning domain of the selected display.
+ *
+ **/
+
+static int pan_selected(CtkDisplayLayout *ctk_object, int x, int y, int snap)
+{
+ nvLayoutPtr layout = ctk_object->layout;
+ nvDisplayPtr display;
+ nvScreenPtr screen;
+ nvGpuPtr gpu;
+ int *dim;
+ int *pan;
+ int orig_dim[4];
+
+
+
+ /* Get the dimensions of the display to pan */
+ display = get_selected(ctk_object);
+ if (!display || !display->screen || !display->cur_mode) {
+ return 0;
+ }
+ gpu = display->gpu;
+ screen = display->screen;
+ dim = display->cur_mode->dim;
+ pan = display->cur_mode->pan;
+ orig_dim[W] = pan[W];
+ orig_dim[H] = pan[H];
+
+
+ /* Resize the panning */
+ ctk_object->modify_dim[W] += x;
+ ctk_object->modify_dim[H] += y;
+
+
+ /* Panning can never be smaller then the display viewport */
+ if (ctk_object->modify_dim[W] < dim[W]) {
+ ctk_object->modify_dim[W] = dim[W];
+ }
+ if (ctk_object->modify_dim[H] < dim[H]) {
+ ctk_object->modify_dim[H] = dim[H];
+ }
+
+ pan[W] = ctk_object->modify_dim[W]; /* Snap from panning dimensions */
+ pan[H] = ctk_object->modify_dim[H];
+
+
+ /* Snap to other screens and dimensions */
+ if (snap && ctk_object->snap_strength) {
+ snap_pan(ctk_object, pan, dim);
+ }
+
+
+ /* Panning should not cause us to exceed the maximum layout dimensions */
+ x = MAX_LAYOUT_WIDTH - pan[X];
+ if (pan[W] > x) {
+ ctk_object->modify_dim[W] += x - pan[W];
+ pan[W] = x;
+ }
+ y = MAX_LAYOUT_HEIGHT - pan[Y];
+ if (pan[H] > y) {
+ ctk_object->modify_dim[H] += y - pan[H];
+ pan[H] = y;
+ }
+
+
+ /* Panning should not cause us to exceed the maximum screen dimensions */
+ x = screen->dim[X] + gpu->max_width - pan[X];
+ if (pan[W] > x) {
+ ctk_object->modify_dim[W] += x - pan[W];
+ pan[W] = x;
+ }
+ y = screen->dim[Y] + gpu->max_height - pan[Y];
+ if (pan[H] > y) {
+ ctk_object->modify_dim[H] += y - pan[H];
+ pan[H] = y;
+ }
+
+
+ /* Panning can never be smaller then the display viewport */
+ if (pan[W] < dim[W]) {
+ pan[W] = dim[W];
+ }
+ if (pan[H] < dim[H]) {
+ pan[H] = dim[H];
+ }
+
+
+ /* Recalculate layout dimensions and scaling */
+ calc_layout(layout);
+ offset_layout(layout, -layout->dim[X], -layout->dim[Y], 1);
+ recenter_layout(layout);
+ sync_scaling(ctk_object);
+
+
+ if (orig_dim[W] != pan[W] || orig_dim[H] != pan[H]) {
+ return 1;
+ }
+
+ return 0;
+
+} /* pan_selected() */
+
+
+
+/** select_display() *************************************************
+ *
+ * Moves the specified display to the top of the Zorder.
+ *
+ **/
+
+static void select_display(CtkDisplayLayout *ctk_object, nvDisplayPtr display)
+{
+ int z;
+
+ for (z = 0; z < ctk_object->Zcount; z++) {
+
+ /* Find the display in question */
+ if (ctk_object->Zorder[z] == display) {
+
+ /* Bubble it to the top */
+ while (z > 0) {
+ ctk_object->Zorder[z] = ctk_object->Zorder[z-1];
+ z--;
+ }
+ ctk_object->Zorder[0] = display;
+ ctk_object->Zselected = 1;
+ break;
+ }
+ }
+
+} /* select_display() */
+
+
+
+/** select_default_display() *****************************************
+ *
+ * Select the top left most display
+ *
+ */
+
+#define DIST_SQR(D) (((D)[X] * (D)[X]) + ((D)[Y] * (D)[Y]))
+
+static void select_default_display(CtkDisplayLayout *ctk_object)
+{
+ nvDisplayPtr display = NULL;
+ int z;
+
+ for (z = 0; z < ctk_object->Zcount; z++) {
+
+ if (!ctk_object->Zorder[z]->cur_mode) continue;
+
+ if (!display ||
+ (DIST_SQR(display->cur_mode->dim) >
+ DIST_SQR(ctk_object->Zorder[z]->cur_mode->dim))) {
+ display = ctk_object->Zorder[z];
+ }
+ }
+
+ if (display) {
+ select_display(ctk_object, display);
+ }
+
+} /* select_default_display() */
+
+
+
+/** pushback_display() ***********************************************
+ *
+ * Moves the specified display to the end of the Zorder
+ *
+ **/
+
+static void pushback_display(CtkDisplayLayout *ctk_object,
+ nvDisplayPtr display)
+{
+ int z;
+
+ if (!ctk_object->Zcount) {
+ return;
+ }
+
+ for (z = 0; z < ctk_object->Zcount; z++) {
+
+ /* Find the display */
+ if (ctk_object->Zorder[z] == display) {
+
+ /* Bubble it down */
+ while (z < ctk_object->Zcount -1) {
+ ctk_object->Zorder[z] = ctk_object->Zorder[z+1];
+ z++;
+ }
+ ctk_object->Zorder[ctk_object->Zcount -1] = display;
+ break;
+ }
+ }
+
+} /* pushback_display() */
+
+
+
+/** get_display_tooltip() ********************************************
+ *
+ * Returns the text to use for displaying a tooltip from the given
+ * display:
+ *
+ * MONITOR NAME : WIDTHxHEIGHT @ HERTZ (GPU NAME)
+ *
+ * The caller should free the string that is returned.
+ *
+ **/
+
+static char *get_display_tooltip(CtkDisplayLayout *ctk_object,
+ nvDisplayPtr display)
+{
+ char *tip;
+
+
+ /* No display given */
+ if (!display) {
+ return NULL;
+ }
+
+
+ /* Display does not have a screen (not configured) */
+ if (!(display->screen)) {
+ tip = g_strdup_printf("%s : Disabled (GPU: %s)",
+ display->name, display->gpu->name);
+
+
+ /* Basic view */
+ } else if (!ctk_object->advanced_mode) {
+
+ /* Display has no mode */
+ if (!display->cur_mode) {
+ tip = g_strdup_printf("%s", display->name);
+
+
+ /* Display does not have a current modeline (Off) */
+ } else if (!(display->cur_mode->modeline)) {
+ tip = g_strdup_printf("%s : Off",
+ display->name);
+
+ /* Display has mode/modeline */
+ } else {
+ float ref = GET_MODELINE_REFRESH_RATE(display->cur_mode->modeline);
+ tip = g_strdup_printf("%s : %dx%d @ %.0f Hz",
+ display->name,
+ display->cur_mode->modeline->data.hdisplay,
+ display->cur_mode->modeline->data.vdisplay,
+ ref);
+ }
+
+
+ /* Advanced view */
+ } else {
+
+
+ /* Display has no mode */
+ if (!display->cur_mode) {
+ tip = g_strdup_printf("%s : (Screen: %d) (GPU: %s)",
+ display->name,
+ display->screen->scrnum,
+ display->gpu->name);
+
+ /* Display does not have a current modeline (Off) */
+ } else if (!(display->cur_mode->modeline)) {
+ tip = g_strdup_printf("%s : Off (Screen: %d) (GPU: %s)",
+ display->name,
+ display->screen->scrnum,
+ display->gpu->name);
+
+ /* Display has mode/modeline */
+ } else {
+ float ref = GET_MODELINE_REFRESH_RATE(display->cur_mode->modeline);
+ tip = g_strdup_printf("%s : %dx%d @ %.0f Hz (Screen: %d) "
+ "(GPU: %s)",
+ display->name,
+ display->cur_mode->modeline->data.hdisplay,
+ display->cur_mode->modeline->data.vdisplay,
+ ref,
+ display->screen->scrnum,
+ display->gpu->name);
+ }
+ }
+
+ return tip;
+
+} /* get_display_tooltip() */
+
+
+
+/** get_display_tooltip_under_mouse() ********************************
+ *
+ * Returns the tooltip text that should be used to give information
+ * about the display under the mouse at x, y.
+ *
+ * The caller should free the string that is returned.
+ *
+ **/
+
+static char *get_display_tooltip_under_mouse(CtkDisplayLayout *ctk_object,
+ int x, int y)
+{
+ int z;
+ static nvDisplayPtr last_display = NULL;
+
+
+ /* Scale and offset x & y so they reside in clickable area */
+ x = (x -ctk_object->img_dim[X]) / ctk_object->scale;
+ y = (y -ctk_object->img_dim[Y]) / ctk_object->scale;
+
+
+ /* Find the first display under the cursor */
+ z = 0;
+ while (z < ctk_object->Zcount) {
+ if (ctk_object->Zorder[z]->cur_mode &&
+ point_in_dim(ctk_object->Zorder[z]->cur_mode->dim, x, y)) {
+ if (ctk_object->Zorder[z] == last_display) {
+ return NULL;
+ }
+ last_display = ctk_object->Zorder[z];
+ return get_display_tooltip(ctk_object, ctk_object->Zorder[z]);
+ }
+ z++;
+ }
+
+ /* Check display pannings as a last resort */
+ z = 0;
+ while (z < ctk_object->Zcount) {
+ if (ctk_object->Zorder[z]->cur_mode &&
+ point_in_dim(ctk_object->Zorder[z]->cur_mode->pan, x, y)) {
+ if (ctk_object->Zorder[z] == last_display) {
+ return NULL;
+ }
+ last_display = ctk_object->Zorder[z];
+ return get_display_tooltip(ctk_object, ctk_object->Zorder[z]);
+ }
+ z++;
+ }
+
+
+ if (last_display) {
+ last_display = NULL;
+ return g_strdup("*** No Display ***");
+ }
+
+ return NULL;
+
+} /* get_display_tooltip_under_mouse() */
+
+
+
+/** click_layout() ***************************************************
+ *
+ * Preforms a click in the layout, possibly selecting a display.
+ *
+ **/
+
+static int click_layout(CtkDisplayLayout *ctk_object, int x, int y)
+{
+ int z;
+ nvDisplayPtr cur_selected;
+
+
+ /* Make sure there is something to click */
+ if (!ctk_object->Zcount) {
+ return 0;
+ }
+
+
+ /* Keep track of the currently selected display */
+ cur_selected = ctk_object->Zorder[0];
+
+ /* Assume user didn't actually click inside a display for now */
+ ctk_object->clicked_outside = 1;
+
+ /* Push selected screen to the back of Z order */
+ ctk_object->Zselected = 0;
+ if (ctk_object->select_next) {
+ pushback_display(ctk_object, ctk_object->Zorder[0]);
+ }
+
+ /* Find the first display under the cursor */
+ z = 0;
+ while (z < ctk_object->Zcount) {
+ if (ctk_object->Zorder[z]->cur_mode &&
+ point_in_dim(ctk_object->Zorder[z]->cur_mode->dim, x, y)) {
+ select_display(ctk_object, ctk_object->Zorder[z]);
+ ctk_object->clicked_outside = 0;
+ break;
+ }
+ z++;
+ }
+
+ /* Check if we clicked on a panning domain */
+ if (!(ctk_object->Zselected)) {
+ z = 0;
+ while (z < ctk_object->Zcount) {
+ if (ctk_object->Zorder[z]->cur_mode &&
+ point_in_dim(ctk_object->Zorder[z]->cur_mode->pan, x, y)) {
+ select_display(ctk_object, ctk_object->Zorder[z]);
+ ctk_object->clicked_outside = 0;
+ break;
+ }
+ z++;
+ }
+ }
+
+ /* Reselect the last display */
+ if (ctk_object->clicked_outside && cur_selected) {
+ select_display(ctk_object, cur_selected);
+ }
+
+ /* Sync modify dimensions to the newly selected display */
+ sync_modify(ctk_object);
+
+ return 1;
+
+} /* click_layout() */
+
+
+
+/** ctk_display_layout_get_type() ************************************
+ *
+ * Returns the CtkDisplayLayout type.
+ *
+ **/
+
+GType ctk_display_layout_get_type(void)
+{
+ static GType ctk_display_layout_type = 0;
+
+ if (!ctk_display_layout_type) {
+ static const GTypeInfo ctk_display_layout_info = {
+ sizeof (CtkDisplayLayoutClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof(CtkDisplayLayout),
+ 0, /* n_preallocs */
+ NULL, /* instance_init */
+ };
+
+ ctk_display_layout_type = g_type_register_static
+ (GTK_TYPE_VBOX, "CtkDisplayLayout", &ctk_display_layout_info, 0);
+ }
+
+ return ctk_display_layout_type;
+
+} /* ctk_display_layout_get_type() */
+
+
+
+/** ctk_display_layout_new() *****************************************
+ *
+ * CTK Display Layout widget creation.
+ *
+ */
+GtkWidget* ctk_display_layout_new(NvCtrlAttributeHandle *handle,
+ CtkConfig *ctk_config,
+ nvLayoutPtr layout,
+ int width,
+ int height,
+ ctk_display_layout_selected_callback selected_callback,
+ void *selected_callback_data,
+ ctk_display_layout_modified_callback modified_callback,
+ void *modified_callback_data)
+{
+ GObject *object;
+ CtkDisplayLayout *ctk_object;
+ GtkWidget *tmp;
+ PangoFontDescription *font_description;
+ int i;
+
+
+ /* Make sure we have a handle */
+ g_return_val_if_fail(handle != NULL, NULL);
+
+
+ /* Create the ctk object */
+ object = g_object_new(CTK_TYPE_DISPLAY_LAYOUT, NULL);
+ ctk_object = CTK_DISPLAY_LAYOUT(object);
+
+ /* Setup widget properties */
+ ctk_object->ctk_config = ctk_config;
+ ctk_object->selected_callback = selected_callback;
+ ctk_object->selected_callback_data = selected_callback_data;
+ ctk_object->modified_callback = modified_callback;
+ ctk_object->modified_callback_data = modified_callback_data;
+
+ ctk_object->handle = handle;
+ ctk_object->layout = layout;
+ calc_layout(layout);
+ sync_scaling(ctk_object);
+ zorder_layout(ctk_object);
+ select_default_display(ctk_object);
+
+
+ /* Setup Pango layout/font */
+ ctk_object->pango_layout =
+ gtk_widget_create_pango_layout(GTK_WIDGET(ctk_object), NULL);
+
+ pango_layout_set_alignment(ctk_object->pango_layout, PANGO_ALIGN_CENTER);
+
+ font_description = pango_font_description_new();
+ pango_font_description_set_family(font_description, "Sans");
+ pango_font_description_set_weight(font_description, PANGO_WEIGHT_BOLD);
+
+ pango_layout_set_font_description(ctk_object->pango_layout, font_description);
+
+
+ /* Setup colors */
+ gdk_color_parse(LAYOUT_IMG_FG_COLOR, &(ctk_object->fg_color));
+ gdk_color_parse(LAYOUT_IMG_BG_COLOR, &(ctk_object->bg_color));
+ gdk_color_parse(LAYOUT_IMG_SELECT_COLOR, &(ctk_object->select_color));
+
+ /* Parse the device color palettes */
+ ctk_object->color_palettes =
+ (GdkColor *)calloc(1, NUM_COLORS * sizeof(GdkColor));
+ for (i = 0; i < NUM_COLORS; i++) {
+ gdk_color_parse(__palettes_color_names[i],
+ &(ctk_object->color_palettes[i]));
+ }
+
+
+ /* Setup the layout state variables */
+ ctk_object->snap_strength = DEFAULT_SNAP_STRENGTH;
+ ctk_object->need_swap = 0;
+ ctk_object->select_next = 0;
+
+
+ /* Make the drawing area */
+ tmp = gtk_drawing_area_new();
+ gtk_widget_add_events(tmp,
+ GDK_EXPOSURE_MASK |
+ GDK_BUTTON_PRESS_MASK |
+ GDK_BUTTON_RELEASE_MASK |
+ GDK_POINTER_MOTION_MASK);
+
+ g_signal_connect (G_OBJECT (tmp), "expose_event",
+ G_CALLBACK (expose_event_callback), (gpointer)(ctk_object));
+
+ g_signal_connect (G_OBJECT (tmp), "configure_event",
+ G_CALLBACK (configure_event_callback), (gpointer)(ctk_object));
+
+ g_signal_connect (G_OBJECT (tmp), "motion_notify_event",
+ G_CALLBACK (motion_event_callback), (gpointer)(ctk_object));
+
+ g_signal_connect (G_OBJECT (tmp), "button_press_event",
+ G_CALLBACK (button_press_event_callback), (gpointer)(ctk_object));
+
+ g_signal_connect (G_OBJECT (tmp), "button_release_event",
+ G_CALLBACK (button_release_event_callback), (gpointer)(ctk_object));
+
+ GTK_WIDGET_SET_FLAGS(tmp, GTK_DOUBLE_BUFFERED);
+
+ ctk_object->drawing_area = tmp;
+ gtk_widget_set_size_request(tmp, width, height);
+
+
+ /* Set container properties of the object */
+ gtk_box_set_spacing(GTK_BOX(ctk_object), 0);
+
+ ctk_object->tooltip_area = gtk_event_box_new();
+ ctk_object->tooltip_group = gtk_tooltips_new();
+
+ gtk_tooltips_enable(ctk_object->tooltip_group);
+ gtk_tooltips_set_tip(ctk_object->tooltip_group,
+ ctk_object->tooltip_area,
+ "*** No Display ***", NULL);
+
+ gtk_container_add(GTK_CONTAINER(ctk_object->tooltip_area), tmp);
+ gtk_box_pack_start(GTK_BOX(object), ctk_object->tooltip_area,
+ TRUE, TRUE, 0);
+
+ return GTK_WIDGET(ctk_object);
+
+} /* ctk_display_layout_new() */
+
+
+
+/** do_swap() ********************************************************
+ *
+ * Preforms a swap from the back buffer if one is needed.
+ *
+ **/
+
+static void do_swap(CtkDisplayLayout *ctk_object)
+{
+ if (ctk_object->need_swap) {
+
+ gdk_draw_pixmap(ctk_object->drawing_area->window,
+ ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE(ctk_object->drawing_area)],
+ ctk_object->pixmap,
+ 0,0,
+ 0,0,
+ ctk_object->width,
+ ctk_object->height);
+
+ ctk_object->need_swap = 0;
+ }
+
+} /* do_swap() */
+
+
+
+/** draw_rect() ******************************************************
+ *
+ * Draws a solid or wireframe rectangle to scale of the given color
+ * in the given widget.
+ *
+ **/
+
+static void draw_rect(CtkDisplayLayout *ctk_object,
+ int *dim,
+ GdkColor *color,
+ int fill)
+{
+ int w = (int)(ctk_object->scale * (dim[X] + dim[W])) - (int)(ctk_object->scale * (dim[X]));
+ int h = (int)(ctk_object->scale * (dim[Y] + dim[H])) - (int)(ctk_object->scale * (dim[Y]));
+
+ /* Setup color to use */
+ gdk_gc_set_rgb_fg_color(ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE (ctk_object->drawing_area)],
+ color);
+
+ /* Draw the rectangle */
+ gdk_draw_rectangle(ctk_object->pixmap,
+ ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE (ctk_object->drawing_area)],
+ fill,
+ ctk_object->img_dim[X] + ctk_object->scale * dim[X],
+ ctk_object->img_dim[Y] + ctk_object->scale * dim[Y],
+ w,
+ h);
+
+ ctk_object->need_swap = 1;
+
+} /* draw_rect() */
+
+
+
+/** draw_rect_strs() *************************************************
+ *
+ * Draws possibly 2 rows of text in the middle of a bounding,
+ * scaled rectangle. If the text does not fit, it is not drawn.
+ *
+ **/
+
+static void draw_rect_strs(CtkDisplayLayout *ctk_object,
+ int *dim,
+ GdkColor *color,
+ const char *str_1,
+ const char *str_2)
+{
+ GdkGC *gdk_gc;
+ GtkWidget *drawing_area;
+ char *str;
+
+ int txt_w;
+ int txt_h;
+ int txt_x, txt_x1, txt_x2;
+ int txt_y, txt_y1, txt_y2;
+
+ int draw_1 = 0;
+ int draw_2 = 0;
+
+ drawing_area = ctk_object->drawing_area;
+ gdk_gc = drawing_area->style->fg_gc[GTK_WIDGET_STATE(drawing_area)];
+
+ if (str_1) {
+ pango_layout_set_text(ctk_object->pango_layout, str_1, -1);
+ pango_layout_get_pixel_size(ctk_object->pango_layout, &txt_w, &txt_h);
+
+ if (txt_w +8 <= ctk_object->scale * dim[W] &&
+ txt_h +8 <= ctk_object->scale * dim[H]) {
+ draw_1 = 1;
+ }
+ }
+
+ if (str_2) {
+ pango_layout_set_text(ctk_object->pango_layout, str_2, -1);
+ pango_layout_get_pixel_size(ctk_object->pango_layout, &txt_w, &txt_h);
+
+ if (txt_w +8 <= ctk_object->scale * dim[W] &&
+ txt_h +8 <= ctk_object->scale * dim[H]) {
+ draw_2 = 1;
+ }
+
+ str = g_strconcat(str_1, "\n", str_2, NULL);
+
+ pango_layout_set_text(ctk_object->pango_layout, str, -1);
+ pango_layout_get_pixel_size(ctk_object->pango_layout, &txt_w, &txt_h);
+
+ if (draw_1 && draw_2 &&
+ txt_h +8 > ctk_object->scale * dim[H]) {
+ draw_2 = 0;
+ }
+
+ g_free(str);
+ }
+
+ if (draw_1 && !draw_2) {
+ pango_layout_set_text(ctk_object->pango_layout, str_1, -1);
+ pango_layout_get_pixel_size(ctk_object->pango_layout, &txt_w, &txt_h);
+
+ txt_x1 = ctk_object->scale*(dim[X] + dim[W] / 2) - (txt_w / 2);
+ txt_y1 = ctk_object->scale*(dim[Y] + dim[H] / 2) - (txt_h / 2);
+
+ /* Write name */
+ gdk_gc_set_rgb_fg_color(gdk_gc, color);
+
+ gdk_draw_layout(ctk_object->pixmap, gdk_gc,
+ ctk_object->img_dim[X] + txt_x1,
+ ctk_object->img_dim[Y] + txt_y1,
+ ctk_object->pango_layout);
+
+ ctk_object->need_swap = 1;
+ }
+
+ else if (!draw_1 && draw_2) {
+ pango_layout_set_text(ctk_object->pango_layout, str_2, -1);
+ pango_layout_get_pixel_size(ctk_object->pango_layout, &txt_w, &txt_h);
+
+ txt_x2 = ctk_object->scale*(dim[X] + dim[W] / 2) - (txt_w / 2);
+ txt_y2 = ctk_object->scale*(dim[Y] + dim[H] / 2) - (txt_h / 2);
+
+ /* Write dimensions */
+ gdk_gc_set_rgb_fg_color(gdk_gc, color);
+
+ gdk_draw_layout(ctk_object->pixmap, gdk_gc,
+ ctk_object->img_dim[X] + txt_x2,
+ ctk_object->img_dim[Y] + txt_y2,
+ ctk_object->pango_layout);
+
+ ctk_object->need_swap = 1;
+ }
+
+ else if (draw_1 && draw_2) {
+ str = g_strconcat(str_1, "\n", str_2, NULL);
+
+ pango_layout_set_text(ctk_object->pango_layout, str, -1);
+ pango_layout_get_pixel_size(ctk_object->pango_layout, &txt_w, &txt_h);
+
+ txt_x = ctk_object->scale*(dim[X] + dim[W] / 2) - (txt_w / 2);
+ txt_y = ctk_object->scale*(dim[Y] + dim[H] / 2) - (txt_h / 2);
+
+ /* Write both */
+ gdk_gc_set_rgb_fg_color(gdk_gc, color);
+
+ gdk_draw_layout(ctk_object->pixmap, gdk_gc,
+ ctk_object->img_dim[X] + txt_x,
+ ctk_object->img_dim[Y] + txt_y,
+ ctk_object->pango_layout);
+
+ g_free(str);
+ }
+
+} /* draw_rect_strs() */
+
+
+
+/** draw_display() ***************************************************
+ *
+ * Draws a display to scale within the layout.
+ *
+ **/
+
+static void draw_display(CtkDisplayLayout *ctk_object,
+ nvDisplayPtr display)
+{
+ nvModePtr mode;
+ int color;
+ char *tmp_str;
+
+ if (!display || !(display->cur_mode)) {
+ return;
+ }
+
+ mode = display->cur_mode;
+ color = NUM_COLORS_PER_PALETTE * NvCtrlGetTargetId(display->gpu->handle);
+
+
+ /* Draw panning */
+ draw_rect(ctk_object, mode->pan,
+ &(ctk_object->color_palettes[color +((mode->modeline)?BG_PAN_ON:BG_PAN_OFF)]),
+ 1);
+ draw_rect(ctk_object, mode->pan, &(ctk_object->fg_color), 0);
+
+
+ /* Draw viewport */
+ draw_rect(ctk_object, mode->dim,
+ &(ctk_object->color_palettes[color +((mode->modeline)?BG_SCR_ON:BG_SCR_OFF)]),
+ 1);
+ draw_rect(ctk_object, mode->dim, &(ctk_object->fg_color), 0);
+
+
+ /* Draw text information */
+ if (!mode->display->screen) {
+ tmp_str = g_strdup("(Disabled)");
+ } else if (mode->modeline) {
+ tmp_str = g_strdup_printf("%dx%d", mode->dim[W], mode->dim[H]);
+ } else {
+ tmp_str = g_strdup("(Off)");
+ }
+ draw_rect_strs(ctk_object,
+ mode->dim,
+ &(ctk_object->fg_color),
+ display->name,
+ tmp_str);
+ g_free(tmp_str);
+
+} /* draw_display() */
+
+
+
+/** draw_layout() ****************************************************
+ *
+ * Draws a layout.
+ *
+ **/
+
+static void draw_layout(CtkDisplayLayout *ctk_object)
+{
+ int z;
+ GdkColor bg_color; /* Background color */
+ GdkColor bd_color; /* Border color */
+ nvGpuPtr gpu;
+ nvScreenPtr screen;
+
+
+ /* Draw the metamode's effective size */
+ gdk_color_parse("#888888", &bg_color);
+ gdk_color_parse("#777777", &bd_color);
+
+ gdk_gc_set_line_attributes
+ (ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE(ctk_object->drawing_area)],
+ 1, GDK_LINE_ON_OFF_DASH, GDK_CAP_NOT_LAST,
+ GDK_JOIN_ROUND);
+
+ for (gpu = ctk_object->layout->gpus; gpu; gpu = gpu->next) {
+ for (screen = gpu->screens; screen; screen = screen->next) {
+ draw_rect(ctk_object, screen->cur_metamode->edim, &bg_color, 1);
+ draw_rect(ctk_object, screen->cur_metamode->edim,
+ &(ctk_object->fg_color), 0);
+ }
+ }
+
+ gdk_gc_set_line_attributes
+ (ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE(ctk_object->drawing_area)],
+ 1, GDK_LINE_SOLID, GDK_CAP_NOT_LAST,
+ GDK_JOIN_ROUND);
+
+
+ /* Draw display devices from back to front */
+ for (z = ctk_object->Zcount - 1; z >= 0; z--) {
+ draw_display(ctk_object, ctk_object->Zorder[z]);
+ ctk_object->need_swap = 1;
+ }
+
+
+ /* Hilite the selected display device */
+ if (ctk_object->Zselected && ctk_object->Zcount) {
+ GtkWidget *widget = ctk_object->drawing_area;
+ int w, h;
+ int size; /* Hilite line size */
+ int offset; /* Hilite box offset */
+ int *dim;
+
+ dim = ctk_object->Zorder[0]->cur_mode->dim;
+
+ /* Draw red selection border */
+ w = (int)(ctk_object->scale * (dim[X] + dim[W])) - (int)(ctk_object->scale * (dim[X]));
+ h = (int)(ctk_object->scale * (dim[Y] + dim[H])) - (int)(ctk_object->scale * (dim[Y]));
+
+ /* Setup color to use */
+ gdk_gc_set_rgb_fg_color(widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ &(ctk_object->select_color));
+
+ /* If dislay is too small, just color the whole thing */
+ size = 3;
+ offset = (size/2) +1;
+
+ if ((w -(2* offset) < 0) || (h -(2 *offset) < 0)) {
+ draw_rect(ctk_object, dim, &(ctk_object->select_color), 1);
+ draw_rect(ctk_object, dim, &(ctk_object->fg_color), 0);
+
+ } else {
+ gdk_gc_set_line_attributes(widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ size, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+
+ gdk_draw_rectangle(ctk_object->pixmap,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ 0,
+ ctk_object->img_dim[X] +(ctk_object->scale * dim[X]) +offset,
+ ctk_object->img_dim[Y] +(ctk_object->scale * dim[Y]) +offset,
+ w -(2 * offset),
+ h -(2 * offset));
+
+ gdk_gc_set_line_attributes(widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ 1, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+ }
+
+ /* Uncomment to show unsnapped dimensions */
+ //gdk_color_parse("#DD4444", &bg_color);
+ //gdk_gc_set_rgb_fg_color(widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ // &(bg_color));
+ //draw_rect(ctk_object, ctk_object->modify_dim, &bg_color, 0);
+
+ ctk_object->need_swap = 1;
+ }
+
+} /* draw_layout() */
+
+
+
+/** clear_layout() ***************************************************
+ *
+ * Clears the layout.
+ *
+ **/
+
+static void clear_layout(CtkDisplayLayout *ctk_object)
+{
+ GtkWidget *widget = ctk_object->drawing_area;
+ GdkColor color;
+
+
+
+ /* Clear to background color */
+ gdk_gc_set_rgb_fg_color(widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ &(ctk_object->bg_color));
+ gdk_draw_rectangle(ctk_object->pixmap,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ TRUE,
+ 2,
+ 2,
+ widget->allocation.width -4,
+ widget->allocation.height -4);
+
+
+ /* Add white trim */
+ gdk_color_parse("white", &color);
+ gdk_gc_set_rgb_fg_color(widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ &color);
+ gdk_draw_rectangle(ctk_object->pixmap,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ FALSE,
+ 1,
+ 1,
+ widget->allocation.width -3,
+ widget->allocation.height -3);
+
+
+ /* Add layout border */
+ gdk_gc_set_rgb_fg_color(widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ &(ctk_object->fg_color));
+ gdk_draw_rectangle(ctk_object->pixmap,
+ widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ FALSE,
+ 0,
+ 0,
+ widget->allocation.width -1,
+ widget->allocation.height -1);
+
+ ctk_object->need_swap = 1;
+
+} /* clear_layout() */
+
+
+
+/** draw_all() *******************************************************
+ *
+ * Clears and redraws the entire layout.
+ *
+ **/
+
+static void draw_all(CtkDisplayLayout *ctk_object)
+{
+ GdkGCValues old_gc_values;
+ GtkWidget *widget = ctk_object->drawing_area;
+
+
+ /* Redraw everything */
+ gdk_gc_get_values(widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ &old_gc_values);
+
+ clear_layout(ctk_object);
+
+ draw_layout(ctk_object);
+
+ gdk_gc_set_values(widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ &old_gc_values,
+ GDK_GC_FOREGROUND);
+
+} /* draw_all() */
+
+
+
+/** ctk_display_layout_redraw() **************************************
+ *
+ * Redraw everything in the layout and makes sure the widget is
+ * updated.
+ *
+ **/
+
+void ctk_display_layout_redraw(CtkDisplayLayout *ctk_object)
+{
+ nvLayoutPtr layout = ctk_object->layout;
+
+ /* Recalculate layout dimensions and scaling */
+ calc_layout(layout);
+ offset_layout(layout, -layout->dim[X], -layout->dim[Y], 1);
+ recenter_layout(layout);
+ sync_scaling(ctk_object);
+ sync_modify(ctk_object);
+
+ /* Redraw */
+ draw_all(ctk_object);
+
+ /* Refresh GUI */
+ do_swap(ctk_object);
+
+} /* ctk_display_layout_redraw() */
+
+
+
+/** ctk_display_layout_set_layout() **********************************
+ *
+ * Configures the display layout widget to show the given layout.
+ *
+ **/
+
+void ctk_display_layout_set_layout(CtkDisplayLayout *ctk_object,
+ nvLayoutPtr layout)
+{
+ /* Setup for the new layout */
+ ctk_object->layout = layout;
+ zorder_layout(ctk_object);
+ select_default_display(ctk_object);
+ calc_layout(layout);
+ offset_layout(layout, -layout->dim[X], -layout->dim[Y], 1);
+ recenter_layout(layout);
+ sync_scaling(ctk_object);
+ sync_modify(ctk_object);
+
+ /* Redraw */
+ draw_all(ctk_object);
+
+ /* Refresh GUI */
+ do_swap(ctk_object);
+
+} /* ctk_display_layout_set_layout() */
+
+
+
+/** ctk_display_layout_get_selected_display() ************************
+ *
+ * Returns the selected display.
+ *
+ **/
+
+nvDisplayPtr ctk_display_layout_get_selected_display(CtkDisplayLayout *ctk_object)
+{
+ return get_selected(ctk_object);
+
+} /* ctk_display_layout_get_selected_display() */
+
+
+
+/** ctk_display_layout_get_selected_screen() *************************
+ *
+ * Returns the selected screen.
+ *
+ **/
+
+nvScreenPtr ctk_display_layout_get_selected_screen(CtkDisplayLayout *ctk_object)
+{
+ nvDisplayPtr display = get_selected(ctk_object);
+ if (display) {
+ return display->screen;
+ }
+ return NULL;
+
+} /* ctk_display_layout_get_selected_screen() */
+
+
+
+/** ctk_display_layout_get_selected_gpu() ****************************
+ *
+ * Returns the selected gpu.
+ *
+ **/
+
+nvGpuPtr ctk_display_layout_get_selected_gpu(CtkDisplayLayout *ctk_object)
+{
+ nvDisplayPtr display = get_selected(ctk_object);
+ if (display) {
+ return display->gpu;
+ }
+ return NULL;
+
+} /* ctk_display_layout_get_selected_gpu() */
+
+
+
+/** ctk_display_layout_set_screen_metamode() *************************
+ *
+ * Sets which metamode the screen should be use.
+ *
+ **/
+
+void ctk_display_layout_set_screen_metamode(CtkDisplayLayout *ctk_object,
+ nvScreenPtr screen,
+ int new_metamode_idx)
+{
+ if (!screen) return;
+
+ /* Make sure the metamode exists */
+ if (new_metamode_idx < 0) {
+ new_metamode_idx = 0;
+ } else if (new_metamode_idx >= screen->num_metamodes) {
+ new_metamode_idx = screen->num_metamodes -1;
+ }
+
+ /* Select the new metamode and recalculate layout dimensions and scaling */
+ set_screen_metamode(ctk_object->layout, screen, new_metamode_idx);
+ recenter_layout(ctk_object->layout);
+ sync_scaling(ctk_object);
+ sync_modify(ctk_object);
+
+ /* Redraw the layout */
+ ctk_display_layout_redraw(ctk_object);
+
+} /* ctk_display_layout_set_screen_metamode() */
+
+
+
+/** ctk_display_layout_add_screen_metamode() *************************
+ *
+ * Adds a new metamode to the screen.
+ *
+ **/
+
+void ctk_display_layout_add_screen_metamode(CtkDisplayLayout *ctk_object,
+ nvScreenPtr screen)
+{
+ nvDisplayPtr display = get_selected(ctk_object);
+ nvMetaModePtr metamode;
+
+
+ if (!screen || !screen->gpu) return;
+
+
+ /* Add a metamode to the screen */
+ metamode = (nvMetaModePtr)calloc(1, sizeof(nvMetaMode));
+ if (!metamode) return;
+
+ /* Duplicate the currently selected metamode */
+ metamode->id = -1;
+ metamode->source = METAMODE_SOURCE_NVCONTROL;
+
+ /* Add the metamode after the currently selected metamode */
+ metamode->next = screen->cur_metamode->next;
+ screen->cur_metamode->next = metamode;
+ screen->num_metamodes++;
+
+
+ /* Add a mode to each display */
+ for (display = screen->gpu->displays; display; display = display->next) {
+ nvModePtr mode;
+
+ if (display->screen != screen) continue; /* Display not in screen */
+
+ /* Create the mode */
+ mode = (nvModePtr)calloc(1, sizeof(nvMode));
+ if (!mode) goto fail;
+
+ /* Link the mode to the metamode */
+ mode->metamode = metamode;
+
+ /* Duplicate the currently selected mode */
+ mode->display = display;
+ if (display->cur_mode) {
+ mode->modeline = display->cur_mode->modeline;
+ mode->dim[X] = display->cur_mode->dim[X];
+ mode->dim[Y] = display->cur_mode->dim[Y];
+ mode->dim[W] = display->cur_mode->dim[W];
+ mode->dim[H] = display->cur_mode->dim[H];
+ mode->pan[X] = display->cur_mode->pan[X];
+ mode->pan[Y] = display->cur_mode->pan[Y];
+ mode->pan[W] = display->cur_mode->pan[W];
+ mode->pan[H] = display->cur_mode->pan[H];
+ mode->position_type = display->cur_mode->position_type;
+ mode->relative_to = display->cur_mode->relative_to;
+ }
+
+ /* Add the mode after the currently selected mode */
+ mode->next = display->cur_mode->next;
+ display->cur_mode->next = mode;
+ display->num_modes++;
+ }
+
+ /* Select the newly created metamode */
+ ctk_display_layout_set_screen_metamode(ctk_object,
+ screen,
+ (screen->cur_metamode_idx+1));
+ return;
+
+ fail:
+ /* XXX Need to bail better:
+ * - Remove metamode from screen
+ * - Remove any excess metamodes from the displays
+ */
+ return;
+
+} /* ctk_display_layout_add_screen_metamode() */
+
+
+
+/** ctk_display_layout_delete_screen_metamode() **********************
+ *
+ * Deletes a metamode from the screen (also deletes corresponding
+ * modes from the screen's displays.)
+ *
+ **/
+
+void ctk_display_layout_delete_screen_metamode(CtkDisplayLayout *ctk_object,
+ nvScreenPtr screen,
+ int metamode_idx)
+{
+ nvDisplayPtr display;
+ nvMetaModePtr metamode;
+ nvMetaModePtr metamode_prev;
+ nvModePtr mode ;
+ nvModePtr mode_prev;
+ int i;
+
+
+ if (!screen || !screen->gpu || metamode_idx >= screen->num_metamodes) {
+ return;
+ }
+
+
+ /* Don't delete the last metamode */
+ if (screen->num_metamodes <= 1) {
+ return;
+ }
+
+
+ /* Find the metamode */
+ metamode_prev = NULL;
+ metamode = screen->metamodes;
+ i = 0;
+ while (metamode && i < metamode_idx) {
+ metamode_prev = metamode;
+ metamode = metamode->next;
+ i++;
+ }
+
+
+ /* Remove the metamode from the list */
+ if (!metamode_prev) {
+ screen->metamodes = screen->metamodes->next;
+ } else {
+ metamode_prev->next = metamode->next;
+ }
+ screen->num_metamodes--;
+
+ if (screen->cur_metamode == metamode) {
+ screen->cur_metamode = metamode->next;
+ }
+ if (screen->cur_metamode_idx >= screen->num_metamodes) {
+ screen->cur_metamode_idx = screen->num_metamodes -1;
+ }
+
+ free(metamode);
+
+
+ /* Delete the mode from each display in the screen */
+ for (display = screen->gpu->displays; display; display = display->next) {
+
+ if (display->screen != screen) continue;
+
+ /* Find the mode */
+ mode_prev = NULL;
+ mode = display->modes;
+ for (i = 0; i != metamode_idx; i++) {
+ mode_prev = mode;
+ mode = mode->next;
+ }
+
+ /* Remove the mode from the list */
+ if (!mode_prev) {
+ display->modes = display->modes->next;
+ } else {
+ mode_prev->next = mode->next;
+ }
+ display->num_modes--;
+
+ if (display->cur_mode == mode) {
+ display->cur_mode = mode->next;
+ }
+
+ /* Delete the mode */
+ free(mode);
+ }
+
+
+ /* Update which metamode should be selected */
+ ctk_display_layout_set_screen_metamode
+ (ctk_object, screen, screen->cur_metamode_idx);
+
+} /* ctk_display_layout_delete_screen_metamode() */
+
+
+
+/** ctk_display_layout_set_mode_modeline() ***************************
+ *
+ * Sets which modeline the mode should use.
+ *
+ **/
+
+void ctk_display_layout_set_mode_modeline(CtkDisplayLayout *ctk_object,
+ nvModePtr mode,
+ nvModeLinePtr modeline)
+{
+ nvLayoutPtr layout = ctk_object->layout;
+ nvModeLinePtr old_modeline;
+
+ if (!mode) {
+ return;
+ }
+
+ /* Set the new modeline */
+ old_modeline = mode->modeline;
+ mode->modeline = modeline;
+
+
+ /* Setup the mode's dimensions based on the modeline */
+ if (modeline) {
+ mode->dim[W] = modeline->data.hdisplay;
+ mode->dim[H] = modeline->data.vdisplay;
+
+ if (mode->pan[W] < modeline->data.hdisplay) {
+ mode->pan[W] = modeline->data.hdisplay;
+ }
+ if (mode->pan[H] < modeline->data.vdisplay) {
+ mode->pan[H] = modeline->data.vdisplay;
+ }
+
+ /* If the old modeline did not have panning dimensions */
+ if (!old_modeline ||
+ (mode->pan[W] == old_modeline->data.hdisplay)) {
+ mode->pan[W] = modeline->data.hdisplay;
+ }
+ if (!old_modeline ||
+ (mode->pan[H] == old_modeline->data.vdisplay)) {
+ mode->pan[H] = modeline->data.vdisplay;
+ }
+
+ } else if (mode->display) {
+ /* Display is being turned off, set the default width/height */
+ mode->dim[W] = mode->display->modelines->data.hdisplay;
+ mode->dim[H] = mode->display->modelines->data.vdisplay;
+ mode->pan[W] = mode->display->modelines->data.hdisplay;
+ mode->pan[H] = mode->display->modelines->data.vdisplay;
+ }
+
+ /* The metamode that this mode belongs to should now be
+ * considered a user metamode.
+ */
+ if (mode->metamode) {
+ mode->metamode->source = METAMODE_SOURCE_NVCONTROL;
+ }
+
+ /* Recalculate layout dimensions and scaling */
+ calc_layout(layout);
+ offset_layout(layout, -layout->dim[X], -layout->dim[Y], 1);
+ recenter_layout(layout);
+ sync_scaling(ctk_object);
+ sync_modify(ctk_object);
+
+
+ /* Redraw the layout */
+ ctk_display_layout_redraw(ctk_object);
+
+} /* ctk_display_layout_set_display_modeline() */
+
+
+
+/** ctk_display_layout_set_display_position() ************************
+ *
+ * Sets the absolute/relative position of the display.
+ *
+ **/
+
+void ctk_display_layout_set_display_position(CtkDisplayLayout *ctk_object,
+ nvDisplayPtr display,
+ int position_type,
+ nvDisplayPtr relative_to,
+ int x, int y)
+{
+ GdkGCValues old_gc_values;
+ int modified = 0;
+ nvLayoutPtr layout = ctk_object->layout;
+
+
+ if (!display) return;
+
+ if (position_type != CONF_ADJ_ABSOLUTE && !relative_to) return;
+
+
+ /* Backup the foreground color and clear the layout */
+ gdk_gc_get_values
+ (ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE(ctk_object->drawing_area)],
+ &old_gc_values);
+
+ clear_layout(ctk_object);
+
+
+ /* XXX When transitioning from absolute to relative, make sure
+ * all displays that are relative to us become absolute.
+ * This is to avoid relationship loops. Eventually, we'll want
+ * to be able to handle weird loops since X does this.
+ */
+
+ if (display->cur_mode->position_type == CONF_ADJ_ABSOLUTE &&
+ position_type != CONF_ADJ_ABSOLUTE) {
+
+ nvDisplayPtr other;
+
+ for (other = display->gpu->displays; other; other = other->next) {
+
+ if (other->screen != display->screen) continue;
+
+ if (!other->cur_mode) continue;
+
+ if (other->cur_mode->relative_to == display) {
+ other->cur_mode->position_type = CONF_ADJ_ABSOLUTE;
+ other->cur_mode->relative_to = NULL;
+ }
+ }
+ }
+
+
+ /* Set the new positioning type */
+ display->cur_mode->position_type = position_type;
+ display->cur_mode->relative_to = relative_to;
+
+ switch (position_type) {
+ case CONF_ADJ_ABSOLUTE:
+ /* Do the move by offsetting */
+ sync_modify(ctk_object);
+ modified = move_selected(ctk_object,
+ x - display->cur_mode->dim[X],
+ y - display->cur_mode->dim[Y],
+ 0);
+
+ /* Report back result of move */
+ if (ctk_object->modified_callback &&
+ (modified ||
+ x != display->cur_mode->dim[X] ||
+ y != display->cur_mode->dim[Y])) {
+ ctk_object->modified_callback
+ (ctk_object->layout, ctk_object->modified_callback_data);
+ }
+ break;
+
+ default:
+ /* Recalculate the layout */
+ calc_layout(layout);
+ offset_layout(layout, -layout->dim[X], -layout->dim[Y], 1);
+ recenter_layout(layout);
+ sync_scaling(ctk_object);
+ sync_modify(ctk_object);
+ break;
+ }
+
+
+ /* Redraw the layout and reset the foreground color */
+ draw_layout(ctk_object);
+
+ gdk_gc_set_values
+ (ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE(ctk_object->drawing_area)],
+ &old_gc_values, GDK_GC_FOREGROUND);
+
+ do_swap(ctk_object);
+
+} /* ctk_display_layout_set_display_position() */
+
+
+
+/** ctk_display_layout_set_display_panning() *************************
+ *
+ * Sets the panning domain of the display.
+ *
+ **/
+
+void ctk_display_layout_set_display_panning(CtkDisplayLayout *ctk_object,
+ nvDisplayPtr display,
+ int width, int height)
+{
+ GdkGCValues old_gc_values;
+ int modified = 0;
+
+
+ if (!display) return;
+
+
+ /* Backup the foreground color */
+ gdk_gc_get_values(ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE(ctk_object->drawing_area)],
+ &old_gc_values);
+
+ clear_layout(ctk_object);
+
+
+ /* Change the panning */
+ sync_modify(ctk_object);
+ modified = pan_selected(ctk_object,
+ width - display->cur_mode->pan[W],
+ height - display->cur_mode->pan[H],
+ 0);
+
+
+ /* Report back result of move */
+ if (ctk_object->modified_callback &&
+ (modified ||
+ width != display->cur_mode->pan[W] ||
+ height != display->cur_mode->pan[H])) {
+ ctk_object->modified_callback(ctk_object->layout,
+ ctk_object->modified_callback_data);
+ }
+
+ draw_layout(ctk_object);
+
+
+ /* Reset the foreground color */
+ gdk_gc_set_values(ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE(ctk_object->drawing_area)],
+ &old_gc_values,
+ GDK_GC_FOREGROUND);
+
+ do_swap(ctk_object);
+
+
+} /* ctk_display_layout_set_display_panning() */
+
+
+
+/** ctk_display_layout_update_display_count() ************************
+ *
+ * Updates the number of displays shown in the layout by re-building
+ * the Zorder list.
+ *
+ **/
+
+void ctk_display_layout_update_display_count(CtkDisplayLayout *ctk_object,
+ nvDisplayPtr display)
+{
+ /* Update the Z order */
+ zorder_layout(ctk_object);
+ if (display) {
+ /* Select the previously selected display */
+ select_display(ctk_object, display);
+ } else if (ctk_object->Zcount) {
+ /* Select the new topmost display */
+ select_display(ctk_object, ctk_object->Zorder[0]);
+ }
+
+} /* ctk_display_layout_update_display_count() */
+
+
+
+/** ctk_display_layout_set_screen_depth() ****************************
+ *
+ * Sets which modeline the screen should use.
+ *
+ **/
+
+void ctk_display_layout_set_screen_depth(CtkDisplayLayout *ctk_object,
+ nvScreenPtr screen,
+ int depth)
+{
+ /* Setup screen's default depth */
+ if (screen) {
+ screen->depth = depth;
+ }
+
+} /* ctk_display_layout_set_screen_depth() */
+
+
+
+/** ctk_display_layout_set_screen_position() *************************
+ *
+ * Sets the absolute/relative position of the screen.
+ *
+ **/
+
+void ctk_display_layout_set_screen_position(CtkDisplayLayout *ctk_object,
+ nvScreenPtr screen,
+ int position_type,
+ nvScreenPtr relative_to,
+ int x, int y)
+{
+ GdkGCValues old_gc_values;
+ int modified = 0;
+ nvLayoutPtr layout = ctk_object->layout;
+ nvGpuPtr gpu;
+ int draw;
+
+ if (!screen) return;
+
+ if (position_type != CONF_ADJ_ABSOLUTE && !relative_to) return;
+
+
+ /* If there is no GC for the drawing area, don't draw */
+ draw = ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE(ctk_object->drawing_area)] ?
+ 1 : 0;
+
+
+ /* Backup the foreground color and clear the layout */
+ if (draw) {
+ gdk_gc_get_values
+ (ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE(ctk_object->drawing_area)],
+ &old_gc_values);
+ clear_layout(ctk_object);
+ }
+
+
+ /* XXX When transitioning from absolute to relative, make sure
+ * all screens that are relative to us become absolute.
+ * This is to avoid relationship loops. Eventually, we'll want
+ * to be able to handle weird loops since X does this.
+ */
+
+ if (screen->position_type == CONF_ADJ_ABSOLUTE &&
+ position_type != CONF_ADJ_ABSOLUTE) {
+
+ nvScreenPtr other;
+
+ for (gpu = layout->gpus; gpu; gpu = gpu->next) {
+ for (other = gpu->screens; other; other = other->next) {
+ if (other->relative_to == screen) {
+ other->position_type = CONF_ADJ_ABSOLUTE;
+ other->relative_to = NULL;
+ }
+ }
+ }
+ }
+
+
+ /* Set the new positioning type */
+ screen->relative_to = relative_to;
+ screen->position_type = position_type;
+
+ switch (position_type) {
+ case CONF_ADJ_ABSOLUTE:
+ {
+ nvDisplayPtr other;
+ int x_offset = x - screen->dim[X];
+ int y_offset = y - screen->dim[Y];
+
+ /* Do the move by offsetting */
+ calc_screen(screen);
+ sync_modify(ctk_object);
+ offset_screen(screen, x_offset, y_offset);
+ for (other = screen->gpu->displays; other; other = other->next) {
+ if (other->screen != screen) continue;
+ offset_display(other, x_offset, y_offset, 1);
+ }
+
+ /* Recalculate the layout */
+ calc_layout(layout);
+ offset_layout(layout, -layout->dim[X], -layout->dim[Y], 1);
+ recenter_layout(layout);
+ sync_scaling(ctk_object);
+ sync_modify(ctk_object);
+
+ /* Report back result of move */
+ if (ctk_object->modified_callback &&
+ (modified ||
+ x != screen->cur_metamode->edim[X] ||
+ y != screen->cur_metamode->edim[Y])) {
+ ctk_object->modified_callback
+ (ctk_object->layout, ctk_object->modified_callback_data);
+ }
+ }
+ break;
+
+ case CONF_ADJ_RELATIVE:
+
+ /* Fall Through */
+ screen->x_offset = x;
+ screen->y_offset = y;
+
+ default:
+ /* Other relative positioning */
+
+ /* XXX Need to validate cases where displays are
+ * positioned relative to each other in a
+ * circular setup
+ *
+ * eg. CRT-0 left of CRT-1
+ * CRT-1 clones CRT-0 <- Shouldn't allow this
+ *
+ * also:
+ *
+ * CRT-0 left of CRT-1
+ * CRT-1 left of CRT-2
+ * CRT-2 clones CRT-0 ... Eep!
+ */
+
+ /* Recalculate the layout */
+ calc_layout(layout);
+ offset_layout(layout, -layout->dim[X], -layout->dim[Y], 1);
+ recenter_layout(layout);
+ sync_scaling(ctk_object);
+ sync_modify(ctk_object);
+ break;
+ }
+
+
+ /* Redraw the layout and reset the foreground color */
+ if (draw) {
+ draw_layout(ctk_object);
+
+ gdk_gc_set_values
+ (ctk_object->drawing_area->style->fg_gc[GTK_WIDGET_STATE(ctk_object->drawing_area)],
+ &old_gc_values, GDK_GC_FOREGROUND);
+
+ do_swap(ctk_object);
+ }
+
+} /* ctk_display_layout_set_screen_position() */
+
+
+
+/** ctk_display_layout_set_advanced_mode() ***************************
+ *
+ * Enables/Disables the user's ability to modify advanced layout
+ * bells and whisles.
+ *
+ * In advanced mode the user has access to:
+ *
+ * - Per-display panning.
+ * - Modeline timing modifications. (Add/Delete)
+ * - Multiple metamodes. (Add/Delete)
+ *
+ *
+ * In basic mode:
+ *
+ * - User can only modify the current metamode.
+ *
+ *
+ **/
+
+void ctk_display_layout_set_advanced_mode(CtkDisplayLayout *ctk_object,
+ int advanced_mode)
+{
+ ctk_object->advanced_mode = advanced_mode;
+
+} /* ctk_display_layout_set_allow_panning() */
+
+
+
+/** expose_event_callback() ******************************************
+ *
+ * Handles expose events.
+ *
+ **/
+
+static gboolean
+expose_event_callback(GtkWidget *widget, GdkEventExpose *event, gpointer data)
+{
+ CtkDisplayLayout *ctk_object = CTK_DISPLAY_LAYOUT(data);
+
+
+ if (event->count) {
+ return TRUE;
+ }
+
+ /* Redraw the layout */
+ ctk_display_layout_redraw(ctk_object);
+
+ return TRUE;
+
+} /* expose_event_callback() */
+
+
+
+/** configure_event_callback() ***************************************
+ *
+ * Handles configure events.
+ *
+ **/
+
+static gboolean
+configure_event_callback(GtkWidget *widget, GdkEventConfigure *event,
+ gpointer data)
+{
+ CtkDisplayLayout *ctk_object = CTK_DISPLAY_LAYOUT(data);
+ int width = widget->allocation.width;
+ int height = widget->allocation.height;
+
+ ctk_object->width = width;
+ ctk_object->height = height;
+ ctk_object->img_dim[X] = LAYOUT_IMG_OFFSET + LAYOUT_IMG_BORDER_PADDING;
+ ctk_object->img_dim[Y] = LAYOUT_IMG_OFFSET + LAYOUT_IMG_BORDER_PADDING;
+ ctk_object->img_dim[W] = width -2*(ctk_object->img_dim[X]);
+ ctk_object->img_dim[H] = height -2*(ctk_object->img_dim[Y]);
+
+ sync_scaling(ctk_object);
+
+ ctk_object->pixmap = gdk_pixmap_new(widget->window, width, height, -1);
+
+ return TRUE;
+
+} /* configure_event_callback() */
+
+
+
+/** motion_event_callback() ******************************************
+ *
+ * Handles mouse motion events.
+ *
+ **/
+
+static gboolean
+motion_event_callback(GtkWidget *widget, GdkEventMotion *event, gpointer data)
+{
+ CtkDisplayLayout *ctk_object = CTK_DISPLAY_LAYOUT(data);
+ GdkGCValues old_gc_values;
+
+ static int init = 1;
+ static int __modify_panning;
+
+ if (init) {
+ init = 0;
+ __modify_panning = (event->state & ShiftMask)?1:0;
+ }
+
+
+ if (ctk_object->last_mouse_x == event->x &&
+ ctk_object->last_mouse_y == event->y) {
+ return TRUE;
+ }
+
+
+ /* Mouse moved, allow user to reselect the current display */
+ ctk_object->select_next = 0;
+
+
+ /* Backup the foreground color */
+ gdk_gc_get_values(widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ &old_gc_values);
+
+
+ /* Modify screen layout */
+ if (ctk_object->button1 && !ctk_object->clicked_outside) {
+ int modified = 0;
+ int delta_x =
+ (event->x - ctk_object->last_mouse_x) / ctk_object->scale;
+ int delta_y =
+ (event->y - ctk_object->last_mouse_y) / ctk_object->scale;
+
+
+ clear_layout(ctk_object);
+
+ /* Swap between panning and moving */
+ if (__modify_panning != (event->state & ShiftMask)?1:0) {
+ __modify_panning = (event->state & ShiftMask)?1:0;
+ sync_modify(ctk_object);
+ }
+ if (!(event->state & ShiftMask) || !ctk_object->advanced_mode) {
+ modified = move_selected(ctk_object, delta_x, delta_y, 1);
+ } else {
+ modified = pan_selected(ctk_object, delta_x, delta_y, 1);
+ }
+
+ if (modified && ctk_object->modified_callback) {
+ ctk_object->modified_callback(ctk_object->layout,
+ ctk_object->modified_callback_data);
+ }
+
+ draw_layout(ctk_object);
+
+
+
+ /* Update the tooltip under the mouse */
+ } else {
+ char *tip =
+ get_display_tooltip_under_mouse(ctk_object, event->x, event->y);
+
+ if (tip) {
+ gtk_tooltips_set_tip(ctk_object->tooltip_group,
+ ctk_object->tooltip_area,
+ tip, NULL);
+
+ gtk_tooltips_force_window(ctk_object->tooltip_group);
+ g_free(tip);
+ }
+ }
+
+
+ ctk_object->last_mouse_x = event->x;
+ ctk_object->last_mouse_y = event->y;
+
+
+ /* Reset the foreground color */
+ gdk_gc_set_values(widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+ &old_gc_values,
+ GDK_GC_FOREGROUND);
+
+
+ /* Refresh GUI */
+ do_swap(ctk_object);
+
+ return TRUE;
+
+} /* motion_event_callback() */
+
+
+
+/** button_press_event_callback() ************************************
+ *
+ * Handles mouse button press events.
+ *
+ **/
+
+static gboolean
+button_press_event_callback(GtkWidget *widget, GdkEventButton *event,
+ gpointer data)
+{
+ CtkDisplayLayout *ctk_object = CTK_DISPLAY_LAYOUT(data);
+ nvDisplayPtr last_selected; /* Last display selected */
+ nvDisplayPtr new_selected;
+
+ /* Scale and offset x & y so they reside in the clickable area */
+ int x = (event->x -ctk_object->img_dim[X]) / ctk_object->scale;
+ int y = (event->y -ctk_object->img_dim[Y]) / ctk_object->scale;
+
+ static Time time = 0;
+
+
+ ctk_object->last_mouse_x = event->x;
+ ctk_object->last_mouse_y = event->y;
+
+
+ switch (event->button) {
+
+ /* Select a display device */
+ case Button1:
+ ctk_object->button1 = 1;
+ last_selected = get_selected(ctk_object);
+
+
+ /* Do the click */
+ click_layout(ctk_object, x, y);
+
+ new_selected = get_selected(ctk_object);
+
+ /* If the user just clicked on the currently selected display,
+ * the next time they click here, we should instead select
+ * the next display in the Z order.
+ */
+ ctk_object->select_next =
+ (last_selected == new_selected)?1:0;
+
+ if (ctk_object->selected_callback) {
+ ctk_object->selected_callback(ctk_object->layout,
+ ctk_object->selected_callback_data);
+ }
+
+ if (last_selected != new_selected) {
+ /* Selected new display - Redraw */
+ time = event->time;
+
+ } else if (new_selected && time && (event->time - time < 500)) {
+ /* Double clicked on display - XXX Could flash display here */
+ time = 0;
+
+ } else {
+ /* Selected same display - Do noting */
+ time = event->time;
+ }
+
+
+ /* Redraw everything */
+ draw_all(ctk_object);
+ break;
+
+ default:
+ break;
+ }
+
+
+ /* Refresh GUI */
+ do_swap(ctk_object);
+
+ return TRUE;
+
+} /* button_press_event_callback() */
+
+
+
+/** button_release_event_callback() **********************************
+ *
+ * Handles mouse button release events.
+ *
+ **/
+
+static gboolean
+button_release_event_callback(GtkWidget *widget, GdkEventButton *event,
+ gpointer data)
+{
+ CtkDisplayLayout *ctk_object = CTK_DISPLAY_LAYOUT(data);
+
+
+ switch (event->button) {
+
+ case Button1:
+ ctk_object->button1 = 0;
+ break;
+
+ case Button2:
+ ctk_object->button2 = 0;
+ break;
+
+ case Button3:
+ ctk_object->button3 = 0;
+ break;
+
+ default:
+ break;
+ }
+
+
+ /* Refresh GUI */
+ do_swap(ctk_object);
+
+ return TRUE;
+
+} /* button_release_event_callback() */
diff --git a/src/gtk+-2.x/ctkdisplaylayout.h b/src/gtk+-2.x/ctkdisplaylayout.h
new file mode 100644
index 0000000..8b0da25
--- /dev/null
+++ b/src/gtk+-2.x/ctkdisplaylayout.h
@@ -0,0 +1,457 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
+ * of the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+#ifndef __CTK_DISPLAYLAYOUT_H__
+#define __CTK_DISPLAYLAYOUT_H__
+
+#include "ctkevent.h"
+#include "ctkconfig.h"
+
+#include "XF86Config-parser/xf86Parser.h"
+
+
+G_BEGIN_DECLS
+
+#define CTK_TYPE_DISPLAY_LAYOUT (ctk_display_layout_get_type())
+
+#define CTK_DISPLAY_LAYOUT(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), CTK_TYPE_DISPLAY_LAYOUT, \
+ CtkDisplayLayout))
+
+#define CTK_DISPLAY_LAYOUT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), CTK_TYPE_DISPLAY_LAYOUT, \
+ CtkDisplayLayoutClass))
+
+#define CTK_IS_DISPLAY_LAYOUT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CTK_TYPE_DISPLAY_LAYOUT))
+
+#define CTK_IS_DISPLAY_LAYOUT_CLASS(class) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), CTK_TYPE_DISPLAY_LAYOUT))
+
+#define CTK_DISPLAY_LAYOUT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_DISPLAY_LAYOUT, \
+ CtkDisplayLayoutClass))
+
+#define CTK_DISPLAY_LAYOUT_TOOLTIP_WIDGET(obj) \
+ ((CTK_SCALE(obj))->tooltip_widget)
+
+
+
+/* Maximums */
+#define MAX_DEVICES 8 /* Max number of GPUs */
+
+
+/* Rectangle/Dim data positions */
+#define LEFT 0
+#define TOP 1
+#define WIDTH 2
+#define HEIGHT 3
+#define X LEFT
+#define Y TOP
+#define W WIDTH
+#define H HEIGHT
+
+
+/* XF86VIDMODE */
+#define V_PHSYNC 0x0001
+#define V_NHSYNC 0x0002
+#define V_PVSYNC 0x0004
+#define V_NVSYNC 0x0008
+#define V_INTERLACE 0x0010
+#define V_DBLSCAN 0x0020
+#define V_CSYNC 0x0040
+#define V_PCSYNC 0x0080
+#define V_NCSYNC 0x0100
+#define V_HSKEW 0x0200 /* hskew provided */
+#define V_BCAST 0x0400
+#define V_CUSTOM 0x0800 /* timing numbers customized by editor */
+#define V_VSCAN 0x1000
+
+
+/* NV-CONTROL modeline sources */
+#define MODELINE_SOURCE_XSERVER 0x001
+#define MODELINE_SOURCE_XCONFIG 0x002
+#define MODELINE_SOURCE_BUILTIN 0x004
+#define MODELINE_SOURCE_VESA 0x008
+#define MODELINE_SOURCE_EDID 0x010
+#define MODELINE_SOURCE_NVCONTROL 0x020
+
+#define MODELINE_SOURCE_USER \
+ ((MODELINE_SOURCE_XCONFIG)|(MODELINE_SOURCE_NVCONTROL))
+
+
+/* NV-CONTROL metamode sources */
+#define METAMODE_SOURCE_XCONFIG 0x001
+#define METAMODE_SOURCE_IMPLICIT 0x002
+#define METAMODE_SOURCE_NVCONTROL 0x004
+
+#define METAMODE_SOURCE_USER \
+ ((METAMODE_SOURCE_XCONFIG)|(METAMODE_SOURCE_NVCONTROL))
+
+
+
+
+/*** M A C R O S *************************************************************/
+
+
+#define NV_MIN(A, B) ((A)<(B)?(A):(B))
+#define NV_MAX(A, B) ((A)>(B)?(A):(B))
+
+
+/* Determines if the mode is the nvidia-auto-select mode. */
+#define IS_NVIDIA_DEFAULT_MODE(m) \
+(!strcmp(( m )->data.identifier, "nvidia-auto-select"))
+
+
+/* Calculates the vertical refresh rate of the modeline in Hz */
+#define GET_MODELINE_REFRESH_RATE(m) \
+(((double)((m)->data.clock) * 1000) / \
+ ((double)((m)->data.htotal) * (double)((m)->data.vtotal)))
+
+
+/* Calculates the horizontal refresh rate (sync) of the modeline in kHz */
+#define GET_MODELINE_HSYNC(m) \
+(((double)((m)->data.clock)) / (2.0f * (double)((m)->data.htotal)))
+
+
+
+
+/*** T Y P E D E F I N I T I O N S *****************************************/
+
+
+typedef struct nvModeLineRec {
+ struct nvModeLineRec *next;
+
+ XConfigModeLineRec data; /* Modeline information */
+
+ /* Extra information */
+ unsigned int source;
+ char *xconfig_name;
+
+} nvModeLine, *nvModeLinePtr;
+
+
+
+/* Mode (A particular configuration for a display within an X Screen) */
+typedef struct nvModeRec {
+ struct nvModeRec *next;
+
+ /* Defines a single mode for a dispay device as part of an X Screen's
+ * metamode.
+ *
+ * "WxH_Hz +x+y @WxH"
+ *
+ * "modeline_reference_name +offset @panning"
+ */
+
+ struct nvDisplayRec *display; /* Display device mode belongs to */
+ struct nvMetaModeRec *metamode; /* Metamode the mode is in */
+ struct nvModeLineRec *modeline; /* Modeline this mode references */
+ int dummy; /* Dummy mode, don't print out */
+
+ int dim[4]; /* Viewport (absolute) */
+ int pan[4]; /* Panning Domain (absolute) */
+
+ int position_type; /* Relative, Absolute, etc. */
+ struct nvDisplayRec *relative_to; /* Display Relative/RightOf etc */
+
+} nvMode, *nvModePtr;
+
+
+
+/* Display Device (CRT, DFP, TV, Projector ...) */
+typedef struct nvDisplayRec {
+ struct nvDisplayRec *next;
+ XConfigMonitorPtr conf_monitor;
+
+ struct nvGpuRec *gpu; /* GPU the display belongs to */
+ struct nvScreenRec *screen; /* X Screen the display is tied to */
+
+ unsigned int device_mask; /* Bit mask to identify the display */
+ char *name; /* Display name (from NV-CONTROL) */
+
+ nvModeLinePtr modelines; /* Modelines validated by X */
+ int num_modelines;
+
+ nvModePtr modes; /* List of modes this display uses */
+ int num_modes;
+ nvModePtr cur_mode; /* Current mode display uses */
+
+} nvDisplay, *nvDisplayPtr;
+
+
+
+/* MetaMode (A particular configuration for an X Screen) */
+typedef struct nvMetaModeRec {
+ struct nvMetaModeRec *next;
+
+ int id; /* Magic id */
+ int source; /* Source of the metamode */
+ Bool switchable; /* Can the metamode be accessed through Ctrl Alt +- */
+
+ // Used for drawing metamode boxes
+ int dim[4]; /* Bounding box of all modes */
+
+ // Used for applying and generating metamodes (effective dimensions)
+ int edim[4]; /* Bounding box of all non-NULL modes */
+
+ char *string; /* Temp string used for modifying the metamode list */
+
+} nvMetaMode, *nvMetaModePtr;
+
+
+
+/* X Screen */
+typedef struct nvScreenRec {
+ struct nvScreenRec *next;
+ XConfigScreenPtr conf_screen;
+ XConfigDevicePtr conf_device;
+
+ /* An X Screen may have one or more displays connected to it
+ * if TwinView is on.
+ *
+ * Fathers all displays (and their modes). From this
+ * Structure a metamodes string can be generated:
+ *
+ * "AAA,BBB,CCC ; DDD,EEE,FFF ; GGG,HHH,III"
+ */
+
+ NvCtrlAttributeHandle *handle; /* NV-CONTROL handle to X Screen */
+ CtkEvent *ctk_event;
+ int scrnum;
+
+ struct nvGpuRec *gpu; /* GPU driving this X screen */
+
+ int depth; /* Depth of the screen */
+
+ unsigned int displays_mask; /* Display devices on this X Screen */
+ int num_displays; /* # of displays using this screen */
+
+ nvMetaModePtr metamodes; /* List of metamodes */
+ int num_metamodes; /* # modes per display device */
+ nvMetaModePtr cur_metamode; /* Current metamode to display */
+ int cur_metamode_idx; /* Current metamode to display */
+
+ // Used for generating metamode strings.
+ int dim[4]; /* Bounding box of all metamodes (Absolute coords) */
+
+ int position_type; /* Relative, Absolute, etc. */
+ struct nvScreenRec *relative_to; /* Screen Relative/RightOf etc */
+ int x_offset; /* Offsets for relative positioning */
+ int y_offset;
+
+} nvScreen, *nvScreenPtr;
+
+
+
+/* GPU (Device) */
+typedef struct nvGpuRec {
+ struct nvGpuRec *next;
+
+ NvCtrlAttributeHandle *handle; /* NV-CONTROL handle to GPU */
+ CtkEvent *ctk_event;
+
+ struct nvLayoutRec *layout; /* Layout this GPU belongs to */
+
+ int max_width;
+ int max_height;
+ int max_displays;
+
+ char *name; /* Name of the GPU */
+
+ unsigned int connected_displays; /* Bitmask of connected displays */
+
+ int pci_bus;
+ int pci_device;
+ int pci_func;
+
+ nvScreenPtr screens; /* List of screens this GPU drives */
+ int num_screens;
+
+ nvDisplayPtr displays; /* List of displays attached to screen */
+ int num_displays;
+
+} nvGpu, *nvGpuPtr;
+
+
+
+/* Layout */
+typedef struct nvLayoutRec {
+ XConfigLayoutPtr conf_layout;
+ char *filename;
+
+ NvCtrlAttributeHandle *handle;
+
+ nvGpuPtr gpus; /* List of GPUs in the layout */
+ int num_gpus;
+
+ // Used for drawing the layout.
+ int dim[4]; /* Bounding box of All X Screens (Absolute coords) */
+
+ int xinerama_enabled;
+
+} nvLayout, *nvLayoutPtr;
+
+
+
+typedef void (* ctk_display_layout_selected_callback) (nvLayoutPtr, void *);
+typedef void (* ctk_display_layout_modified_callback) (nvLayoutPtr, void *);
+
+
+
+typedef struct _CtkDisplayLayout
+{
+ GtkVBox parent;
+
+ NvCtrlAttributeHandle *handle;
+ CtkConfig *ctk_config;
+
+ GtkWidget *drawing_area; /* Drawing area */
+ GtkWidget *tooltip_area; /* Tooltip area */
+ GtkTooltips *tooltip_group; /* Tooltip group */
+
+ /* Layout configuration */
+ nvLayoutPtr layout;
+
+ /* Double buffering of layout image */
+ GdkPixmap *pixmap;
+ int need_swap;
+
+ /* Image information */
+ int width; /* Real widget dimensions */
+ int height;
+ int img_dim[4]; /* Dimensions used to draw in */
+ float scale;
+
+ /* Colors */
+ GdkColor *color_palettes; /* Colors to use to display screens */
+ GdkColor fg_color;
+ GdkColor bg_color;
+ GdkColor select_color;
+
+ /* Pango layout for strings in layout image */
+
+ PangoLayout *pango_layout;
+
+ /* Display Z-Order */
+ nvDisplayPtr *Zorder; /* Z ordering of dispays in layout */
+ int Zcount; /* Number of displays in Z order list */
+ int Zselected; /* Is first item selected? */
+
+ /* Settings */
+ int snap_strength;
+ int advanced_mode; /* Allow advanced layout modifications: */
+ /* - panning */
+ /* - multiple modes */
+
+ /* State */
+ int select_next; /* On click, select next screen in Z order. */
+ int modify_dim[4]; /* Used to snap when moving/panning */
+ int clicked_outside; /* User clicked outside displays, don't move */
+
+ int button1;
+ int button2;
+ int button3;
+ int last_mouse_x;
+ int last_mouse_y;
+
+ ctk_display_layout_selected_callback selected_callback;
+ void *selected_callback_data;
+ ctk_display_layout_modified_callback modified_callback;
+ void *modified_callback_data;
+
+} CtkDisplayLayout;
+
+
+typedef struct _CtkDisplayLayoutClass
+{
+ GtkVBoxClass parent_class;
+} CtkDisplayLayoutClass;
+
+
+
+GType ctk_display_layout_get_type (void) G_GNUC_CONST;
+
+GtkWidget* ctk_display_layout_new (NvCtrlAttributeHandle *,
+ CtkConfig *,
+ nvLayoutPtr, /* Layout to display */
+ int, /* Width of image */
+ int, /* Height of image */
+ ctk_display_layout_selected_callback,
+ void *selected_callback_data,
+ ctk_display_layout_modified_callback,
+ void *modified_callback_data
+ );
+
+void ctk_display_layout_redraw (CtkDisplayLayout *);
+
+
+void ctk_display_layout_set_layout (CtkDisplayLayout *, nvLayoutPtr);
+
+
+nvDisplayPtr ctk_display_layout_get_selected_display (CtkDisplayLayout *);
+nvScreenPtr ctk_display_layout_get_selected_screen (CtkDisplayLayout *);
+nvGpuPtr ctk_display_layout_get_selected_gpu (CtkDisplayLayout *);
+
+
+void ctk_display_layout_set_mode_modeline (CtkDisplayLayout *,
+ nvModePtr mode,
+ nvModeLinePtr modeline);
+
+void ctk_display_layout_set_display_position (CtkDisplayLayout *ctk_object,
+ nvDisplayPtr display,
+ int position_type,
+ nvDisplayPtr relative_to,
+ int x, int y);
+void ctk_display_layout_set_display_panning (CtkDisplayLayout *ctk_object,
+ nvDisplayPtr display,
+ int width, int height);
+
+void ctk_display_layout_update_display_count (CtkDisplayLayout *,
+ nvDisplayPtr);
+
+void ctk_display_layout_set_screen_depth (CtkDisplayLayout *ctk_object,
+ nvScreenPtr screen, int depth);
+void ctk_display_layout_set_screen_position (CtkDisplayLayout *ctk_object,
+ nvScreenPtr screen,
+ int position_type,
+ nvScreenPtr relative_to,
+ int x, int y);
+void ctk_display_layout_set_screen_metamode (CtkDisplayLayout *,
+ nvScreenPtr screen,
+ int new_mode);
+void ctk_display_layout_add_screen_metamode (CtkDisplayLayout *, nvScreenPtr);
+void ctk_display_layout_delete_screen_metamode (CtkDisplayLayout *,
+ nvScreenPtr,
+ int metamode_idx);
+
+
+void ctk_display_layout_set_advanced_mode (CtkDisplayLayout *ctk_object,
+ int advanced_mode);
+
+
+
+G_END_DECLS
+
+#endif /* __CTK_DISPLAYLAYOUT_H__ */
diff --git a/src/gtk+-2.x/ctkevent.c b/src/gtk+-2.x/ctkevent.c
index 30b77ff..4103436 100644
--- a/src/gtk+-2.x/ctkevent.c
+++ b/src/gtk+-2.x/ctkevent.c
@@ -219,10 +219,21 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class)
MAKE_SIGNAL(NV_CTRL_XV_SYNC_TO_DISPLAY);
MAKE_SIGNAL(NV_CTRL_GVO_OVERRIDE_HW_CSC);
MAKE_SIGNAL(NV_CTRL_GVO_COMPOSITE_TERMINATION);
+ MAKE_SIGNAL(NV_CTRL_ASSOCIATED_DISPLAY_DEVICES);
MAKE_SIGNAL(NV_CTRL_FRAMELOCK_SLAVES);
MAKE_SIGNAL(NV_CTRL_FRAMELOCK_MASTERABLE);
MAKE_SIGNAL(NV_CTRL_PROBE_DISPLAYS);
MAKE_SIGNAL(NV_CTRL_REFRESH_RATE);
+ MAKE_SIGNAL(NV_CTRL_INITIAL_PIXMAP_PLACEMENT);
+ MAKE_SIGNAL(NV_CTRL_PCI_BUS);
+ MAKE_SIGNAL(NV_CTRL_PCI_DEVICE);
+ MAKE_SIGNAL(NV_CTRL_PCI_FUNCTION);
+ MAKE_SIGNAL(NV_CTRL_FRAMELOCK_FPGA_REVISION);
+ MAKE_SIGNAL(NV_CTRL_MAX_SCREEN_WIDTH);
+ MAKE_SIGNAL(NV_CTRL_MAX_SCREEN_HEIGHT);
+ MAKE_SIGNAL(NV_CTRL_MAX_DISPLAYS);
+ MAKE_SIGNAL(NV_CTRL_DYNAMIC_TWINVIEW);
+ MAKE_SIGNAL(NV_CTRL_MULTIGPU_DISPLAY_OWNER);
#undef MAKE_SIGNAL
@@ -233,7 +244,7 @@ static void ctk_event_class_init(CtkEventClass *ctk_event_class)
* knows about.
*/
-#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_REFRESH_RATE
+#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_MULTIGPU_DISPLAY_OWNER
#warning "There are attributes that do not emit signals!"
#endif
@@ -347,7 +358,7 @@ static void ctk_event_register_source(CtkEvent *ctk_event)
-GtkObject *ctk_event_new (NvCtrlAttributeHandle *handle)
+GtkObject *ctk_event_new(NvCtrlAttributeHandle *handle)
{
GObject *object;
CtkEvent *ctk_event;
@@ -368,6 +379,7 @@ GtkObject *ctk_event_new (NvCtrlAttributeHandle *handle)
} /* ctk_event_new() */
+
static gboolean ctk_event_prepare(GSource *source, gint *timeout)
{
*timeout = -1;
@@ -380,6 +392,8 @@ static gboolean ctk_event_prepare(GSource *source, gint *timeout)
return FALSE;
}
+
+
static gboolean ctk_event_check(GSource *source)
{
CtkEventSource *event_source = (CtkEventSource *) source;
@@ -393,6 +407,26 @@ static gboolean ctk_event_check(GSource *source)
}
+
+static int get_screen_of_root(Display *dpy, Window root)
+{
+ int screen = -1;
+
+ /* Find the screen the window belongs to */
+ screen = XScreenCount(dpy);
+
+ while (screen > 0) {
+ screen--;
+ if (root == RootWindow(dpy, screen)) {
+ break;
+ }
+ }
+
+ return screen;
+}
+
+
+
#define CTK_EVENT_BROADCAST(ES, SIG, PTR, TYPE, ID) \
do { \
CtkEventNode *e = (ES)->ctk_events; \
@@ -494,16 +528,8 @@ static gboolean ctk_event_dispatch(GSource *source,
int screen;
/* Find the screen the window belongs to */
- screen = XScreenCount(xrandrevent->display);
- screen--;
- while (screen > 0) {
- if (xrandrevent->root ==
- RootWindow(xrandrevent->display, screen)) {
- break;
- }
- screen--;
- }
- if (screen > 0) {
+ screen = get_screen_of_root(xrandrevent->display, xrandrevent->root);
+ if (screen >= 0) {
CTK_EVENT_BROADCAST(event_source,
signal_RRScreenChangeNotify,
&event,
@@ -515,3 +541,44 @@ static gboolean ctk_event_dispatch(GSource *source,
return TRUE;
} /* ctk_event_dispatch() */
+
+
+
+/* ctk_event_emit() - Emits signal(s) on a registered ctk_event object.
+ * This function is primarly used to simulate NV-CONTROL events such
+ * that various parts of nvidia-settings can communicate (internally)
+ */
+void ctk_event_emit(CtkEvent *ctk_event,
+ unsigned int mask, int attrib, int value)
+{
+ CtkEventStruct event;
+ CtkEventSource *source;
+ Display *dpy = NvCtrlGetDisplayPtr(ctk_event->handle);
+
+
+ if (attrib > NV_CTRL_LAST_ATTRIBUTE) return;
+
+
+ /* Find the event source */
+ source = event_sources;
+ while (source) {
+ if (source->dpy == dpy) {
+ break;
+ }
+ source = source->next;
+ }
+ if (!source) return;
+
+
+ /* Broadcast event to all relavent ctk_event objects */
+ event.attribute = attrib;
+ event.value = value;
+ event.display_mask = mask;
+
+ CTK_EVENT_BROADCAST(source,
+ signals[attrib],
+ &event,
+ NvCtrlGetTargetType(ctk_event->handle),
+ NvCtrlGetTargetId(ctk_event->handle));
+
+} /* ctk_event_emit() */
diff --git a/src/gtk+-2.x/ctkevent.h b/src/gtk+-2.x/ctkevent.h
index 45d83a7..9eb77d4 100644
--- a/src/gtk+-2.x/ctkevent.h
+++ b/src/gtk+-2.x/ctkevent.h
@@ -74,6 +74,9 @@ struct _CtkEventStruct
GType ctk_event_get_type (void) G_GNUC_CONST;
GtkObject* ctk_event_new (NvCtrlAttributeHandle*);
+void ctk_event_emit(CtkEvent *ctk_event,
+ unsigned int mask, int attrib, int value);
+
#define CTK_EVENT_NAME(x) ("CTK_EVENT_" #x)
diff --git a/src/gtk+-2.x/ctkframelock.c b/src/gtk+-2.x/ctkframelock.c
index 4f013d7..2c7fca9 100644
--- a/src/gtk+-2.x/ctkframelock.c
+++ b/src/gtk+-2.x/ctkframelock.c
@@ -172,9 +172,6 @@ struct _nvDisplayDataRec {
GtkWidget *rate_text;
guint rate;
- GtkWidget *timing_label;
- GtkWidget *timing_hbox; /* LED */
-
GtkWidget *stereo_label;
GtkWidget *stereo_hbox; /* LED */
};
@@ -187,6 +184,9 @@ struct _nvGPUDataRec {
guint clients_mask;
gboolean enabled; /* Sync enabled */
+ GtkWidget *timing_label;
+ GtkWidget *timing_hbox; /* LED */
+
/* Signal Handler IDs */
gulong signal_ids[NUM_GPU_SIGNALS];
@@ -221,7 +221,10 @@ struct _nvFrameLockDataRec {
GtkWidget *port1_label;
GtkWidget *port1_hbox; /* IMAGE */
guint port1_ethernet_error;
-
+
+ GtkWidget *revision_label;
+ GtkWidget *revision_text;
+
GtkWidget *extra_info_hbox;
};
@@ -1360,6 +1363,7 @@ static void do_select_gpu_data(nvGPUDataPtr data, gint select)
return;
}
SELECT_WIDGET(data->label, select);
+ SELECT_WIDGET(data->timing_label, select);
}
@@ -1380,7 +1384,6 @@ static void do_select_display_data(nvDisplayDataPtr data, gint select)
SELECT_WIDGET(data->client_label, select);
SELECT_WIDGET(data->rate_label, select);
SELECT_WIDGET(data->rate_text, select);
- SELECT_WIDGET(data->timing_label, select);
SELECT_WIDGET(data->stereo_label, select);
}
@@ -1924,6 +1927,15 @@ static nvListEntryPtr list_entry_new_with_framelock(nvFrameLockDataPtr data)
gtk_box_pack_start(GTK_BOX(data->extra_info_hbox), data->delay_text,
FALSE, FALSE, 0);
+ vseparator = gtk_vseparator_new();
+ gtk_box_pack_start(GTK_BOX(data->extra_info_hbox), vseparator,
+ FALSE, FALSE, 0);
+
+ gtk_box_pack_start(GTK_BOX(data->extra_info_hbox), data->revision_label,
+ FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(data->extra_info_hbox), data->revision_text,
+ FALSE, FALSE, 0);
+
return entry;
}
@@ -1949,6 +1961,21 @@ static nvListEntryPtr list_entry_new_with_gpu(nvGPUDataPtr data)
gtk_box_pack_start(GTK_BOX(entry->data_hbox), data->label,
FALSE, FALSE, 5);
+ {
+ GtkWidget *frame;
+ GtkWidget *hbox;
+
+ hbox = gtk_hbox_new(FALSE, 5);
+
+ frame = gtk_frame_new(NULL);
+ gtk_box_pack_end(GTK_BOX(entry->data_hbox), frame, FALSE, FALSE, 0);
+ gtk_container_set_border_width(GTK_CONTAINER(hbox), 2);
+ gtk_container_add(GTK_CONTAINER(frame), hbox);
+
+ gtk_box_pack_start(GTK_BOX(hbox), data->timing_label, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), data->timing_hbox, FALSE, FALSE, 0);
+ }
+
return entry;
}
@@ -2006,12 +2033,6 @@ static nvListEntryPtr list_entry_new_with_display(nvDisplayDataPtr data)
vseparator = gtk_vseparator_new();
gtk_box_pack_start(GTK_BOX(hbox), vseparator, FALSE, FALSE, 0);
- gtk_box_pack_start(GTK_BOX(hbox), data->timing_label, FALSE, FALSE, 0);
- gtk_box_pack_start(GTK_BOX(hbox), data->timing_hbox, FALSE, FALSE, 0);
-
- vseparator = gtk_vseparator_new();
- gtk_box_pack_start(GTK_BOX(hbox), vseparator, FALSE, FALSE, 0);
-
gtk_box_pack_start(GTK_BOX(hbox), data->stereo_label, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), data->stereo_hbox, FALSE, FALSE, 0);
}
@@ -3042,7 +3063,43 @@ void list_entry_update_framelock_status(CtkFramelock *ctk_framelock,
void list_entry_update_gpu_status(CtkFramelock *ctk_framelock,
nvListEntryPtr entry)
{
- /* Do nothing */
+ nvGPUDataPtr data = (nvGPUDataPtr)(entry->data);
+ gboolean framelock_enabled;
+ gboolean has_server;
+ gboolean has_client;
+ gboolean use_house_sync;
+ gint house = 0;
+
+ framelock_enabled = ctk_framelock->framelock_enabled;
+
+ use_house_sync = gtk_toggle_button_get_active
+ (GTK_TOGGLE_BUTTON(ctk_framelock->use_house_sync));
+
+ if (entry->parent && entry->parent->data) {
+ nvFrameLockDataPtr framelock_data =
+ (nvFrameLockDataPtr)(entry->parent->data);
+
+ NvCtrlGetAttribute(framelock_data->handle, NV_CTRL_FRAMELOCK_HOUSE_STATUS,
+ &house);
+ }
+
+ has_client = data->clients_mask;
+ has_server = data->server_mask;
+
+ /* Check Timing Sync */
+ if (!framelock_enabled ||
+ (!has_server && !has_client) ||
+ (has_server && (use_house_sync || !house))) {
+ gtk_widget_set_sensitive(data->timing_label, FALSE);
+ update_image(data->timing_hbox, ctk_framelock->led_grey);
+ } else {
+ gint timing;
+ NvCtrlGetAttribute(data->handle, NV_CTRL_FRAMELOCK_TIMING, &timing);
+ gtk_widget_set_sensitive(data->timing_label, TRUE);
+ update_image(data->timing_hbox,
+ timing ? ctk_framelock->led_green :
+ ctk_framelock->led_red);
+ }
}
@@ -3078,26 +3135,6 @@ void list_entry_update_display_status(CtkFramelock *ctk_framelock,
gpu_is_server = (gpu_server_entry && (gpu_server_entry == entry->parent));
- /* Check Timing Sync. Due to a current restriction, timing information
- * is unavailable on client display devices that are driven by the same
- * gpu that is driving the server display device while "use house sync"
- * is off (gpu is using the internal timings of the server display
- * device).
- */
- if (!framelock_enabled ||
- (!is_server && !is_client) ||
- (gpu_is_server && !use_house_sync)) {
- gtk_widget_set_sensitive(data->timing_label, FALSE);
- update_image(data->timing_hbox, ctk_framelock->led_grey);
- } else {
- gint timing;
- NvCtrlGetAttribute(data->handle, NV_CTRL_FRAMELOCK_TIMING, &timing);
- gtk_widget_set_sensitive(data->timing_label, TRUE);
- update_image(data->timing_hbox,
- timing ? ctk_framelock->led_green :
- ctk_framelock->led_red);
- }
-
/* Check Stereo Sync. If frame lock is disabled or this display device
* is neither a client/server or the display device is a server and the
* GPU driving it is not using the house sync signal, gray out the LED.
@@ -3775,7 +3812,7 @@ GtkWidget* ctk_framelock_new(NvCtrlAttributeHandle *handle,
ret = NvCtrlQueryTargetCount(handle,
NV_CTRL_TARGET_TYPE_FRAMELOCK,
- &num_framelocks);
+ (int *)&num_framelocks);
if (ret != NvCtrlSuccess) return NULL;
if (!num_framelocks) return NULL;
@@ -4297,7 +4334,7 @@ static unsigned int add_display_devices(CtkFramelock *ctk_framelock,
/* Query list of devices on this GPU. */
ret = NvCtrlGetAttribute(gpu_data->handle,
NV_CTRL_ENABLED_DISPLAYS,
- &enabled_displays);
+ (int *)&enabled_displays);
if (ret != NvCtrlSuccess || !enabled_displays) {
goto fail;
}
@@ -4305,7 +4342,7 @@ static unsigned int add_display_devices(CtkFramelock *ctk_framelock,
/* Query master device */
ret = NvCtrlGetAttribute(gpu_data->handle,
NV_CTRL_FRAMELOCK_MASTER,
- &master_mask);
+ (int *)&master_mask);
if (ret != NvCtrlSuccess) {
goto fail;
}
@@ -4313,7 +4350,7 @@ static unsigned int add_display_devices(CtkFramelock *ctk_framelock,
/* Query slave devices */
ret = NvCtrlGetAttribute(gpu_data->handle,
NV_CTRL_FRAMELOCK_SLAVES,
- &slaves_mask);
+ (int *)&slaves_mask);
if (ret != NvCtrlSuccess) {
goto fail;
}
@@ -4370,7 +4407,7 @@ static unsigned int add_display_devices(CtkFramelock *ctk_framelock,
ret = NvCtrlGetDisplayAttribute(gpu_data->handle,
display_mask,
NV_CTRL_REFRESH_RATE,
- &(display_data->rate));
+ (int *)&(display_data->rate));
if (ret != NvCtrlSuccess) {
goto fail;
}
@@ -4393,9 +4430,6 @@ static unsigned int add_display_devices(CtkFramelock *ctk_framelock,
fvalue = ((float)(display_data->rate)) / 100.0f;
snprintf(str, 32, "%.2f Hz", fvalue);
display_data->rate_text = gtk_label_new(str);
-
- display_data->timing_label = gtk_label_new("Timing:");
- display_data->timing_hbox = gtk_hbox_new(FALSE, 0);
display_data->stereo_label = gtk_label_new("Stereo:");
display_data->stereo_hbox = gtk_hbox_new(FALSE, 0);
@@ -4536,6 +4570,9 @@ static unsigned int add_gpu_devices(CtkFramelock *ctk_framelock,
NV_CTRL_ATTRIBUTES_NV_CONTROL_SUBSYSTEM);
gpu_data->label = gtk_label_new("");
+ gpu_data->timing_label = gtk_label_new("Timing:");
+ gpu_data->timing_hbox = gtk_hbox_new(FALSE, 0);
+
/* Create the GPU list entry */
entry = list_entry_new_with_gpu(gpu_data);
@@ -4610,32 +4647,10 @@ static unsigned int add_framelock_devices(CtkFramelock *ctk_framelock,
/* Get number of G-Sync devices on this server */
- /* XXX If we check for FRAMELOCK_SUPPORTED here, we
- * might get a false negative since another
- * X screen on the same server could support
- * frame lock.
- */
-
- /* does this NV-CONTROL handle support frame lock? */
- /*
- NvCtrlGetAttribute(h, NV_CTRL_FRAMELOCK, &value);
- if (value != NV_CTRL_FRAMELOCK_SUPPORTED) {
- if (error_dialog) {
- error_msg(ctk_framelock, "<span weight=\"bold\" "
- "size=\"larger\">Unable "
- "to add X screen to frame lock group</span>\n\n"
- "This X Screen does not support frame lock.");
- } else {
- nv_error_msg("Unable to add X screen to frame lock group; "
- "this X Screen does not support frame lock.");
- }
- NvCtrlAttributeClose(h);
- return NULL;
- }*/
ret = NvCtrlQueryTargetCount(handle,
NV_CTRL_TARGET_TYPE_FRAMELOCK,
- &num_framelocks);
+ (int *)&num_framelocks);
if (ret != NvCtrlSuccess) {
goto fail;
}
@@ -4643,6 +4658,8 @@ static unsigned int add_framelock_devices(CtkFramelock *ctk_framelock,
/* Add frame lock devices found */
for (framelock_id = 0; framelock_id < num_framelocks; framelock_id++) {
int gpus_added = 0;
+ int val;
+ char *revision_str = NULL;
/* Create the frame lock data structure */
framelock_data =
@@ -4658,6 +4675,17 @@ static unsigned int add_framelock_devices(CtkFramelock *ctk_framelock,
framelock_id,
NV_CTRL_ATTRIBUTES_NV_CONTROL_SUBSYSTEM);
+ /* Get the framelock revision information */
+
+ ret = NvCtrlGetAttribute(framelock_data->handle,
+ NV_CTRL_FRAMELOCK_FPGA_REVISION,
+ &val);
+ if (ret != NvCtrlSuccess) {
+ goto fail;
+ }
+ revision_str = g_strdup_printf("%d", val);
+
+
framelock_data->label = gtk_label_new("");
framelock_data->receiving_label = gtk_label_new("Receiving:");
@@ -4678,6 +4706,10 @@ static unsigned int add_framelock_devices(CtkFramelock *ctk_framelock,
framelock_data->port1_label = gtk_label_new("Port 1:");
framelock_data->port1_hbox = gtk_hbox_new(FALSE, 0);
+ framelock_data->revision_label = gtk_label_new("FPGA Revision:");
+ framelock_data->revision_text = gtk_label_new(revision_str);
+ g_free(revision_str);
+
framelock_data->extra_info_hbox = gtk_hbox_new(FALSE, 5);
/* Create the frame lock list entry */
@@ -5114,6 +5146,9 @@ GtkTextBuffer *ctk_framelock_create_help(GtkTextTagTable *table)
ctk_help_para(b, &i, "GPU Device entries display the GPU name and number "
"of a GPU connected to a G-Sync device. Display devices "
"driven by the GPU will be listed under this entry.");
+ ctk_help_para(b, &i, "Timing LED: This indicates that the GPU "
+ "is synchronized with the incoming timing signal from the "
+ "G-Sync device");
ctk_help_heading(b, &i, "Display Device Entry Information");
ctk_help_para(b, &i, "Display Device entries display information and "
@@ -5123,8 +5158,6 @@ GtkTextBuffer *ctk_framelock_create_help(GtkTextTagTable *table)
"The following options are available:");
ctk_help_para(b, &i, __server_checkbox_help);
ctk_help_para(b, &i, __client_checkbox_help);
- ctk_help_para(b, &i, "Timing LED: This indicates that the display device "
- "is synchronized with the incoming timing signal.");
ctk_help_para(b, &i, "Stereo LED: This indicates whether or not the "
"display device is sync'ed to the stereo signal coming from "
"the G-Sync device. This LED is only available to display "
@@ -5217,10 +5250,12 @@ void ctk_framelock_select(GtkWidget *w)
/* Start the frame lock timers */
ctk_config_start_timer(ctk_framelock->ctk_config,
- (GSourceFunc) update_framelock_status);
+ (GSourceFunc) update_framelock_status,
+ (gpointer) ctk_framelock);
ctk_config_start_timer(ctk_framelock->ctk_config,
- (GSourceFunc) check_for_ethernet);
+ (GSourceFunc) check_for_ethernet,
+ (gpointer) ctk_framelock);
}
@@ -5238,8 +5273,10 @@ void ctk_framelock_unselect(GtkWidget *w)
/* Stop the frame lock timers */
ctk_config_stop_timer(ctk_framelock->ctk_config,
- (GSourceFunc) update_framelock_status);
+ (GSourceFunc) update_framelock_status,
+ (gpointer) ctk_framelock);
ctk_config_stop_timer(ctk_framelock->ctk_config,
- (GSourceFunc) check_for_ethernet);
+ (GSourceFunc) check_for_ethernet,
+ (gpointer) ctk_framelock);
}
diff --git a/src/gtk+-2.x/ctkglx.c b/src/gtk+-2.x/ctkglx.c
index cd09875..650b625 100644
--- a/src/gtk+-2.x/ctkglx.c
+++ b/src/gtk+-2.x/ctkglx.c
@@ -33,6 +33,7 @@
#include "glx_banner.h"
#include "ctkimage.h"
#include "ctkglx.h"
+#include "ctkutils.h"
#include "ctkconfig.h"
#include "ctkhelp.h"
@@ -151,32 +152,6 @@ GType ctk_glx_get_type(void)
} /* ctk_glx_get_type() */
-static void add_table_row(GtkWidget *table,
- const gint row,
- const gint value_alignment,
- const gchar *name,
- const gchar *value)
-{
- GtkWidget *label;
-
-
- label = gtk_label_new(name);
- gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.0f);
- gtk_label_set_selectable(GTK_LABEL(label), TRUE);
-
- gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1,
- GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
-
- label = gtk_label_new(value);
- gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
- gtk_misc_set_alignment(GTK_MISC(label), value_alignment, 0.0f);
- gtk_label_set_selectable(GTK_LABEL(label), TRUE);
-
- gtk_table_attach(GTK_TABLE(table), label, 1, 2, row, row + 1,
- GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
-} /* add_table_row() */
-
-
static void dummy_button_signal(GtkWidget *widget,
gpointer user_data)
{
@@ -452,10 +427,10 @@ GtkWidget* ctk_glx_new(NvCtrlAttributeHandle *handle,
/* Failure (no GLX) */
fail_glx_not_supported:
- label = gtk_label_new("The OpenGL extension 'GLX' is not supported by\n"
- "the X server or there was a problem retrieving\n"
- "GLX information from the X server."
- );
+ label =
+ gtk_label_new("GLX not available: either the GLX extension is not\n"
+ "available on this X server, or there was a problem\n"
+ "retrieving GLX information from the X server.");
gtk_label_set_selectable(GTK_LABEL(label), TRUE);
gtk_container_add(GTK_CONTAINER(ctk_glx), label);
@@ -601,9 +576,12 @@ void ctk_glx_probe_info(GtkWidget *widget)
table = gtk_table_new(2, 2, FALSE);
gtk_table_set_row_spacings(GTK_TABLE(table), 3);
gtk_table_set_col_spacings(GTK_TABLE(table), 15);
- add_table_row(table, 0, 0, "Direct Rendering:", direct_rendering);
- add_table_row(table, 1, 0, "GLX Extensions:",
- glx_extensions?glx_extensions:"");
+ add_table_row(table, 0,
+ 0, 0, "Direct Rendering:",
+ 0, 0, direct_rendering);
+ add_table_row(table, 1,
+ 0, 0, "GLX Extensions:",
+ 0, 0, glx_extensions);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), hbox2, FALSE, FALSE, 5);
gtk_box_pack_start(GTK_BOX(hbox), table, FALSE, FALSE, 0);
@@ -622,12 +600,15 @@ void ctk_glx_probe_info(GtkWidget *widget)
table = gtk_table_new(3, 2, FALSE);
gtk_table_set_row_spacings(GTK_TABLE(table), 3);
gtk_table_set_col_spacings(GTK_TABLE(table), 15);
- add_table_row(table, 0, 0, "Vendor:",
- server_vendor?server_vendor:"");
- add_table_row(table, 1, 0, "Version:",
- server_version?server_version:"");
- add_table_row(table, 2, 0, "Extensions:",
- server_extensions?server_extensions:"");
+ add_table_row(table, 0,
+ 0, 0, "Vendor:",
+ 0, 0, server_vendor);
+ add_table_row(table, 1,
+ 0, 0, "Version:",
+ 0, 0, server_version);
+ add_table_row(table, 2,
+ 0, 0, "Extensions:",
+ 0, 0, server_extensions);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), hbox2, FALSE, FALSE, 5);
gtk_box_pack_start(GTK_BOX(hbox), table, FALSE, FALSE, 0);
@@ -646,12 +627,15 @@ void ctk_glx_probe_info(GtkWidget *widget)
table = gtk_table_new(3, 2, FALSE);
gtk_table_set_row_spacings(GTK_TABLE(table), 3);
gtk_table_set_col_spacings(GTK_TABLE(table), 15);
- add_table_row(table, 0, 0, "Vendor:",
- client_vendor?client_vendor:"");
- add_table_row(table, 1, 0, "Version:",
- client_version?client_version:"");
- add_table_row(table, 2, 0, "Extensions:",
- client_extensions?client_extensions:"");
+ add_table_row(table, 0,
+ 0, 0, "Vendor:",
+ 0, 0, client_vendor);
+ add_table_row(table, 1,
+ 0, 0, "Version:",
+ 0, 0, client_version);
+ add_table_row(table, 2,
+ 0, 0, "Extensions:",
+ 0, 0, client_extensions);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), hbox2, FALSE, FALSE, 5);
gtk_box_pack_start(GTK_BOX(hbox), table, FALSE, FALSE, 0);
@@ -671,10 +655,18 @@ void ctk_glx_probe_info(GtkWidget *widget)
vbox2 = gtk_vbox_new(FALSE, 0);
gtk_table_set_row_spacings(GTK_TABLE(table), 3);
gtk_table_set_col_spacings(GTK_TABLE(table), 15);
- add_table_row(table, 0, 0, "Vendor:", opengl_vendor);
- add_table_row(table, 1, 0, "Renderer:", opengl_renderer);
- add_table_row(table, 2, 0, "Version:", opengl_version);
- add_table_row(table, 3, 0, "Extensions:", opengl_extensions);
+ add_table_row(table, 0,
+ 0, 0, "Vendor:",
+ 0, 0, opengl_vendor);
+ add_table_row(table, 1,
+ 0, 0, "Renderer:",
+ 0, 0, opengl_renderer);
+ add_table_row(table, 2,
+ 0, 0, "Version:",
+ 0, 0, opengl_version);
+ add_table_row(table, 3,
+ 0, 0, "Extensions:",
+ 0, 0, opengl_extensions);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), hbox2, FALSE, FALSE, 5);
gtk_box_pack_start(GTK_BOX(hbox), table, FALSE, FALSE, 0);
diff --git a/src/gtk+-2.x/ctkgpu.c b/src/gtk+-2.x/ctkgpu.c
new file mode 100644
index 0000000..0a2d7d3
--- /dev/null
+++ b/src/gtk+-2.x/ctkgpu.c
@@ -0,0 +1,480 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
+ * of the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+#include <gtk/gtk.h>
+#include "NvCtrlAttributes.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "thermal_banner.h"
+#include "ctkimage.h"
+
+#include "ctkgpu.h"
+#include "ctkhelp.h"
+#include "ctkutils.h"
+
+
+static void probe_displays_received(GtkObject *object, gpointer arg1,
+ gpointer user_data);
+
+GType ctk_gpu_get_type(
+ void
+)
+{
+ static GType ctk_gpu_type = 0;
+
+ if (!ctk_gpu_type) {
+ static const GTypeInfo info_ctk_gpu = {
+ sizeof (CtkGpuClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (CtkGpu),
+ 0, /* n_preallocs */
+ NULL, /* instance_init */
+ };
+
+ ctk_gpu_type =
+ g_type_register_static(GTK_TYPE_VBOX,
+ "CtkGpu", &info_ctk_gpu, 0);
+ }
+
+ return ctk_gpu_type;
+}
+
+
+static gchar *make_display_device_list(NvCtrlAttributeHandle *handle,
+ unsigned int display_devices)
+{
+ gchar *displays = NULL;
+ gchar *type;
+ gchar *name;
+ gchar *tmp_str;
+ unsigned int mask;
+ ReturnStatus ret;
+
+
+ /* List of Display Device connected on GPU */
+
+ for (mask = 1; mask; mask <<= 1) {
+
+ if (!(mask & display_devices)) continue;
+
+ type = display_device_mask_to_display_device_name(mask);
+ name = NULL;
+
+ ret =
+ NvCtrlGetStringDisplayAttribute(handle,
+ mask,
+ NV_CTRL_STRING_DISPLAY_DEVICE_NAME,
+ &name);
+ if (ret != NvCtrlSuccess) {
+ tmp_str = g_strdup_printf("Unknown (%s)", type);
+ } else {
+ tmp_str = g_strdup_printf("%s (%s)", name, type);
+ XFree(name);
+ }
+ free(type);
+
+ if (displays) {
+ name = g_strdup_printf("%s,\n%s", tmp_str, displays);
+ g_free(displays);
+ g_free(tmp_str);
+ } else {
+ name = tmp_str;
+ }
+ displays = name;
+ }
+
+ if (!displays) {
+ displays = g_strdup("None");
+ }
+
+ return displays;
+
+} /* make_display_device_list() */
+
+
+
+GtkWidget* ctk_gpu_new(
+ NvCtrlAttributeHandle *handle,
+ NvCtrlAttributeHandle **screen_handles,
+ CtkEvent *ctk_event
+)
+{
+ GObject *object;
+ CtkGpu *ctk_gpu;
+ GtkWidget *label;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *banner;
+ GtkWidget *hseparator;
+ GtkWidget *table;
+
+ char *product_name, *vbios_version, *video_ram, *irq;
+ gchar *bus_type, *bus_rate, *bus;
+ int pci_bus;
+ int pci_device;
+ int pci_func;
+ gchar *pci_bus_id;
+
+ gchar *__pci_bus_id_unknown = "?:?:?";
+
+ int tmp;
+ ReturnStatus ret;
+
+ gchar *screens;
+ gchar *displays;
+
+ unsigned int display_devices;
+ int xinerama_enabled;
+ int *pData;
+ int len;
+ int i;
+
+
+ /*
+ * get the data that we will display below
+ *
+ * XXX should be able to update any of this if an attribute
+ * changes.
+ */
+
+ /* NV_CTRL_XINERAMA */
+
+ ret = NvCtrlGetAttribute(handle, NV_CTRL_XINERAMA, &xinerama_enabled);
+ if (ret != NvCtrlSuccess) {
+ xinerama_enabled = FALSE;
+ }
+
+ /* NV_CTRL_STRING_PRODUCT_NAME */
+
+ ret = NvCtrlGetStringAttribute(handle, NV_CTRL_STRING_PRODUCT_NAME,
+ &product_name);
+ if (ret != NvCtrlSuccess) product_name = NULL;
+
+ /* NV_CTRL_BUS_TYPE */
+
+ ret = NvCtrlGetAttribute(handle, NV_CTRL_BUS_TYPE, &tmp);
+ bus_type = NULL;
+ if (ret == NvCtrlSuccess) {
+ if (tmp == NV_CTRL_BUS_TYPE_AGP) bus_type = "AGP";
+ else if (tmp == NV_CTRL_BUS_TYPE_PCI) bus_type = "PCI";
+ else if (tmp == NV_CTRL_BUS_TYPE_PCI_EXPRESS) bus_type = "PCI Express";
+ else if (tmp == NV_CTRL_BUS_TYPE_INTEGRATED) bus_type = "Integrated";
+ }
+
+ /* NV_CTRL_BUS_RATE */
+
+ bus_rate = NULL;
+ if (tmp == NV_CTRL_BUS_TYPE_AGP ||
+ tmp == NV_CTRL_BUS_TYPE_PCI_EXPRESS) {
+ ret = NvCtrlGetAttribute(handle, NV_CTRL_BUS_RATE, &tmp);
+ if (ret == NvCtrlSuccess) {
+ bus_rate = g_strdup_printf("%dX", tmp);
+ }
+ }
+
+ if (bus_rate) {
+ bus = g_strdup_printf("%s %s", bus_type, bus_rate);
+ g_free(bus_rate);
+ } else {
+ bus = g_strdup(bus_type);
+ }
+
+ /* NV_CTRL_PCI_BUS & NV_CTRL_PCI_DEVICE & NV__CTRL_PCI_FUNCTION */
+
+ pci_bus_id = NULL;
+ ret = NvCtrlGetAttribute(handle, NV_CTRL_PCI_BUS, &pci_bus);
+ if (ret != NvCtrlSuccess) pci_bus_id = __pci_bus_id_unknown;
+
+ ret = NvCtrlGetAttribute(handle, NV_CTRL_PCI_DEVICE, &pci_device);
+ if (ret != NvCtrlSuccess) pci_bus_id = __pci_bus_id_unknown;
+
+ ret = NvCtrlGetAttribute(handle, NV_CTRL_PCI_FUNCTION, &pci_func);
+ if (ret != NvCtrlSuccess) pci_bus_id = __pci_bus_id_unknown;
+
+ if (!pci_bus_id) {
+ pci_bus_id = g_strdup_printf("%d:%d:%d",
+ pci_bus, pci_device, pci_func);
+ } else {
+ pci_bus_id = g_strdup(__pci_bus_id_unknown);
+ }
+
+ /* NV_CTRL_STRING_VBIOS_VERSION */
+
+ ret = NvCtrlGetStringAttribute(handle, NV_CTRL_STRING_VBIOS_VERSION,
+ &vbios_version);
+ if (ret != NvCtrlSuccess) vbios_version = NULL;
+
+ /* NV_CTRL_VIDEO_RAM */
+
+ ret = NvCtrlGetAttribute(handle, NV_CTRL_VIDEO_RAM, &tmp);
+ if (ret != NvCtrlSuccess) {
+ video_ram = NULL;
+ } else {
+ video_ram = g_strdup_printf("%d MB", tmp >> 10);
+ }
+
+ /* NV_CTRL_IRQ */
+
+ ret = NvCtrlGetAttribute(handle, NV_CTRL_IRQ, &tmp);
+ if (ret != NvCtrlSuccess) {
+ irq = NULL;
+ } else {
+ irq = g_strdup_printf("%d", tmp);
+ }
+
+ /* List of X Screens using GPU */
+
+ if (xinerama_enabled) {
+
+ /* In Xinerama, there is only one logical X screen */
+
+ screens = g_strdup("Screen 0 (Xinerama)");
+
+ } else {
+ gchar *tmp_str;
+ screens = NULL;
+
+ ret = NvCtrlGetBinaryAttribute(handle,
+ 0,
+ NV_CTRL_BINARY_DATA_XSCREENS_USING_GPU,
+ (unsigned char **)(&pData),
+ &len);
+ if (ret == NvCtrlSuccess) {
+ for (i = 1; i <= pData[0]; i++) {
+
+ if (screens) {
+ tmp_str = g_strdup_printf("%s,\nScreen %d",
+ screens, pData[i]);
+ } else {
+ tmp_str = g_strdup_printf("Screen %d", pData[i]);
+ }
+ g_free(screens);
+ screens = tmp_str;
+ }
+ if (!screens) {
+ screens = g_strdup("None");
+
+ } else if (pData[0] > 0) {
+
+ ret = NvCtrlGetAttribute(screen_handles[pData[1]],
+ NV_CTRL_SHOW_SLI_HUD,
+ &tmp);
+
+ if (ret == NvCtrlSuccess) {
+ tmp_str = g_strdup_printf("%s (SLI)", screens);
+ g_free(screens);
+ screens = tmp_str;
+ }
+ }
+ }
+ }
+
+ /* List of Display Device connected on GPU */
+
+ displays = NULL;
+ ret = NvCtrlGetAttribute(handle, NV_CTRL_CONNECTED_DISPLAYS,
+ (int *)&display_devices);
+ if (ret == NvCtrlSuccess) {
+ displays = make_display_device_list(handle, display_devices);
+ }
+
+ /* now, create the object */
+
+ object = g_object_new(CTK_TYPE_GPU, NULL);
+ ctk_gpu = CTK_GPU(object);
+
+ /* cache the attribute handle */
+
+ ctk_gpu->handle = handle;
+
+ /* set container properties of the object */
+
+ gtk_box_set_spacing(GTK_BOX(ctk_gpu), 10);
+
+ /* banner */
+
+ banner = ctk_banner_image_new(&thermal_banner_image);
+ gtk_box_pack_start(GTK_BOX(ctk_gpu), banner, FALSE, FALSE, 0);
+
+ /*
+ * GPU information: TOP->MIDDLE - LEFT->RIGHT
+ *
+ * This displays basic display adatper information, including
+ * product name, bios version, bus type, video ram and interrupt
+ * line.
+ */
+
+ vbox = gtk_vbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(ctk_gpu), vbox, TRUE, TRUE, 0);
+
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+
+ label = gtk_label_new("Graphics Card Information");
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+ hseparator = gtk_hseparator_new();
+ gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5);
+
+ table = gtk_table_new(17, 2, FALSE);
+ gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
+ gtk_table_set_row_spacings(GTK_TABLE(table), 3);
+ gtk_table_set_col_spacings(GTK_TABLE(table), 15);
+ gtk_container_set_border_width(GTK_CONTAINER(table), 5);
+
+ add_table_row(table, 0,
+ 0, 0.5, "Graphics Processor:",
+ 0, 0.5, product_name);
+ add_table_row(table, 1,
+ 0, 0.5, "VBIOS Version:",
+ 0, 0.5, vbios_version);
+ add_table_row(table, 2,
+ 0, 0.5, "Memory:",
+ 0, 0.5, video_ram);
+ /* spacing */
+ add_table_row(table, 6,
+ 0, 0.5, "Bus Type:",
+ 0, 0.5, bus);
+ add_table_row(table, 7,
+ 0, 0.5, "Bus ID:",
+ 0, 0.5, pci_bus_id);
+ add_table_row(table, 8,
+ 0, 0.5, "IRQ:",
+ 0, 0.5, irq);
+ /* spacing */
+ add_table_row(table, 12,
+ 0, 0, "X Screens:",
+ 0, 0, screens);
+ /* spacing */
+ ctk_gpu->displays =
+ add_table_row(table, 16,
+ 0, 0, "Display Devices:",
+ 0, 0, displays);
+
+ XFree(product_name);
+ XFree(vbios_version);
+ g_free(video_ram);
+ g_free(bus);
+ g_free(pci_bus_id);
+ g_free(irq);
+ g_free(screens);
+ g_free(displays);
+
+ gtk_widget_show_all(GTK_WIDGET(object));
+
+ /* Handle events */
+
+ g_signal_connect(G_OBJECT(ctk_event),
+ CTK_EVENT_NAME(NV_CTRL_PROBE_DISPLAYS),
+ G_CALLBACK(probe_displays_received),
+ (gpointer) ctk_gpu);
+
+ return GTK_WIDGET(object);
+}
+
+
+GtkTextBuffer *ctk_gpu_create_help(GtkTextTagTable *table)
+{
+ GtkTextIter i;
+ GtkTextBuffer *b;
+
+ b = gtk_text_buffer_new(table);
+
+ gtk_text_buffer_get_iter_at_offset(b, &i, 0);
+
+ ctk_help_title(b, &i, "Graphics Card Information Help");
+
+ ctk_help_para(b, &i, "This page in the NVIDIA "
+ "X Server Control Panel describes basic "
+ "information about the Graphics Processing Unit "
+ "(GPU).");
+
+ ctk_help_heading(b, &i, "Graphics Processor");
+ ctk_help_para(b, &i, "This is the product name of the GPU.");
+
+ ctk_help_heading(b, &i, "VBIOS Version");
+ ctk_help_para(b, &i, "This is the Video BIOS version.");
+
+ ctk_help_heading(b, &i, "Memory");
+ ctk_help_para(b, &i, "This is the overall amount of memory "
+ "available to your GPU. With TurboCache(TM) GPUs, "
+ "this value may exceed the amount of video "
+ "memory installed on the graphics card. With "
+ "integrated GPUs, the value may exceed the amount of "
+ "dedicated system memory set aside by the system "
+ "BIOS for use by the integrated GPU.");
+
+ ctk_help_heading(b, &i, "Bus Type");
+ ctk_help_para(b, &i, "This is the bus type which is "
+ "used to connect the NVIDIA GPU to the rest of "
+ "your computer; possible values are AGP, PCI, "
+ "PCI Express and Integrated.");
+
+ ctk_help_heading(b, &i, "Bus ID");
+ ctk_help_para(b, &i, "This is the GPU's PCI identification string, "
+ "reported in the form 'bus:device:function'. It uniquely "
+ "identifies the GPU's location in the host system. "
+ "This string can be used as-is with the 'BusID' X "
+ "configuration file option to unambiguously associate "
+ "Device sections with this GPU.");
+
+ ctk_help_heading(b, &i, "IRQ");
+ ctk_help_para(b, &i, "This is the interrupt request line assigned to "
+ "this GPU.");
+
+ ctk_help_heading(b, &i, "X Screens");
+ ctk_help_para(b, &i, "This is the list of X Screens driven by this GPU.");
+
+ ctk_help_heading(b, &i, "Display Devices");
+ ctk_help_para(b, &i, "This is the list of Display Devices (CRTs, TVs etc) "
+ "enabled on this GPU.");
+
+ ctk_help_finish(b);
+
+ return b;
+}
+
+
+
+static void probe_displays_received(GtkObject *object, gpointer arg1,
+ gpointer user_data)
+{
+ CtkEventStruct *event_struct = (CtkEventStruct *) arg1;
+ CtkGpu *ctk_object = CTK_GPU(user_data);
+ unsigned int probed_displays = event_struct->value;
+ gchar *str;
+
+
+ str = make_display_device_list(ctk_object->handle, probed_displays);
+
+ gtk_label_set_text(GTK_LABEL(ctk_object->displays), str);
+
+ g_free(str);
+}
diff --git a/src/gtk+-2.x/ctkdevice.h b/src/gtk+-2.x/ctkgpu.h
index d567383..60a6220 100644
--- a/src/gtk+-2.x/ctkdevice.h
+++ b/src/gtk+-2.x/ctkgpu.h
@@ -22,54 +22,62 @@
*
*/
-#ifndef __CTK_DEVICE_H__
-#define __CTK_DEVICE_H__
+#ifndef __CTK_GPU_H__
+#define __CTK_GPU_H__
#include <gtk/gtk.h>
+#include "ctkevent.h"
+
#include "NvCtrlAttributes.h"
G_BEGIN_DECLS
-#define CTK_TYPE_DEVICE (ctk_device_get_type())
+#define CTK_TYPE_GPU (ctk_gpu_get_type())
-#define CTK_DEVICE(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), CTK_TYPE_DEVICE, CtkDevice))
+#define CTK_GPU(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), CTK_TYPE_GPU, CtkGpu))
-#define CTK_DEVICE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), CTK_TYPE_DEVICE, CtkDeviceClass))
+#define CTK_GPU_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), CTK_TYPE_GPU, CtkGpuClass))
-#define CTK_IS_DEVICE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CTK_TYPE_DEVICE))
+#define CTK_IS_GPU(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CTK_TYPE_GPU))
-#define CTK_IS_DEVICE_CLASS(class) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), CTK_TYPE_DEVICE))
+#define CTK_IS_GPU_CLASS(class) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), CTK_TYPE_GPU))
-#define CTK_DEVICE_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_DEVICE, CtkDeviceClass))
+#define CTK_GPU_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_GPU, CtkGpuClass))
-typedef struct _CtkDevice CtkDevice;
-typedef struct _CtkDeviceClass CtkDeviceClass;
+typedef struct _CtkGpu CtkGpu;
+typedef struct _CtkGpuClass CtkGpuClass;
-struct _CtkDevice
+struct _CtkGpu
{
GtkVBox parent;
NvCtrlAttributeHandle *handle;
+
+ GtkWidget *displays;
};
-struct _CtkDeviceClass
+struct _CtkGpuClass
{
GtkVBoxClass parent_class;
};
-GType ctk_device_get_type (void) G_GNUC_CONST;
-GtkWidget* ctk_device_new (NvCtrlAttributeHandle *handle);
+GType ctk_gpu_get_type (void) G_GNUC_CONST;
+GtkWidget* ctk_gpu_new (NvCtrlAttributeHandle *handle,
+ NvCtrlAttributeHandle **screen_handles,
+ CtkEvent *ctk_event);
+
+GtkTextBuffer *ctk_gpu_create_help(GtkTextTagTable *);
+
-GtkTextBuffer *ctk_device_create_help(GtkTextTagTable *, const gchar *);
G_END_DECLS
-#endif /* __CTK_DEVICE_H__ */
+#endif /* __CTK_GPU_H__ */
diff --git a/src/gtk+-2.x/ctkgvo-csc.c b/src/gtk+-2.x/ctkgvo-csc.c
index 1a7f06e..5b0366b 100644
--- a/src/gtk+-2.x/ctkgvo-csc.c
+++ b/src/gtk+-2.x/ctkgvo-csc.c
@@ -27,7 +27,6 @@
#include <string.h>
-#include "crt_banner.h"
#include "ctkimage.h"
#include "ctkgvo-csc.h"
@@ -70,8 +69,6 @@
/*
* TODO: ability to save/restore CSC to/from file.
- *
- * TODO: should use the same banner used on the front SDI page
*/
@@ -167,11 +164,11 @@ GType ctk_gvo_csc_get_type(void)
GtkWidget* ctk_gvo_csc_new(NvCtrlAttributeHandle *handle,
CtkConfig *ctk_config,
- CtkEvent *ctk_event)
+ CtkEvent *ctk_event,
+ CtkGvo *gvo_parent)
{
GObject *object;
CtkGvoCsc *ctk_gvo_csc;
- GtkWidget *banner;
GtkWidget *frame;
GtkWidget *hbox, *hbox2;
GtkWidget *vbox, *vbox2;
@@ -217,13 +214,21 @@ GtkWidget* ctk_gvo_csc_new(NvCtrlAttributeHandle *handle,
ctk_gvo_csc = CTK_GVO_CSC(object);
ctk_gvo_csc->handle = handle;
ctk_gvo_csc->ctk_config = ctk_config;
+ ctk_gvo_csc->gvo_parent = gvo_parent;
gtk_box_set_spacing(GTK_BOX(object), 10);
/* banner */
- banner = ctk_banner_image_new(&crt_banner_image);
- gtk_box_pack_start(GTK_BOX(object), banner, FALSE, FALSE, 0);
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, 0);
+
+ frame = gtk_frame_new(NULL);
+ gtk_box_pack_start(GTK_BOX(hbox), frame, FALSE, FALSE, 0);
+
+ gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
+
+ ctk_gvo_csc->banner_frame = frame;
/* checkbox to enable override of HW CSC */
@@ -1045,3 +1050,42 @@ static GtkWidget *build_opengl_only_msg(void)
return frame;
} /* build_opengl_only_msg() */
+
+
+
+void ctk_gvo_csc_select(GtkWidget *widget)
+{
+ CtkGvoCsc *ctk_gvo_csc = CTK_GVO_CSC(widget);
+ CtkGvo *ctk_gvo = ctk_gvo_csc->gvo_parent;
+
+ /* Grab the GVO parent banner table */
+
+ gtk_container_add(GTK_CONTAINER(ctk_gvo_csc->banner_frame),
+ ctk_gvo->banner.table);
+
+ /* Set lastest LED state of this GVO device */
+
+ ctk_gvo_pack_banner_slot(&ctk_gvo->banner, 1, ctk_gvo->banner.img.vid1);
+ ctk_gvo_pack_banner_slot(&ctk_gvo->banner, 2, ctk_gvo->banner.img.vid2);
+ ctk_gvo_pack_banner_slot(&ctk_gvo->banner, 3, ctk_gvo->banner.img.sdi);
+ ctk_gvo_pack_banner_slot(&ctk_gvo->banner, 4, ctk_gvo->banner.img.comp);
+
+ ctk_config_start_timer(ctk_gvo->ctk_config, (GSourceFunc) ctk_gvo_probe,
+ (gpointer) ctk_gvo);
+}
+
+
+
+void ctk_gvo_csc_unselect(GtkWidget *widget)
+{
+ CtkGvoCsc *ctk_gvo_csc = CTK_GVO_CSC(widget);
+ CtkGvo *ctk_gvo = ctk_gvo_csc->gvo_parent;
+
+ /* Return the GVO parent banner table */
+
+ gtk_container_remove(GTK_CONTAINER(ctk_gvo_csc->banner_frame),
+ ctk_gvo->banner.table);
+
+ ctk_config_stop_timer(ctk_gvo->ctk_config, (GSourceFunc) ctk_gvo_probe,
+ (gpointer) ctk_gvo);
+}
diff --git a/src/gtk+-2.x/ctkgvo-csc.h b/src/gtk+-2.x/ctkgvo-csc.h
index 7561039..bdbf1f4 100644
--- a/src/gtk+-2.x/ctkgvo-csc.h
+++ b/src/gtk+-2.x/ctkgvo-csc.h
@@ -27,6 +27,7 @@
#include "ctkevent.h"
#include "ctkconfig.h"
+#include "ctkgvo.h"
G_BEGIN_DECLS
@@ -61,6 +62,9 @@ struct _CtkGvoCsc
NvCtrlAttributeHandle *handle;
CtkConfig *ctk_config;
+ CtkGvo *gvo_parent;
+ GtkWidget *banner_frame;
+
float matrix[3][3]; // [row][column]
float offset[3];
float scale[3];
@@ -90,11 +94,14 @@ struct _CtkGvoCscClass
GType ctk_gvo_csc_get_type (void) G_GNUC_CONST;
GtkWidget* ctk_gvo_csc_new (NvCtrlAttributeHandle *,
- CtkConfig *, CtkEvent *);
+ CtkConfig *, CtkEvent *, CtkGvo *);
//GtkTextBuffer *ctk_gvo_csc_create_help(GtkTextTagTable *,
// CtkGvoCsc *);
+void ctk_gvo_csc_select(GtkWidget *);
+void ctk_gvo_csc_unselect(GtkWidget *);
+
G_END_DECLS
#endif /* __CTK_GVO_CSC_H__ */
diff --git a/src/gtk+-2.x/ctkgvo.c b/src/gtk+-2.x/ctkgvo.c
index 93f624c..f364ad9 100644
--- a/src/gtk+-2.x/ctkgvo.c
+++ b/src/gtk+-2.x/ctkgvo.c
@@ -145,8 +145,6 @@ static void update_offset_spin_buttons(CtkGvo *ctk_gvo);
static void x_offset_changed(GtkSpinButton *spinbutton, gpointer user_data);
static void y_offset_changed(GtkSpinButton *spinbutton, gpointer user_data);
-static gint probe(gpointer data);
-
static void register_for_gvo_events(CtkGvo *ctk_gvo);
static void gvo_event_received(GtkObject *object,
@@ -226,16 +224,16 @@ static const FormatName videoFormatNames[] = {
{ NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_25_00_SMPTE274, "1920 x 1080PsF 25.00 Hz (SMPTE274)" },
{ NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_29_97_SMPTE274, "1920 x 1080PsF 29.97 Hz (SMPTE274)" },
{ NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_30_00_SMPTE274, "1920 x 1080PsF 30.00 Hz (SMPTE274)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080I_23_98_SMPTE372, "2048 x 1080i 23.98 Hz (SMPTE372)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080I_24_00_SMPTE372, "2048 x 1080i 24.00 Hz (SMPTE372)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080I_25_00_SMPTE372, "2048 x 1080i 25.00 Hz (SMPTE372)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080I_29_97_SMPTE372, "2048 x 1080i 29.97 Hz (SMPTE372)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080I_30_00_SMPTE372, "2048 x 1080i 30.00 Hz (SMPTE372)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080P_23_98_SMPTE372, "2048 x 1080p 23.98 Hz (SMPTE372)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080P_24_00_SMPTE372, "2048 x 1080p 24.00 Hz (SMPTE372)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080P_25_00_SMPTE372, "2048 x 1080p 25.00 Hz (SMPTE372)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080P_29_97_SMPTE372, "2048 x 1080p 29.97 Hz (SMPTE372)" },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080P_30_00_SMPTE372, "2048 x 1080p 30.00 Hz (SMPTE372)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_2048I_47_96_SMPTE372, "2048 x 1080i 47.96 Hz (SMPTE372)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_2048I_48_00_SMPTE372, "2048 x 1080i 48.00 Hz (SMPTE372)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_2048I_50_00_SMPTE372, "2048 x 1080i 50.00 Hz (SMPTE372)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_2048I_59_94_SMPTE372, "2048 x 1080i 59.94 Hz (SMPTE372)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_2048I_60_00_SMPTE372, "2048 x 1080i 60.00 Hz (SMPTE372)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_2048P_23_98_SMPTE372, "2048 x 1080p 23.98 Hz (SMPTE372)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_2048P_24_00_SMPTE372, "2048 x 1080p 24.00 Hz (SMPTE372)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_2048P_25_00_SMPTE372, "2048 x 1080p 25.00 Hz (SMPTE372)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_2048P_29_97_SMPTE372, "2048 x 1080p 29.97 Hz (SMPTE372)" },
+ { NV_CTRL_GVO_VIDEO_FORMAT_2048P_30_00_SMPTE372, "2048 x 1080p 30.00 Hz (SMPTE372)" },
{ -1, NULL },
};
@@ -269,16 +267,16 @@ static FormatDetails videoFormatDetails[] = {
{ NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_25_00_SMPTE274, 0, 0, 0 },
{ NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_29_97_SMPTE274, 0, 0, 0 },
{ NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_30_00_SMPTE274, 0, 0, 0 },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080I_23_98_SMPTE372, 0, 0, 0 },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080I_24_00_SMPTE372, 0, 0, 0 },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080I_25_00_SMPTE372, 0, 0, 0 },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080I_29_97_SMPTE372, 0, 0, 0 },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080I_30_00_SMPTE372, 0, 0, 0 },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080P_23_98_SMPTE372, 0, 0, 0 },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080P_24_00_SMPTE372, 0, 0, 0 },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080P_25_00_SMPTE372, 0, 0, 0 },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080P_29_97_SMPTE372, 0, 0, 0 },
- { NV_CTRL_GVO_VIDEO_FORMAT_1080P_30_00_SMPTE372, 0, 0, 0 },
+ { NV_CTRL_GVO_VIDEO_FORMAT_2048I_47_96_SMPTE372, 0, 0, 0 },
+ { NV_CTRL_GVO_VIDEO_FORMAT_2048I_48_00_SMPTE372, 0, 0, 0 },
+ { NV_CTRL_GVO_VIDEO_FORMAT_2048I_50_00_SMPTE372, 0, 0, 0 },
+ { NV_CTRL_GVO_VIDEO_FORMAT_2048I_59_94_SMPTE372, 0, 0, 0 },
+ { NV_CTRL_GVO_VIDEO_FORMAT_2048I_60_00_SMPTE372, 0, 0, 0 },
+ { NV_CTRL_GVO_VIDEO_FORMAT_2048P_23_98_SMPTE372, 0, 0, 0 },
+ { NV_CTRL_GVO_VIDEO_FORMAT_2048P_24_00_SMPTE372, 0, 0, 0 },
+ { NV_CTRL_GVO_VIDEO_FORMAT_2048P_25_00_SMPTE372, 0, 0, 0 },
+ { NV_CTRL_GVO_VIDEO_FORMAT_2048P_29_97_SMPTE372, 0, 0, 0 },
+ { NV_CTRL_GVO_VIDEO_FORMAT_2048P_30_00_SMPTE372, 0, 0, 0 },
{ -1, -1, -1, -1 },
};
@@ -426,11 +424,17 @@ GtkWidget* ctk_gvo_new(NvCtrlAttributeHandle *handle,
}
}
- add_table_row(table, 0, 0, "Firmware Version:", firmware);
+ add_table_row(table, 0,
+ 0, 0.5, "Firmware Version:",
+ 0, 0.5, firmware);
ctk_gvo->current_resolution_label =
- add_table_row(table, 1, 0, "Current SDI Resolution:", "Inactive");
+ add_table_row(table, 1,
+ 0, 0.5, "Current SDI Resolution:",
+ 0, 0.5, "Inactive");
ctk_gvo->current_state_label =
- add_table_row(table, 2, 0, "Current SDI State:", "Inactive");
+ add_table_row(table, 2,
+ 0, 0.5, "Current SDI State:",
+ 0, 0.5, "Inactive");
/*
@@ -793,7 +797,7 @@ GtkWidget* ctk_gvo_new(NvCtrlAttributeHandle *handle,
ctk_config_add_timer(ctk_gvo->ctk_config,
DEFAULT_GVO_PROBE_TIME_INTERVAL,
"Graphics To Video Probe",
- (GSourceFunc) probe,
+ (GSourceFunc) ctk_gvo_probe,
(gpointer) ctk_gvo);
@@ -808,55 +812,12 @@ GtkWidget* ctk_gvo_new(NvCtrlAttributeHandle *handle,
} /* ctk_gvo_new() */
-void ctk_gvo_select(GtkWidget *widget)
-{
- CtkGvo *ctk_gvo = CTK_GVO(widget);
-
- gtk_container_add(GTK_CONTAINER(ctk_gvo->banner_frame),
- ctk_gvo->banner.table);
-
- ctk_config_start_timer(ctk_gvo->ctk_config, (GSourceFunc) probe);
-}
-
-void ctk_gvo_unselect(GtkWidget *widget)
-{
- CtkGvo *ctk_gvo = CTK_GVO(widget);
-
- gtk_container_remove(GTK_CONTAINER(ctk_gvo->banner_frame),
- ctk_gvo->banner.table);
-
- ctk_config_start_timer(ctk_gvo->ctk_config, (GSourceFunc) probe);
-}
-
/**************************************************************************/
/*
* code for handling the GVO banner
*/
-
-#define GVO_BANNER_LEFT 0
-#define GVO_BANNER_VID1_GREEN 1
-#define GVO_BANNER_VID1_GREY 2
-#define GVO_BANNER_VID1_RED 3
-#define GVO_BANNER_VID1_YELLOW 4
-#define GVO_BANNER_VID2_GREEN 5
-#define GVO_BANNER_VID2_GREY 6
-#define GVO_BANNER_VID2_RED 7
-#define GVO_BANNER_VID2_YELLOW 8
-#define GVO_BANNER_SDI_SYNC_GREEN 9
-#define GVO_BANNER_SDI_SYNC_GREY 10
-#define GVO_BANNER_SDI_SYNC_RED 11
-#define GVO_BANNER_SDI_SYNC_YELLOW 12
-#define GVO_BANNER_COMP_SYNC_GREEN 13
-#define GVO_BANNER_COMP_SYNC_GREY 14
-#define GVO_BANNER_COMP_SYNC_RED 15
-#define GVO_BANNER_COMP_SYNC_YELLOW 16
-#define GVO_BANNER_RIGHT 17
-
-#define GVO_BANNER_COUNT 18
-
-
/* value for controlling LED state */
#define GVO_LED_VID_OUT_NOT_IN_USE 0
@@ -872,8 +833,6 @@ void ctk_gvo_unselect(GtkWidget *widget)
#define GVO_LED_COMP_SYNC_SYNC 1
-static GtkWidget *__gvo_banner_widget[GVO_BANNER_COUNT];
-
/* XXX we can get rid of a bunch of these images */
static const nv_image_t *__gvo_banner_imgs[GVO_BANNER_COUNT] = {
@@ -899,22 +858,26 @@ static const nv_image_t *__gvo_banner_imgs[GVO_BANNER_COUNT] = {
/*
- * pack_gvo_banner_slot() - update slot 'slot' in the banner with the
+ * ctk_gvo_pack_banner_slot() - update slot 'slot' in the banner with the
* image specified by 'new'
*/
-static void pack_gvo_banner_slot(CtkGvoBanner *banner,
- gint slot, gint new, gint old)
+void ctk_gvo_pack_banner_slot(CtkGvoBanner *banner, gint slot, gint new)
{
- if (old >= 0) {
+ GList *list;
+
+ /* Remove last image, if any */
+ list = gtk_container_get_children(GTK_CONTAINER(banner->slots[slot]));
+ if (list) {
gtk_container_remove(GTK_CONTAINER(banner->slots[slot]),
- __gvo_banner_widget[old]);
+ (GtkWidget *)(list->data));
+ g_list_free(list);
}
- gtk_box_pack_start(GTK_BOX(banner->slots[slot]),
- __gvo_banner_widget[new], TRUE, TRUE, 0);
+ gtk_box_pack_start(GTK_BOX(banner->slots[slot]), banner->imgs[new],
+ TRUE, TRUE, 0);
-} /* pack_gvo_banner_slot() */
+} /* ctk_gvo_pack_banner_slot() */
@@ -928,21 +891,25 @@ static void init_gvo_banner(CtkGvoBanner *banner)
const nv_image_t *img;
guint8 *image_buffer = NULL;
+ /* Create the banner table */
+
banner->table = gtk_table_new(1, 6, FALSE);
gtk_object_ref(GTK_OBJECT(banner->table));
-
+
gtk_table_set_row_spacings(GTK_TABLE(banner->table), 0);
gtk_table_set_col_spacings(GTK_TABLE(banner->table), 0);
+ /* Create the banner images */
+
for (i = 0; i < GVO_BANNER_COUNT; i++) {
-
- if (__gvo_banner_widget[i]) continue;
-
+
+ if (banner->imgs[i]) continue;
+
img = __gvo_banner_imgs[i];
-
+
image_buffer = decompress_image_data(img);
- __gvo_banner_widget[i] = gtk_image_new_from_pixbuf
+ banner->imgs[i] = gtk_image_new_from_pixbuf
(gdk_pixbuf_new_from_data(image_buffer, GDK_COLORSPACE_RGB,
FALSE, 8, img->width, img->height,
img->width * img->bytes_per_pixel,
@@ -953,33 +920,25 @@ static void init_gvo_banner(CtkGvoBanner *banner)
* gtk_container_remove() later, it doesn't get destroyed
*/
- gtk_object_ref(GTK_OBJECT(__gvo_banner_widget[i]));
-
+ gtk_object_ref(GTK_OBJECT(banner->imgs[i]));
- gtk_widget_show(__gvo_banner_widget[i]);
+
+ gtk_widget_show(banner->imgs[i]);
}
+
/*
- * fill in the banner table with initial images, and the
- * containers for the LED images that will get swapped in and out.
+ * fill in the banner table containers for the LED images
+ * that will get swapped in and out.
*/
-
- gtk_table_attach(GTK_TABLE(banner->table),
- __gvo_banner_widget[GVO_BANNER_LEFT],
- 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
-
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < 6; i++) {
banner->slots[i] = gtk_hbox_new(FALSE, 0);
gtk_object_ref(GTK_OBJECT(banner->slots[i]));
gtk_table_attach(GTK_TABLE(banner->table), banner->slots[i],
i+1, i+2, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
}
-
- gtk_table_attach(GTK_TABLE(banner->table),
- __gvo_banner_widget[GVO_BANNER_RIGHT],
- 5, 6, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
-
+
/*
* initialize LED state
@@ -995,10 +954,8 @@ static void init_gvo_banner(CtkGvoBanner *banner)
banner->img.sdi = GVO_BANNER_SDI_SYNC_GREY;
banner->img.comp = GVO_BANNER_COMP_SYNC_GREY;
- pack_gvo_banner_slot(banner, 0, banner->img.vid1, -1);
- pack_gvo_banner_slot(banner, 1, banner->img.vid2, -1);
- pack_gvo_banner_slot(banner, 2, banner->img.sdi, -1);
- pack_gvo_banner_slot(banner, 3, banner->img.comp, -1);
+ ctk_gvo_pack_banner_slot(banner, 0, GVO_BANNER_LEFT);
+ ctk_gvo_pack_banner_slot(banner, 5, GVO_BANNER_RIGHT);
gtk_widget_show_all(GTK_WIDGET(banner->table));
@@ -1047,7 +1004,7 @@ static gboolean update_gvo_banner(gpointer data)
}
if (old != new) {
- pack_gvo_banner_slot(banner, 0, new, old);
+ ctk_gvo_pack_banner_slot(banner, 1, new);
banner->img.vid1 = new;
}
@@ -1078,7 +1035,7 @@ static gboolean update_gvo_banner(gpointer data)
}
if (old != new) {
- pack_gvo_banner_slot(banner, 1, new, old);
+ ctk_gvo_pack_banner_slot(banner, 2, new);
banner->img.vid2 = new;
}
@@ -1111,7 +1068,7 @@ static gboolean update_gvo_banner(gpointer data)
}
if (old != new) {
- pack_gvo_banner_slot(banner, 2, new, old);
+ ctk_gvo_pack_banner_slot(banner, 3, new);
banner->img.sdi = new;
}
@@ -1132,7 +1089,7 @@ static gboolean update_gvo_banner(gpointer data)
}
if (old != new) {
- pack_gvo_banner_slot(banner, 3, new, old);
+ ctk_gvo_pack_banner_slot(banner, 4, new);
banner->img.comp = new;
}
@@ -2133,7 +2090,7 @@ static gint detect_input_done(gpointer data)
/* reprobe */
- probe((gpointer) ctk_gvo);
+ ctk_gvo_probe((gpointer) ctk_gvo);
/* un-press the detect button */
@@ -2470,10 +2427,10 @@ static void y_offset_changed(GtkSpinButton *spinbutton, gpointer user_data)
/**************************************************************************/
/*
- * probe() - query the incoming signal
+ * ctk_gvo_probe() - query the incoming signal
*/
-static gint probe(gpointer data)
+gint ctk_gvo_probe(gpointer data)
{
ReturnStatus ret;
gint input, sdi, comp;
@@ -2534,7 +2491,7 @@ static gint probe(gpointer data)
return TRUE;
-} /* probe() */
+} /* ctk_gvo_probe() */
/**************************************************************************/
@@ -2761,6 +2718,38 @@ static void gvo_event_received(GtkObject *object,
/**************************************************************************/
+void ctk_gvo_select(GtkWidget *widget)
+{
+ CtkGvo *ctk_gvo = CTK_GVO(widget);
+
+ gtk_container_add(GTK_CONTAINER(ctk_gvo->banner_frame),
+ ctk_gvo->banner.table);
+
+ /* Set lastest LED state of this GVO device */
+
+ ctk_gvo_pack_banner_slot(&ctk_gvo->banner, 1, ctk_gvo->banner.img.vid1);
+ ctk_gvo_pack_banner_slot(&ctk_gvo->banner, 2, ctk_gvo->banner.img.vid2);
+ ctk_gvo_pack_banner_slot(&ctk_gvo->banner, 3, ctk_gvo->banner.img.sdi);
+ ctk_gvo_pack_banner_slot(&ctk_gvo->banner, 4, ctk_gvo->banner.img.comp);
+
+ ctk_config_start_timer(ctk_gvo->ctk_config, (GSourceFunc) ctk_gvo_probe,
+ (gpointer) ctk_gvo);
+}
+
+
+
+void ctk_gvo_unselect(GtkWidget *widget)
+{
+ CtkGvo *ctk_gvo = CTK_GVO(widget);
+
+ gtk_container_remove(GTK_CONTAINER(ctk_gvo->banner_frame),
+ ctk_gvo->banner.table);
+
+ ctk_config_stop_timer(ctk_gvo->ctk_config, (GSourceFunc) ctk_gvo_probe,
+ (gpointer) ctk_gvo);
+}
+
+
GtkTextBuffer* ctk_gvo_create_help (GtkTextTagTable *table)
{
diff --git a/src/gtk+-2.x/ctkgvo.h b/src/gtk+-2.x/ctkgvo.h
index b495cfd..7a1734f 100644
--- a/src/gtk+-2.x/ctkgvo.h
+++ b/src/gtk+-2.x/ctkgvo.h
@@ -57,11 +57,35 @@ typedef struct _CtkGvoClass CtkGvoClass;
typedef struct _CtkGvoBanner CtkGvoBanner;
+#define GVO_BANNER_LEFT 0
+#define GVO_BANNER_VID1_GREEN 1
+#define GVO_BANNER_VID1_GREY 2
+#define GVO_BANNER_VID1_RED 3
+#define GVO_BANNER_VID1_YELLOW 4
+#define GVO_BANNER_VID2_GREEN 5
+#define GVO_BANNER_VID2_GREY 6
+#define GVO_BANNER_VID2_RED 7
+#define GVO_BANNER_VID2_YELLOW 8
+#define GVO_BANNER_SDI_SYNC_GREEN 9
+#define GVO_BANNER_SDI_SYNC_GREY 10
+#define GVO_BANNER_SDI_SYNC_RED 11
+#define GVO_BANNER_SDI_SYNC_YELLOW 12
+#define GVO_BANNER_COMP_SYNC_GREEN 13
+#define GVO_BANNER_COMP_SYNC_GREY 14
+#define GVO_BANNER_COMP_SYNC_RED 15
+#define GVO_BANNER_COMP_SYNC_YELLOW 16
+#define GVO_BANNER_RIGHT 17
+
+#define GVO_BANNER_COUNT 18
+
+
struct _CtkGvoBanner
{
+ GtkWidget *imgs[GVO_BANNER_COUNT];
+
GtkWidget *table;
-
- GtkWidget *slots[4];
+
+ GtkWidget *slots[6];
struct {
guint8 vid1;
@@ -143,6 +167,8 @@ GtkWidget* ctk_gvo_new (NvCtrlAttributeHandle *,
void ctk_gvo_select (GtkWidget *);
void ctk_gvo_unselect (GtkWidget *);
GtkTextBuffer* ctk_gvo_create_help (GtkTextTagTable *);
+void ctk_gvo_pack_banner_slot (CtkGvoBanner *, gint slot, gint new);
+gint ctk_gvo_probe (gpointer data);
G_END_DECLS
diff --git a/src/gtk+-2.x/ctkhelp.c b/src/gtk+-2.x/ctkhelp.c
index 5df77ca..378efb4 100644
--- a/src/gtk+-2.x/ctkhelp.c
+++ b/src/gtk+-2.x/ctkhelp.c
@@ -29,6 +29,7 @@
#include "ctkconstants.h"
#include "help_banner.h"
+#include "ctkimage.h"
#include <stdlib.h>
@@ -74,13 +75,10 @@ GtkWidget* ctk_help_new(GtkWidget *toggle_button, GtkTextTagTable *tag_table)
GtkWidget *alignment;
GtkWidget *button;
GtkWidget *sw;
- GtkWidget *image;
+ GtkWidget *banner;
GtkWidget *frame;
GtkWidget *textview;
- guint8 *image_buffer = NULL;
- const nv_image_t *img;
-
object = g_object_new(CTK_TYPE_HELP, NULL);
ctk_help = CTK_HELP(object);
@@ -102,22 +100,8 @@ GtkWidget* ctk_help_new(GtkWidget *toggle_button, GtkTextTagTable *tag_table)
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
- frame = gtk_frame_new(NULL);
- gtk_box_pack_start(GTK_BOX(hbox), frame, FALSE, FALSE, 0);
-
- gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
-
- img = &help_banner_image;
-
- image_buffer = decompress_image_data(img);
-
- image = gtk_image_new_from_pixbuf
- (gdk_pixbuf_new_from_data(image_buffer, GDK_COLORSPACE_RGB,
- FALSE, 8, img->width, img->height,
- img->width * img->bytes_per_pixel,
- free_decompressed_image, NULL));
-
- gtk_container_add(GTK_CONTAINER(frame), image);
+ banner = ctk_banner_image_new(&help_banner_image);
+ gtk_box_pack_start(GTK_BOX(hbox), banner, TRUE, TRUE, 0);
/* create the scroll window to hold the text viewer */
diff --git a/src/gtk+-2.x/ctkimage.c b/src/gtk+-2.x/ctkimage.c
index 319c55f..d8939f5 100644
--- a/src/gtk+-2.x/ctkimage.c
+++ b/src/gtk+-2.x/ctkimage.c
@@ -32,6 +32,7 @@
#include "image.h"
#include "ctkimage.h"
+#include "ctkbanner.h"
/*
@@ -108,14 +109,14 @@ GtkWidget* ctk_banner_image_new(const nv_image_t *img)
GtkWidget *frame;
- image = ctk_image_new(img);
+ image = ctk_banner_new(img);
if (!image) return NULL;
hbox = gtk_hbox_new(FALSE, 0);
frame = gtk_frame_new(NULL);
- gtk_box_pack_start(GTK_BOX(hbox), frame, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0);
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
gtk_container_add(GTK_CONTAINER(frame), image);
diff --git a/src/gtk+-2.x/ctkimagesliders.c b/src/gtk+-2.x/ctkimagesliders.c
index 5c3ee1e..80152a0 100644
--- a/src/gtk+-2.x/ctkimagesliders.c
+++ b/src/gtk+-2.x/ctkimagesliders.c
@@ -34,22 +34,27 @@
#define FRAME_PADDING 5
-static void
-dvc_adjustment_value_changed(GtkAdjustment *, gpointer);
+static const char *__digital_vibrance_help = "The Digital Vibrance slider "
+"alters the level of Digital Vibrance for this display device.";
-static void dvc_update_slider(CtkImageSliders *ctk_image_sliders, gint value);
+static const char *__image_sharpening_help = "The Image Sharpening slider "
+"alters the level of Image Sharpening for this display device.";
-static void dvc_update_received(GtkObject *, gpointer arg1, gpointer);
-static void
-image_sharpening_adjustment_value_changed(GtkAdjustment *, gpointer);
+static GtkWidget * add_scale(CtkConfig *ctk_config,
+ int attribute,
+ char *name,
+ const char *help,
+ gint value_type,
+ gpointer callback_data);
-static void
-image_sharpening_update_slider(CtkImageSliders *ctk_image_sliders, gint value);
+static void setup_scale(CtkImageSliders *ctk_image_sliders,
+ int attribute, GtkWidget *scale);
-static void image_sharpening_update_received(GtkObject *, gpointer arg1,
- gpointer);
+static void scale_value_changed(GtkAdjustment *adjustment,
+ gpointer user_data);
+static void scale_value_received(GtkObject *, gpointer arg1, gpointer);
GType ctk_image_sliders_get_type(void)
@@ -89,40 +94,7 @@ GtkWidget* ctk_image_sliders_new(NvCtrlAttributeHandle *handle,
GtkWidget *frame;
GtkWidget *vbox;
- GtkWidget *scale;
- GtkWidget *widget;
-
- ReturnStatus ret0, ret1, ret2, ret3;
-
- NVCTRLAttributeValidValuesRec dvc_valid, sharp_valid;
-
- int dvc, sharp;
-
- /*
- * retrieve the valid values and current value for DVC and Image
- * Sharpening; if we were unable to query any of those, then
- * return NULL.
- */
-
- ret0 = NvCtrlGetValidDisplayAttributeValues(handle, display_device_mask,
- NV_CTRL_DIGITAL_VIBRANCE,
- &dvc_valid);
-
- ret1 = NvCtrlGetDisplayAttribute(handle, display_device_mask,
- NV_CTRL_DIGITAL_VIBRANCE,
- &dvc);
- ret2 = NvCtrlGetValidDisplayAttributeValues(handle, display_device_mask,
- NV_CTRL_IMAGE_SHARPENING,
- &sharp_valid);
-
- ret3 = NvCtrlGetDisplayAttribute(handle, display_device_mask,
- NV_CTRL_IMAGE_SHARPENING,
- &sharp);
-
- if ((ret0 != NvCtrlSuccess) && (ret1 != NvCtrlSuccess) &&
- (ret2 != NvCtrlSuccess) && (ret3 != NvCtrlSuccess)) return NULL;
-
/*
* now that we know that we will have atleast one attribute,
* create the object
@@ -133,6 +105,7 @@ GtkWidget* ctk_image_sliders_new(NvCtrlAttributeHandle *handle,
ctk_image_sliders = CTK_IMAGE_SLIDERS(object);
ctk_image_sliders->handle = handle;
ctk_image_sliders->ctk_config = ctk_config;
+ ctk_image_sliders->ctk_event = ctk_event;
ctk_image_sliders->reset_button = reset_button;
ctk_image_sliders->display_device_mask = display_device_mask;
ctk_image_sliders->name = name;
@@ -144,83 +117,44 @@ GtkWidget* ctk_image_sliders_new(NvCtrlAttributeHandle *handle,
gtk_container_set_border_width(GTK_CONTAINER(vbox), FRAME_PADDING);
gtk_container_add(GTK_CONTAINER(frame), vbox);
gtk_box_pack_start(GTK_BOX(object), frame, FALSE, FALSE, 0);
+ ctk_image_sliders->frame = frame;
-
- /* DVC */
+ /* Digital Vibrance */
- if ((ret0 == NvCtrlSuccess) && (ret1 == NvCtrlSuccess)) {
-
- ctk_image_sliders->dvc_adjustment =
- gtk_adjustment_new(dvc,
- dvc_valid.u.range.min,
- dvc_valid.u.range.max,
- 1, 5, 0);
-
- g_signal_connect(G_OBJECT(ctk_image_sliders->dvc_adjustment),
- "value_changed",
- G_CALLBACK(dvc_adjustment_value_changed),
- (gpointer) ctk_image_sliders);
-
- g_signal_connect(G_OBJECT(ctk_event),
- CTK_EVENT_NAME(NV_CTRL_DIGITAL_VIBRANCE),
- G_CALLBACK(dvc_update_received),
- (gpointer) ctk_image_sliders);
-
- scale = ctk_scale_new
- (GTK_ADJUSTMENT(ctk_image_sliders->dvc_adjustment),
- "Digital Vibrance", ctk_config, G_TYPE_DOUBLE);
-
- gtk_box_pack_start(GTK_BOX(vbox), scale, TRUE, TRUE, 0);
-
- widget = CTK_SCALE(scale)->gtk_scale;
+ ctk_image_sliders->digital_vibrance =
+ add_scale(ctk_config,
+ NV_CTRL_DIGITAL_VIBRANCE, "Digital Vibrance",
+ __digital_vibrance_help, G_TYPE_DOUBLE, ctk_image_sliders);
+
+ g_signal_connect(G_OBJECT(ctk_event),
+ CTK_EVENT_NAME(NV_CTRL_DIGITAL_VIBRANCE),
+ G_CALLBACK(scale_value_received),
+ (gpointer) ctk_image_sliders);
+
+ gtk_box_pack_start(GTK_BOX(vbox), ctk_image_sliders->digital_vibrance,
+ TRUE, TRUE, 0);
- ctk_config_set_tooltip(ctk_config, widget,
- "The Digital Vibrance slider alters the level "
- "of Digital Vibrance for this display device.");
- } else {
- ctk_image_sliders->dvc_adjustment = NULL;
- }
-
-
/* Image Sharpening */
+
+ ctk_image_sliders->image_sharpening =
+ add_scale(ctk_config,
+ NV_CTRL_IMAGE_SHARPENING, "Image Sharpening",
+ __image_sharpening_help, G_TYPE_DOUBLE, ctk_image_sliders);
- if ((ret2 == NvCtrlSuccess) && (ret3 == NvCtrlSuccess)) {
-
- ctk_image_sliders->image_sharpening_adjustment =
- gtk_adjustment_new(sharp,
- sharp_valid.u.range.min,
- sharp_valid.u.range.max,
- 1, 5, 0);
-
- g_signal_connect
- (G_OBJECT(ctk_image_sliders->image_sharpening_adjustment),
- "value_changed",
- G_CALLBACK(image_sharpening_adjustment_value_changed),
- (gpointer) ctk_image_sliders);
-
- g_signal_connect(G_OBJECT(ctk_event),
- CTK_EVENT_NAME(NV_CTRL_IMAGE_SHARPENING),
- G_CALLBACK(image_sharpening_update_received),
- (gpointer) ctk_image_sliders);
-
- scale = ctk_scale_new
- (GTK_ADJUSTMENT(ctk_image_sliders->image_sharpening_adjustment),
- "Image Sharpening", ctk_config, G_TYPE_DOUBLE);
-
- gtk_box_pack_start(GTK_BOX(vbox), scale, TRUE, TRUE, 0);
-
- widget = CTK_SCALE(scale)->gtk_scale;
-
- ctk_config_set_tooltip(ctk_config, widget,
- "The Image Sharpening slider alters the level "
- "of Image Sharpening for this display device.");
- } else {
- ctk_image_sliders->image_sharpening_adjustment = NULL;
- }
+ g_signal_connect(G_OBJECT(ctk_event),
+ CTK_EVENT_NAME(NV_CTRL_IMAGE_SHARPENING),
+ G_CALLBACK(scale_value_received),
+ (gpointer) ctk_image_sliders);
+ gtk_box_pack_start(GTK_BOX(vbox), ctk_image_sliders->image_sharpening,
+ TRUE, TRUE, 0);
gtk_widget_show_all(GTK_WIDGET(object));
+ /* update the GUI */
+
+ ctk_image_sliders_setup(ctk_image_sliders);
+
return GTK_WIDGET(object);
} /* ctk_image_sliders_new() */
@@ -228,257 +162,314 @@ GtkWidget* ctk_image_sliders_new(NvCtrlAttributeHandle *handle,
/*
- * ctk_image_sliders_reset() -
+ * Returns whether or not the scale is active
*/
-void ctk_image_sliders_reset(CtkImageSliders *ctk_image_sliders)
+static gint get_scale_active(CtkScale *scale)
{
- if (!ctk_image_sliders) return;
+ GtkAdjustment *adj = scale->gtk_adjustment;
- if (ctk_image_sliders->dvc_adjustment) {
+ return
+ GPOINTER_TO_INT(g_object_get_data(G_OBJECT(adj), "attribute active"));
+
+} /* get_scale_active() */
+
+
+
+/*
+ * add_scale() - if the specified attribute exists and we can
+ * query its valid values, create a new scale widget
+ */
+
+static GtkWidget * add_scale(CtkConfig *ctk_config,
+ int attribute,
+ char *name,
+ const char *help,
+ gint value_type,
+ gpointer callback_data)
+{
+ GtkObject *adj;
+ GtkWidget *scale;
+
+
+ adj = gtk_adjustment_new(0, 0, 10, 1, 1, 0);
- NvCtrlSetDisplayAttribute(ctk_image_sliders->handle,
- ctk_image_sliders->display_device_mask,
- NV_CTRL_DIGITAL_VIBRANCE,
- 0);
+ g_object_set_data(G_OBJECT(adj), "attribute",
+ GINT_TO_POINTER(attribute));
- dvc_update_slider(ctk_image_sliders, 0);
- }
+ g_object_set_data(G_OBJECT(adj), "attribute name", name);
+
+ g_object_set_data(G_OBJECT(adj), "attribute active",
+ GINT_TO_POINTER(0));
- if (ctk_image_sliders->image_sharpening_adjustment) {
+ g_signal_connect(G_OBJECT(adj), "value_changed",
+ G_CALLBACK(scale_value_changed),
+ (gpointer) callback_data);
- NvCtrlSetDisplayAttribute(ctk_image_sliders->handle,
- ctk_image_sliders->display_device_mask,
- NV_CTRL_IMAGE_SHARPENING,
- 0);
+ scale = ctk_scale_new(GTK_ADJUSTMENT(adj), name, ctk_config, value_type);
- image_sharpening_update_slider(ctk_image_sliders, 0);
+ if (help) {
+ ctk_config_set_tooltip(ctk_config, CTK_SCALE_TOOLTIP_WIDGET(scale),
+ help);
}
-} /* ctk_image_sliders_reset() */
+ return scale;
+
+} /* add_scale() */
/*
- * post_dvc_update() - helper function for
- * dvc_adjustment_value_changed() and dvc_update_received(); this does
- * whatever work is necessary after the the DVC adjustment widget is
- * updated -- currently, this is just posting a statusbar message.
+ * post_scale_value_changed() - helper function for
+ * scale_value_changed() and value_changed(); this does whatever
+ * work is necessary after the adjustment has been updated --
+ * currently, this just means posting a statusbar message.
*/
-static void post_dvc_update(CtkImageSliders *ctk_image_sliders, int value)
+static void post_scale_value_changed(GtkAdjustment *adjustment,
+ CtkImageSliders *ctk_image_sliders,
+ gint value)
{
+ char *name = g_object_get_data(G_OBJECT(adjustment), "attribute name");
+
+ gtk_widget_set_sensitive(ctk_image_sliders->reset_button, TRUE);
+
ctk_config_statusbar_message(ctk_image_sliders->ctk_config,
- "Digital Vibrance for %s set to %d.",
- ctk_image_sliders->name, value);
+ "%s set to %d.", name, value);
-} /* post_dvc_update() */
+} /* post_scale_value_changed() */
/*
- * dvc_adjustment_value_changed() - update the DVC value with the
- * current value of the adjustment widget.
+ * scale_value_changed() - callback when any of the adjustments
+ * in the CtkImageSliders are changed: get the new value from the
+ * adjustment, send it to the X server, and do any post-adjustment
+ * work.
*/
-static void dvc_adjustment_value_changed(GtkAdjustment *adjustment,
- gpointer user_data)
+static void scale_value_changed(GtkAdjustment *adjustment,
+ gpointer user_data)
{
- CtkImageSliders *ctk_image_sliders;
- int value;
+ CtkImageSliders *ctk_image_sliders =
+ CTK_IMAGE_SLIDERS(user_data);
- ctk_image_sliders = CTK_IMAGE_SLIDERS(user_data);
+ gint value;
+ gint attribute;
- value = (int) gtk_adjustment_get_value(adjustment);
+ value = (gint) gtk_adjustment_get_value(adjustment);
+
+ user_data = g_object_get_data(G_OBJECT(adjustment), "attribute");
+ attribute = GPOINTER_TO_INT(user_data);
NvCtrlSetDisplayAttribute(ctk_image_sliders->handle,
ctk_image_sliders->display_device_mask,
- NV_CTRL_DIGITAL_VIBRANCE,
- value);
+ attribute, (int) value);
- post_dvc_update(ctk_image_sliders, value);
-
-} /* dvc_adjustment_value_changed() */
+ post_scale_value_changed(adjustment, ctk_image_sliders, value);
+
+} /* scale_value_changed() */
/*
- * dvc_update_slider() - update the slider with the specified value
+ * ctk_image_sliders_reset() -
*/
-static void dvc_update_slider(CtkImageSliders *ctk_image_sliders, gint value)
+void ctk_image_sliders_reset(CtkImageSliders *ctk_image_sliders)
{
- GtkAdjustment *adjustment =
- GTK_ADJUSTMENT(ctk_image_sliders->dvc_adjustment);
-
- g_signal_handlers_block_by_func(G_OBJECT(adjustment),
- G_CALLBACK(dvc_adjustment_value_changed),
- (gpointer) ctk_image_sliders);
-
- gtk_adjustment_set_value(adjustment, value);
-
- g_signal_handlers_unblock_by_func(G_OBJECT(adjustment),
- G_CALLBACK(dvc_adjustment_value_changed),
- (gpointer) ctk_image_sliders);
+ if (!ctk_image_sliders) return;
+
+ if (get_scale_active(CTK_SCALE(ctk_image_sliders->digital_vibrance))) {
+ NvCtrlSetDisplayAttribute(ctk_image_sliders->handle,
+ ctk_image_sliders->display_device_mask,
+ NV_CTRL_DIGITAL_VIBRANCE,
+ 0);
+ }
+
+ if (get_scale_active(CTK_SCALE(ctk_image_sliders->image_sharpening))) {
+ NvCtrlSetDisplayAttribute(ctk_image_sliders->handle,
+ ctk_image_sliders->display_device_mask,
+ NV_CTRL_IMAGE_SHARPENING,
+ 0);
+ }
+
+ ctk_image_sliders_setup(ctk_image_sliders);
-} /* dvc_update_slider() */
+} /* ctk_image_sliders_reset() */
/*
- * dvc_update_received() - callback function for when the
- * NV_CTRL_DIGITAL_VIBRANCE attribute is changed by another NV-CONTROL
- * client.
+ * scale_value_received() - callback function for changed image settings; this
+ * is called when we receive an event indicating that another
+ * NV-CONTROL client changed any of the settings that we care about.
*/
-static void dvc_update_received(GtkObject *object,
- gpointer arg1, gpointer user_data)
+static void scale_value_received(GtkObject *object, gpointer arg1,
+ gpointer user_data)
{
- CtkEventStruct *event_struct = (CtkEventStruct *) arg1;
- CtkImageSliders *ctk_image_sliders = CTK_IMAGE_SLIDERS(user_data);
+ CtkEventStruct *event_struct;
+ CtkImageSliders *ctk_image_sliders =
+ CTK_IMAGE_SLIDERS(user_data);
- /* if the event is not for this display device, return */
+ GtkAdjustment *adj;
+ GtkWidget *scale;
+ gint val;
+
+ event_struct = (CtkEventStruct *) arg1;
+
+ /* if the event is not for this display device, return */
+
if (!(event_struct->display_mask &
ctk_image_sliders->display_device_mask)) {
return;
}
- dvc_update_slider(ctk_image_sliders, event_struct->value);
-
- post_dvc_update(ctk_image_sliders, event_struct->value);
+ switch (event_struct->attribute) {
+ case NV_CTRL_DIGITAL_VIBRANCE:
+ scale = ctk_image_sliders->digital_vibrance;
+ break;
+ case NV_CTRL_IMAGE_SHARPENING:
+ scale = ctk_image_sliders->image_sharpening;
+ break;
+ default:
+ return;
+ }
-} /* dvc_update_received() */
-
+ adj = CTK_SCALE(scale)->gtk_adjustment;
+ val = gtk_adjustment_get_value(GTK_ADJUSTMENT(adj));
+ if (val != event_struct->value) {
+
+ val = event_struct->value;
-/*
- * post_image_sharpening_update() - helper function for
- * image_sharpening_adjustment_value_changed() and
- * image_sharpening_update_received(); this does whatever work is
- * necessary after the the image sharpening adjustment widget is
- * updated -- currently, this is just posting a statusbar message.
- */
+ g_signal_handlers_block_by_func(adj, scale_value_changed,
+ ctk_image_sliders);
+
+ gtk_adjustment_set_value(GTK_ADJUSTMENT(adj), val);
+
+ post_scale_value_changed(GTK_ADJUSTMENT(adj),
+ ctk_image_sliders, val);
+
+ g_signal_handlers_unblock_by_func(adj, scale_value_changed,
+ ctk_image_sliders);
+ }
-static void
-post_image_sharpening_update(CtkImageSliders *ctk_image_sliders, gint value)
-{
- ctk_config_statusbar_message(ctk_image_sliders->ctk_config,
- "Image Sharpening for %s set to %d.",
- ctk_image_sliders->name, value);
-
-} /* post_image_sharpening_update() */
+} /* scale_value_received() */
/*
- * image_sharpening_adjustment_value_changed() -
+ * add_image_sliders_help() -
*/
-static void
-image_sharpening_adjustment_value_changed(GtkAdjustment *adjustment,
- gpointer user_data)
+void add_image_sliders_help(CtkImageSliders *ctk_image_sliders,
+ GtkTextBuffer *b,
+ GtkTextIter *i)
{
- CtkImageSliders *ctk_image_sliders;
- int value;
-
- ctk_image_sliders = CTK_IMAGE_SLIDERS(user_data);
-
- value = (int) gtk_adjustment_get_value(adjustment);
+ ctk_help_heading(b, i, "Digital Vibrance");
+ ctk_help_para(b, i, "Digital Vibrance, a mechanism for "
+ "controlling color separation and intensity, boosts "
+ "the color saturation of an image so that all images "
+ "including 2D, 3D, and video appear brighter and "
+ "crisper (even on flat panels) in your applications.");
+
+ ctk_help_heading(b, i, "Image Sharpening");
+ ctk_help_para(b, i, "Use the Image Sharpening slider to adjust the "
+ "sharpness of the image quality by amplifying high "
+ "frequency content.");
- NvCtrlSetDisplayAttribute(ctk_image_sliders->handle,
- ctk_image_sliders->display_device_mask,
- NV_CTRL_IMAGE_SHARPENING,
- value);
-
- post_image_sharpening_update(ctk_image_sliders, value);
-
-} /* image_sharpening_adjustment_value_changed() */
+} /* add_image_sliders_help() */
-/*
- * image_sharpening_update_slider() - update the slider with the
- * specified value
+/* Update GUI state of the scale to reflect current settings
+ * on the X Driver.
*/
-static void image_sharpening_update_slider(CtkImageSliders *ctk_image_sliders,
- gint value)
+static void setup_scale(CtkImageSliders *ctk_image_sliders,
+ int attribute,
+ GtkWidget *scale)
{
- GtkAdjustment *adjustment =
- GTK_ADJUSTMENT(ctk_image_sliders->image_sharpening_adjustment);
-
- g_signal_handlers_block_by_func
- (G_OBJECT(adjustment),
- G_CALLBACK(image_sharpening_adjustment_value_changed),
- (gpointer) ctk_image_sliders);
+ ReturnStatus ret0, ret1;
+ NVCTRLAttributeValidValuesRec valid;
+ NvCtrlAttributeHandle *handle = ctk_image_sliders->handle;
+ unsigned int mask = ctk_image_sliders->display_device_mask;
+ int val;
+ GtkAdjustment *adj = CTK_SCALE(scale)->gtk_adjustment;
- gtk_adjustment_set_value(adjustment, value);
+
+ /* Read settings from X server */
+ ret0 = NvCtrlGetValidDisplayAttributeValues(handle, mask,
+ attribute, &valid);
- g_signal_handlers_unblock_by_func
- (G_OBJECT(adjustment),
- G_CALLBACK(image_sharpening_adjustment_value_changed),
- (gpointer) ctk_image_sliders);
+ ret1 = NvCtrlGetDisplayAttribute(handle, mask, attribute, &val);
-} /* image_sharpening_update_slider() */
+ if ((ret0 == NvCtrlSuccess) && (ret1 == NvCtrlSuccess) &&
+ (valid.type == ATTRIBUTE_TYPE_RANGE)) {
+ g_signal_handlers_block_by_func(adj, scale_value_changed,
+ ctk_image_sliders);
+ adj->lower = valid.u.range.min;
+ adj->upper = valid.u.range.max;
+ gtk_adjustment_changed(GTK_ADJUSTMENT(adj));
-/*
- * image_sharpening_update_received() - callback function for when the
- * NV_CTRL_IMAGE_SHARPENING attribute is change by another NV-CONTROL
- * client.
- */
+ gtk_adjustment_set_value(GTK_ADJUSTMENT(adj), val);
-static void image_sharpening_update_received(GtkObject *object,
- gpointer arg1, gpointer user_data)
-{
- CtkEventStruct *event_struct = (CtkEventStruct *) arg1;
- CtkImageSliders *ctk_image_sliders = CTK_IMAGE_SLIDERS(user_data);
-
- /* if the event is not for this display device, return */
+ g_signal_handlers_unblock_by_func(adj, scale_value_changed,
+ ctk_image_sliders);
- if (!(event_struct->display_mask &
- ctk_image_sliders->display_device_mask)) {
- return;
+ g_object_set_data(G_OBJECT(adj), "attribute active",
+ GINT_TO_POINTER(1));
+
+ gtk_widget_set_sensitive(scale, TRUE);
+ gtk_widget_show(scale);
+ } else {
+ g_object_set_data(G_OBJECT(adj), "attribute active",
+ GINT_TO_POINTER(0));
+
+ gtk_widget_set_sensitive(scale, FALSE);
+ gtk_widget_hide(scale);
}
-
- image_sharpening_update_slider(ctk_image_sliders, event_struct->value);
- post_image_sharpening_update(ctk_image_sliders, event_struct->value);
-
-} /* image_sharpening_update_received() */
+} /* setup_scale() */
/*
- * add_image_sliders_help() -
+ * Updates the page to reflect the current configuration of
+ * the display device.
*/
-
-gboolean add_image_sliders_help(CtkImageSliders *ctk_image_sliders,
- GtkTextBuffer *b,
- GtkTextIter *i)
+void ctk_image_sliders_setup(CtkImageSliders *ctk_image_sliders)
{
- gboolean ret = FALSE;
-
- if (ctk_image_sliders->dvc_adjustment) {
- ctk_help_heading(b, i, "Digital Vibrance");
- ctk_help_para(b, i, "Digital Vibrance, a mechanism for "
- "controlling color separation and intensity, boosts "
- "the color saturation of an image so that all images "
- "including 2D, 3D, and video appear brighter and "
- "crisper (even on flat panels) in your applications.");
- ret = TRUE;
- }
+ int active;
- if (ctk_image_sliders->image_sharpening_adjustment) {
- ctk_help_heading(b, i, "Image Sharpening");
- ctk_help_para(b, i, "Use the Image Sharpening slider to adjust the "
- "sharpness of the image quality by amplifying high "
- "frequency content.");
- ret = TRUE;
- }
- return ret;
+ if (!ctk_image_sliders) return;
+
+ /* Update sliders */
-} /* add_image_sliders_help() */
+ /* NV_CTRL_DIGITAL_VIBRANCE */
+
+ setup_scale(ctk_image_sliders, NV_CTRL_DIGITAL_VIBRANCE,
+ ctk_image_sliders->digital_vibrance);
+
+ /* NV_CTRL_IMAGE_SHARPENING */
+
+ setup_scale(ctk_image_sliders, NV_CTRL_IMAGE_SHARPENING,
+ ctk_image_sliders->image_sharpening);
+
+ active =
+ get_scale_active(CTK_SCALE(ctk_image_sliders->digital_vibrance)) ||
+ get_scale_active(CTK_SCALE(ctk_image_sliders->image_sharpening));
+
+ if (!active) {
+ gtk_widget_hide(ctk_image_sliders->frame);
+ } else {
+ gtk_widget_show(ctk_image_sliders->frame);
+ }
+
+} /* ctk_image_sliders_setup() */
diff --git a/src/gtk+-2.x/ctkimagesliders.h b/src/gtk+-2.x/ctkimagesliders.h
index 1b9fc87..21172e6 100644
--- a/src/gtk+-2.x/ctkimagesliders.h
+++ b/src/gtk+-2.x/ctkimagesliders.h
@@ -58,16 +58,16 @@ struct _CtkImageSliders
GtkVBox parent;
NvCtrlAttributeHandle *handle;
+ unsigned int display_device_mask;
+ char *name;
+
CtkConfig *ctk_config;
+ CtkEvent *ctk_event;
GtkWidget *reset_button;
- GtkObject *dvc_adjustment;
- GtkObject *image_sharpening_adjustment;
-
- char *name;
-
- unsigned int display_device_mask;
- unsigned int active_attributes;
+ GtkWidget *frame;
+ GtkWidget *digital_vibrance;
+ GtkWidget *image_sharpening;
};
struct _CtkImageSlidersClass
@@ -84,9 +84,11 @@ GtkWidget* ctk_image_sliders_new (NvCtrlAttributeHandle *,
void ctk_image_sliders_reset(CtkImageSliders *);
-gboolean add_image_sliders_help(CtkImageSliders *ctk_image_sliders,
- GtkTextBuffer *b,
- GtkTextIter *i);
+void ctk_image_sliders_setup(CtkImageSliders *ctk_image_sliders);
+
+void add_image_sliders_help(CtkImageSliders *ctk_image_sliders,
+ GtkTextBuffer *b,
+ GtkTextIter *i);
G_END_DECLS
diff --git a/src/gtk+-2.x/ctkmultisample.c b/src/gtk+-2.x/ctkmultisample.c
index 79795d1..7c1a560 100644
--- a/src/gtk+-2.x/ctkmultisample.c
+++ b/src/gtk+-2.x/ctkmultisample.c
@@ -33,6 +33,7 @@
#include "ctkconfig.h"
#include "ctkhelp.h"
+#include "ctkimage.h"
/* local prototypes */
@@ -184,14 +185,11 @@ GtkWidget *ctk_multisample_new(NvCtrlAttributeHandle *handle,
GObject *object;
CtkMultisample *ctk_multisample;
GtkWidget *hbox, *vbox = NULL;
- GtkWidget *image;
+ GtkWidget *banner;
GtkWidget *frame;
GtkWidget *check_button;
GtkWidget *scale;
- guint8 *image_buffer = NULL;
- const nv_image_t *img;
-
gint val, app_control, override, i;
NVCTRLAttributeValidValuesRec valid;
@@ -214,21 +212,9 @@ GtkWidget *ctk_multisample_new(NvCtrlAttributeHandle *handle,
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start(GTK_BOX(object), hbox, FALSE, FALSE, 0);
- frame = gtk_frame_new(NULL);
- gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
- gtk_box_pack_start(GTK_BOX(hbox), frame, FALSE, FALSE, 0);
-
- img = &antialiasing_banner_image;
- image_buffer = decompress_image_data(img);
+ banner = ctk_banner_image_new(&antialiasing_banner_image);
+ gtk_box_pack_start(GTK_BOX(hbox), banner, TRUE, TRUE, 0);
- image = gtk_image_new_from_pixbuf
- (gdk_pixbuf_new_from_data(image_buffer, GDK_COLORSPACE_RGB,
- FALSE, 8, img->width, img->height,
- img->width * img->bytes_per_pixel,
- free_decompressed_image, NULL));
-
- gtk_container_add(GTK_CONTAINER(frame), image);
-
/* FSAA slider */
ret = NvCtrlGetValidAttributeValues(handle, NV_CTRL_FSAA_MODE, &valid);
@@ -1205,9 +1191,9 @@ GtkTextBuffer *ctk_multisample_create_help(GtkTextTagTable *table,
"expense of some performance.");
ctk_help_para(b, &i, "You can also configure Anisotropic filtering "
- "using the __GL_DEFAULT_LOG_ANISO environment varible "
+ "using the __GL_LOG_MAX_ANISO environment varible "
"(see the README for details). The "
- "__GL_DEFAULT_LOG_ANISO environment variable overrides "
+ "__GL_LOG_MAX_ANISO environment variable overrides "
"the value in nvidia-settings.");
ctk_help_term(b, &i, "Override Application Setting");
diff --git a/src/gtk+-2.x/ctkopengl.c b/src/gtk+-2.x/ctkopengl.c
index 82d867a..bd34faa 100644
--- a/src/gtk+-2.x/ctkopengl.c
+++ b/src/gtk+-2.x/ctkopengl.c
@@ -151,10 +151,74 @@ GtkWidget* ctk_opengl_new(NvCtrlAttributeHandle *handle,
GtkWidget *vbox;
GtkWidget *check_button;
GtkWidget *scale;
- gint force_generic_cpu_value, aa_line_gamma_value, val;
- ReturnStatus ret;
- NVCTRLAttributeValidValuesRec valid;
+ gint sync_to_vblank;
+ gint flipping_allowed;
+ gint force_stereo;
+ gint xinerama_stereo;
+ NVCTRLAttributeValidValuesRec image_settings_valid;
+ gint image_settings_value;
+ gint aa_line_gamma;
+ gint force_generic_cpu;
+ gint show_sli_hud;
+
+ ReturnStatus ret_sync_to_vblank;
+ ReturnStatus ret_flipping_allowed;
+ ReturnStatus ret_force_stereo;
+ ReturnStatus ret_xinerama_stereo;
+ ReturnStatus ret_image_settings;
+ ReturnStatus ret_aa_line_gama;
+ ReturnStatus ret_force_generic_cpu;
+ ReturnStatus ret_show_sli_hud;
+
+ /* Query OpenGL settings */
+
+ ret_sync_to_vblank =
+ NvCtrlGetAttribute(handle, NV_CTRL_SYNC_TO_VBLANK, &sync_to_vblank);
+
+ ret_flipping_allowed =
+ NvCtrlGetAttribute(handle, NV_CTRL_FLIPPING_ALLOWED,
+ &flipping_allowed);
+
+ ret_force_stereo =
+ NvCtrlGetAttribute(handle, NV_CTRL_FORCE_STEREO, &force_stereo);
+
+ ret_xinerama_stereo =
+ NvCtrlGetAttribute(handle, NV_CTRL_XINERAMA_STEREO, &xinerama_stereo);
+
+ ret_image_settings =
+ NvCtrlGetValidAttributeValues(handle, NV_CTRL_IMAGE_SETTINGS,
+ &image_settings_valid);
+ if ((ret_image_settings == NvCtrlSuccess) &&
+ (image_settings_valid.type == ATTRIBUTE_TYPE_RANGE)) {
+ ret_image_settings =
+ NvCtrlGetAttribute(handle, NV_CTRL_IMAGE_SETTINGS,
+ &image_settings_value);
+ } else {
+ ret_image_settings = NvCtrlError;
+ }
+
+ ret_aa_line_gama = NvCtrlGetAttribute(handle, NV_CTRL_OPENGL_AA_LINE_GAMMA,
+ &aa_line_gamma);
+
+ ret_force_generic_cpu = NvCtrlGetAttribute(handle,
+ NV_CTRL_FORCE_GENERIC_CPU,
+ &force_generic_cpu);
+
+ ret_show_sli_hud = NvCtrlGetAttribute(handle, NV_CTRL_SHOW_SLI_HUD,
+ &show_sli_hud);
+
+ /* There are no OpenGL settings to change (OpenGL disabled?) */
+ if ((ret_sync_to_vblank != NvCtrlSuccess) &&
+ (ret_flipping_allowed != NvCtrlSuccess) &&
+ (ret_force_stereo != NvCtrlSuccess) &&
+ (ret_xinerama_stereo != NvCtrlSuccess) &&
+ (ret_image_settings != NvCtrlSuccess) &&
+ (ret_aa_line_gama != NvCtrlSuccess) &&
+ (ret_force_generic_cpu != NvCtrlSuccess) &&
+ (ret_show_sli_hud != NvCtrlSuccess)) {
+ return NULL;
+ }
object = g_object_new(CTK_TYPE_OPENGL, NULL);
@@ -197,15 +261,15 @@ GtkWidget* ctk_opengl_new(NvCtrlAttributeHandle *handle,
* retrace.
*/
- ret = NvCtrlGetAttribute(handle, NV_CTRL_SYNC_TO_VBLANK, &val);
- if (ret == NvCtrlSuccess) {
+ if (ret_sync_to_vblank == NvCtrlSuccess) {
label = gtk_label_new("Sync to VBlank");
check_button = gtk_check_button_new();
gtk_container_add(GTK_CONTAINER(check_button), label);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), val);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button),
+ sync_to_vblank);
gtk_box_pack_start(GTK_BOX(vbox), check_button, FALSE, FALSE, 0);
@@ -229,15 +293,15 @@ GtkWidget* ctk_opengl_new(NvCtrlAttributeHandle *handle,
* allow flipping
*/
- ret = NvCtrlGetAttribute(handle, NV_CTRL_FLIPPING_ALLOWED, &val);
- if (ret == NvCtrlSuccess) {
+ if (ret_flipping_allowed == NvCtrlSuccess) {
label = gtk_label_new("Allow Flipping");
check_button = gtk_check_button_new();
gtk_container_add(GTK_CONTAINER(check_button), label);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), val);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button),
+ flipping_allowed);
gtk_box_pack_start(GTK_BOX(vbox), check_button, FALSE, FALSE, 0);
@@ -259,15 +323,15 @@ GtkWidget* ctk_opengl_new(NvCtrlAttributeHandle *handle,
ctk_opengl->allow_flipping_button = check_button;
}
- ret = NvCtrlGetAttribute(handle, NV_CTRL_FORCE_STEREO, &val);
- if (ret == NvCtrlSuccess) {
+ if (ret_force_stereo == NvCtrlSuccess) {
label = gtk_label_new("Force Stereo Flipping");
check_button = gtk_check_button_new();
gtk_container_add(GTK_CONTAINER(check_button), label);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), val);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button),
+ force_stereo);
gtk_box_pack_start(GTK_BOX(vbox), check_button, FALSE, FALSE, 0);
@@ -286,15 +350,15 @@ GtkWidget* ctk_opengl_new(NvCtrlAttributeHandle *handle,
ctk_opengl->force_stereo_button = check_button;
}
- ret = NvCtrlGetAttribute(handle, NV_CTRL_XINERAMA_STEREO, &val);
- if (ret == NvCtrlSuccess) {
+ if (ret_xinerama_stereo == NvCtrlSuccess) {
label = gtk_label_new("Allow Xinerama Stereo Flipping");
check_button = gtk_check_button_new();
gtk_container_add(GTK_CONTAINER(check_button), label);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), val);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button),
+ xinerama_stereo);
gtk_box_pack_start(GTK_BOX(vbox), check_button, FALSE, FALSE, 0);
@@ -317,10 +381,7 @@ GtkWidget* ctk_opengl_new(NvCtrlAttributeHandle *handle,
* Image Quality settings.
*/
- ret = NvCtrlGetValidAttributeValues(handle, NV_CTRL_IMAGE_SETTINGS, &valid);
-
- if ((ret == NvCtrlSuccess) && (valid.type == ATTRIBUTE_TYPE_RANGE) &&
- (NvCtrlGetAttribute(handle, NV_CTRL_IMAGE_SETTINGS, &val) == NvCtrlSuccess)) {
+ if (ret_image_settings == NvCtrlSuccess) {
frame = gtk_frame_new("Image Settings");
gtk_box_pack_start(GTK_BOX(vbox), frame, FALSE, FALSE, 3);
@@ -329,8 +390,9 @@ GtkWidget* ctk_opengl_new(NvCtrlAttributeHandle *handle,
gtk_container_set_border_width(GTK_CONTAINER(hbox), FRAME_PADDING);
gtk_container_add(GTK_CONTAINER(frame), hbox);
- scale = gtk_hscale_new_with_range(valid.u.range.min, valid.u.range.max, 1);
- gtk_range_set_value(GTK_RANGE(scale), val);
+ scale = gtk_hscale_new_with_range(image_settings_valid.u.range.min,
+ image_settings_valid.u.range.max, 1);
+ gtk_range_set_value(GTK_RANGE(scale), image_settings_value);
gtk_scale_set_draw_value(GTK_SCALE(scale), TRUE);
gtk_scale_set_value_pos(GTK_SCALE(scale), GTK_POS_TOP);
@@ -377,18 +439,14 @@ GtkWidget* ctk_opengl_new(NvCtrlAttributeHandle *handle,
* NV_CTRL_OPENGL_AA_LINE_GAMMA
*/
- ret = NvCtrlGetAttribute(ctk_opengl->handle,
- NV_CTRL_OPENGL_AA_LINE_GAMMA,
- &aa_line_gamma_value);
-
- if (ret == NvCtrlSuccess) {
+ if (ret_aa_line_gama == NvCtrlSuccess) {
label = gtk_label_new("Enable gamma correction for antialiased lines");
check_button = gtk_check_button_new();
gtk_container_add(GTK_CONTAINER(check_button), label);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button),
- aa_line_gamma_value ==
+ aa_line_gamma ==
NV_CTRL_OPENGL_AA_LINE_GAMMA_ENABLE);
gtk_box_pack_start(GTK_BOX(vbox), check_button, FALSE, FALSE, 0);
@@ -416,18 +474,14 @@ GtkWidget* ctk_opengl_new(NvCtrlAttributeHandle *handle,
* Force Generic CPU
*/
- ret = NvCtrlGetAttribute(ctk_opengl->handle,
- NV_CTRL_FORCE_GENERIC_CPU,
- &force_generic_cpu_value);
-
- if (ret == NvCtrlSuccess) {
+ if (ret_force_generic_cpu == NvCtrlSuccess) {
label = gtk_label_new("Disable use of enhanced CPU instruction sets");
check_button = gtk_check_button_new();
gtk_container_add(GTK_CONTAINER(check_button), label);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button),
- force_generic_cpu_value ==
+ force_generic_cpu ==
NV_CTRL_FORCE_GENERIC_CPU_ENABLE);
gtk_box_pack_start(GTK_BOX(vbox), check_button, FALSE, FALSE, 0);
@@ -448,15 +502,15 @@ GtkWidget* ctk_opengl_new(NvCtrlAttributeHandle *handle,
ctk_opengl->force_generic_cpu_button = check_button;
}
- ret = NvCtrlGetAttribute(handle, NV_CTRL_SHOW_SLI_HUD, &val);
- if (ret == NvCtrlSuccess) {
+ if (ret_show_sli_hud == NvCtrlSuccess) {
label = gtk_label_new("Enable SLI Heads-Up-Display");
check_button = gtk_check_button_new();
gtk_container_add(GTK_CONTAINER(check_button), label);
- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button), val);
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_button),
+ show_sli_hud);
gtk_box_pack_start(GTK_BOX(vbox), check_button, FALSE, FALSE, 0);
diff --git a/src/gtk+-2.x/ctkscreen.c b/src/gtk+-2.x/ctkscreen.c
new file mode 100644
index 0000000..0931328
--- /dev/null
+++ b/src/gtk+-2.x/ctkscreen.c
@@ -0,0 +1,474 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
+ * of the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+#include <gtk/gtk.h>
+#include "NvCtrlAttributes.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <X11/Xlib.h>
+#include <X11/extensions/Xrandr.h>
+
+
+#include "big_banner_penguin.h"
+#include "big_banner_bsd.h"
+#include "big_banner_sun.h"
+
+#include "image.h"
+
+#include "ctkscreen.h"
+#include "ctkhelp.h"
+#include "ctkutils.h"
+#include "ctkimage.h"
+
+void ctk_screen_event_handler(GtkWidget *widget,
+ XRRScreenChangeNotifyEvent *ev,
+ gpointer data);
+
+static void associated_displays_received(GtkObject *object, gpointer arg1,
+ gpointer user_data);
+
+GType ctk_screen_get_type(
+ void
+)
+{
+ static GType ctk_screen_type = 0;
+
+ if (!ctk_screen_type) {
+ static const GTypeInfo info_ctk_screen = {
+ sizeof (CtkScreenClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (CtkScreen),
+ 0, /* n_preallocs */
+ NULL, /* instance_init */
+ };
+
+ ctk_screen_type =
+ g_type_register_static(GTK_TYPE_VBOX,
+ "CtkScreen", &info_ctk_screen, 0);
+ }
+
+ return ctk_screen_type;
+}
+
+
+
+static gchar *make_display_device_list(NvCtrlAttributeHandle *handle,
+ unsigned int display_devices)
+{
+ gchar *displays = NULL;
+ gchar *type;
+ gchar *name;
+ gchar *tmp_str;
+ unsigned int mask;
+ ReturnStatus ret;
+
+
+ /* List of Display Device connected on GPU */
+
+ for (mask = 1; mask; mask <<= 1) {
+
+ if (!(mask & display_devices)) continue;
+
+ type = display_device_mask_to_display_device_name(mask);
+ name = NULL;
+
+ ret =
+ NvCtrlGetStringDisplayAttribute(handle,
+ mask,
+ NV_CTRL_STRING_DISPLAY_DEVICE_NAME,
+ &name);
+ if (ret != NvCtrlSuccess) {
+ tmp_str = g_strdup_printf("Unknown (%s)", type);
+ } else {
+ tmp_str = g_strdup_printf("%s (%s)", name, type);
+ XFree(name);
+ }
+ free(type);
+
+ if (displays) {
+ name = g_strdup_printf("%s,\n%s", tmp_str, displays);
+ g_free(displays);
+ g_free(tmp_str);
+ } else {
+ name = tmp_str;
+ }
+ displays = name;
+ }
+
+ if (!displays) {
+ displays = g_strdup("None");
+ }
+
+ return displays;
+
+} /* make_display_device_list() */
+
+
+
+/*
+ * Calculations of the screen dimensions and resolution are based on
+ * the dxpyinfo utility code.
+ *
+ * Copyright Information for xdpyinfo:
+ *
+ ***********************************************************************
+ *
+ * xdpyinfo - print information about X display connecton
+ *
+ *
+Copyright 1988, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+ *
+ * Author: Jim Fulton, MIT X Consortium
+ *
+ ***********************************************************************
+ *
+ */
+
+GtkWidget* ctk_screen_new(NvCtrlAttributeHandle *handle,
+ CtkEvent *ctk_event)
+{
+ GObject *object;
+ CtkScreen *ctk_screen;
+ GtkWidget *label;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *banner;
+ GtkWidget *hseparator;
+ GtkWidget *table;
+
+ ReturnStatus ret;
+
+ gchar *screen_number;
+ gchar *display_name;
+ gchar *dimensions;
+ gchar *resolution;
+ gchar *depth;
+ gchar *gpus;
+ gchar *displays;
+
+ double xres, yres;
+ gint os_val;
+
+ unsigned int display_devices;
+
+ int *pData;
+ int len;
+ int i;
+
+ /*
+ * get the data that we will display below
+ */
+
+ screen_number = g_strdup_printf("%d", NvCtrlGetTargetId(handle));
+
+ display_name = NvCtrlGetDisplayName(handle);
+
+ dimensions = g_strdup_printf("%dx%d pixels (%dx%d millimeters)",
+ NvCtrlGetScreenWidth(handle),
+ NvCtrlGetScreenHeight(handle),
+ NvCtrlGetScreenWidthMM(handle),
+ NvCtrlGetScreenHeightMM(handle));
+
+ /*
+ * there are 2.54 centimeters to an inch; so there are 25.4 millimeters.
+ *
+ * dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch))
+ * = N pixels / (M inch / 25.4)
+ * = N * 25.4 pixels / M inch
+ */
+
+ xres = (((double) NvCtrlGetScreenWidth(handle)) * 25.4) /
+ ((double) NvCtrlGetScreenWidthMM(handle));
+
+ yres = (((double) NvCtrlGetScreenHeight(handle)) * 25.4) /
+ ((double) NvCtrlGetScreenHeightMM(handle));
+
+ resolution = g_strdup_printf("%dx%d dots per inch",
+ (int) (xres + 0.5),
+ (int) (yres + 0.5));
+
+ depth = g_strdup_printf("%d", NvCtrlGetScreenPlanes(handle));
+
+ /* get the list of GPUs driving this X screen */
+
+ gpus = NULL;
+ ret = NvCtrlGetBinaryAttribute(handle,
+ 0,
+ NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN,
+ (unsigned char **)(&pData),
+ &len);
+ if (ret == NvCtrlSuccess) {
+ for (i = 1; i <= pData[0]; i++) {
+ gchar *tmp_str;
+ gchar *gpu_name;
+
+ ret = NvCtrlGetStringAttribute(handle,
+ NV_CTRL_STRING_PRODUCT_NAME,
+ &gpu_name);
+ if (ret != NvCtrlSuccess) {
+ gpu_name = "Unknown";
+ }
+ if (gpus) {
+ tmp_str = g_strdup_printf("%s,\n%s (GPU %d)",
+ gpus, gpu_name, pData[i]);
+ } else {
+ tmp_str = g_strdup_printf("%s (GPU %d)", gpu_name, pData[i]);
+ }
+ if (ret == NvCtrlSuccess) {
+ XFree(gpu_name);
+ }
+ g_free(gpus);
+ gpus = tmp_str;
+ }
+ if (!gpus) {
+ gpus = g_strdup("None");
+ }
+ }
+
+ /* get the list of Display Devices displaying this X screen */
+
+ displays = NULL;
+ ret = NvCtrlGetAttribute(handle, NV_CTRL_ASSOCIATED_DISPLAY_DEVICES,
+ (int *)&display_devices);
+ if (ret == NvCtrlSuccess) {
+ displays = make_display_device_list(handle, display_devices);
+ }
+
+ /* NV_CTRL_OPERATING_SYSTEM */
+
+ os_val = NV_CTRL_OPERATING_SYSTEM_LINUX;
+ ret = NvCtrlGetAttribute(handle, NV_CTRL_OPERATING_SYSTEM, &os_val);
+
+
+ /* now, create the object */
+
+ object = g_object_new(CTK_TYPE_SCREEN, NULL);
+ ctk_screen = CTK_SCREEN(object);
+
+ /* cache the attribute handle */
+
+ ctk_screen->handle = handle;
+
+ /* set container properties of the object */
+
+ gtk_box_set_spacing(GTK_BOX(ctk_screen), 10);
+
+ /* banner */
+
+ if (os_val == NV_CTRL_OPERATING_SYSTEM_LINUX) {
+ banner = ctk_banner_image_new(&big_banner_penguin_image);
+ } else if (os_val == NV_CTRL_OPERATING_SYSTEM_FREEBSD) {
+ banner = ctk_banner_image_new(&big_banner_bsd_image);
+ } else if (os_val == NV_CTRL_OPERATING_SYSTEM_SUNOS) {
+ banner = ctk_banner_image_new(&big_banner_sun_image);
+ } else {
+ banner = ctk_banner_image_new(&big_banner_penguin_image);
+ }
+ gtk_box_pack_start(GTK_BOX(ctk_screen), banner, FALSE, FALSE, 0);
+
+ /*
+ * Screen information: TOP->MIDDLE - LEFT->RIGHT
+ *
+ * This displays basic X Screen information, including
+ * the X Screen number, the display connection used to
+ * talk to the X Screen, dimensions, resolution, depth (planes)
+ * the list of GPUs driving the X Screen and the list of
+ * display devices displaying the X Screen.
+ */
+
+ vbox = gtk_vbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(ctk_screen), vbox, TRUE, TRUE, 0);
+
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+
+ label = gtk_label_new("X Screen Information");
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+ hseparator = gtk_hseparator_new();
+ gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5);
+
+ table = gtk_table_new(16, 2, FALSE);
+ gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
+ gtk_table_set_row_spacings(GTK_TABLE(table), 3);
+ gtk_table_set_col_spacings(GTK_TABLE(table), 15);
+ gtk_container_set_border_width(GTK_CONTAINER(table), 5);
+
+ add_table_row(table, 0, 0, 0.5, "Screen Number:", 0, 0.5, screen_number);
+ add_table_row(table, 1, 0, 0.5, "Display Name:", 0, 0.5, display_name);
+ /* spacing */
+ ctk_screen->dimensions =
+ add_table_row(table, 5, 0, 0.5, "Dimensions:", 0, 0.5, dimensions);
+ add_table_row(table, 6, 0, 0.5, "Resolution:", 0, 0.5, resolution);
+ add_table_row(table, 7, 0, 0.5, "Depth:", 0, 0.5, depth);
+ /* spacing */
+ add_table_row(table, 11, 0, 0, "GPUs:", 0, 0, gpus);
+ /* spacing */
+ ctk_screen->displays =
+ add_table_row(table, 15, 0, 0, "Displays:", 0, 0, displays);
+
+ g_free(screen_number);
+ free(display_name);
+ g_free(dimensions);
+ g_free(resolution);
+ g_free(depth);
+ g_free(gpus);
+ g_free(displays);
+
+ /* Handle updates to the list of associated display devices */
+ g_signal_connect(G_OBJECT(ctk_event),
+ CTK_EVENT_NAME(NV_CTRL_ASSOCIATED_DISPLAY_DEVICES),
+ G_CALLBACK(associated_displays_received),
+ (gpointer) ctk_screen);
+
+ /* Setup widget to handle XRRScreenChangeNotify events */
+ g_signal_connect(G_OBJECT(ctk_event), "CTK_EVENT_RRScreenChangeNotify",
+ G_CALLBACK(ctk_screen_event_handler),
+ (gpointer) ctk_screen);
+
+ gtk_widget_show_all(GTK_WIDGET(object));
+
+ return GTK_WIDGET(object);
+}
+
+
+GtkTextBuffer *ctk_screen_create_help(GtkTextTagTable *table,
+ const gchar *screen_name)
+{
+ GtkTextIter i;
+ GtkTextBuffer *b;
+
+ b = gtk_text_buffer_new(table);
+
+ gtk_text_buffer_get_iter_at_offset(b, &i, 0);
+
+ ctk_help_title(b, &i, "X Screen Information Help");
+
+ ctk_help_para(b, &i, "This page in the NVIDIA "
+ "X Server Control Panel describes basic "
+ "information about the X Screen '%s'.",
+ screen_name);
+
+ ctk_help_heading(b, &i, "Screen Number");
+ ctk_help_para(b, &i, "This is the X Screen number.");
+
+ ctk_help_heading(b, &i, "Display Name");
+ ctk_help_para(b, &i, "This is the display connection string used to "
+ "communicate with the X Screen on the X Server.");
+
+ ctk_help_heading(b, &i, "Dimensions");
+ ctk_help_para(b, &i, "This displays the X Screen's horizontal and "
+ "vertical dimensions in pixels and millimeters.");
+
+ ctk_help_heading(b, &i, "Resolution");
+ ctk_help_para(b, &i, "This is the resolution (in dots per inch) of the "
+ "X Screen.");
+
+ ctk_help_heading(b, &i, "Depth");
+ ctk_help_para(b, &i, "This is the number of planes (depth) the X Screen "
+ "has available.");
+
+ ctk_help_heading(b, &i, "GPUs");
+ ctk_help_para(b, &i, "This is the list of GPUs that drive this X Screen.");
+
+ ctk_help_heading(b, &i, "Display Devices");
+ ctk_help_para(b, &i, "This is the list of Display Devices (CRTs, TVs etc) "
+ "enabled on this X Screen.");
+
+ ctk_help_finish(b);
+
+ return b;
+}
+
+
+
+/*
+ * When XConfigureRequest events happens outside of the control panel,
+ * they are trapped by this function so the gui can be updated
+ * with the new screen information.
+ */
+void ctk_screen_event_handler(GtkWidget *widget,
+ XRRScreenChangeNotifyEvent *ev,
+ gpointer data)
+{
+ CtkScreen *ctk_screen = (CtkScreen *) data;
+
+ gchar *dimensions = g_strdup_printf("%dx%d pixels (%dx%d millimeters)",
+ ev->width, ev->height,
+ ev->mwidth, ev->mheight);
+
+ gtk_label_set_text(GTK_LABEL(ctk_screen->dimensions),
+ dimensions);
+
+ g_free(dimensions);
+
+} /* ctk_screen_event_handler() */
+
+
+
+/*
+ * When the list of associated displays on this screen changes, we should
+ * update the display device list shown on the page.
+ */
+static void associated_displays_received(GtkObject *object, gpointer arg1,
+ gpointer user_data)
+{
+ CtkEventStruct *event_struct = (CtkEventStruct *) arg1;
+ CtkScreen *ctk_object = CTK_SCREEN(user_data);
+ unsigned int associated_displays = event_struct->value;
+ gchar *str;
+
+ str = make_display_device_list(ctk_object->handle, associated_displays);
+
+ gtk_label_set_text(GTK_LABEL(ctk_object->displays), str);
+
+ g_free(str);
+
+} /* associated_displays_received() */
diff --git a/src/gtk+-2.x/ctkscreen.h b/src/gtk+-2.x/ctkscreen.h
new file mode 100644
index 0000000..75f8422
--- /dev/null
+++ b/src/gtk+-2.x/ctkscreen.h
@@ -0,0 +1,80 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
+ * of the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+#ifndef __CTK_SCREEN_H__
+#define __CTK_SCREEN_H__
+
+#include <gtk/gtk.h>
+
+#include "NvCtrlAttributes.h"
+#include "ctkevent.h"
+
+G_BEGIN_DECLS
+
+#define CTK_TYPE_SCREEN (ctk_screen_get_type())
+
+#define CTK_SCREEN(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), CTK_TYPE_SCREEN, CtkScreen))
+
+#define CTK_SCREEN_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), CTK_TYPE_SCREEN, CtkScreenClass))
+
+#define CTK_IS_SCREEN(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CTK_TYPE_SCREEN))
+
+#define CTK_IS_SCREEN_CLASS(class) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), CTK_TYPE_SCREEN))
+
+#define CTK_SCREEN_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_SCREEN, CtkScreenClass))
+
+
+typedef struct _CtkScreen CtkScreen;
+typedef struct _CtkScreenClass CtkScreenClass;
+
+struct _CtkScreen
+{
+ GtkVBox parent;
+
+ NvCtrlAttributeHandle *handle;
+
+ GtkWidget *dimensions;
+ GtkWidget *displays;
+};
+
+struct _CtkScreenClass
+{
+ GtkVBoxClass parent_class;
+};
+
+GType ctk_screen_get_type (void) G_GNUC_CONST;
+GtkWidget* ctk_screen_new (NvCtrlAttributeHandle *handle,
+ CtkEvent *ctk_event);
+
+GtkTextBuffer *ctk_screen_create_help(GtkTextTagTable *, const gchar *);
+
+G_END_DECLS
+
+#endif /* __CTK_SCREEN_H__ */
+
diff --git a/src/gtk+-2.x/ctkserver.c b/src/gtk+-2.x/ctkserver.c
new file mode 100644
index 0000000..32eba03
--- /dev/null
+++ b/src/gtk+-2.x/ctkserver.c
@@ -0,0 +1,496 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
+ * of the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+#include <stdlib.h> /* malloc */
+#include <stdio.h> /* snprintf */
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+
+#include "big_banner_penguin.h"
+#include "big_banner_bsd.h"
+#include "big_banner_sun.h"
+#include "ctkimage.h"
+
+#include "ctkserver.h"
+#include "ctkevent.h"
+#include "ctkhelp.h"
+#include "ctkutils.h"
+
+
+GType ctk_server_get_type(void)
+{
+ static GType ctk_server_type = 0;
+
+ if (!ctk_server_type) {
+ static const GTypeInfo ctk_server_info = {
+ sizeof (CtkServerClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof(CtkServer),
+ 0, /* n_preallocs */
+ NULL, /* instance_init */
+ };
+
+ ctk_server_type = g_type_register_static
+ (GTK_TYPE_VBOX, "CtkServer", &ctk_server_info, 0);
+ }
+
+ return ctk_server_type;
+}
+
+
+
+/*
+ * Code taken and modified from xdpyinfo.c
+ *
+ * Copyright Information for xdpyinfo:
+ *
+ ***********************************************************************
+ *
+ * xdpyinfo - print information about X display connecton
+ *
+ *
+Copyright 1988, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+ *
+ * Author: Jim Fulton, MIT X Consortium
+ *
+ ***********************************************************************
+ *
+ */
+static gchar * get_server_vendor_version(NvCtrlAttributeHandle *handle)
+{
+ int vendrel = NvCtrlGetVendorRelease(handle);
+ char *vendstr = NvCtrlGetServerVendor(handle);
+ gchar *version = NULL;
+ gchar *tmp;
+
+ if (vendrel < 0 || !vendstr) return NULL;
+
+ /* XFree86 */
+
+ if (g_strrstr(vendstr, "XFree86")) {
+
+ if (vendrel < 336) {
+ /*
+ * vendrel was set incorrectly for 3.3.4 and 3.3.5, so handle
+ * those cases here.
+ */
+ version = g_strdup_printf("%d.%d.%d",
+ vendrel / 100,
+ (vendrel / 10) % 10,
+ vendrel % 10);
+ } else if (vendrel < 3900) {
+ /* 3.3.x versions, other than the exceptions handled above */
+ if (((vendrel / 10) % 10) || (vendrel % 10)) {
+ if (vendrel % 10) {
+ version = g_strdup_printf("%d.%d.%d.%d",
+ vendrel / 1000,
+ (vendrel / 100) % 10,
+ (vendrel / 10) % 10,
+ vendrel % 10);
+ } else {
+ version = g_strdup_printf("%d.%d.%d",
+ vendrel / 1000,
+ (vendrel / 100) % 10,
+ (vendrel / 10) % 10);
+ }
+ } else {
+ version = g_strdup_printf("%d.%d",
+ vendrel / 1000,
+ (vendrel / 100) % 10);
+ }
+ } else if (vendrel < 40000000) {
+ /* 4.0.x versions */
+ if (vendrel % 10) {
+ version = g_strdup_printf("%d.%d.%d",
+ vendrel / 1000,
+ (vendrel / 10) % 10,
+ vendrel % 10);
+ } else {
+ version = g_strdup_printf("%d.%d",
+ vendrel / 1000,
+ (vendrel / 10) % 10);
+ }
+ } else {
+ /* post-4.0.x */
+ if (vendrel % 1000) {
+ version = g_strdup_printf("%d.%d.%d.%d",
+ vendrel / 10000000,
+ (vendrel / 100000) % 100,
+ (vendrel / 1000) % 100,
+ vendrel % 1000);
+ } else {
+ version = g_strdup_printf("%d.%d.%d",
+ vendrel / 10000000,
+ (vendrel / 100000) % 100,
+ (vendrel / 1000) % 100);
+ }
+ }
+ }
+
+ /* X.Org */
+
+ if (g_strrstr(vendstr, "X.Org")) {
+ tmp = g_strdup_printf("%d.%d.%d",
+ vendrel / 10000000,
+ (vendrel / 100000) % 100,
+ (vendrel / 1000) % 100);
+ if (vendrel % 1000) {
+ version = g_strdup_printf("%s.%d", tmp, vendrel % 1000);
+ } else {
+ version = g_strdup(tmp);
+ }
+
+ g_free(tmp);
+ }
+
+ /* DMX */
+
+ if (g_strrstr(vendstr, "DMX")) {
+ int major, minor, year, month, day;
+
+ major = vendrel / 100000000;
+ vendrel -= major * 100000000;
+ minor = vendrel / 1000000;
+ vendrel -= minor * 1000000;
+ year = vendrel / 10000;
+ vendrel -= year * 10000;
+ month = vendrel / 100;
+ vendrel -= month * 100;
+ day = vendrel;
+
+ /* Add other epoch tests here */
+ if (major > 0 && minor > 0) year += 2000;
+
+ /* Do some sanity tests in case there is
+ * another server with the same vendor
+ * string. That server could easily use
+ * values < 100000000, which would have
+ * the effect of keeping our major
+ * number 0. */
+ if (major > 0 && major <= 20
+ && minor >= 0 && minor <= 99
+ && year >= 2000
+ && month >= 1 && month <= 12
+ && day >= 1 && day <= 31)
+ version = g_strdup_printf("%d.%d.%04d%02d%02d\n",
+ major, minor, year, month, day);
+ }
+
+ /* Add the vendor release number */
+
+ if (version) {
+ tmp = g_strdup_printf("%s (%d)", version, vendrel);
+ } else {
+ tmp = g_strdup_printf("%d", vendrel);
+ }
+ g_free(version);
+ version = tmp;
+
+ return version;
+}
+
+
+
+/*
+ * CTK Server widget creation
+ *
+ */
+GtkWidget* ctk_server_new(NvCtrlAttributeHandle *handle,
+ CtkConfig *ctk_config)
+{
+ GObject *object;
+ CtkServer *ctk_object;
+ GtkWidget *label;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *banner;
+ GtkWidget *hseparator;
+ GtkWidget *table;
+
+ gchar *os;
+ gchar *arch;
+ gchar *driver_version;
+
+ gchar *dname = NvCtrlGetDisplayName(handle);
+ gchar *display_name;
+ gchar *server_version;
+ gchar *vendor_str;
+ gchar *vendor_ver;
+ gchar *num_screens;
+
+ ReturnStatus ret;
+ int tmp, os_val;
+ int xinerama_enabled;
+
+ /*
+ * get the data that we will display below
+ *
+ */
+
+ /* NV_CTRL_XINERAMA */
+
+ ret = NvCtrlGetAttribute(handle, NV_CTRL_XINERAMA, &xinerama_enabled);
+ if (ret != NvCtrlSuccess) {
+ xinerama_enabled = FALSE;
+ }
+
+ /* NV_CTRL_OPERATING_SYSTEM */
+
+ os_val = NV_CTRL_OPERATING_SYSTEM_LINUX;
+ ret = NvCtrlGetAttribute(handle, NV_CTRL_OPERATING_SYSTEM, &os_val);
+ os = NULL;
+ if (ret == NvCtrlSuccess) {
+ if (os_val == NV_CTRL_OPERATING_SYSTEM_LINUX) os = "Linux";
+ else if (os_val == NV_CTRL_OPERATING_SYSTEM_FREEBSD) os = "FreeBSD";
+ else if (os_val == NV_CTRL_OPERATING_SYSTEM_SUNOS) os = "SunOS";
+ }
+ if (!os) os = "Unknown";
+
+ /* NV_CTRL_ARCHITECTURE */
+
+ ret = NvCtrlGetAttribute(handle, NV_CTRL_ARCHITECTURE, &tmp);
+ arch = NULL;
+ if (ret == NvCtrlSuccess) {
+ if (tmp == NV_CTRL_ARCHITECTURE_X86) arch = "x86";
+ else if (tmp == NV_CTRL_ARCHITECTURE_X86_64) arch = "x86_64";
+ else if (tmp == NV_CTRL_ARCHITECTURE_IA64) arch = "ia64";
+ }
+ if (!arch) arch = "Unknown";
+ os = g_strdup_printf("%s-%s", os, arch);
+
+ /* NV_CTRL_STRING_NVIDIA_DRIVER_VERSION */
+
+ ret = NvCtrlGetStringAttribute(handle,
+ NV_CTRL_STRING_NVIDIA_DRIVER_VERSION,
+ &driver_version);
+ if (ret != NvCtrlSuccess) driver_version = NULL;
+
+ /* Display Name */
+
+ display_name = nv_standardize_screen_name(dname, -2);
+
+ /* X Server Version */
+
+ server_version = g_strdup_printf("%d.%d",
+ NvCtrlGetProtocolVersion(handle),
+ NvCtrlGetProtocolRevision(handle));
+
+ /* Server Vendor String */
+
+ vendor_str = g_strdup(NvCtrlGetServerVendor(handle));
+
+ /* Server Vendor Version */
+
+ vendor_ver = get_server_vendor_version(handle);
+
+ /* # Logical X Screens */
+
+ if (xinerama_enabled) {
+ num_screens = g_strdup_printf("%d (Xinerama)",
+ NvCtrlGetScreenCount(handle));
+ } else {
+ num_screens = g_strdup_printf("%d", NvCtrlGetScreenCount(handle));
+ }
+
+
+ /* now, create the object */
+
+ object = g_object_new(CTK_TYPE_SERVER, NULL);
+ ctk_object = CTK_SERVER(object);
+
+ /* cache the attribute handle */
+
+ ctk_object->handle = handle;
+
+ /* set container properties of the object */
+
+ gtk_box_set_spacing(GTK_BOX(ctk_object), 10);
+
+ /* banner */
+
+ if (os_val == NV_CTRL_OPERATING_SYSTEM_LINUX) {
+ banner = ctk_banner_image_new(&big_banner_penguin_image);
+ } else if (os_val == NV_CTRL_OPERATING_SYSTEM_FREEBSD) {
+ banner = ctk_banner_image_new(&big_banner_bsd_image);
+ } else if (os_val == NV_CTRL_OPERATING_SYSTEM_SUNOS) {
+ banner = ctk_banner_image_new(&big_banner_sun_image);
+ } else {
+ banner = ctk_banner_image_new(&big_banner_penguin_image);
+ }
+ gtk_box_pack_start(GTK_BOX(ctk_object), banner, FALSE, FALSE, 0);
+
+ /*
+ * This displays basic System information, including
+ * display name, Operating system type and the NVIDIA driver version.
+ */
+
+ vbox = gtk_vbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(ctk_object), vbox, TRUE, TRUE, 0);
+
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+
+ label = gtk_label_new("System Information");
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+ hseparator = gtk_hseparator_new();
+ gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5);
+
+ table = gtk_table_new(2, 2, FALSE);
+ gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
+
+ gtk_table_set_row_spacings(GTK_TABLE(table), 3);
+ gtk_table_set_col_spacings(GTK_TABLE(table), 15);
+
+ gtk_container_set_border_width(GTK_CONTAINER(table), 5);
+
+ add_table_row(table, 0,
+ 0, 0.5, "Operating System:", 0, 0.5, os);
+ add_table_row(table, 1,
+ 0, 0.5, "NVIDIA Driver Version:", 0, 0.5, driver_version);
+
+ /*
+ * This displays basic X Server information, including
+ * version number, vendor information and the number of
+ * X Screens.
+ */
+
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+
+ label = gtk_label_new("X Server Information");
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+ hseparator = gtk_hseparator_new();
+ gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5);
+
+ table = gtk_table_new(11, 2, FALSE);
+ gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
+ gtk_table_set_row_spacings(GTK_TABLE(table), 3);
+ gtk_table_set_col_spacings(GTK_TABLE(table), 15);
+ gtk_container_set_border_width(GTK_CONTAINER(table), 5);
+
+ add_table_row(table, 0,
+ 0, 0.5, "Display Name:", 0, 0.5, display_name);
+ /* separator */
+ add_table_row(table, 4,
+ 0, 0.5, "Server Version Number:", 0, 0.5, server_version);
+ add_table_row(table, 5,
+ 0, 0.5, "Server Vendor String:", 0, 0.5, vendor_str);
+ add_table_row(table, 6,
+ 0, 0.5, "Server Vendor Version:", 0, 0.5, vendor_ver);
+ /* separator */
+ add_table_row(table, 10,
+ 0, 0, "X Screens:", 0, 0, num_screens);
+
+ g_free(display_name);
+ g_free(os);
+ XFree(driver_version);
+
+ g_free(server_version);
+ g_free(vendor_str);
+ g_free(vendor_ver);
+ g_free(num_screens);
+
+ gtk_widget_show_all(GTK_WIDGET(object));
+
+ return GTK_WIDGET(object);
+}
+
+
+
+/*
+ * Server Information help screen
+ */
+GtkTextBuffer *ctk_server_create_help(GtkTextTagTable *table,
+ CtkServer *ctk_object)
+{
+ GtkTextIter i;
+ GtkTextBuffer *b;
+
+ b = gtk_text_buffer_new(table);
+
+ gtk_text_buffer_get_iter_at_offset(b, &i, 0);
+
+ ctk_help_title(b, &i, "X Server Information Help");
+
+ ctk_help_heading(b, &i, "Operating System");
+ ctk_help_para(b, &i, "This is the operating system on which the NVIDIA "
+ "X driver is running; possible values are "
+ "'Linux', 'FreeBSD', and 'SunOS'. This also specifies the "
+ "platform on which the operating system is running, such "
+ "as x86, x86_64, or ia64");
+
+ ctk_help_heading(b, &i, "NVIDIA Driver Version");
+ ctk_help_para(b, &i, "This is the version of the NVIDIA Accelerated "
+ "Graphics Driver currently in use.");
+
+ ctk_help_heading(b, &i, "Display Name");
+ ctk_help_para(b, &i, "This is the display connection string used to "
+ "communicate with the X Server.");
+
+ ctk_help_heading(b, &i, "X Server Version");
+ ctk_help_para(b, &i, "This is the version number of the X Server.");
+
+ ctk_help_heading(b, &i, "X Server Vendor String");
+ ctk_help_para(b, &i, "This is the X Server vendor information string.");
+
+ ctk_help_heading(b, &i, "X Server Vendor Version");
+ ctk_help_para(b, &i, "This is the vertsion number of the X Server "
+ "vendor.");
+
+ ctk_help_heading(b, &i, "X Screens");
+ ctk_help_para(b, &i, "This is the number of X Screens on the "
+ "display. (When Xinerama is enabled this is always 1).");
+
+ ctk_help_finish(b);
+
+ return b;
+}
diff --git a/src/gtk+-2.x/ctkserver.h b/src/gtk+-2.x/ctkserver.h
new file mode 100644
index 0000000..fff97e9
--- /dev/null
+++ b/src/gtk+-2.x/ctkserver.h
@@ -0,0 +1,77 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
+ * of the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+#ifndef __CTK_SERVER_H__
+#define __CTK_SERVER_H__
+
+#include "ctkevent.h"
+#include "ctkconfig.h"
+
+G_BEGIN_DECLS
+
+#define CTK_TYPE_SERVER (ctk_server_get_type())
+
+#define CTK_SERVER(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), CTK_TYPE_SERVER, \
+ CtkServer))
+
+#define CTK_SERVER_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), CTK_TYPE_SERVER, \
+ CtkServerClass))
+
+#define CTK_IS_SERVER(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CTK_TYPE_SERVER))
+
+#define CTK_IS_SERVER_CLASS(class) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), CTK_TYPE_SERVER))
+
+#define CTK_SERVER_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_SERVER, \
+ CtkServerClass))
+
+
+typedef struct _CtkServer
+{
+ GtkVBox parent;
+
+ CtkConfig *ctk_config;
+ NvCtrlAttributeHandle *handle;
+
+} CtkServer;
+
+typedef struct _CtkServerClass
+{
+ GtkVBoxClass parent_class;
+} CtkServerClass;
+
+
+GType ctk_server_get_type (void) G_GNUC_CONST;
+GtkWidget* ctk_server_new (NvCtrlAttributeHandle *, CtkConfig *);
+
+GtkTextBuffer *ctk_server_create_help(GtkTextTagTable *,
+ CtkServer *);
+
+G_END_DECLS
+
+#endif /* __CTK_SERVER_H__ */
diff --git a/src/gtk+-2.x/ctkthermal.c b/src/gtk+-2.x/ctkthermal.c
index 6f9b327..b7ca619 100644
--- a/src/gtk+-2.x/ctkthermal.c
+++ b/src/gtk+-2.x/ctkthermal.c
@@ -291,11 +291,15 @@ GtkWidget* ctk_thermal_new(NvCtrlAttributeHandle *handle,
/* Register a timer callback to update the temperatures */
+ s = g_strdup_printf("Thermal Monitor (GPU %d)",
+ NvCtrlGetTargetId(handle));
+
ctk_config_add_timer(ctk_thermal->ctk_config,
DEFAULT_UPDATE_THERMAL_INFO_TIME_INTERVAL,
- "Thermal Monitor",
+ s,
(GSourceFunc) update_thermal_info,
(gpointer) ctk_thermal);
+ g_free(s);
update_thermal_info(ctk_thermal);
gtk_widget_show_all(GTK_WIDGET(ctk_thermal));
@@ -341,7 +345,8 @@ void ctk_thermal_start_timer(GtkWidget *widget)
/* Start the thermal timer */
ctk_config_start_timer(ctk_thermal->ctk_config,
- (GSourceFunc) update_thermal_info);
+ (GSourceFunc) update_thermal_info,
+ (gpointer) ctk_thermal);
}
void ctk_thermal_stop_timer(GtkWidget *widget)
@@ -351,5 +356,6 @@ void ctk_thermal_stop_timer(GtkWidget *widget)
/* Stop the thermal timer */
ctk_config_stop_timer(ctk_thermal->ctk_config,
- (GSourceFunc) update_thermal_info);
+ (GSourceFunc) update_thermal_info,
+ (gpointer) ctk_thermal);
}
diff --git a/src/gtk+-2.x/ctkui.c b/src/gtk+-2.x/ctkui.c
index 456875e..5ee98fe 100644
--- a/src/gtk+-2.x/ctkui.c
+++ b/src/gtk+-2.x/ctkui.c
@@ -42,9 +42,14 @@ char *ctk_get_display(void)
return gdk_get_display();
}
-void ctk_main(NvCtrlAttributeHandle **attribute_handles,
- int num_screens, ParsedAttribute *p, ConfigProperties *conf)
+void ctk_main(NvCtrlAttributeHandle **screen_handles, int num_screen_handles,
+ NvCtrlAttributeHandle **gpu_handles, int num_gpu_handles,
+ NvCtrlAttributeHandle **vcsc_handles, int num_vcsc_handles,
+ ParsedAttribute *p, ConfigProperties *conf)
{
- ctk_window_new(attribute_handles, num_screens, p, conf);
+ ctk_window_new(screen_handles, num_screen_handles,
+ gpu_handles, num_gpu_handles,
+ vcsc_handles, num_vcsc_handles,
+ p, conf);
gtk_main();
}
diff --git a/src/gtk+-2.x/ctkui.h b/src/gtk+-2.x/ctkui.h
index c186ead..2993565 100644
--- a/src/gtk+-2.x/ctkui.h
+++ b/src/gtk+-2.x/ctkui.h
@@ -33,7 +33,10 @@ void ctk_init(int *argc, char **argv[]);
char *ctk_get_display(void);
-void ctk_main(NvCtrlAttributeHandle **, int, ParsedAttribute*,
+void ctk_main(NvCtrlAttributeHandle **, int,
+ NvCtrlAttributeHandle **, int,
+ NvCtrlAttributeHandle **, int,
+ ParsedAttribute*,
ConfigProperties*);
#endif /* __CTK_UI_H__ */
diff --git a/src/gtk+-2.x/ctkutils.c b/src/gtk+-2.x/ctkutils.c
index 10900d7..28a8f85 100644
--- a/src/gtk+-2.x/ctkutils.c
+++ b/src/gtk+-2.x/ctkutils.c
@@ -29,14 +29,18 @@
GtkWidget *add_table_row(GtkWidget *table,
const gint row,
- const gint value_alignment,
+ const gfloat name_xalign, // 0 = left, 1 = right
+ const gfloat name_yalign, // 0 = top, 1 = bottom
const gchar *name,
+ const gfloat value_xalign,
+ const gfloat value_yalign,
const gchar *value)
{
GtkWidget *label;
label = gtk_label_new(name);
- gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
+ gtk_label_set_selectable(GTK_LABEL(label), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(label), name_xalign, name_yalign);
gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1,
GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
@@ -44,7 +48,8 @@ GtkWidget *add_table_row(GtkWidget *table,
label = gtk_label_new("Unknown");
else
label = gtk_label_new(value);
- gtk_misc_set_alignment(GTK_MISC(label), value_alignment, 0.5);
+ gtk_label_set_selectable(GTK_LABEL(label), TRUE);
+ gtk_misc_set_alignment(GTK_MISC(label), value_xalign, value_yalign);
gtk_table_attach(GTK_TABLE(table), label, 1, 2, row, row + 1,
GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
diff --git a/src/gtk+-2.x/ctkutils.h b/src/gtk+-2.x/ctkutils.h
index 586cc8b..0cc28cf 100644
--- a/src/gtk+-2.x/ctkutils.h
+++ b/src/gtk+-2.x/ctkutils.h
@@ -30,8 +30,9 @@
G_BEGIN_DECLS
-GtkWidget *add_table_row(GtkWidget *, const gint, const gint, const gchar *,
- const gchar *);
+GtkWidget *add_table_row(GtkWidget *, const gint,
+ const gfloat, const gfloat, const gchar *,
+ const gfloat, const gfloat, const gchar *);
G_END_DECLS
diff --git a/src/gtk+-2.x/ctkvcsc.c b/src/gtk+-2.x/ctkvcsc.c
new file mode 100644
index 0000000..60daf6e
--- /dev/null
+++ b/src/gtk+-2.x/ctkvcsc.c
@@ -0,0 +1,255 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2006 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
+ * of the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+#include <stdlib.h> /* malloc */
+#include <stdio.h> /* snprintf */
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+
+#include "ctkimage.h"
+#include "frame_lock_banner.h"
+
+#include "ctkvcsc.h"
+#include "ctkevent.h"
+#include "ctkhelp.h"
+#include "ctkutils.h"
+
+
+GType ctk_vcsc_get_type(void)
+{
+ static GType ctk_vcsc_type = 0;
+
+ if (!ctk_vcsc_type) {
+ static const GTypeInfo ctk_vcsc_info = {
+ sizeof (CtkVcscClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof(CtkVcsc),
+ 0, /* n_preallocs */
+ NULL, /* instance_init */
+ };
+
+ ctk_vcsc_type = g_type_register_static
+ (GTK_TYPE_VBOX, "CtkVcsc", &ctk_vcsc_info, 0);
+ }
+
+ return ctk_vcsc_type;
+}
+
+
+
+/*
+ * CTK VCSC (Visual Computing System Controller) widget creation
+ *
+ */
+GtkWidget* ctk_vcsc_new(NvCtrlAttributeHandle *handle,
+ CtkConfig *ctk_config)
+{
+ GObject *object;
+ CtkVcsc *ctk_object;
+ GtkWidget *label;
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+ GtkWidget *banner;
+ GtkWidget *hseparator;
+ GtkWidget *table;
+
+ gchar *product_name;
+ gchar *serial_number;
+ gchar *build_date;
+ gchar *product_id;
+ gchar *firmware_version;
+ gchar *hardware_version;
+
+ ReturnStatus ret;
+
+ /*
+ * get the static string data that we will display below
+ */
+
+ /* Product Name */
+ ret = NvCtrlGetStringAttribute(handle,
+ NV_CTRL_STRING_VCSC_PRODUCT_NAME,
+ &product_name);
+ if (ret != NvCtrlSuccess) {
+ product_name = g_strdup("Unable to determine");
+ }
+
+ /* Serial Number */
+ ret = NvCtrlGetStringAttribute(handle,
+ NV_CTRL_STRING_VCSC_SERIAL_NUMBER,
+ &serial_number);
+ if (ret != NvCtrlSuccess) {
+ serial_number = g_strdup("Unable to determine");
+ }
+
+ /* Build Date */
+ ret = NvCtrlGetStringAttribute(handle,
+ NV_CTRL_STRING_VCSC_BUILD_DATE,
+ &build_date);
+ if (ret != NvCtrlSuccess) {
+ build_date = g_strdup("Unable to determine");
+ }
+
+ /* Product ID */
+ ret = NvCtrlGetStringAttribute(handle,
+ NV_CTRL_STRING_VCSC_PRODUCT_ID,
+ &product_id);
+ if (ret != NvCtrlSuccess) {
+ product_id = g_strdup("Unable to determine");
+ }
+
+ /* Firmware Version */
+ ret = NvCtrlGetStringAttribute(handle,
+ NV_CTRL_STRING_VCSC_FIRMWARE_VERSION,
+ &firmware_version);
+ if (ret != NvCtrlSuccess) {
+ firmware_version = g_strdup("Unable to determine");
+ }
+
+ /* Hardware Version */
+ ret = NvCtrlGetStringAttribute(handle,
+ NV_CTRL_STRING_VCSC_HARDWARE_VERSION,
+ &hardware_version);
+ if (ret != NvCtrlSuccess) {
+ hardware_version = g_strdup("Unable to determine");
+ }
+
+
+ /* now, create the object */
+
+ object = g_object_new(CTK_TYPE_VCSC, NULL);
+ ctk_object = CTK_VCSC(object);
+
+ /* cache the attribute handle */
+
+ ctk_object->handle = handle;
+
+ /* set container properties of the object */
+
+ gtk_box_set_spacing(GTK_BOX(ctk_object), 10);
+
+ /* banner */
+
+ banner = ctk_banner_image_new(&frame_lock_banner_image);
+ gtk_box_pack_start(GTK_BOX(ctk_object), banner, FALSE, FALSE, 0);
+
+ /*
+ * This displays basic System information, including
+ * display name, Operating system type and the NVIDIA driver version.
+ */
+
+ vbox = gtk_vbox_new(FALSE, 5);
+ gtk_box_pack_start(GTK_BOX(ctk_object), vbox, TRUE, TRUE, 0);
+
+ hbox = gtk_hbox_new(FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
+
+ label = gtk_label_new("VCSC Information");
+ gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
+
+ hseparator = gtk_hseparator_new();
+ gtk_box_pack_start(GTK_BOX(hbox), hseparator, TRUE, TRUE, 5);
+
+ table = gtk_table_new(5, 2, FALSE);
+ gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
+
+ gtk_table_set_row_spacings(GTK_TABLE(table), 3);
+ gtk_table_set_col_spacings(GTK_TABLE(table), 15);
+
+ gtk_container_set_border_width(GTK_CONTAINER(table), 5);
+
+ add_table_row(table, 0,
+ 0, 0.5, "Product Name:", 0, 0.5, product_name);
+ add_table_row(table, 1,
+ 0, 0.5, "Serial Number:", 0, 0.5, serial_number);
+ add_table_row(table, 2,
+ 0, 0.5, "Build Date:", 0, 0.5, build_date);
+ add_table_row(table, 3,
+ 0, 0.5, "Product ID:", 0, 0.5, product_id);
+ add_table_row(table, 4,
+ 0, 0.5, "Firmware version:", 0, 0.5, firmware_version);
+ add_table_row(table, 5,
+ 0, 0.5, "Hardware version:", 0, 0.5, hardware_version);
+
+ g_free(product_name);
+ g_free(serial_number);
+ g_free(build_date);
+ g_free(product_id);
+ g_free(firmware_version);
+ g_free(hardware_version);
+
+ gtk_widget_show_all(GTK_WIDGET(object));
+
+ return GTK_WIDGET(object);
+}
+
+
+
+/*
+ * VCSC help screen
+ */
+GtkTextBuffer *ctk_vcsc_create_help(GtkTextTagTable *table,
+ CtkVcsc *ctk_object)
+{
+ GtkTextIter i;
+ GtkTextBuffer *b;
+
+ b = gtk_text_buffer_new(table);
+
+ gtk_text_buffer_get_iter_at_offset(b, &i, 0);
+
+ ctk_help_title(b, &i, "VCSC (Visual Computing System Controller) Help");
+
+ ctk_help_heading(b, &i, "Product Name");
+ ctk_help_para(b, &i, "This is the product name of the VCSC system.");
+
+ ctk_help_heading(b, &i, "Serial Number");
+ ctk_help_para(b, &i, "This is the unique serial number of the VCSC "
+ "system.");
+
+ ctk_help_heading(b, &i, "Build Date");
+ ctk_help_para(b, &i, "This is the date the VCSC system was build, "
+ "shown in a 'week.year' format");
+
+ ctk_help_heading(b, &i, "Product ID");
+ ctk_help_para(b, &i, "This identifies the VCSC configuration.");
+
+ ctk_help_heading(b, &i, "Firmware Version");
+ ctk_help_para(b, &i, "This is the firmware version currently running on "
+ "the VCSC system.");
+
+ ctk_help_heading(b, &i, "Hardware Version");
+ ctk_help_para(b, &i, "This is the hardware version of the VCSC system.");
+
+ ctk_help_finish(b);
+
+ return b;
+}
+
diff --git a/src/gtk+-2.x/ctkvcsc.h b/src/gtk+-2.x/ctkvcsc.h
new file mode 100644
index 0000000..b05a985
--- /dev/null
+++ b/src/gtk+-2.x/ctkvcsc.h
@@ -0,0 +1,77 @@
+/*
+ * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
+ * and Linux systems.
+ *
+ * Copyright (C) 2006 NVIDIA Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of Version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
+ * of the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ */
+
+#ifndef __CTK_VCSC_H__
+#define __CTK_VCSC_H__
+
+#include "ctkevent.h"
+#include "ctkconfig.h"
+
+G_BEGIN_DECLS
+
+#define CTK_TYPE_VCSC (ctk_vcsc_get_type())
+
+#define CTK_VCSC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST ((obj), CTK_TYPE_VCSC, \
+ CtkVcsc))
+
+#define CTK_VCSC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST ((klass), CTK_TYPE_VCSC, \
+ CtkVcscClass))
+
+#define CTK_IS_VCSC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CTK_TYPE_VCSC))
+
+#define CTK_IS_VCSC_CLASS(class) \
+ (G_TYPE_CHECK_CLASS_TYPE ((klass), CTK_TYPE_VCSC))
+
+#define CTK_VCSC_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_VCSC, \
+ CtkVcscClass))
+
+
+typedef struct _CtkVcsc
+{
+ GtkVBox parent;
+
+ CtkConfig *ctk_config;
+ NvCtrlAttributeHandle *handle;
+
+} CtkVcsc;
+
+typedef struct _CtkVcscClass
+{
+ GtkVBoxClass parent_class;
+} CtkVcscClass;
+
+
+GType ctk_vcsc_get_type (void) G_GNUC_CONST;
+GtkWidget* ctk_vcsc_new (NvCtrlAttributeHandle *, CtkConfig *);
+
+GtkTextBuffer *ctk_vcsc_create_help(GtkTextTagTable *,
+ CtkVcsc *);
+
+G_END_DECLS
+
+#endif /* __CTK_VCSC_H__ */
diff --git a/src/gtk+-2.x/ctkwindow.c b/src/gtk+-2.x/ctkwindow.c
index 7ce9bfc..b1cf971 100644
--- a/src/gtk+-2.x/ctkwindow.c
+++ b/src/gtk+-2.x/ctkwindow.c
@@ -32,6 +32,7 @@
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <stdio.h>
+#include <stdlib.h>
#include "ctkwindow.h"
@@ -40,7 +41,8 @@
#include "ctkgvo-csc.h"
#include "ctkconfig.h"
-#include "ctkdevice.h"
+#include "ctkscreen.h"
+#include "ctkgpu.h"
#include "ctkcolorcorrection.h"
#include "ctkxvideo.h"
#include "ctkrandr.h"
@@ -50,12 +52,15 @@
#include "ctkmultisample.h"
#include "ctkthermal.h"
#include "ctkclocks.h"
+#include "ctkvcsc.h"
-#include "ctkdisplaydevice.h"
#include "ctkdisplaydevice-crt.h"
#include "ctkdisplaydevice-tv.h"
#include "ctkdisplaydevice-dfp.h"
+#include "ctkdisplayconfig.h"
+#include "ctkserver.h"
+
#include "ctkhelp.h"
#include "ctkevent.h"
#include "ctkconstants.h"
@@ -73,6 +78,20 @@ enum {
};
+typedef struct {
+ CtkWindow *window;
+ CtkEvent *event;
+ NvCtrlAttributeHandle *gpu_handle;
+ GtkTextTagTable *tag_table;
+
+ GtkTreeIter parent_iter;
+
+ GtkTreeIter *display_iters;
+ int num_displays;
+
+} UpdateDisplaysData;
+
+
typedef void (*config_file_attributes_func_t)(GtkWidget *, ParsedAttribute *);
typedef void (*select_widget_func_t)(GtkWidget *);
typedef void (*unselect_widget_func_t)(GtkWidget *);
@@ -94,11 +113,14 @@ static void save_settings_and_exit(CtkWindow *);
static void add_special_config_file_attributes(CtkWindow *ctk_window);
-static void add_display_devices(GtkWidget *widget, GtkTextBuffer *help,
- CtkWindow *ctk_window, GtkTreeIter *iter,
+static void add_display_devices(CtkWindow *ctk_window, GtkTreeIter *iter,
NvCtrlAttributeHandle *handle,
CtkEvent *ctk_event,
- GtkTextTagTable *tag_table);
+ GtkTextTagTable *tag_table,
+ UpdateDisplaysData *data);
+
+static void update_display_devices(GtkObject *object, gpointer arg1,
+ gpointer user_data);
static GObjectClass *parent_class;
@@ -173,7 +195,7 @@ static void ctk_window_real_destroy(GtkObject *object)
/*
- * close_button_clicked() - called when the
+ * close_button_clicked() - called when the "Quit" button is clicked.
*/
static void close_button_clicked(GtkButton *button, gpointer user_data)
@@ -262,11 +284,11 @@ static void tree_selection_changed(GtkTreeSelection *selection,
/* Call the unselect func for the existing widget, if any */
- if ( ctk_window->widget ) {
+ if (ctk_window->widget) {
gtk_tree_model_get(model, &(ctk_window->iter),
CTK_WINDOW_UNSELECT_WIDGET_FUNC_COLUMN,
&unselect_func, -1);
- if ( unselect_func ) {
+ if (unselect_func) {
(*unselect_func)(ctk_window->widget);
}
}
@@ -345,7 +367,12 @@ static gboolean tree_view_key_event(GtkWidget *tree_view, GdkEvent *event,
* ctk_window_new() - create a new CtkWindow widget
*/
-GtkWidget *ctk_window_new(NvCtrlAttributeHandle **handles, gint num_handles,
+GtkWidget *ctk_window_new(NvCtrlAttributeHandle **screen_handles,
+ gint num_screen_handles,
+ NvCtrlAttributeHandle **gpu_handles,
+ gint num_gpu_handles,
+ NvCtrlAttributeHandle **vcsc_handles,
+ gint num_vcsc_handles,
ParsedAttribute *p, ConfigProperties *conf)
{
GObject *object;
@@ -380,8 +407,6 @@ GtkWidget *ctk_window_new(NvCtrlAttributeHandle **handles, gint num_handles,
ctk_window = CTK_WINDOW(object);
gtk_container_set_border_width(GTK_CONTAINER(ctk_window), CTK_WINDOW_PAD);
- ctk_window->handles = handles;
- ctk_window->num_handles = num_handles;
ctk_window->attribute_list = p;
/* create the config object */
@@ -523,21 +548,70 @@ GtkWidget *ctk_window_new(NvCtrlAttributeHandle **handles, gint num_handles,
ctk_window->page_viewer = hbox;
ctk_window->page = NULL;
+
+ /* X Server info & configuration */
+
+ if (num_screen_handles) {
+
+ NvCtrlAttributeHandle *screen_handle = NULL;
+ GtkWidget *child;
+ int i;
+
+ /*
+ * XXX For now, just use the first handle in the list
+ * to communicate with the X server for these two
+ * pages.
+ */
+
+ for (i = 0 ; i < num_screen_handles; i++) {
+ if (screen_handles[i]) {
+ screen_handle = screen_handles[i];
+ break;
+ }
+ }
+ if (screen_handle) {
+
+ /* X Server information */
+
+ child = ctk_server_new(screen_handle, ctk_config);
+ add_page(child,
+ ctk_server_create_help(tag_table,
+ CTK_SERVER(child)),
+ ctk_window, NULL, NULL, "X Server Information",
+ NULL, NULL, NULL);
+
+ /* X Server Display Configuration */
+
+ child = ctk_display_config_new(screen_handle, ctk_config);
+ if (child) {
+ add_page(child,
+ ctk_display_config_create_help(tag_table,
+ CTK_DISPLAY_CONFIG(child)),
+ ctk_window, NULL, NULL,
+ "X Server Display Configuration",
+ NULL, NULL, NULL);
+ }
+ }
+ }
+
+
/* add the per-screen entries into the tree model */
- for (i = 0; i < num_handles; i++) {
+ for (i = 0; i < num_screen_handles; i++) {
GtkTreeIter iter;
gchar *screen_name;
GtkWidget *child;
+ NvCtrlAttributeHandle *screen_handle = screen_handles[i];
- if (!handles[i]) continue;
+ if (!screen_handle) continue;
/* create the object for receiving NV-CONTROL events */
- ctk_event = CTK_EVENT(ctk_event_new(handles[i]));
+ ctk_event = CTK_EVENT(ctk_event_new(screen_handle));
- screen_name = NvCtrlGetDisplayName(handles[i]);
+ screen_name = g_strdup_printf("X Screen %d",
+ NvCtrlGetTargetId(screen_handle));
/* create the screen entry */
@@ -545,22 +619,24 @@ GtkWidget *ctk_window_new(NvCtrlAttributeHandle **handles, gint num_handles,
gtk_tree_store_set(ctk_window->tree_store, &iter,
CTK_WINDOW_LABEL_COLUMN, screen_name, -1);
- /* device information */
+ /* Screen information */
+
+ screen_name = NvCtrlGetDisplayName(screen_handle);
- child = ctk_device_new(handles[i]);
+ child = ctk_screen_new(screen_handle, ctk_event);
gtk_object_ref(GTK_OBJECT(child));
gtk_tree_store_set(ctk_window->tree_store, &iter,
CTK_WINDOW_WIDGET_COLUMN, child, -1);
gtk_tree_store_set(ctk_window->tree_store, &iter,
CTK_WINDOW_HELP_COLUMN,
- ctk_device_create_help(tag_table, screen_name), -1);
+ ctk_screen_create_help(tag_table, screen_name), -1);
gtk_tree_store_set(ctk_window->tree_store, &iter,
CTK_WINDOW_CONFIG_FILE_ATTRIBUTES_FUNC_COLUMN,
NULL, -1);
/* color correction */
- child = ctk_color_correction_new(handles[i], ctk_config,
+ child = ctk_color_correction_new(screen_handle, ctk_config,
ctk_window->attribute_list,
ctk_event);
if (child) {
@@ -571,7 +647,7 @@ GtkWidget *ctk_window_new(NvCtrlAttributeHandle **handles, gint num_handles,
/* xvideo settings */
- child = ctk_xvideo_new(handles[i], ctk_config, ctk_event);
+ child = ctk_xvideo_new(screen_handle, ctk_config, ctk_event);
if (child) {
help = ctk_xvideo_create_help(tag_table, CTK_XVIDEO(child));
add_page(child, help, ctk_window, &iter, NULL,
@@ -580,7 +656,7 @@ GtkWidget *ctk_window_new(NvCtrlAttributeHandle **handles, gint num_handles,
/* randr settings */
- child = ctk_randr_new(handles[i], ctk_config, ctk_event);
+ child = ctk_randr_new(screen_handle, ctk_config, ctk_event);
if (child) {
help = ctk_randr_create_help(tag_table, CTK_RANDR(child));
add_page(child, help, ctk_window, &iter, NULL,
@@ -589,7 +665,7 @@ GtkWidget *ctk_window_new(NvCtrlAttributeHandle **handles, gint num_handles,
/* cursor shadow */
- child = ctk_cursor_shadow_new(handles[i], ctk_config, ctk_event);
+ child = ctk_cursor_shadow_new(screen_handle, ctk_config, ctk_event);
if (child) {
help = ctk_cursor_shadow_create_help(tag_table,
CTK_CURSOR_SHADOW(child));
@@ -599,7 +675,7 @@ GtkWidget *ctk_window_new(NvCtrlAttributeHandle **handles, gint num_handles,
/* opengl settings */
- child = ctk_opengl_new(handles[i], ctk_config, ctk_event);
+ child = ctk_opengl_new(screen_handle, ctk_config, ctk_event);
if (child) {
help = ctk_opengl_create_help(tag_table, CTK_OPENGL(child));
add_page(child, help, ctk_window, &iter, NULL, "OpenGL Settings",
@@ -609,7 +685,7 @@ GtkWidget *ctk_window_new(NvCtrlAttributeHandle **handles, gint num_handles,
/* GLX Information */
- child = ctk_glx_new(handles[i], ctk_config, ctk_event);
+ child = ctk_glx_new(screen_handle, ctk_config, ctk_event);
if (child) {
help = ctk_glx_create_help(tag_table, CTK_GLX(child));
add_page(child, help, ctk_window, &iter, NULL,
@@ -619,7 +695,7 @@ GtkWidget *ctk_window_new(NvCtrlAttributeHandle **handles, gint num_handles,
/* multisample settings */
- child = ctk_multisample_new(handles[i], ctk_config, ctk_event);
+ child = ctk_multisample_new(screen_handle, ctk_config, ctk_event);
if (child) {
help = ctk_multisample_create_help(tag_table,
CTK_MULTISAMPLE(child));
@@ -627,20 +703,12 @@ GtkWidget *ctk_window_new(NvCtrlAttributeHandle **handles, gint num_handles,
"Antialiasing Settings", NULL, NULL, NULL);
}
- /* thermal information */
-
- child = ctk_thermal_new(handles[i], ctk_config);
- if (child) {
- help = ctk_thermal_create_help(tag_table, CTK_THERMAL(child));
- add_page(child, help, ctk_window, &iter, NULL, "Thermal Monitor",
- NULL, ctk_thermal_start_timer, ctk_thermal_stop_timer);
- }
-
/* gvo (Graphics To Video Out) */
- child = ctk_gvo_new(handles[i], GTK_WIDGET(ctk_window),
+ child = ctk_gvo_new(screen_handle, GTK_WIDGET(ctk_window),
ctk_config, ctk_event);
if (child) {
+ GtkWidget *gvo_parent = child;
GtkTreeIter child_iter;
help = ctk_gvo_create_help(tag_table);
add_page(child, help, ctk_window, &iter, &child_iter,
@@ -649,17 +717,78 @@ GtkWidget *ctk_window_new(NvCtrlAttributeHandle **handles, gint num_handles,
/* add GVO sub-pages */
- child = ctk_gvo_csc_new(handles[i],
- ctk_config, ctk_event);
+ child = ctk_gvo_csc_new(screen_handle, ctk_config, ctk_event,
+ CTK_GVO(gvo_parent));
if (child) {
add_page(child, NULL, ctk_window, &child_iter, NULL,
- "Color Space Conversion", NULL, NULL, NULL);
+ "Color Space Conversion", NULL,
+ ctk_gvo_csc_select, ctk_gvo_csc_unselect);
}
}
+ }
+
+ /* add the per-gpu entries into the tree model */
+
+ for (i = 0; i < num_gpu_handles; i++) {
+
+ GtkTreeIter iter;
+ gchar *gpu_product_name;
+ gchar *gpu_name;
+ GtkWidget *child;
+ ReturnStatus ret;
+ NvCtrlAttributeHandle *gpu_handle = gpu_handles[i];
+ UpdateDisplaysData *data;
+
+
+ if (!gpu_handle) continue;
+
+ /* create the gpu entry name */
+ ret = NvCtrlGetStringDisplayAttribute(gpu_handle, 0,
+ NV_CTRL_STRING_PRODUCT_NAME,
+ &gpu_product_name);
+ if (ret == NvCtrlSuccess && gpu_product_name) {
+ gpu_name = g_strdup_printf("GPU %d - (%s)",
+ NvCtrlGetTargetId(gpu_handle),
+ gpu_product_name);
+ } else {
+ gpu_name = g_strdup_printf("GPU %d - (Unknown)",
+ NvCtrlGetTargetId(gpu_handle));
+ }
+ if (!gpu_name) continue;
+
+ /* create the object for receiving NV-CONTROL events */
+
+ ctk_event = CTK_EVENT(ctk_event_new(gpu_handle));
+
+ /* create the gpu entry */
+
+ gtk_tree_store_append(ctk_window->tree_store, &iter, NULL);
+ gtk_tree_store_set(ctk_window->tree_store, &iter,
+ CTK_WINDOW_LABEL_COLUMN, gpu_name, -1);
+ child = ctk_gpu_new(gpu_handle, screen_handles, ctk_event);
+ gtk_object_ref(GTK_OBJECT(child));
+ gtk_tree_store_set(ctk_window->tree_store, &iter,
+ CTK_WINDOW_WIDGET_COLUMN, child, -1);
+ gtk_tree_store_set(ctk_window->tree_store, &iter,
+ CTK_WINDOW_HELP_COLUMN,
+ ctk_gpu_create_help(tag_table), -1);
+ gtk_tree_store_set(ctk_window->tree_store, &iter,
+ CTK_WINDOW_CONFIG_FILE_ATTRIBUTES_FUNC_COLUMN,
+ NULL, -1);
+
+ /* thermal information */
+
+ child = ctk_thermal_new(gpu_handle, ctk_config);
+ if (child) {
+ help = ctk_thermal_create_help(tag_table, CTK_THERMAL(child));
+ add_page(child, help, ctk_window, &iter, NULL, "Thermal Monitor",
+ NULL, ctk_thermal_start_timer, ctk_thermal_stop_timer);
+ }
+
/* clocks (GPU overclocking) */
- child = ctk_clocks_new(handles[i], ctk_config, ctk_event);
+ child = ctk_clocks_new(gpu_handle, ctk_config, ctk_event);
if (child) {
help = ctk_clocks_create_help(tag_table, CTK_CLOCKS(child));
add_page(child, help, ctk_window, &iter, NULL, "Clock Frequencies",
@@ -667,14 +796,69 @@ GtkWidget *ctk_window_new(NvCtrlAttributeHandle **handles, gint num_handles,
}
/* display devices */
+ data = (UpdateDisplaysData *)calloc(1, sizeof(UpdateDisplaysData));
+ data->window = ctk_window;
+ data->event = ctk_event;
+ data->gpu_handle = gpu_handle;
+ data->parent_iter = iter;
+ data->tag_table = tag_table;
- child = ctk_display_device_new(handles[i], ctk_config, ctk_event);
- if (child) {
- help = ctk_display_device_create_help(tag_table,
- CTK_DISPLAY_DEVICE(child));
- add_display_devices(child, help, ctk_window,
- &iter, handles[i], ctk_event, tag_table);
+ g_signal_connect(G_OBJECT(ctk_event),
+ CTK_EVENT_NAME(NV_CTRL_PROBE_DISPLAYS),
+ G_CALLBACK(update_display_devices),
+ (gpointer) data);
+
+ add_display_devices(ctk_window, &iter, gpu_handle, ctk_event,
+ tag_table, data);
+ }
+
+ /* add the per-vcsc (e.g. Quadro Plex) entries into the tree model */
+
+ for (i = 0; i < num_vcsc_handles; i++) {
+
+ GtkTreeIter iter;
+ gchar *vcsc_product_name;
+ gchar *vcsc_name;
+ GtkWidget *child;
+ ReturnStatus ret;
+ NvCtrlAttributeHandle *vcsc_handle = vcsc_handles[i];
+
+ if (!vcsc_handle) continue;
+
+ /* create the vcsc entry name */
+
+ ret = NvCtrlGetStringDisplayAttribute(vcsc_handle, 0,
+ NV_CTRL_STRING_VCSC_PRODUCT_NAME,
+ &vcsc_product_name);
+ if (ret == NvCtrlSuccess && vcsc_product_name) {
+ vcsc_name = g_strdup_printf("VCSC %d - (%s)",
+ NvCtrlGetTargetId(vcsc_handle),
+ vcsc_product_name);
+ } else {
+ vcsc_name = g_strdup_printf("VCSC %d - (Unknown)",
+ NvCtrlGetTargetId(vcsc_handle));
}
+ if (!vcsc_name) continue;
+
+ /* create the object for receiving NV-CONTROL events */
+
+ ctk_event = CTK_EVENT(ctk_event_new(vcsc_handle));
+
+ /* create the vcsc entry */
+
+ gtk_tree_store_append(ctk_window->tree_store, &iter, NULL);
+ gtk_tree_store_set(ctk_window->tree_store, &iter,
+ CTK_WINDOW_LABEL_COLUMN, vcsc_name, -1);
+ child = ctk_vcsc_new(vcsc_handle, ctk_config);
+ gtk_object_ref(GTK_OBJECT(child));
+ gtk_tree_store_set(ctk_window->tree_store, &iter,
+ CTK_WINDOW_WIDGET_COLUMN, child, -1);
+ gtk_tree_store_set(ctk_window->tree_store, &iter,
+ CTK_WINDOW_HELP_COLUMN,
+ ctk_gpu_create_help(tag_table), -1);
+ gtk_tree_store_set(ctk_window->tree_store, &iter,
+ CTK_WINDOW_CONFIG_FILE_ATTRIBUTES_FUNC_COLUMN,
+ NULL, -1);
}
/*
@@ -682,10 +866,13 @@ GtkWidget *ctk_window_new(NvCtrlAttributeHandle **handles, gint num_handles,
* frame lock
*/
- for (i = 0; i < num_handles; i++) {
- if (!handles[i]) continue;
+ for (i = 0; i < num_screen_handles; i++) {
+
+ NvCtrlAttributeHandle *screen_handle = screen_handles[i];
+
+ if (!screen_handle) continue;
- widget = ctk_framelock_new(handles[i], GTK_WIDGET(ctk_window),
+ widget = ctk_framelock_new(screen_handle, GTK_WIDGET(ctk_window),
ctk_config, ctk_window->attribute_list);
if (!widget) continue;
@@ -905,52 +1092,56 @@ static void add_special_config_file_attributes(CtkWindow *ctk_window)
* add_display_devices() - add the display device pages
*/
-static void add_display_devices(GtkWidget *widget, GtkTextBuffer *help,
- CtkWindow *ctk_window, GtkTreeIter *iter,
+static void add_display_devices(CtkWindow *ctk_window, GtkTreeIter *iter,
NvCtrlAttributeHandle *handle,
CtkEvent *ctk_event,
- GtkTextTagTable *tag_table)
+ GtkTextTagTable *tag_table,
+ UpdateDisplaysData *data)
{
- GtkTreeIter child_iter;
+ GtkWidget *widget;
+ GtkTextBuffer *help;
ReturnStatus ret;
- int i, enabled, n, mask;
+ int i, connected, n, mask;
char *name;
+ char *type;
+ gchar *title;
- if (!widget) {
- return;
- }
- /* retrieve the enabled display device mask */
+ /* retrieve the connected display device mask */
- ret = NvCtrlGetAttribute(handle, NV_CTRL_ENABLED_DISPLAYS, &enabled);
+ ret = NvCtrlGetAttribute(handle, NV_CTRL_CONNECTED_DISPLAYS, &connected);
if (ret != NvCtrlSuccess) {
return;
}
- /* count how many display devices are enabled */
+ /* count how many display devices are connected */
for (i = 0, n = 0; i < 24; i++) {
- if (enabled & (1 << i)) n++;
+ if (connected & (1 << i)) n++;
}
if (n == 0) {
return;
- } else if (n == 1) {
- name = "Display Device";
- } else {
- name = "Display Devices";
}
- add_page(widget, help, ctk_window, iter, &child_iter, name,
- NULL, NULL, NULL);
+
+ if (data->display_iters) {
+ free(data->display_iters);
+ }
+ data->display_iters =
+ (GtkTreeIter *)calloc(1, n * sizeof(GtkTreeIter));
+ data->num_displays = 0;
+ if (!data->display_iters) return;
+
/*
- * create pages for each of the display devices driven by this X
- * screen.
+ * create pages for each of the display devices driven by this handle.
*/
for (i = 0; i < 24; i++) {
mask = (1 << i);
- if (!(mask & enabled)) continue;
+ if (!(mask & connected)) continue;
+
+ type = display_device_mask_to_display_device_name(mask);
ret =
NvCtrlGetStringDisplayAttribute(handle, mask,
@@ -958,13 +1149,17 @@ static void add_display_devices(GtkWidget *widget, GtkTextBuffer *help,
&name);
if ((ret != NvCtrlSuccess) || (!name)) {
- name = "Unknown";
+ title = g_strdup_printf("%s - (Unknown)", type);
+ } else {
+ title = g_strdup_printf("%s - (%s)", type, name);
+ XFree(name);
}
+ free(type);
if (mask & CTK_DISPLAY_DEVICE_CRT_MASK) {
widget = ctk_display_device_crt_new
- (handle, ctk_window->ctk_config, ctk_event, mask, name);
+ (handle, ctk_window->ctk_config, ctk_event, mask, title);
help = ctk_display_device_crt_create_help
(tag_table, CTK_DISPLAY_DEVICE_CRT(widget));
@@ -972,7 +1167,7 @@ static void add_display_devices(GtkWidget *widget, GtkTextBuffer *help,
} else if (mask & CTK_DISPLAY_DEVICE_TV_MASK) {
widget = ctk_display_device_tv_new
- (handle, ctk_window->ctk_config, ctk_event, mask, name);
+ (handle, ctk_window->ctk_config, ctk_event, mask, title);
help = ctk_display_device_tv_create_help
(tag_table, CTK_DISPLAY_DEVICE_TV(widget));
@@ -980,18 +1175,88 @@ static void add_display_devices(GtkWidget *widget, GtkTextBuffer *help,
} else if (mask & CTK_DISPLAY_DEVICE_DFP_MASK) {
widget = ctk_display_device_dfp_new
- (handle, ctk_window->ctk_config, ctk_event, mask, name);
+ (handle, ctk_window->ctk_config, ctk_event, mask, title);
help = ctk_display_device_dfp_create_help
(tag_table, CTK_DISPLAY_DEVICE_DFP(widget));
} else {
+ g_free(title);
continue;
}
- add_page(widget, help, ctk_window, &child_iter,
- NULL, name, NULL, NULL, NULL);
+ add_page(widget, help, ctk_window, iter,
+ &(data->display_iters[data->num_displays]), title,
+ NULL, NULL, NULL);
+ g_free(title);
+ data->num_displays++;
}
} /* add_display_devices() */
-
+
+
+/*
+ * update_display_devices() - Callback handler for the NV_CTRL_PROBE_DISPLAYS
+ * NV-CONTROL event. Updates the list of display devices connected to the
+ * GPU for which the event happened.
+ *
+ */
+
+static void update_display_devices(GtkObject *object, gpointer arg1,
+ gpointer user_data)
+{
+ UpdateDisplaysData *data = (UpdateDisplaysData *) user_data;
+
+ CtkWindow *ctk_window = data->window;
+ CtkEvent *ctk_event = data->event;
+ NvCtrlAttributeHandle *gpu_handle = data->gpu_handle;
+ GtkTreeIter parent_iter = data->parent_iter;
+ GtkTextTagTable *tag_table = data->tag_table;
+ GtkTreePath* parent_path;
+ gboolean parent_expanded;
+ GtkTreeSelection *tree_selection =
+ gtk_tree_view_get_selection(ctk_window->treeview);
+
+
+ /* Keep track if the parent row is expanded */
+ parent_path =
+ gtk_tree_model_get_path(GTK_TREE_MODEL(ctk_window->tree_store),
+ &parent_iter);
+ parent_expanded =
+ gtk_tree_view_row_expanded(ctk_window->treeview, parent_path);
+
+
+ /* Remove previous display devices */
+ while (data->num_displays) {
+
+ GtkTreeIter *iter = &(data->display_iters[data->num_displays -1]);
+ GtkWidget *widget;
+
+ /* Select the parent (GPU) iter if we're removing the selected page */
+ if (gtk_tree_selection_iter_is_selected(tree_selection, iter)) {
+ gtk_tree_selection_select_iter(tree_selection, &parent_iter);
+ }
+
+ /* unref the page so we don't leak memory */
+ gtk_tree_model_get(GTK_TREE_MODEL(ctk_window->tree_store), iter,
+ CTK_WINDOW_WIDGET_COLUMN, &widget, -1);
+ g_object_unref(widget);
+
+ /* XXX Call a widget-specific cleanup function? */
+
+ /* Remove the entry */
+ gtk_tree_store_remove(ctk_window->tree_store, iter);
+
+ data->num_displays--;
+ }
+
+ /* Add back all the connected display devices */
+ add_display_devices(ctk_window, &parent_iter, gpu_handle, ctk_event,
+ tag_table, data);
+
+ /* Expand the GPU entry if it used to be */
+ if (parent_expanded) {
+ gtk_tree_view_expand_row(ctk_window->treeview, parent_path, TRUE);
+ }
+
+} /* update_display_devices() */
diff --git a/src/gtk+-2.x/ctkwindow.h b/src/gtk+-2.x/ctkwindow.h
index c88c23d..3f5749a 100644
--- a/src/gtk+-2.x/ctkwindow.h
+++ b/src/gtk+-2.x/ctkwindow.h
@@ -53,6 +53,11 @@ G_BEGIN_DECLS
(G_TYPE_INSTANCE_GET_CLASS ((obj), CTK_TYPE_WINDOW, CtkWindowClass))
+#define CTK_DISPLAY_DEVICE_CRT_MASK 0x000000FF
+#define CTK_DISPLAY_DEVICE_TV_MASK 0x0000FF00
+#define CTK_DISPLAY_DEVICE_DFP_MASK 0x00FF0000
+
+
typedef struct _CtkWindow CtkWindow;
typedef struct _CtkWindowClass CtkWindowClass;
@@ -60,9 +65,6 @@ struct _CtkWindow
{
GtkWindow parent;
- NvCtrlAttributeHandle **handles;
- gint num_handles;
-
GtkTreeStore *tree_store;
GtkTreeView *treeview;
@@ -90,6 +92,8 @@ struct _CtkWindowClass
GType ctk_window_get_type (void) G_GNUC_CONST;
GtkWidget* ctk_window_new (NvCtrlAttributeHandle**, gint,
+ NvCtrlAttributeHandle**, gint,
+ NvCtrlAttributeHandle**, gint,
ParsedAttribute *, ConfigProperties *conf);
G_END_DECLS
diff --git a/src/gtk+-2.x/ctkxvideo.c b/src/gtk+-2.x/ctkxvideo.c
index d423625..6bb7d2b 100644
--- a/src/gtk+-2.x/ctkxvideo.c
+++ b/src/gtk+-2.x/ctkxvideo.c
@@ -22,6 +22,7 @@
*
*/
+#include <stdlib.h>
#include <gtk/gtk.h>
#include "NvCtrlAttributes.h"
@@ -473,6 +474,8 @@ GtkWidget* ctk_xvideo_new(NvCtrlAttributeHandle *handle,
GtkWidget *radio[24], *prev_radio;
int i, n, current = -1, mask;
char *name;
+ char *type;
+ gchar *name_str;
frame = gtk_frame_new("Sync to this display device");
gtk_box_pack_start(GTK_BOX(object), frame, FALSE, FALSE, 0);
@@ -487,7 +490,7 @@ GtkWidget* ctk_xvideo_new(NvCtrlAttributeHandle *handle,
mask = 1 << i;
if (!(enabled & mask)) continue;
-
+
/* get the name of the display device */
ret = NvCtrlGetStringDisplayAttribute(handle, mask,
@@ -497,6 +500,14 @@ GtkWidget* ctk_xvideo_new(NvCtrlAttributeHandle *handle,
if ((ret != NvCtrlSuccess) || (!name)) {
name = g_strdup("Unknown");
}
+
+ /* get the display device type */
+
+ type = display_device_mask_to_display_device_name(mask);
+
+ name_str = g_strdup_printf("%s (%s)", name, type);
+ XFree(name);
+ free(type);
if (n==0) {
prev_radio = NULL;
@@ -504,7 +515,8 @@ GtkWidget* ctk_xvideo_new(NvCtrlAttributeHandle *handle,
prev_radio = radio[n-1];
}
radio[n] = xv_sync_to_display_radio_button_add(ctk_xvideo, vbox,
- prev_radio, name, mask, n);
+ prev_radio, name_str, mask, n);
+ g_free(name_str);
ctk_config_set_tooltip(ctk_config, radio[n],
__xv_sync_to_display_help);
diff --git a/src/image_data/Makefile.inc b/src/image_data/Makefile.inc
index 6606291..f0800e3 100644
--- a/src/image_data/Makefile.inc
+++ b/src/image_data/Makefile.inc
@@ -30,6 +30,7 @@ SRC += \
image.c
EXTRA_DIST += \
+ Makefile.inc \
HOWTO-ADD-IMAGES \
antialiasing_banner.h \
big_banner_bsd.h \
@@ -86,4 +87,8 @@ EXTRA_DIST += \
led_grey.h \
rj45_input.h \
rj45_output.h \
- rj45_unused.h
+ rj45_unused.h \
+ blank_banner.h
+
+dist_list::
+ @ echo $(SRC) $(EXTRA_DIST)
diff --git a/src/image_data/antialiasing_banner.h b/src/image_data/antialiasing_banner.h
index 7ad99fc..8a65a84 100644
--- a/src/image_data/antialiasing_banner.h
+++ b/src/image_data/antialiasing_banner.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t antialiasing_banner_image = {
- 360, 60, 3,
+ 360, 60, 3, 180,
"\1IX\31\203_y\24\1k\211\26\377\200\221\33\312\200\221\33\202\225\235e\4\200"
"\201\203stt\213\213\215\227\227\230\202\234\236\235\1\243\243\244\202\234"
"\236\235\2\221\221\223\213\213\215\203\221\221\223\1\213\213\215\202\200"
diff --git a/src/image_data/big_banner_bsd.h b/src/image_data/big_banner_bsd.h
index 4095aff..83c3f53 100644
--- a/src/image_data/big_banner_bsd.h
+++ b/src/image_data/big_banner_bsd.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t big_banner_bsd_image = {
- 360, 110, 3,
+ 360, 110, 3, 180,
"\11R\\+Wb._k2gt6o~;w\205>|\213B\177\217C\200\217D\377\200\220D\321\200\220"
"D\24\207\225V\222\233t\205\211vpppxxy\200\200\200\205\205\206\207\207\211"
"\212\212\213\213\213\214\215\215\217\220\220\223\224\224\226\230\230\231"
diff --git a/src/image_data/big_banner_penguin.h b/src/image_data/big_banner_penguin.h
index 8678103..c4613ef 100644
--- a/src/image_data/big_banner_penguin.h
+++ b/src/image_data/big_banner_penguin.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t big_banner_penguin_image = {
- 360, 110, 3,
+ 360, 110, 3, 180,
"\11R\\+Wb._k2gt6o~;w\205>|\213B\177\217C\200\217D\377\200\220D\321\200\220"
"D\24\207\225V\222\233t\205\211vpppxxy\200\200\200\205\205\206\207\207\211"
"\212\212\213\213\213\214\215\215\217\220\220\223\224\224\226\230\230\231"
diff --git a/src/image_data/big_banner_sun.h b/src/image_data/big_banner_sun.h
index 158d0d3..9193ee2 100644
--- a/src/image_data/big_banner_sun.h
+++ b/src/image_data/big_banner_sun.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t big_banner_sun_image = {
- 360, 110, 3,
+ 360, 110, 3, 180,
"\377\376\376\376\333\376\376\376\5\231\236v\177\177\177jjkvvw\177\177\177"
"\202\205\205\206\202\212\212\214\7\220\220\217\217\216\224\223\223\224\227"
"\227\231\223\223\224\212\212\214\205\205\206\202\212\212\214\203\205\205"
diff --git a/src/image_data/blank_banner.h b/src/image_data/blank_banner.h
new file mode 100644
index 0000000..e2f25e0
--- /dev/null
+++ b/src/image_data/blank_banner.h
@@ -0,0 +1,1485 @@
+/* GIMP RGB C-Source image dump 1-byte-run-length-encoded */
+
+#include "image.h"
+
+static const nv_image_t blank_banner_image = {
+ 360, 60, 3, 180,
+ "\10S]\21Xc\22`k\23hv\25p\177\27x\205\30}\213\32\200\217\33\377\200\220\33"
+ "\306\200\220\33\35\201\221\40\217\231S\222\233e\202\204|zz{\212\212\213\224"
+ "\224\225\232\232\233\236\236\240\240\240\241\236\236\240\233\233\235\217"
+ "\217\221\211\211\215\215\215\217\221\221\222\220\220\222\211\211\213\202"
+ "\202\205\203\203\207\215\215\217\220\220\223\217\217\221\220\220\222\221"
+ "\221\223\214\214\217\201\201\205\200\200\203\217\217\221\203\230\230\230"
+ "\5\224\224\225\200\200\204{{\200\204\204\207\216\216\221\202\217\217\222"
+ "\5\220\220\223\210\210\213yy\177{{\200\220\220\222\205\230\230\230\5\212"
+ "\212\215ttzyy\177\212\212\217\227\227\230\202\230\230\230\5\221\221\224\177"
+ "\177\203rryzz\200\217\217\221\202\230\230\230\1\227\227\227\202\225\225\227"
+ "\13\227\227\227\230\230\230\224\224\225\211\211\214\200\200\202zz\200{{\200"
+ "\177\177\202\204\204\210\211\211\214\215\215\217\202\216\216\220\12\214\214"
+ "\217\212\212\215\211\211\213\206\206\212\205\205\211\205\205\210\204\204"
+ "\210\204\204\207\205\205\210\204\204\210\205\205\205\211\2\206\206\211\206"
+ "\206\212\203\207\207\212\202\206\206\212\7\204\204\207\202\202\205\200\200"
+ "\203\177\177\201\200\200\204\212\212\214\224\224\225\202\230\230\230\13\227"
+ "\227\227\221\221\223\211\211\215\205\205\212\213\213\217\222\222\225\227"
+ "\227\230\230\230\230\226\226\227\216\216\221\205\205\212\202\204\204\211"
+ "\16\206\206\213\213\213\220\224\224\226\227\227\227\225\225\230\212\212\217"
+ "{{\200ssyttzuu{\177\177\202\214\214\220\221\221\224\226\226\226\204\230\230"
+ "\230\1\226\226\227\202\217\217\221\2\211\211\214\203\203\207\202\202\202"
+ "\206\17\204\204\210\211\211\214\207\207\210\177\177\200||}xxxnnn`k\25iu\26"
+ "s\200\31\177\213\33\210\230\35\221\241\37\226\250\40\231\254!\202\233\255"
+ "!\377\234\256!\304\234\256!\27\241\262;\260\272u\243\251\200yyz\207\207\210"
+ "\226\226\230\242\242\242\247\247\252\256\256\256\257\257\260\261\261\262"
+ "\251\251\253\235\235\240\232\232\235\241\241\242\244\244\244\235\235\237"
+ "\223\223\227\216\216\222\226\226\231\237\237\242\240\240\243\240\240\242"
+ "\202\240\240\243\4\226\226\231\215\215\222\227\226\232\250\250\251\203\252"
+ "\252\252\4\233\233\236\210\210\215\214\214\222\231\231\235\202\237\237\243"
+ "\5\240\240\244\232\232\237\211\211\217\202\202\212\232\232\235\205\252\252"
+ "\252!\240\240\242\204\204\213\200\200\210\230\230\234\246\246\251\252\252"
+ "\252\251\251\252\241\241\244\213\213\222\177\177\205\213\213\220\241\241"
+ "\244\252\252\252\252\252\251\251\251\251\247\247\251\251\251\251\252\252"
+ "\252\251\251\252\241\241\244\221\221\225\206\206\215\207\207\214\214\214"
+ "\222\224\224\231\233\233\236\237\237\242\240\240\242\235\235\241\233\233"
+ "\236\227\227\233\225\225\231\223\223\230\202\223\223\227\5\223\223\230\225"
+ "\225\231\225\225\232\227\227\233\231\231\233\204\231\231\234\4\231\231\233"
+ "\227\227\232\226\226\232\226\226\231\203\225\225\231\203\226\226\232$\225"
+ "\225\231\223\223\230\220\220\225\215\215\222\214\214\221\223\223\230\236"
+ "\236\241\251\251\251\252\252\252\251\251\252\243\243\245\227\227\234\221"
+ "\221\226\224\224\231\237\237\242\251\251\251\252\252\252\251\251\252\241"
+ "\241\243\225\225\232\222\222\231\224\224\231\226\226\233\235\235\242\247"
+ "\247\250\251\251\252\244\244\250\225\225\233\201\201\211\200\200\205\200"
+ "\200\206\201\201\210\217\217\224\235\235\242\242\242\245\251\251\251\204"
+ "\252\252\252\26\244\244\245\236\236\242\234\234\240\223\223\230\217\217\224"
+ "\221\221\225\220\220\224\223\223\227\225\225\227\215\215\220\202\202\204"
+ "\200\200\200wwyly\27u\202\32\200\217\34\216\237\37\232\253\"\243\267$\253"
+ "\277%\256\303&\257\304&\377\260\305&\305\260\305&\11\275\314Z\307\321\202"
+ "\241\245\211~~\200\221\221\222\242\242\244\253\253\255\266\266\267\275\275"
+ "\276\202\277\277\301\21\265\265\270\252\252\257\255\255\260\265\265\266\263"
+ "\263\263\252\251\255\235\235\242\236\236\242\251\251\255\260\260\263\260"
+ "\260\262\260\260\264\261\261\264\254\254\261\236\236\244\236\236\243\262"
+ "\262\264\203\273\273\273\5\270\270\271\237\237\245\225\225\234\241\241\247"
+ "\254\254\261\202\257\257\264\5\256\256\262\237\237\245\216\216\226\237\237"
+ "\244\271\271\272\202\273\273\273\7\272\272\272\273\273\273\266\266\270\230"
+ "\230\237\212\212\223\236\236\244\264\264\267\202\272\272\273\7\264\264\267"
+ "\235\235\243\212\212\222\230\230\237\266\266\267\273\273\273\273\273\272"
+ "\203\272\272\272\26\273\273\273\272\272\273\260\260\264\235\235\242\223\223"
+ "\232\227\227\236\240\240\246\252\252\256\261\261\264\262\262\265\257\257"
+ "\263\252\252\256\247\247\252\243\243\250\241\241\247\243\243\247\245\245"
+ "\251\250\250\253\254\254\256\257\257\262\261\261\264\264\264\266\202\266"
+ "\266\270\203\267\267\270\10\266\266\270\265\265\267\263\263\265\261\261\263"
+ "\256\256\260\253\253\256\251\251\254\250\250\252\203\246\246\251\202\246"
+ "\246\252\"\244\244\251\241\241\246\236\236\243\233\233\241\236\236\243\255"
+ "\255\260\272\272\272\273\273\273\272\272\273\264\264\266\244\244\251\235"
+ "\235\241\237\237\245\256\256\262\272\272\272\273\273\273\272\272\272\257"
+ "\257\263\244\244\252\241\241\250\243\243\251\247\247\254\262\261\265\272"
+ "\272\272\271\271\273\264\264\267\233\232\241\212\212\223\214\214\223\214"
+ "\214\224\222\222\231\245\245\252\261\261\265\266\266\270\204\273\273\273"
+ "\6\271\271\272\260\260\264\256\256\263\245\245\252\235\235\243\237\237\243"
+ "\202\235\235\242\16\237\237\243\235\235\240\216\216\221\205\205\210\177\177"
+ "\200u\200\32\200\214\35\215\234\40\234\255$\252\274'\264\310)\272\317*\276"
+ "\324+\277\324,\377\300\325,\304\300\325,\25\301\325/\323\337{\325\336\215"
+ "\221\223\210\205\205\207\233\233\234\251\251\253\265\265\267\301\301\303"
+ "\306\306\311\314\314\317\313\313\315\277\277\302\272\272\276\302\302\303"
+ "\305\305\305\277\277\300\263\263\265\251\251\255\257\257\262\273\273\276"
+ "\202\275\275\300\202\300\300\303\4\266\266\273\250\250\257\263\263\270\311"
+ "\311\311\203\313\313\313\13\276\276\302\244\244\253\246\246\255\265\265\272"
+ "\275\275\301\276\276\303\275\275\302\266\266\272\240\240\250\243\243\252"
+ "\303\303\304\205\313\313\313\13\265\265\272\225\225\237\240\240\247\273\273"
+ "\301\310\310\312\311\311\313\304\304\307\254\254\263\225\225\240\242\242"
+ "\251\301\301\304\202\313\313\313\203\312\312\312\24\313\313\313\312\312\312"
+ "\273\273\300\250\250\260\242\242\250\251\251\257\264\264\271\275\275\302"
+ "\302\302\304\300\300\303\273\273\300\265\265\271\261\261\266\261\261\265"
+ "\264\264\267\270\270\273\277\277\301\303\303\305\306\306\310\310\310\311"
+ "\207\311\311\311\205\311\311\312\10\311\311\311\307\307\311\304\305\306\301"
+ "\301\303\274\274\300\267\267\273\265\265\271\264\264\271\202\264\264\267"
+ "\"\263\263\266\261\261\265\256\256\263\250\250\260\253\253\262\271\271\276"
+ "\311\311\311\313\313\313\312\312\313\301\301\304\260\260\266\247\247\256"
+ "\252\252\262\272\272\277\311\311\311\313\313\313\311\311\311\300\300\303"
+ "\262\262\270\260\260\266\262\262\270\267\267\276\305\305\307\312\312\313"
+ "\310\310\313\267\267\275\234\234\244\226\226\237\230\230\241\231\231\242"
+ "\244\244\253\267\267\275\303\303\306\311\311\312\204\313\313\313\25\304\304"
+ "\306\276\276\302\267\267\274\254\254\261\253\253\261\253\253\260\250\250"
+ "\255\247\247\253\250\250\253\234\234\236\214\213\216\203\203\206|\206\34"
+ "\207\225\37\226\245\"\247\270&\265\307)\300\322,\306\332-\311\335-\312\336"
+ ".\377\313\337.\304\313\337.\25\321\342H\342\353\222\306\317\224\177\177\200"
+ "\216\216\220\243\243\244\261\261\262\275\275\276\312\312\314\317\317\322"
+ "\330\330\332\321\321\325\310\310\314\314\314\317\322\322\323\321\321\321"
+ "\312\312\313\273\273\277\264\264\271\277\277\302\311\311\315\202\312\312"
+ "\315\5\315\315\321\307\307\314\272\272\300\266\266\274\315\315\321\203\331"
+ "\331\331\13\326\326\327\274\274\302\253\253\263\271\271\277\306\306\313\311"
+ "\311\317\312\312\317\304\304\311\263\263\272\246\246\257\304\304\310\203"
+ "\331\331\331\15\330\330\330\331\331\331\320\320\322\250\250\261\242\242\254"
+ "\275\275\303\322\322\326\325\325\331\322\322\327\275\275\303\241\241\253"
+ "\253\253\262\315\315\320\202\331\331\331\203\330\330\330\21\331\331\331\327"
+ "\327\330\307\307\312\260\260\270\256\256\265\272\272\277\307\307\313\317"
+ "\317\322\320\320\322\311\311\316\302\302\307\276\276\302\275\275\302\302"
+ "\302\305\310\310\314\321\321\323\326\326\327\202\327\327\330\2\326\326\327"
+ "\324\324\326\204\322\322\325\4\323\323\325\324\324\326\325\325\327\326\326"
+ "\327\202\327\327\327\3\327\327\330\327\327\331\330\330\331\202\331\331\331"
+ "\7\330\330\331\327\327\327\322\322\324\315\315\320\306\306\312\303\303\306"
+ "\300\300\304\202\276\276\303\2\275\275\301\272\272\276\202\264\264\273\34"
+ "\301\301\306\324\324\325\331\331\331\330\330\331\315\315\321\271\271\277"
+ "\256\256\267\262\262\272\304\304\311\327\327\327\331\331\331\327\327\330"
+ "\312\312\320\275\275\303\273\273\303\276\276\304\310\310\317\327\327\327"
+ "\330\330\331\322\322\326\265\265\275\241\241\253\242\242\253\243\243\254"
+ "\245\245\256\265\265\274\312\312\320\322\322\326\204\331\331\331\23\327\327"
+ "\327\314\314\321\310\310\315\271\271\300\265\265\274\266\266\273\263\263"
+ "\270\256\256\262\256\256\261\247\247\253\224\224\230\207\207\211\200\213"
+ "\35\213\231\40\235\254$\255\276'\274\317*\306\331-\314\340.\202\317\343/"
+ "\377\320\344/\304\320\344/\34\333\352b\346\360\224\261\267\223\201\201\202"
+ "\225\225\226\250\250\251\267\267\270\304\304\306\317\317\321\330\330\332"
+ "\334\334\336\326\326\332\322\322\326\332\332\333\337\337\337\334\334\334"
+ "\320\320\323\300\300\305\301\301\305\316\316\321\324\324\327\323\323\327"
+ "\325\325\330\330\330\333\314\314\321\276\276\304\310\310\316\341\341\342"
+ "\203\344\344\344\13\327\327\332\272\272\302\267\267\277\312\312\320\323\323"
+ "\331\324\324\331\322\322\330\303\303\312\260\260\271\272\272\302\340\340"
+ "\340\202\344\344\344\15\343\343\343\344\344\344\343\343\343\302\302\311\250"
+ "\250\262\273\273\303\323\323\331\335\335\342\333\333\340\314\314\323\256"
+ "\256\267\260\260\272\326\326\331\202\344\344\344\203\343\343\343\25\344\344"
+ "\344\343\343\344\322\322\327\272\272\301\270\270\300\306\306\313\324\324"
+ "\331\332\332\336\331\331\335\322\322\325\311\311\316\306\306\314\313\313"
+ "\320\325\325\331\337\337\340\343\343\344\342\342\343\340\340\340\332\332"
+ "\334\326\326\330\323\323\326\202\322\322\324\202\322\322\325\7\323\323\325"
+ "\324\324\326\325\325\326\326\326\327\326\326\330\327\327\331\330\330\331"
+ "\202\331\331\331\3\331\331\332\331\331\333\332\332\333\203\333\333\333!\332"
+ "\332\332\327\327\330\321\321\322\311\311\314\302\302\306\300\300\304\301"
+ "\301\305\301\301\306\300\300\306\274\274\303\273\273\302\311\311\316\337"
+ "\337\340\344\344\344\343\343\343\323\323\330\274\274\304\264\264\275\271"
+ "\271\301\317\317\324\342\342\342\344\344\344\341\341\343\322\322\330\304"
+ "\304\315\304\304\314\312\312\322\331\331\335\343\343\343\342\342\344\322"
+ "\322\330\262\262\273\252\251\263\202\254\254\265\4\261\261\272\311\311\320"
+ "\332\331\336\340\340\341\204\344\344\344\3\333\333\336\325\324\331\311\310"
+ "\316\202\276\276\304\16\275\276\303\266\266\273\260\257\264\256\256\261\236"
+ "\236\241\213\213\215\201\214\37\220\234\"\241\257&\263\303+\301\321.\312"
+ "\3330\320\3411\321\3432\377\323\3452\305\323\3452\33\342\355z\350\361\227"
+ "\236\241\217\206\206\210\234\234\235\256\256\257\273\273\275\310\310\313"
+ "\324\324\326\336\336\337\342\342\344\331\331\334\334\334\340\346\346\347"
+ "\347\347\347\343\343\344\326\326\331\307\307\314\314\314\321\332\332\335"
+ "\333\333\337\332\332\337\335\335\341\335\335\342\316\316\324\305\305\314"
+ "\334\334\340\203\355\355\355\13\354\354\355\321\321\330\273\273\303\303\303"
+ "\313\327\327\333\334\334\342\333\333\341\324\324\333\277\277\307\265\265"
+ "\276\325\325\332\203\355\355\355\3\354\354\354\355\355\355\341\341\344\202"
+ "\266\266\300\7\322\322\331\340\340\347\343\343\350\331\331\340\276\276\307"
+ "\260\260\272\324\324\332\202\355\355\355\203\354\354\354Q\355\355\355\354"
+ "\354\355\337\337\343\304\304\314\277\277\307\317\316\325\335\335\342\344"
+ "\344\347\340\340\344\330\330\335\320\320\326\321\321\326\333\332\335\345"
+ "\345\346\353\353\354\354\354\355\352\352\352\346\346\347\341\341\343\324"
+ "\333\212\343\346\177\343\345~\343\345}\344\345{\344\346z\345\346v\345\347"
+ "s\345\347o\342\347k\340\347f\332\345`\324\344Z\322\345W\320\346U\316\344"
+ "T\313\343R\311\342O\306\341M\303\336K\302\335I\300\333G\277\332F\276\331"
+ "F\276\330F\276\327G\275\325G\273\324E\300\324W\276\276\303\304\304\311\306"
+ "\306\314\304\304\313\303\303\313\326\326\332\352\352\353\355\355\355\351"
+ "\351\352\323\323\332\275\275\306\270\270\302\302\302\311\334\334\341\354"
+ "\354\354\355\355\355\347\347\350\323\323\333\313\313\324\316\316\325\331"
+ "\331\337\347\347\351\355\355\355\346\346\351\306\307\317\261\260\273\262"
+ "\262\273\264\263\275\262\262\274\302\302\312\335\335\343\345\345\350\353"
+ "\353\354\203\355\355\355\23\347\347\351\336\336\343\326\326\333\306\306\315"
+ "\304\304\311\305\305\312\276\276\302\264\264\271\256\256\263\245\245\250"
+ "\217\217\221\202\215\37\222\236#\244\262'\266\305+\305\325.\315\3360\322"
+ "\3431\323\3452\377\324\3462\304\324\3462\25\326\347>\347\360\215\333\343"
+ "\227\207\210\205\216\216\217\242\242\243\262\262\264\301\301\303\317\317"
+ "\321\331\331\333\342\342\344\342\342\345\337\337\342\347\347\352\356\356"
+ "\357\357\357\357\350\350\352\331\331\334\317\317\323\327\327\333\342\342"
+ "\346\202\341\341\345\5\346\346\351\336\336\343\313\313\323\321\321\327\354"
+ "\354\356\203\363\363\363\13\352\352\355\311\311\321\300\300\311\321\321\330"
+ "\340\340\345\342\342\350\337\337\345\317\317\326\272\272\303\305\305\316"
+ "\355\355\357\202\363\363\363\16\362\362\362\363\363\363\360\360\361\316\316"
+ "\325\262\262\275\311\311\322\337\337\347\346\346\354\341\341\347\310\310"
+ "\322\264\264\300\314\314\323\360\360\361\363\363\363\203\362\362\362\202"
+ "\363\363\363>\347\347\351\312\312\322\305\305\315\325\325\333\344\344\351"
+ "\351\351\355\345\345\350\332\332\337\325\325\332\332\332\336\347\347\351"
+ "\360\360\361\363\363\363\361\361\361\353\353\355\350\350\351\346\346\351"
+ "\342\342\344\317\324\200\367\362\217\350\350\206\351\347\203\351\347\200"
+ "\352\350}\351\351z\351\351y\353\351v\345\351r\343\351n\340\351n\340\354n"
+ "\334\351i\327\351f\325\352a\317\352]\315\353X\312\352W\307\347T\303\342O"
+ "\300\336K\274\335I\272\330G\270\326B\263\324@\262\320=\253\3163\266\320E"
+ "\265\265\270\303\303\310\315\315\323\315\315\325\310\310\317\311\311\321"
+ "\336\336\343\360\360\362\363\363\363\351\351\354\320\320\327\300\300\311"
+ "\274\274\306\310\310\322\343\343\350\202\363\363\363\20\351\351\354\326\326"
+ "\336\321\321\330\325\325\335\343\343\351\362\362\362\362\362\363\340\340"
+ "\346\275\275\306\264\264\300\273\272\304\271\271\302\273\273\305\325\325"
+ "\333\351\351\355\356\356\361\203\363\363\363\23\361\361\361\347\347\353\341"
+ "\341\346\317\317\326\307\307\316\312\312\317\304\304\312\270\270\274\256"
+ "\256\262\247\247\253\224\224\230\200\213\40\220\234$\243\260)\265\304.\303"
+ "\3231\312\3332\316\3374\322\3445\377\333\3557\304\333\3557\34\340\360V\354"
+ "\365\231\306\315\230\200\200\201\223\223\224\246\246\247\266\266\270\305"
+ "\305\307\322\322\324\336\336\337\344\344\345\342\342\346\343\343\345\357"
+ "\357\361\364\364\364\363\363\363\353\353\355\332\332\336\325\325\332\342"
+ "\342\346\350\350\353\344\344\350\346\346\351\351\351\355\334\334\342\316"
+ "\316\325\340\340\344\367\367\367\203\370\370\370\12\344\344\350\306\306\317"
+ "\311\311\321\334\334\343\346\346\353\345\345\353\335\335\343\307\307\320"
+ "\300\300\311\342\342\346\203\370\370\370\3\370\370\367\370\370\370\346\346"
+ "\351\202\275\275\310\10\332\332\341\345\345\355\346\346\354\323\323\334\271"
+ "\271\304\304\304\316\357\357\361\370\370\370\204\367\367\3679\370\370\370"
+ "\357\357\361\322\322\332\310\310\320\330\330\336\350\350\354\355\355\361"
+ "\350\350\353\336\336\343\333\333\340\343\343\346\360\360\362\370\370\370"
+ "\367\367\370\363\363\364\355\355\360\353\353\355\352\352\354\353\353\355"
+ "\344\344\347\306\315z\373\373\224\375\375\212\375\375\213\375\375\205\370"
+ "\367{\357\357y\352\347u\347\347r\343\350n\337\351k\337\351h\333\351e\330"
+ "\351b\324\351]\321\351[\320\351X\313\352U\310\350T\305\345P\304\340K\300"
+ "\337J\275\333I\273\331D\271\327E\271\325C\265\323@\261\3218\265\317F\264"
+ "\264\267\303\303\311\317\317\325\323\323\332\317\317\326\313\313\322\317"
+ "\317\326\343\343\351\202\367\367\370\30\351\351\355\315\315\326\300\300\312"
+ "\277\277\312\316\316\327\355\355\361\370\370\370\367\367\370\350\350\356"
+ "\327\327\337\325\325\335\336\336\344\360\360\363\370\370\370\363\363\366"
+ "\321\321\332\270\270\303\275\275\307\300\300\312\273\273\306\310\310\321"
+ "\345\345\353\360\357\364\366\366\370\203\370\370\370\22\356\356\362\350\347"
+ "\354\331\331\337\311\311\321\312\312\320\311\311\317\273\273\301\254\254"
+ "\261\245\245\250\227\227\232\200\213\40\222\236%\246\263*\270\307.\306\326"
+ "2\314\3353\317\3404\325\3466\377\333\3557\304\333\3557\23\344\361j\354\365"
+ "\231\262\267\225\203\203\205\230\230\231\253\253\254\273\273\275\313\313"
+ "\314\326\326\330\340\340\342\347\347\350\341\341\345\350\350\353\364\364"
+ "\365\367\367\367\366\366\366\354\354\356\332\332\337\334\334\341\202\351"
+ "\351\354\6\350\350\354\353\353\357\352\352\357\327\327\336\326\326\333\356"
+ "\356\361\203\372\372\372\13\370\370\371\333\333\340\306\306\317\322\322\331"
+ "\343\343\351\350\350\355\345\345\353\327\327\336\300\300\312\317\317\327"
+ "\364\364\365\202\372\372\372\16\371\371\371\372\372\372\371\371\371\317\316"
+ "\327\265\265\300\310\310\323\341\341\350\346\346\355\336\336\346\303\303"
+ "\316\274\273\307\342\342\350\372\372\372\372\372\371\203\371\371\371O\372"
+ "\372\372\371\371\371\337\337\344\312\312\323\325\325\333\346\346\354\356"
+ "\356\363\351\351\355\337\337\344\333\333\340\347\347\353\365\365\367\372"
+ "\372\372\370\370\371\363\363\365\356\356\361\353\353\356\351\351\354\351"
+ "\351\353\345\345\347\330\330\327\217\227h\233\236h\231\235g\240\246e\301"
+ "\307r\356\366\202\375\375|\375\375w\375\375s\352\357n\335\347i\333\350h\333"
+ "\351c\326\351`\321\351]\321\351Z\315\352W\312\351T\307\345P\304\342O\302"
+ "\337L\277\335I\274\334G\272\330E\272\326C\267\324A\265\323?\262\3219\264"
+ "\316F\273\273\273\316\316\321\322\322\330\326\326\333\324\323\332\317\317"
+ "\327\313\313\323\322\322\332\360\360\362\372\372\372\371\371\371\340\340"
+ "\346\306\306\321\300\277\312\301\300\313\331\331\340\366\366\367\372\372"
+ "\372\366\366\370\340\340\350\326\326\336\331\331\340\351\351\357\371\371"
+ "\372\372\372\372\344\344\352\276\276\311\274\274\307\303\303\315\202\300"
+ "\300\312\3\331\331\337\356\356\364\366\366\370\203\372\372\372\22\365\365"
+ "\367\353\353\357\340\340\346\314\314\323\313\313\321\312\312\320\300\300"
+ "\305\255\255\262\242\242\246\230\230\233\203\215!\225\241&\252\270+\274\313"
+ "/\310\3303\317\3374\320\3415\331\3537\377\334\3568\304\334\3568\16\350\363"
+ "}\355\366\232\235\240\217\211\211\213\235\235\236\256\256\257\277\277\300"
+ "\316\316\317\331\331\332\343\343\345\346\346\347\343\343\347\355\355\357"
+ "\370\370\371\202\370\370\370\13\354\354\357\334\334\341\343\343\347\356\356"
+ "\361\354\354\360\352\352\356\356\355\361\350\350\355\325\325\334\336\336"
+ "\344\367\367\370\203\373\373\373\12\365\365\367\322\322\332\307\307\320\330"
+ "\330\337\346\346\355\350\350\356\341\341\347\315\315\326\276\276\311\342"
+ "\342\347\203\373\373\373\15\372\372\372\373\373\373\356\355\361\300\277\311"
+ "\273\273\305\323\323\334\343\342\351\342\342\351\321\321\331\271\271\305"
+ "\324\324\335\370\370\370\373\373\373\203\372\372\372\202\373\373\373B\353"
+ "\353\357\317\317\326\321\321\330\344\344\350\355\355\361\352\352\357\340"
+ "\340\345\336\336\342\351\351\354\367\367\371\373\373\373\371\371\372\362"
+ "\362\365\354\354\356\345\345\346\312\312\315\246\246\250ttvHHIVUYIF[22?1"
+ "0A**8..9<>D_bW\221\227m\303\316h\355\367a\366\375c\344\363g\324\346a\324"
+ "\351^\321\351\\\316\351Y\313\350T\312\347S\306\346R\305\341N\301\340K\276"
+ "\334I\274\332F\270\327D\270\325D\267\322?\267\324?\264\323<\264\315D\274"
+ "\274\274\331\331\332\340\340\343\332\332\337\325\325\333\321\321\330\316"
+ "\315\325\312\312\322\335\335\343\370\370\372\373\373\373\362\362\364\322"
+ "\322\333\303\303\314\300\277\312\306\306\320\346\346\354\202\373\373\373"
+ "\20\356\356\362\331\331\341\326\326\337\341\341\351\366\366\370\373\373\373"
+ "\363\363\366\312\312\323\273\273\305\304\304\316\306\305\317\276\276\311"
+ "\311\311\322\351\351\357\365\365\370\372\372\373\202\373\373\373\22\371\371"
+ "\372\357\357\364\346\346\353\320\320\326\312\312\320\311\311\317\302\302"
+ "\310\257\257\265\237\237\243\227\227\230\205\217\"\230\243'\255\273,\300"
+ "\3160\313\3323\320\3404\322\3425\334\3558\377\335\3568\303\335\3568\34\336"
+ "\356=\353\365\215\347\356\231\214\215\210\216\216\220\240\240\241\262\262"
+ "\264\304\304\304\321\321\322\334\334\335\345\345\347\344\344\347\347\347"
+ "\351\361\361\364\372\372\372\373\373\373\370\370\371\352\352\356\340\340"
+ "\344\351\351\355\360\360\364\354\354\360\355\355\361\360\360\364\343\343"
+ "\350\325\325\334\353\353\357\373\373\374\203\374\374\374\12\355\355\361\314"
+ "\314\324\316\316\326\337\337\346\352\352\357\347\347\355\332\332\341\304"
+ "\303\316\312\312\324\364\364\366\204\374\374\374\14\373\373\374\332\332\341"
+ "\267\266\302\304\304\317\333\333\343\341\341\351\330\330\340\301\301\313"
+ "\303\303\315\357\357\362\374\374\374\374\374\373\203\373\373\373=\374\374"
+ "\374\362\362\365\325\325\335\316\316\326\340\340\346\354\354\361\354\354"
+ "\360\342\342\347\336\336\343\351\351\355\371\371\372\374\374\374\372\372"
+ "\372\361\361\363\333\333\335\241\242\244SST\25\25\26\14\14\14\13\13\13''"
+ "'((4\220\222w\262\263\232\256\260\224\255\256\233\251\252\241\224\224\217"
+ "rqrQQ`klx\203\207\200\244\256e\327\353O\355\375]\325\354^\317\347\\\315\352"
+ "Y\312\351V\307\347T\305\343P\303\340M\302\336K\276\334J\275\333F\271\327"
+ "D\270\325D\265\323?\267\322?\264\324<\262\313C\275\275\275\335\335\335\357"
+ "\357\360\352\352\356\332\332\340\324\323\333\320\317\327\314\314\324\316"
+ "\316\326\351\351\355\202\374\374\374\27\345\345\354\312\312\323\304\304\316"
+ "\300\300\314\320\320\331\362\362\365\374\374\374\371\371\373\346\346\355"
+ "\327\327\340\333\333\343\356\356\363\374\374\374\373\373\373\335\335\344"
+ "\274\274\307\302\301\314\314\314\325\304\304\316\300\300\312\333\333\343"
+ "\363\363\371\371\371\373\203\374\374\374\20\363\363\366\353\352\357\325\325"
+ "\333\310\310\317\310\310\315\306\306\312\263\263\270\236\236\242\222\222"
+ "\226\205\217\"\231\244'\260\275,\302\3211\314\3343\320\3405\324\3456\377"
+ "\335\3568\304\335\3568\16\341\360N\355\366\232\321\331\231\200\200\202\223"
+ "\223\224\245\245\246\265\265\267\307\307\310\324\324\325\337\337\340\346"
+ "\346\350\345\345\350\353\353\356\366\366\367\202\373\373\373\13\367\367\371"
+ "\351\351\355\342\342\347\356\356\361\361\361\365\355\355\361\360\360\363"
+ "\357\357\363\336\336\344\332\332\340\366\366\367\204\375\375\375\11\343\343"
+ "\350\311\311\322\324\324\334\346\346\353\353\353\361\345\345\354\321\321"
+ "\332\300\300\313\335\335\343\203\375\375\375\13\374\374\374\375\375\375\367"
+ "\367\370\307\307\322\272\272\305\315\315\327\336\336\345\335\335\344\312"
+ "\312\324\271\271\305\334\334\343\202\375\375\375\203\374\374\374.\375\375"
+ "\375\374\374\375\337\337\345\314\314\324\331\331\337\351\351\356\355\355"
+ "\361\345\345\351\337\337\344\353\353\357\371\371\373\374\374\374\370\370"
+ "\370\330\330\333\215\214\217**+\1\1\1\5\5\5>>>\213\213\214\211\211\210oo"
+ "qXY\\\310\316o\374\374\200\365\371w\361\370t\350\356\200\330\335\221\275"
+ "\275\256\266\266\270\252\252\252\225\225\232\230\226\243\221\222\213\243"
+ "\262T\342\375N\334\373W\310\345U\310\346Q\304\344Q\304\341P\303\335L\277"
+ "\335J\273\333H\273\332G\202\271\326D(\266\323A\265\322?\264\322<\261\312"
+ "B\274\274\275\336\336\336\363\363\363\373\373\373\352\352\356\327\327\336"
+ "\322\322\331\320\320\327\312\312\323\326\326\336\365\365\367\375\375\375"
+ "\366\366\370\327\327\336\310\310\322\304\304\316\303\303\316\336\336\344"
+ "\372\372\373\375\375\375\363\363\367\337\337\347\330\330\340\346\346\355"
+ "\371\371\373\375\375\375\357\357\363\304\304\317\276\276\311\317\317\330"
+ "\314\314\325\300\300\312\315\315\326\356\356\364\370\370\374\374\374\375"
+ "\202\375\375\375\20\366\366\370\355\355\362\332\332\337\306\306\315\306\306"
+ "\314\310\310\313\267\267\274\240\240\244\217\217\223\205\220\"\234\250'\262"
+ "\300-\304\3221\315\3354\320\3405\326\3466\377\335\3568\304\335\3568\16\343"
+ "\361^\355\366\232\277\305\227\204\204\205\226\226\227\247\247\250\272\272"
+ "\273\311\311\313\327\327\330\340\340\341\346\346\350\346\346\351\356\356"
+ "\361\371\371\371\202\373\373\373\3\367\367\370\347\347\353\346\346\352\202"
+ "\362\362\366\6\356\356\362\361\361\365\355\355\361\332\332\340\341\341\347"
+ "\372\372\373\203\375\375\375\12\373\373\374\333\333\342\311\311\322\332\332"
+ "\341\350\350\356\353\353\361\340\340\347\311\311\323\304\304\316\353\353"
+ "\357\203\375\375\375\14\374\374\374\375\375\375\351\351\356\275\275\310\277"
+ "\277\312\323\323\334\335\335\345\324\324\336\275\275\310\300\300\314\356"
+ "\356\362\375\375\375\204\374\374\374X\375\375\375\362\362\366\320\320\331"
+ "\320\320\330\342\342\347\353\353\357\346\346\353\336\336\344\345\345\351"
+ "\370\370\371\373\373\373\350\350\353\222\222\224%%&\0\0\0\1\1\1ihk\301\300"
+ "\301\311\311\310\250\250\250\231\231\232\234\234\236\247\247\251\305\312"
+ "~\370\370\207\372\372\206\371\371\177\370\370v\356\360l\352\361m\342\351"
+ "\200\312\314\253\275\275\277\271\271\271\264\263\272\246\245\260\213\217"
+ "s\312\344K\340\375P\302\341N\304\342O\304\336M\300\337K\276\334I\274\332"
+ "G\272\327C\270\323C\267\324B\270\325C\266\323@\266\324>\260\310A\273\273"
+ "\274\334\334\335\363\363\363\375\375\375\370\370\372\343\343\350\323\323"
+ "\333\320\320\327\314\314\324\315\315\325\343\343\352\373\373\374\375\375"
+ "\375\345\345\353\313\313\325\310\310\321\304\304\316\312\312\324\356\356"
+ "\362\375\375\375\373\373\374\351\351\357\330\330\341\337\337\347\363\363"
+ "\370\375\375\375\371\371\373\320\320\331\275\275\310\316\316\326\323\323"
+ "\333\305\305\317\304\304\316\345\345\353\367\367\373\373\373\374\202\375"
+ "\375\375\20\371\371\372\357\357\363\336\336\344\307\307\317\304\304\313\307"
+ "\307\313\272\272\277\241\241\247\215\215\221\206\220\"\234\250'\264\303."
+ "\305\3242\317\3374\320\3405\330\3507\377\335\3568\304\335\3568\32\346\362"
+ "n\355\366\232\256\263\225\207\207\211\231\231\233\253\253\254\274\274\276"
+ "\315\315\316\330\330\332\342\342\344\347\347\350\351\351\353\362\362\364"
+ "\371\371\372\373\373\373\374\374\374\365\365\367\346\346\352\351\351\355"
+ "\364\364\367\362\362\365\360\360\363\363\363\367\350\350\355\332\332\341"
+ "\354\354\357\204\375\375\375\12\364\364\367\323\323\333\314\314\324\340\340"
+ "\346\353\353\360\351\351\357\330\330\340\302\302\314\316\316\327\370\370"
+ "\371\202\375\375\375\1\374\374\374\202\375\375\375\12\332\332\341\267\267"
+ "\303\306\306\321\327\327\337\331\331\342\310\310\323\266\266\302\326\326"
+ "\337\373\373\374\375\375\375\203\374\374\374\15\375\375\375\374\374\374\337"
+ "\337\346\314\314\324\331\331\340\350\350\354\347\347\354\337\337\344\341"
+ "\341\346\363\363\365\366\366\366\267\267\27288;\202\0\0\0)665\277\277\300"
+ "\333\333\333\310\310\310\261\261\262\262\262\264\266\266\267\265\265\266"
+ "\244\244\244~\200oZ]TY]Px{d\222\230f\320\326l\362\367c\352\366e\335\352e"
+ "\340\346\220\311\311\306\306\306\307\277\277\301\260\257\271\205\204\205"
+ "\265\307X\343\375N\301\337J\301\335M\277\335J\275\335J\273\331G\271\330E"
+ "\266\323C\267\324B\270\325C\266\323@\266\324=\256\307@\273\273\274\332\332"
+ "\333\361\361\362\202\375\375\375\37\363\363\367\335\335\343\321\321\330\315"
+ "\315\325\312\312\323\322\322\332\361\361\365\375\375\375\364\364\367\327"
+ "\327\336\312\312\324\310\310\323\302\302\315\332\332\342\373\373\374\375"
+ "\375\375\364\364\370\336\336\346\331\331\342\353\353\361\373\373\374\375"
+ "\375\375\337\337\346\277\277\312\311\311\323\330\330\340\315\315\326\301"
+ "\301\314\330\330\340\364\364\371\371\371\374\202\374\374\375\20\372\372\373"
+ "\361\361\365\343\343\350\312\312\322\301\301\310\307\307\312\276\276\302"
+ "\246\246\252\214\214\221\206\221#\236\253(\266\304.\306\3262\316\3374\320"
+ "\3415\331\3527\377\334\3568\304\334\3568\25\347\363|\355\366\232\236\241"
+ "\222\214\214\215\234\234\236\255\255\260\300\300\301\320\320\321\332\332"
+ "\334\343\343\344\346\346\350\352\352\355\366\366\367\373\373\373\374\374"
+ "\374\374\374\375\363\363\366\347\347\354\355\355\361\366\366\371\363\363"
+ "\366\202\362\362\366\3\344\344\351\335\335\343\362\362\365\204\375\375\375"
+ "\11\354\354\360\316\316\326\321\321\331\346\346\354\354\354\362\347\347\355"
+ "\320\320\331\277\277\312\335\335\344\203\375\375\375\14\374\374\374\375\375"
+ "\375\371\371\372\312\312\324\271\271\304\314\314\326\330\330\340\322\322"
+ "\332\276\276\310\276\276\311\354\354\360\375\375\375\204\374\374\374\14\375"
+ "\375\375\363\363\366\322\322\331\321\321\331\340\340\346\347\347\354\337"
+ "\337\345\334\334\342\354\354\357\345\345\350qqt\12\12\12\202\0\0\0#\200\200"
+ "\200\331\331\331\310\310\310\264\264\264\272\272\273\267\267\272\210\210"
+ "\211BBE\34\34\35""88;{y\202\210\210\207zz{WV^aah\207\211\214\221\226{\311"
+ "\325]\371\374h\322\346R\334\350x\330\331\304\323\323\324\316\316\317\256"
+ "\256\263wu}\253\271g\346\375N\274\334A\274\334J\274\331H\273\332H\271\326"
+ "E\267\324C\267\324B\202\266\323B\6\271\326?\254\306@\273\273\274\332\332"
+ "\333\356\356\360\373\373\374\202\375\375\375\6\355\355\361\327\327\336\316"
+ "\316\327\312\312\323\310\310\321\342\342\350\202\374\374\374\26\346\346\355"
+ "\315\315\327\316\316\326\310\310\321\313\313\325\360\360\364\375\375\375"
+ "\373\373\374\347\347\357\330\330\341\342\342\352\370\370\372\375\375\375"
+ "\355\355\362\306\306\320\304\304\316\331\331\341\327\327\337\304\304\317"
+ "\314\314\325\357\357\365\371\371\374\202\374\374\375\20\373\373\373\363\363"
+ "\366\347\347\354\317\317\326\276\276\306\304\304\311\300\300\303\252\252"
+ "\256\216\216\223\206\221\"\237\254(\270\307.\306\3272\316\3364\317\3404\331"
+ "\3537\377\333\3557\304\333\3557\16\351\364\210\354\365\231\220\222\213\217"
+ "\217\220\237\237\240\261\261\262\303\303\304\321\321\323\334\334\335\345"
+ "\345\346\350\350\352\355\355\360\367\367\370\373\373\373\202\374\374\374"
+ "\12\361\361\364\350\350\354\360\360\363\366\366\371\363\363\366\364\364\367"
+ "\362\362\366\340\340\346\341\341\347\370\370\372\204\375\375\375\11\347\347"
+ "\354\314\314\325\326\326\335\351\351\356\354\354\362\343\343\351\312\312"
+ "\323\302\302\315\354\354\360\203\375\375\375\14\374\374\374\375\375\375\354"
+ "\354\360\276\276\312\274\274\307\317\317\331\325\325\337\311\311\323\267"
+ "\267\303\320\320\331\371\371\371\375\375\375\203\374\374\374\202\375\375"
+ "\375\11\345\345\352\314\314\324\330\330\336\343\343\351\342\342\350\332\332"
+ "\340\341\341\346\305\305\310??@\203\0\0\0\16\227\227\230\334\334\334\267"
+ "\267\267\274\274\274\274\274\300xyz\34\34\35\1\1\1\10\10\11mmnc`p\230\233"
+ "w\272\272\263\300\300\300\202\306\306\306M\263\263\263\262\262\271\207\207"
+ "\213\261\270k\367\375k\312\344K\325\347m\334\336\300\327\327\327\326\326"
+ "\327\255\255\257ZVc\255\266q\336\375P\271\331C\274\332I\274\330F\271\326"
+ "D\267\324C\267\325B\266\323B\266\323A\272\327?\253\304>\273\273\274\332\332"
+ "\333\356\356\360\367\367\372\374\374\374\375\375\375\371\371\373\345\345"
+ "\351\321\321\330\313\313\324\307\307\320\325\325\334\366\366\370\375\375"
+ "\375\363\363\366\323\323\334\320\320\330\317\317\330\304\304\320\341\341"
+ "\347\374\374\375\375\375\375\361\361\365\333\333\344\335\335\346\363\363"
+ "\367\375\375\375\367\367\370\320\320\330\301\301\314\332\332\342\340\340"
+ "\347\314\314\325\304\304\316\345\345\353\370\370\375\373\373\375\375\375"
+ "\375\373\373\373\365\365\370\353\353\357\323\323\331\275\275\305\301\301"
+ "\307\302\301\304\256\256\261\221\221\225\207\223\"\242\257)\272\311.\310"
+ "\3303\316\3374\320\3414\377\333\3557\304\333\3557\33\334\356@\353\365\225"
+ "\341\352\231\204\204\204\221\221\223\241\241\243\263\263\264\305\305\306"
+ "\323\323\324\336\336\337\344\344\346\351\351\353\360\360\362\370\370\370"
+ "\373\373\373\374\374\374\373\373\374\360\360\364\351\351\355\362\362\366"
+ "\366\366\371\363\363\367\365\365\370\360\360\364\336\336\344\346\346\353"
+ "\373\373\374\203\375\375\375\4\373\373\374\341\341\350\314\314\325\333\333"
+ "\342\202\353\353\361\4\336\336\345\305\305\317\313\313\325\364\364\366\202"
+ "\375\375\375\6\374\374\374\375\375\374\375\375\375\337\337\345\272\271\304"
+ "\300\300\314\202\321\321\332\3\300\300\314\272\272\306\343\343\350\202\375"
+ "\375\375\203\374\374\374\12\375\375\375\371\371\371\327\327\336\315\315\326"
+ "\334\334\343\343\343\351\335\335\343\333\333\342\237\237\241\25\25\26\202"
+ "\0\0\0/\12\12\13bbb\267\267\266\262\262\262\301\301\301\244\243\250..0\0"
+ "\0\0\1\1\1||}\320\320\320\261\261\262}}~\261\271[\357\365o\344\352\211\322"
+ "\322\310\324\324\326\322\322\324\313\313\314\263\262\266QP`\253\260s\352"
+ "\375d\315\355K\327\353e\302\302\265\330\330\332\332\332\333\256\255\256M"
+ "KW\265\276r\316\361D\271\331G\273\331G\270\327D\267\324C\270\323B\266\323"
+ "B\266\323A\271\330A\251\303>\274\274\274\333\333\334\357\357\360\370\370"
+ "\372\371\371\373\202\375\375\375.\363\363\366\331\331\340\313\313\323\310"
+ "\310\321\313\313\324\353\353\357\375\375\375\371\371\373\335\335\345\320"
+ "\320\331\325\325\337\312\312\324\322\322\333\366\366\370\375\375\375\367"
+ "\367\372\341\341\351\332\332\343\354\354\362\374\374\375\373\373\374\334"
+ "\334\343\277\277\313\327\327\337\345\345\354\325\325\335\302\302\315\333"
+ "\333\342\367\366\372\372\372\375\375\375\375\373\373\373\367\367\370\355"
+ "\355\361\330\330\335\275\275\305\277\276\305\302\302\305\261\261\264\224"
+ "\224\227\207\223!\242\260(\271\313.\307\3311\314\3372\320\3443\377\331\355"
+ "5\304\331\3555\32\335\357J\353\365\230\322\333\231\203\203\204\224\224\225"
+ "\242\242\244\264\264\267\310\310\311\325\325\326\336\336\340\344\344\346"
+ "\352\352\354\361\361\363\371\371\372\373\373\373\374\374\374\372\372\374"
+ "\360\360\363\354\354\360\365\365\370\366\366\371\365\365\371\366\366\372"
+ "\354\354\361\337\337\345\355\355\361\204\375\375\375\12\370\370\371\333\333"
+ "\342\316\316\326\340\340\347\355\355\363\352\352\360\327\327\337\302\302"
+ "\315\332\332\342\373\373\374\202\375\375\375\14\374\374\374\375\375\375\370"
+ "\370\372\320\320\332\267\267\302\305\305\320\321\320\333\314\314\325\271"
+ "\271\305\306\306\320\365\364\370\375\375\375\204\374\374\374k\375\375\375"
+ "\355\355\361\317\317\326\321\321\332\337\337\344\340\340\345\331\331\340"
+ "\343\343\347mmm\4\4\5\0\0\1\0\0\0jjkcbc\261\261\262\306\306\306\220\220\222"
+ "\13\13\13\0\0\0\26\27\30\237\236\237\331\330\331\265\265\266\264\264\265"
+ "\277\277\277\264\272n\371\372}\335\344a\335\347\200\320\320\315\331\331\333"
+ "\333\333\335\322\322\323\237\252p\277\317d\343\375d\364\375[t\2065}}}\324"
+ "\324\325\340\340\342\333\333\335\273\304\177\263\314H\277\340H\271\327F\267"
+ "\326E\271\323D\267\325C\266\323B\266\323C\267\323A\271\327A\246\300=\274"
+ "\274\274\333\333\335\357\357\361\370\370\372\367\367\372\372\372\374\375"
+ "\375\375\373\373\374\347\347\355\317\317\326\311\311\321\307\307\320\337"
+ "\337\346\373\373\374\375\375\375\350\350\356\322\321\333\330\330\340\323"
+ "\323\334\311\311\324\352\352\360\375\375\375\374\374\374\352\352\360\332"
+ "\332\343\347\347\356\372\372\374\375\375\375\351\351\357\301\301\314\323"
+ "\323\334\351\351\360\337\337\347\306\306\320\317\317\330\361\361\366\373"
+ "\373\375\374\374\375\373\373\373\367\367\370\357\357\363\335\335\342\276"
+ "\276\305\273\273\302\301\301\304\263\263\266\227\227\232\207\224\40\242\262"
+ "'\272\312-\307\3310\313\3362\317\3432\377\330\3544\304\330\3544\25\336\357"
+ "U\353\365\230\306\315\227\205\205\207\226\226\227\245\245\247\267\267\271"
+ "\311\311\312\327\327\330\336\336\340\346\346\347\352\352\355\362\362\365"
+ "\371\371\372\373\373\373\374\374\374\371\371\373\356\356\363\355\355\361"
+ "\366\365\371\367\367\372\202\366\366\372\3\351\351\356\341\341\347\364\364"
+ "\366\204\375\375\375\11\365\365\367\327\327\336\321\321\331\344\344\352\355"
+ "\355\363\350\350\356\322\322\332\305\305\317\347\347\353\203\375\375\375"
+ "\12\374\374\374\375\375\375\362\362\365\305\305\320\270\270\304\310\310\322"
+ "\317\317\331\306\306\317\267\267\304\326\326\335\202\375\375\375\203\374"
+ "\374\374\13\375\375\375\374\373\374\340\340\346\313\313\323\326\326\336\335"
+ "\335\344\332\332\341\334\334\342\356\356\361\246\246\246RRS\202\0\0\0_''"
+ "(\247\247\247\277\277\277\327\327\327xxx###\0\0\0...\256\256\257\250\250"
+ "\251\275\275\276\322\322\323\332\332\332\260\266l\367\372v\340\351n\326\343"
+ "_\331\337\222\321\321\323\335\335\330\332\344\207\334\364b\346\375c\366\375"
+ "[x\211833:\246\245\250\322\322\323\342\342\344\335\347\225\314\351N\274\336"
+ "B\275\333I\302\342A\267\324C\266\321D\266\323C\267\324A\265\322@\264\322"
+ "@\271\326@\244\277<\274\274\274\334\334\335\360\360\361\371\371\373\370\370"
+ "\372\367\367\372\374\374\375\375\375\375\364\364\367\330\330\336\312\312"
+ "\323\306\306\317\322\322\333\365\365\370\375\375\375\362\362\366\326\326"
+ "\337\331\331\342\332\332\344\313\313\325\335\335\344\372\372\373\375\375"
+ "\375\362\362\367\335\335\345\342\342\352\367\367\372\375\375\375\361\361"
+ "\364\307\306\321\316\316\330\353\353\361\350\350\357\314\314\326\307\307"
+ "\321\350\350\356\373\373\375\374\374\375\373\373\373\370\370\371\360\360"
+ "\364\340\340\345\300\300\307\272\272\300\300\300\303\266\266\270\232\232"
+ "\236\207\224\40\242\262'\271\313-\306\331/\311\3351\320\3442\377\326\353"
+ "3\304\326\3533\24\336\357^\352\364\227\272\277\226\210\210\211\231\231\232"
+ "\247\247\250\271\271\273\312\312\313\327\327\330\337\337\341\346\346\350"
+ "\354\354\357\364\364\366\372\372\373\373\373\373\374\374\374\370\370\373"
+ "\357\357\363\356\356\362\367\366\371\202\367\367\372\4\366\366\371\350\350"
+ "\355\344\344\351\370\370\371\204\375\375\375\11\363\363\366\324\324\334\323"
+ "\323\333\347\347\355\356\356\363\345\345\354\315\315\326\312\312\324\357"
+ "\357\363\203\375\375\375\14\374\374\374\375\375\375\355\355\360\276\275\311"
+ "\271\271\305\311\310\323\314\314\326\277\277\312\271\271\305\346\345\353"
+ "\375\375\375\375\374\374\203\374\374\374:\375\375\375\367\366\370\326\326"
+ "\335\315\315\325\330\327\337\334\334\342\330\330\337\343\343\350\366\366"
+ "\367\350\350\350rqr\27\26\27\0\0\0\1\1\1\200\200\201\305\305\305\333\333"
+ "\334\257\257\261mnn\0\0\0\2\2\2\200\200\202\263\263\265\323\323\323\350\350"
+ "\350\350\350\351\266\274q\360\372o\334\347h\335\354h\312\341R\325\331\235"
+ "\340\350\177\320\347_\346\375g\346\375Nt\204:!!*\215\215\217\276\276\277"
+ "\323\323\325\336\346\222\272\327F\262\323B\316\356M\310\351@\251\301G\305"
+ "\3515\277\337;\264\320?\263\320A\263\322?\261\317?\266\327?\242\274<\274"
+ "\274\275\334\334\335\360\360\361\202\371\371\3730\367\367\372\371\371\374"
+ "\375\375\375\373\373\373\344\344\352\314\314\325\307\307\317\315\315\326"
+ "\355\355\362\375\375\375\370\370\372\333\333\343\331\331\341\340\340\351"
+ "\320\320\333\322\322\334\364\364\367\375\375\375\367\367\372\342\342\352"
+ "\340\340\350\364\364\370\375\375\375\366\366\370\315\315\327\313\313\325"
+ "\352\352\360\356\356\364\324\324\334\303\303\316\340\341\347\373\373\375"
+ "\374\374\375\372\372\373\370\370\371\361\361\364\343\343\350\303\303\312"
+ "\267\267\276\300\300\302\266\266\270\237\237\240\206\224!\242\264'\272\316"
+ ".\305\3331\310\3362\317\3452\377\324\3533\304\324\3533\23\337\360h\351\364"
+ "\227\254\262\225\212\212\213\231\231\232\250\250\251\272\272\274\313\313"
+ "\315\326\326\330\336\336\340\350\350\352\355\355\360\365\365\367\372\372"
+ "\373\373\373\374\375\375\375\370\370\372\357\357\363\360\360\364\202\367"
+ "\367\372\5\367\367\373\365\365\370\346\346\354\350\350\356\371\371\373\204"
+ "\375\375\375\11\360\360\365\323\323\333\327\327\337\352\352\360\356\356\364"
+ "\343\343\352\311\311\322\322\322\333\371\370\373\202\375\375\375\14\375\374"
+ "\375\374\374\374\375\375\375\345\345\353\271\271\304\274\274\307\312\311"
+ "\325\310\310\321\272\272\306\301\301\314\363\363\364\375\375\375\204\374"
+ "\374\374\5\375\375\375\360\360\363\316\316\326\320\320\327\332\332\340\202"
+ "\331\331\337\5\355\355\361\373\373\373\363\363\363\240\240\240qpq\202\0\0"
+ "\0""4\26\26\27\272\272\273\323\323\325\324\324\326pppRRS\0\0\0\25\25\25\252"
+ "\252\254\327\327\327\353\353\354\350\350\352\276\307|\346\366d\327\350b\327"
+ "\351e\322\350`\317\346U\325\360^\356\375`\266\335+frD21>\220\217\220\274"
+ "\274\274\321\322\307\327\342\200\264\325>\275\333H\333\375M\255\321*U^8\200"
+ "\200\207\224\232r\255\3136\304\352.\270\3329\262\315?\261\317?\266\327>\237"
+ "\271:\274\274\274\334\334\335\360\360\361\371\371\373\372\372\374\370\370"
+ "\372\367\367\372\373\373\374\375\375\375\357\357\363\324\324\333\202\310"
+ "\310\321\1\344\344\351\202\373\373\374%\344\344\351\331\331\341\344\344\353"
+ "\332\332\343\315\315\327\350\350\356\375\375\375\372\372\374\352\352\361"
+ "\340\340\350\361\361\365\375\375\375\373\373\374\326\326\337\310\310\322"
+ "\350\350\357\364\364\371\336\336\346\304\304\316\327\327\337\371\371\374"
+ "\375\375\375\372\372\373\371\371\371\362\362\365\347\347\353\306\306\314"
+ "\266\266\274\277\277\302\270\270\270\241\241\242\206\224\40\242\264&\272"
+ "\317,\303\331.\307\3350\316\344/\377\322\3510\304\322\3510\23\337\357o\350"
+ "\363\226\243\246\222\214\214\215\234\234\235\250\250\252\273\273\275\314"
+ "\314\316\326\326\331\337\337\341\351\351\353\356\356\360\365\365\367\371"
+ "\371\373\373\373\374\374\374\375\367\367\372\357\357\363\361\361\365\202"
+ "\367\367\372\7\367\367\373\363\363\367\346\346\353\355\355\362\373\373\374"
+ "\374\374\375\373\373\375\202\375\375\375\10\355\355\362\323\323\333\332\332"
+ "\342\354\354\362\356\356\363\337\337\346\310\310\322\334\334\342\202\375"
+ "\375\375\203\375\374\375\12\374\374\375\335\335\344\266\266\302\277\277\313"
+ "\312\312\325\304\304\316\270\270\304\314\314\326\370\370\371\375\375\375"
+ "\203\374\374\374\202\374\374\375\14\347\347\354\313\313\323\321\321\331\330"
+ "\330\337\326\326\335\335\335\343\365\365\367\375\375\375\370\370\370\351"
+ "\351\352zz{WWX\202\0\0\0,[Z\\\306\306\310\321\321\323\257\257\260\201\202"
+ "\202'%'\0\0\0BBB\305\305\306\335\335\336\337\337\341\273\306y\342\367^\320"
+ "\346_\322\352_\330\363a\344\375_\321\370;}\226\23x}oljz\250\250\246\300\300"
+ "\301\336\336\271\321\342n\260\324;\313\353P\326\373=\204\241(MPEUT[\232\231"
+ "\233\233\231\240\211\210\212\220\232a\263\3241\266\335,\254\3129\266\326"
+ ">\234\267:\272\272\273\334\334\335\360\360\361\371\371\373\202\372\372\374"
+ "\20\367\367\371\371\371\373\375\375\375\367\367\372\337\337\346\313\313\324"
+ "\310\310\320\333\333\343\370\370\372\375\375\375\352\352\361\332\332\343"
+ "\345\345\355\343\343\354\320\320\332\337\337\345\202\374\374\375\35\361\361"
+ "\365\341\341\351\356\356\363\374\374\375\375\375\375\336\336\344\307\307"
+ "\321\347\347\356\370\370\375\351\351\360\310\310\322\316\316\330\364\364"
+ "\370\375\375\375\372\372\373\371\371\371\363\363\365\351\351\356\311\311"
+ "\317\264\264\273\275\275\301\270\270\270\242\242\243\204\224\37\242\266&"
+ "\271\320+\303\333.\305\335/\315\345.\377\320\351/\304\320\351/\24\340\360"
+ "w\347\363\225\230\233\216\216\216\217\234\234\236\252\252\254\273\273\275"
+ "\314\314\316\325\325\327\337\337\342\351\351\353\357\357\361\364\364\367"
+ "\371\371\373\372\372\374\373\373\375\366\366\371\360\360\364\362\362\365"
+ "\366\366\371\202\367\367\372\20\361\361\365\347\347\354\361\361\365\374\374"
+ "\375\373\373\375\370\370\374\374\374\375\375\374\375\353\353\360\324\324"
+ "\334\334\334\343\355\355\363\355\355\362\334\334\343\311\311\323\342\342"
+ "\351\202\375\375\375\13\375\374\375\374\374\374\374\374\375\373\373\374\325"
+ "\325\336\265\265\302\300\300\313\313\313\324\301\301\314\266\266\302\327"
+ "\327\337\202\374\374\375\203\374\374\374m\374\374\375\373\373\374\337\337"
+ "\345\313\313\324\322\322\332\327\327\336\326\326\334\343\343\350\374\374"
+ "\375\375\375\375\373\373\373\361\361\363\312\312\314}|}334\0\0\0\1\1\2\202"
+ "\203\204\311\311\314\320\320\322\222\222\223\201\200\201+*-\0\0\0""111\267"
+ "\266\274\315\315\317\271\305y\361\373X\342\375V\332\375I\305\3467\224\261"
+ ",v\200U\254\253\267\261\261\271\256\256\257\277\277\274\341\351\216\277\330"
+ "N\265\331=\326\372L\255\320\34fu2__atty\263\263\264\276\276\276\301\301\302"
+ "\252\251\260\216\214\235tr\220\246\256o\275\335;\262\3238\231\2638\271\271"
+ "\271\334\334\335\360\360\361\371\371\373\372\372\374\373\373\375\370\370"
+ "\372\367\367\371\374\374\375\373\373\374\352\352\357\320\320\330\307\307"
+ "\321\327\327\336\363\363\370\375\375\375\361\361\366\333\333\344\346\346"
+ "\356\351\351\361\326\326\337\332\332\342\371\371\373\375\375\375\365\365"
+ "\370\343\343\353\353\353\362\373\373\375\375\375\375\342\342\350\307\307"
+ "\321\344\344\354\371\371\375\360\360\365\315\315\326\312\312\323\360\360"
+ "\363\375\375\375\372\372\373\370\370\371\363\363\365\353\353\357\312\312"
+ "\321\262\262\272\274\274\301\267\267\267\243\243\243\203\223\36\242\266%"
+ "\270\316+\302\332,\303\333-\314\344,\377\316\347-\304\316\347-'\340\357}"
+ "\346\362\224\223\225\214\217\217\220\236\236\237\252\252\254\274\274\276"
+ "\314\314\316\326\326\330\340\340\343\352\352\355\357\357\361\364\364\367"
+ "\370\370\372\371\371\373\372\372\375\366\366\371\360\360\364\362\362\366"
+ "\365\365\371\366\366\372\367\367\372\360\360\364\350\350\355\365\365\367"
+ "\375\375\375\370\370\373\366\366\373\372\372\375\374\374\375\351\351\356"
+ "\325\325\335\337\337\346\356\356\364\354\354\362\330\330\340\312\312\324"
+ "\351\351\356\375\375\375\202\374\374\375\13\374\374\374\375\375\375\372\372"
+ "\373\322\322\333\266\266\303\301\301\314\310\310\322\276\276\312\270\270"
+ "\305\341\341\346\375\375\375\204\374\374\374\10\375\375\375\372\372\373\332"
+ "\332\341\314\314\324\324\324\334\326\326\335\330\330\336\352\352\356\202"
+ "\375\375\375c\374\375\375\367\367\367\355\355\356\255\255\256\203\203\204"
+ "\32\32\32\0\0\0\6\6\6\237\237\242\307\307\312\320\320\320\207\207\207ccd"
+ "LLM\0\0\0\14\14\15jjo\214\216\200\200\213Y\222\235e\236\252}\244\247\241"
+ "\261\257\277\306\305\312\260\260\255\257\257\261\325\330\227\323\344f\265"
+ "\325B\310\355H\302\345-t\216\12rwb\201\200\207\227\227\232\266\266\267\312"
+ "\312\314\333\333\333\335\335\337\326\326\330\313\313\315\274\277\216\273"
+ "\310o\257\3166\263\3206\225\2606\267\267\271\334\334\335\360\360\361\370"
+ "\370\372\372\372\373\374\374\375\372\372\374\367\367\372\372\372\374\374"
+ "\374\375\361\361\365\327\327\336\311\311\322\323\323\333\360\360\364\375"
+ "\375\375\365\365\367\336\336\347\346\346\356\355\355\363\335\335\346\327"
+ "\327\341\363\363\367\375\375\375\370\370\373\347\347\357\352\352\361\372"
+ "\372\374\375\375\375\347\347\354\310\310\322\342\342\352\372\372\375\365"
+ "\365\371\324\324\335\310\310\322\354\354\360\375\375\375\372\372\373\370"
+ "\370\371\363\363\365\354\354\357\315\315\323\262\262\272\273\273\277\267"
+ "\267\267\243\243\243\201\222\35\241\266%\270\317*\301\332+\303\333,\312\344"
+ ",\377\314\346,\304\314\346,'\340\357\201\345\362\224\215\216\210\220\220"
+ "\221\236\236\240\252\252\254\273\273\276\312\312\315\324\324\327\340\340"
+ "\343\354\354\356\357\357\362\363\363\366\367\367\371\370\370\373\371\371"
+ "\374\365\365\371\361\361\365\362\362\366\365\365\370\366\366\372\366\366"
+ "\371\356\356\363\352\352\357\366\366\371\374\374\375\365\365\371\364\364"
+ "\370\371\371\374\374\374\375\350\350\355\326\326\335\341\341\350\357\357"
+ "\365\352\352\360\325\325\336\316\316\327\360\360\365\375\375\375\202\374"
+ "\374\375\13\374\374\374\375\375\375\371\371\372\316\316\327\267\267\303\304"
+ "\304\315\307\307\322\273\273\306\274\274\310\350\350\354\375\375\375\204"
+ "\374\374\374\10\375\375\375\371\371\372\326\326\335\315\315\325\323\323\333"
+ "\325\325\334\333\333\342\362\362\365\202\375\375\375c\374\374\375\371\371"
+ "\373\365\365\366\353\353\353\236\236\236\201\201\201\37\37\37\0\0\0\7\7\7"
+ "\231\231\233\314\314\316\324\324\324\235\235\235\207\207\207\200\200\201"
+ ",,+\24\24\26cbl}|\200\213\211\221\262\257\264\305\305\256\265\265\251\266"
+ "\266\250\320\325\207\322\342^\274\332G\273\340;\300\345-\203\243\6mz?\236"
+ "\236\240\250\247\260\264\264\264\301\301\302\317\317\320\337\337\340\354"
+ "\354\355\355\355\356\350\350\307\335\346v\275\3318\244\307#\247\3044\265"
+ "\3228\222\2532\266\266\267\333\333\334\360\360\361\370\370\372\371\371\373"
+ "\374\374\375\373\373\375\367\367\372\371\371\373\373\373\375\367\367\372"
+ "\340\340\346\313\313\325\322\322\333\354\354\361\375\375\375\367\367\371"
+ "\344\344\353\346\346\356\357\357\364\343\343\353\330\330\340\357\357\363"
+ "\375\375\375\373\373\374\354\354\362\352\352\361\371\371\373\375\375\375"
+ "\353\353\360\312\312\324\341\341\351\372\372\374\371\371\374\333\333\344"
+ "\307\307\321\347\347\355\375\375\375\373\373\373\370\370\371\364\364\365"
+ "\356\356\360\321\321\326\262\262\272\272\272\276\267\267\267\243\243\243"
+ "\200\221\35\242\271%\266\320)\277\331*\300\332+\310\344+\377\311\345+\304"
+ "\311\345+'\340\360\206\343\361\223\210\211\205\221\221\222\236\236\240\253"
+ "\253\255\273\273\276\312\312\315\324\324\327\340\340\343\354\354\356\356"
+ "\356\361\363\363\366\366\366\371\367\367\372\371\371\373\365\365\370\362"
+ "\362\365\362\362\366\364\364\367\365\365\371\365\365\370\356\356\362\354"
+ "\354\361\370\370\372\373\373\374\363\363\367\362\362\366\370\370\373\374"
+ "\374\375\351\351\356\327\327\337\343\343\352\357\357\365\351\351\357\324"
+ "\324\334\322\322\333\366\366\370\375\375\375\202\374\374\375\13\374\374\374"
+ "\375\375\375\370\370\372\314\314\325\271\271\304\304\304\317\307\307\321"
+ "\271\271\306\301\301\315\357\357\362\375\375\375\204\374\374\374\10\375\375"
+ "\375\365\365\370\323\323\333\316\316\326\324\323\333\326\326\334\340\340"
+ "\345\370\370\371\202\375\375\3751\374\374\375\373\373\374\372\372\372\365"
+ "\365\365\347\347\347\230\230\231sst;;=\0\0\0\3\3\3qqr\310\307\310\322\322"
+ "\322\306\306\307\254\254\254\212\212\212^^d\231\240d\304\311\217\304\310"
+ "\225\311\315\226\324\334w\321\341V\305\334J\270\330:\262\332.\253\320\33"
+ "\213\251\27s\200>\236\237\234\304\301\317\260\257\263\270\270\271\315\315"
+ "\316\335\335\335\343\343\344\347\347\351\354\354\306\334\344}\273\320G\236"
+ "\275-\236\276,\250\3044\247\3035\257\3214\215\2460\265\265\267\333\333\333"
+ "\360\360\362\202\370\370\372\202\374\374\375.\371\370\374\367\367\371\373"
+ "\373\374\371\371\374\347\347\354\321\321\331\322\322\333\352\352\357\375"
+ "\375\375\370\370\373\350\350\356\350\350\357\357\357\365\350\350\360\332"
+ "\332\343\354\354\361\375\375\375\374\374\375\357\357\365\352\352\362\371"
+ "\371\373\375\375\375\357\357\364\315\315\326\340\340\350\372\372\374\374"
+ "\374\375\343\343\352\311\311\322\342\342\351\374\375\375\373\373\373\370"
+ "\370\371\365\365\365\357\357\361\322\322\330\262\262\271\272\272\275\267"
+ "\267\267\243\243\243\200\221\34\241\271$\270\322)\277\332+\300\333+\307\344"
+ "*\377\310\345*\304\310\345*\24\341\360\213\343\361\223\203\204\202\222\222"
+ "\224\237\237\241\252\252\255\274\274\276\312\312\315\323\323\327\342\342"
+ "\345\354\354\356\356\356\361\364\364\366\365\365\370\367\367\371\370\370"
+ "\373\365\365\370\363\363\366\362\362\366\363\363\367\202\364\364\367\202"
+ "\356\356\363\2\371\371\373\372\372\374\202\360\360\365\13\367\367\372\374"
+ "\374\375\351\351\356\331\331\340\344\344\352\360\360\365\350\350\356\323"
+ "\323\334\325\325\335\367\367\371\375\375\375\202\374\374\375\13\374\374\374"
+ "\375\375\375\370\370\371\313\313\325\272\272\306\306\306\317\305\305\321"
+ "\272\272\305\307\307\322\365\365\370\375\375\375\204\374\374\374\10\375\375"
+ "\375\362\362\365\323\323\332\320\320\327\324\324\333\326\326\335\344\344"
+ "\351\371\371\372\202\375\375\375\11\374\374\375\373\373\374\374\374\375\373"
+ "\373\373\364\364\364\341\341\342\224\224\224cddYY[\202\0\0\0\36../\232\232"
+ "\234\304\304\305\305\305\307\276\276\300\257\257\260\251\267[\316\354=\301"
+ "\337=\271\3324\262\3260\252\320)\242\310\40\232\270,\217\241D\221\231s\252"
+ "\252\255\305\305\320\272\272\275\261\261\264\277\277\300\316\316\317\337"
+ "\337\340\352\354\334\345\351\246\325\340m\265\315C\233\275+\231\275'\244"
+ "\3021\202\244\3023\6\243\3020\256\3154\211\243.\265\265\266\332\332\333\361"
+ "\361\362\202\370\370\372/\374\373\374\374\374\375\372\372\374\367\367\371"
+ "\371\371\374\373\373\375\353\353\360\324\324\335\324\323\334\350\350\356"
+ "\374\374\375\371\371\373\352\352\361\352\352\360\360\360\365\354\354\363"
+ "\336\336\346\353\353\360\375\375\375\374\374\375\361\361\366\353\353\362"
+ "\370\370\372\375\375\375\362\362\366\320\320\331\340\340\350\372\372\374"
+ "\375\375\375\351\351\356\313\313\325\337\337\346\373\374\375\373\373\373"
+ "\370\370\371\365\365\365\360\360\361\324\324\330\263\263\272\272\272\276"
+ "\267\267\267\243\243\243\177\220\33\242\271$\266\321(\274\330*\277\334+\377"
+ "\305\343)\305\305\343)\32\340\357\215\341\360\222\201\201\201\222\222\224"
+ "\240\240\241\253\253\255\274\274\276\310\310\313\322\322\326\341\341\344"
+ "\353\353\355\355\355\360\363\363\366\365\365\367\366\366\371\367\367\372"
+ "\364\364\367\363\363\367\362\362\366\362\362\365\363\363\367\362\362\366"
+ "\356\356\362\357\357\364\372\372\374\367\367\373\202\355\355\362\13\365\365"
+ "\370\374\374\375\352\352\357\332\332\342\345\345\354\360\360\365\347\347"
+ "\355\323\323\334\332\332\341\370\370\372\375\375\375\202\374\374\375\13\374"
+ "\374\374\375\375\375\370\367\371\313\313\325\274\273\307\306\306\321\306"
+ "\305\320\273\273\306\316\316\327\372\372\374\375\375\375\204\374\374\374"
+ "\10\375\375\375\361\361\365\323\323\332\321\321\330\324\324\334\327\327\336"
+ "\347\347\354\372\372\374\202\375\375\375\203\374\374\375\10\375\375\375\372"
+ "\372\372\357\357\357\332\332\334\255\255\257rrsxxz/.0\202\0\0\0""8++,jjk"
+ "\244\244\247\267\270\271\226\236s\207\230E\213\235O\220\240Y\223\237c\244"
+ "\253\210\252\256\245\265\266\274\302\277\317\310\307\321\273\273\272\274"
+ "\274\274\304\304\304\312\312\313\325\325\305\335\342\237\327\341v\277\322"
+ "K\251\3055\227\271'\230\272&\243\3011\245\3023\244\3022\244\3000\244\301"
+ "0\243\2760\256\3142\207\237,\265\265\266\332\332\333\361\361\362\370\370"
+ "\372\367\367\371\373\373\374\374\374\375\373\373\374\366\366\371\367\367"
+ "\373\372\372\375\360\360\364\331\331\341\325\325\335\351\351\356\374\374"
+ "\375\372\372\373\355\355\363\353\353\362\357\357\366\356\356\364\342\342"
+ "\352\352\352\357\202\374\374\375\33\363\363\371\354\354\363\370\370\372\375"
+ "\375\375\364\364\370\322\322\334\341\341\351\372\372\374\375\375\375\356"
+ "\356\363\316\316\330\333\333\343\372\372\374\372\372\373\370\370\371\365"
+ "\365\365\360\360\361\325\325\331\263\263\273\273\273\277\267\267\267\242"
+ "\242\243~\220\32\241\271\"\265\321&\274\331)\275\333)\377\303\342&\305\303"
+ "\342&\20\337\357\216\340\360\221\200\200\200\222\222\224\241\241\242\252"
+ "\253\255\273\273\276\307\307\312\321\321\325\341\341\344\353\354\356\354"
+ "\354\357\362\362\365\363\363\366\365\365\370\366\366\371\202\364\364\367"
+ "\25\362\362\365\360\360\364\361\361\365\362\362\366\356\356\363\361\361\365"
+ "\372\372\374\365\365\370\353\353\360\353\352\360\363\363\367\374\374\375"
+ "\353\353\360\334\334\343\346\346\354\360\360\365\346\346\355\324\324\334"
+ "\336\336\345\372\372\373\375\375\375\202\374\374\375\11\374\374\374\375\375"
+ "\375\370\370\371\316\316\326\274\274\311\307\307\322\306\306\317\274\274"
+ "\307\322\322\332\202\374\374\375\204\374\374\374\10\375\375\375\361\361\364"
+ "\323\323\333\322\322\331\325\325\334\331\331\337\353\353\357\374\374\374"
+ "\202\375\375\375\203\374\374\375\202\375\375\375!\366\366\367\350\350\353"
+ "\335\335\337\316\316\320\236\236\237\227\230\227\177}\177BBD\3\3\3\2\2\3"
+ "\7\7\7//0nj|}|\206\215\214\230\236\235\252\256\254\274\277\277\276\303\303"
+ "\270\274\274\267\267\267\270\272\272\273\303\305\275\322\325\247\333\342"
+ "\214\317\334f\274\316I\247\3022\227\270&\224\264$\233\272)\241\275-\241\275"
+ "/\204\240\275.\7\237\275.\240\274.\256\314/\205\234+\266\266\266\332\332"
+ "\333\361\361\362\202\367\367\371\16\374\373\374\374\374\375\373\373\375\367"
+ "\367\372\366\366\371\371\371\374\363\363\370\336\336\345\330\330\337\351"
+ "\351\357\373\373\375\372\372\374\357\357\364\356\356\364\202\356\356\365"
+ "\40\346\346\356\350\350\357\373\372\374\374\374\375\365\365\372\356\356\365"
+ "\370\370\372\375\375\375\365\365\370\325\325\336\343\343\353\372\372\374"
+ "\375\375\375\361\361\366\322\322\333\332\332\342\372\372\373\372\373\373"
+ "\370\370\371\364\364\365\360\360\361\326\326\331\263\263\273\273\273\277"
+ "\267\267\267\242\242\243|\216\31\236\271!\263\321%\272\330(\274\332)\300"
+ "\340%\377\300\340$\304\300\340$\12\336\356\217\337\357\220\177\177\200\223"
+ "\223\224\240\240\242\252\251\254\272\272\275\306\306\311\321\321\324\342"
+ "\342\344\202\353\353\356\33\362\362\365\363\363\366\365\365\370\365\365\371"
+ "\363\363\367\364\364\370\362\362\366\357\357\364\360\360\364\360\360\365"
+ "\357\357\363\362\362\366\372\372\374\364\364\367\350\350\356\351\351\356"
+ "\362\362\366\374\374\375\355\355\362\335\335\344\346\346\354\360\357\365"
+ "\346\346\354\325\325\335\340\340\347\372\372\374\375\375\375\202\374\374"
+ "\375\11\374\374\374\375\375\375\371\371\372\320\320\330\276\276\311\307\307"
+ "\321\305\305\317\274\274\311\325\325\334\202\374\374\375\204\374\374\374"
+ "\10\375\375\375\362\362\365\325\325\334\323\323\333\327\327\335\331\331\340"
+ "\356\356\361\374\374\375\202\375\375\375\202\374\374\375\203\375\375\375"
+ "\37\370\370\371\356\356\361\352\352\354\342\342\345\335\335\335\313\313\313"
+ "\260\260\260\227\227\230\177\177\177jjkQQP32=\215\217y\270\270\270\266\265"
+ "\267\264\264\262\271\273\261\303\303\257\316\320\245\322\327\220\317\331"
+ "r\313\330V\274\320E\253\3026\232\270(\223\262\40\217\262\37\230\265'\237"
+ "\272*\237\274.\236\271-\203\236\273,\203\237\273,\7\237\273+\236\271-\253"
+ "\312.\202\231*\265\265\267\332\332\333\361\361\362\202\367\367\371\1\374"
+ "\373\374\202\373\373\375\15\367\367\372\365\365\370\371\371\374\365\365\371"
+ "\341\341\350\334\334\342\354\354\361\373\373\375\372\372\373\361\361\365"
+ "\357\357\365\356\356\365\355\355\364\202\350\350\360\36\372\372\374\374\374"
+ "\375\366\366\373\360\360\366\370\370\373\375\375\375\364\364\370\326\326"
+ "\337\346\346\355\373\373\375\375\375\375\363\363\367\325\325\336\332\332"
+ "\341\372\372\373\373\373\373\370\370\371\364\364\365\360\360\361\325\325"
+ "\331\264\264\274\274\274\300\267\267\267\242\242\243{\217\32\235\271#\262"
+ "\321'\272\331*\272\332+\276\340&\377\276\340%\304\276\340%\32\335\356\220"
+ "\336\357\220\177\177\200\222\222\223\237\237\241\251\251\254\271\271\273"
+ "\305\305\310\320\320\324\342\342\344\352\352\354\353\353\356\361\361\364"
+ "\363\363\366\364\364\367\365\365\370\362\362\366\365\365\370\362\362\365"
+ "\357\357\362\357\357\363\360\357\364\357\357\364\362\362\366\372\372\374"
+ "\363\363\366\202\347\347\354\13\360\360\364\374\373\375\356\356\363\337\337"
+ "\346\346\346\354\357\357\364\345\345\354\326\326\336\342\342\351\372\372"
+ "\374\375\375\375\202\374\374\375\11\374\374\374\375\375\375\371\371\372\323"
+ "\323\332\300\300\312\310\310\321\305\305\320\276\276\313\327\327\336\202"
+ "\374\374\375\204\374\374\374\10\375\375\375\363\363\367\330\327\336\325\325"
+ "\333\330\330\337\333\333\341\357\357\362\374\374\375\202\375\375\375\2\374"
+ "\375\375\374\374\375\203\375\375\375^\370\370\371\360\360\362\357\357\361"
+ "\354\354\356\356\356\357\351\351\351\335\335\335\316\316\317\261\261\262"
+ "\215\215\214yxzont\247\260V\310\332G\300\322H\272\317?\265\3127\261\3068"
+ "\242\2740\230\266&\224\263#\214\255\36\214\256\36\220\262!\226\265'\233\267"
+ "(\233\267*\232\271)\233\267(\234\271)\236\271+\235\270,\235\272,\234\267"
+ "+\236\271-\235\272,\234\272,\236\272-\235\270-\252\311.\201\230+\266\266"
+ "\267\333\333\334\361\361\362\366\366\370\367\367\371\374\374\374\373\373"
+ "\374\374\374\375\367\367\372\365\365\367\370\370\373\366\366\372\345\345"
+ "\352\337\337\346\355\355\363\373\372\375\372\372\374\362\362\367\360\360"
+ "\366\356\355\363\356\356\364\352\352\362\352\352\361\372\372\373\374\374"
+ "\375\367\367\373\362\362\367\371\371\373\375\375\375\364\364\370\331\331"
+ "\341\351\351\357\373\373\375\375\375\375\364\364\371\326\326\340\332\332"
+ "\341\372\372\373\373\373\373\370\370\371\364\364\365\360\360\361\325\325"
+ "\331\264\264\274\276\276\301\267\267\267\242\242\243{\217\32\233\270#\260"
+ "\321(\267\331*\271\333+\275\337&\377\274\337$\304\274\337$\16\334\356\215"
+ "\335\356\220\200\200\200\221\221\223\237\237\240\250\250\252\270\270\272"
+ "\303\303\307\317\317\323\341\341\343\350\350\353\351\351\354\360\360\363"
+ "\362\362\365\202\364\364\367\3\362\362\365\365\365\370\362\362\365\202\355"
+ "\355\361\5\357\357\363\360\360\364\363\363\367\371\371\374\361\361\364\202"
+ "\345\345\353\12\355\355\362\373\373\375\360\360\364\340\340\347\346\346\354"
+ "\356\356\364\345\345\354\327\327\337\345\345\353\373\373\374\203\374\374"
+ "\375\11\374\374\374\375\375\375\372\371\373\326\326\335\303\303\315\310\310"
+ "\322\307\306\320\302\302\314\333\333\341\202\374\374\375\204\374\374\374"
+ "\7\375\375\375\366\366\370\332\332\340\327\327\335\332\332\340\335\335\342"
+ "\361\361\363\210\375\375\375\30\371\371\372\361\361\363\357\357\362\360\360"
+ "\362\366\366\367\367\367\367\362\362\362\346\346\347\333\333\334\322\322"
+ "\324\313\313\314\307\307\310\241\256[\200\246\5\200\242\13\204\245\17\206"
+ "\251\21\210\250\22\216\256\26\223\262\33\225\264\35\230\265\40\232\266!\231"
+ "\267\40\202\232\271\"\40\232\270!\231\271#\232\273$\234\272#\233\274%\235"
+ "\276%\241\300)\243\302+\246\306.\252\3100\254\3121\254\3113\254\3122\273"
+ "\3333\203\233+\267\267\270\333\333\334\360\360\361\366\366\367\367\367\371"
+ "\374\374\374\373\373\374\374\374\375\370\370\372\363\363\367\367\367\372"
+ "\370\370\373\350\350\356\344\344\351\361\361\365\373\373\375\371\371\373"
+ "\202\362\362\367\2\353\353\362\355\355\363\202\354\354\363\14\371\371\373"
+ "\374\374\375\370\370\373\364\364\371\371\371\374\375\375\375\364\364\370"
+ "\333\333\344\353\353\361\373\373\375\375\375\375\366\366\372\202\332\332"
+ "\342\20\372\372\373\373\373\373\370\370\371\364\364\365\360\360\361\325\325"
+ "\331\266\266\275\300\300\302\267\267\267\242\242\243{\220\33\233\267#\262"
+ "\322(\272\332+\273\334+\275\337&\377\274\337#\304\274\337#\15\333\355\212"
+ "\335\356\217\200\200\200\221\221\222\237\237\241\247\247\251\264\264\266"
+ "\301\301\304\316\316\321\341\341\343\346\346\351\347\347\352\357\357\362"
+ "\202\362\362\365#\364\364\367\361\361\364\365\365\370\362\362\366\354\354"
+ "\360\353\353\360\356\356\363\361\361\365\363\363\367\370\370\373\357\357"
+ "\364\344\344\352\343\343\351\352\352\360\372\372\374\362\362\366\342\342"
+ "\351\346\346\354\355\355\363\345\345\353\331\331\341\347\347\355\373\373"
+ "\374\372\372\375\373\373\375\374\374\375\374\374\374\374\374\375\372\372"
+ "\373\332\332\341\304\304\316\311\311\323\307\307\321\304\304\316\334\334"
+ "\343\202\374\374\375\204\374\374\374\7\375\375\375\370\370\372\336\336\344"
+ "\330\330\336\333\333\341\336\336\344\361\361\364\210\375\375\375\17\372\372"
+ "\373\362\362\364\357\357\362\360\360\362\370\370\371\375\375\375\373\373"
+ "\373\366\366\367\356\356\357\350\350\351\343\343\344\336\336\337\251\264"
+ "i\225\263\14\226\262\31\202\224\262\26M\222\262\27\222\260\25\222\257\23"
+ "\220\257\23\220\256\21\214\257\20\220\260\22\215\254\17\214\254\16\213\252"
+ "\17\216\254\17\216\256\17\215\256\16\216\256\17\213\253\14\207\250\11\203"
+ "\242\7\201\240\4~\234\4}\233\4{\231\4{\230\4\203\245\3o\202\40\271\271\271"
+ "\334\334\335\357\357\360\365\365\366\370\370\371\374\374\374\373\373\374"
+ "\374\374\375\367\367\371\363\363\366\367\367\372\370\370\373\354\354\360"
+ "\350\350\355\363\363\367\372\372\375\367\367\372\363\363\367\362\362\367"
+ "\352\352\361\354\354\362\356\356\365\356\356\364\372\372\373\374\374\375"
+ "\371\370\374\365\365\372\372\372\374\375\375\375\363\363\367\335\335\345"
+ "\356\356\363\373\373\375\375\375\375\367\367\372\334\334\344\333\333\343"
+ "\372\372\373\373\373\373\370\370\371\364\364\365\357\357\361\323\323\330"
+ "\270\270\277\302\302\306\267\267\267\242\242\243{\220\35\232\266%\261\320"
+ "*\271\332+\273\334-\274\337'\377\273\337$\304\273\337$\15\332\355\207\334"
+ "\356\220\203\204\202\217\217\220\237\237\241\250\250\252\263\263\266\277"
+ "\277\301\314\314\317\337\337\342\346\346\351\346\346\352\357\357\362\202"
+ "\362\362\365\20\363\363\367\360\360\364\364\364\370\362\362\366\353\353\360"
+ "\352\352\357\355\355\362\361\361\365\363\363\367\367\367\373\356\356\363"
+ "\342\342\351\342\342\350\350\350\356\370\370\373\364\364\370\202\345\345"
+ "\353\21\354\354\362\345\345\354\332\332\342\350\350\356\373\373\374\370\370"
+ "\374\372\372\374\375\375\375\374\374\374\374\374\375\373\373\374\336\337"
+ "\345\306\306\320\311\311\323\310\310\322\306\306\317\335\335\344\202\374"
+ "\374\375\204\374\374\374\10\375\375\375\373\373\373\342\342\347\331\331\337"
+ "\335\335\342\340\337\345\361\361\364\374\374\375\207\375\375\375\5\373\373"
+ "\374\363\363\365\357\357\362\360\360\362\367\367\371\202\375\375\375\6\373"
+ "\373\373\365\365\367\364\364\365\361\361\362\352\352\354\230\231\215\202"
+ "\217\220\200\202\216\220\200=\214\217\177\214\217~\213\217~\213\217}\214"
+ "\220~\217\224\200\222\226\201\225\232\204\230\234\206\235\241\213\243\247"
+ "\220\246\253\224\250\254\226\247\253\226\244\250\222\240\244\216\234\240"
+ "\212\230\235\210\226\232\207\225\231\207\224\231\211\226\232\212\230\234"
+ "\214\235\241\223\301\301\303\341\341\341\360\360\362\364\364\366\370\370"
+ "\372\374\374\374\373\373\374\374\374\375\367\367\371\362\362\366\367\367"
+ "\372\371\371\374\356\356\363\355\355\361\366\366\372\371\371\374\366\366"
+ "\372\364\364\371\361\361\366\350\350\357\353\353\361\357\356\365\357\357"
+ "\366\372\372\374\374\374\374\371\371\374\367\367\374\372\372\374\374\374"
+ "\375\362\362\365\340\340\350\360\360\366\373\373\375\375\375\375\366\366"
+ "\372\336\336\344\336\335\345\202\372\372\373\16\370\370\371\364\364\365\357"
+ "\357\360\321\321\327\272\272\301\304\304\307\270\270\270\242\242\243|\220"
+ "\35\231\265%\262\320+\272\333-\274\335/\274\340(\377\273\337$\304\273\337"
+ "$*\330\354\202\334\356\220\205\206\201\216\216\220\236\236\237\246\246\250"
+ "\261\261\264\275\275\300\313\313\316\336\336\341\345\345\347\344\344\350"
+ "\355\355\361\361\361\364\362\362\365\363\363\367\357\357\363\364\364\370"
+ "\363\363\367\353\353\357\351\351\356\354\354\361\362\362\366\363\363\366"
+ "\366\366\372\356\356\363\341\341\350\341\341\347\346\346\354\367\367\372"
+ "\365\365\372\347\347\355\345\345\353\353\353\361\346\346\354\334\334\344"
+ "\350\351\356\372\372\374\366\366\373\372\372\374\375\375\375\374\374\374"
+ "\202\374\374\375\2\346\346\354\312\312\323\202\311\311\323\2\307\307\321"
+ "\337\337\344\202\374\374\375\204\374\374\374\10\375\375\375\373\373\373\346"
+ "\346\353\333\333\341\336\336\343\341\341\346\360\360\362\374\374\374\207"
+ "\375\375\375\25\374\374\374\365\365\366\357\357\362\360\360\362\366\366\367"
+ "\374\374\375\375\375\375\374\374\374\367\367\371\366\366\370\366\366\367"
+ "\360\360\362\350\350\351\327\327\327\307\307\307\275\275\276\270\270\271"
+ "\265\265\267\266\266\267\271\271\272\273\273\274\202\274\274\274G\272\272"
+ "\274\270\270\271\267\267\270\270\270\271\273\273\274\275\275\275\273\273"
+ "\274\265\265\266\264\264\266\272\272\273\274\274\275\273\273\274\266\266"
+ "\267\265\265\266\272\272\273\274\274\275\273\273\274\301\301\302\322\322"
+ "\322\350\350\351\361\361\363\363\363\366\372\372\373\374\374\374\373\373"
+ "\374\374\374\375\365\365\370\362\362\365\367\367\372\371\371\374\361\361"
+ "\364\361\361\365\370\370\373\367\367\373\364\364\371\365\365\372\360\360"
+ "\365\345\345\354\352\352\361\361\360\367\362\362\370\372\372\374\374\374"
+ "\374\371\371\374\370\370\374\373\373\374\374\374\375\360\360\364\342\342"
+ "\352\362\362\370\371\371\375\374\374\375\366\366\372\336\336\345\340\340"
+ "\347\372\372\374\372\372\373\370\370\371\365\365\365\356\356\360\317\317"
+ "\325\273\273\302\307\307\311\271\271\271\242\242\243}\221\35\233\265$\261"
+ "\320*\274\334-\275\336/\276\340(\377\274\337\"\304\274\337\"\26\327\353}"
+ "\335\356\217\210\212\203\213\213\215\235\235\236\245\245\247\257\257\262"
+ "\273\273\277\312\312\314\335\335\337\345\345\346\342\342\345\355\355\360"
+ "\361\361\364\361\361\365\362\362\366\356\356\362\363\363\366\364\364\367"
+ "\353\353\357\350\350\355\354\354\360\202\362\362\366\21\365\365\371\356\356"
+ "\363\341\341\347\337\337\346\343\343\351\364\364\370\367\367\373\351\351"
+ "\357\345\345\354\353\353\360\346\346\354\336\335\345\351\351\357\372\372"
+ "\374\364\364\372\370\370\373\375\375\375\202\373\373\374\7\375\375\375\355"
+ "\355\363\317\317\330\313\313\324\313\313\323\311\311\323\336\336\345\202"
+ "\374\374\375\204\374\374\374\10\374\374\375\374\374\374\355\355\361\335\335"
+ "\343\337\337\344\342\342\346\356\356\362\374\374\374\210\375\375\375\21\370"
+ "\370\371\361\361\363\357\357\362\363\363\366\373\373\374\375\375\375\374"
+ "\374\375\371\371\372\366\366\370\367\367\371\364\364\365\356\356\360\351"
+ "\351\352\343\343\343\337\337\337\334\334\335\331\331\332\202\326\326\330"
+ "\1\327\327\330\204\327\327\331\25\331\331\332\334\334\334\336\336\336\335"
+ "\335\335\327\327\331\323\323\324\327\327\331\334\334\335\335\335\336\332"
+ "\332\332\323\323\325\326\326\330\334\334\335\335\335\336\332\332\333\335"
+ "\335\336\347\347\350\361\361\362\362\362\364\364\364\366\373\373\373\203"
+ "\373\373\374\21\364\364\367\362\362\365\370\370\372\371\371\374\363\363\366"
+ "\365\365\370\371\371\373\365\365\371\363\363\367\366\366\373\356\356\364"
+ "\344\344\352\353\353\361\361\362\370\363\363\370\373\373\374\374\374\374"
+ "\202\371\371\374\32\373\373\374\374\374\375\357\357\362\346\346\354\363\363"
+ "\370\367\367\374\372\372\375\364\364\371\337\337\345\343\343\352\373\373"
+ "\375\372\372\373\370\370\371\365\365\365\356\356\357\315\315\324\276\276"
+ "\305\310\310\311\271\271\271\242\242\243\177\222\36\232\265&\261\320,\273"
+ "\334/\276\3371\277\341*\377\275\340\"\304\275\340\"\15\325\353v\335\357\217"
+ "\214\217\205\211\211\212\234\234\235\243\243\246\255\255\260\271\271\274"
+ "\306\306\312\332\332\334\344\344\346\342\342\345\354\354\357\202\361\361"
+ "\364\7\362\362\366\356\356\362\361\361\365\364\364\370\353\353\360\350\350"
+ "\354\353\353\360\202\362\362\366\34\364\364\370\356\356\363\340\340\347\337"
+ "\337\345\341\341\347\361\361\365\370\370\373\354\354\361\346\346\354\352"
+ "\352\360\347\347\355\337\337\347\351\351\356\372\372\374\364\364\370\365"
+ "\365\372\374\374\375\374\374\374\372\372\374\374\374\375\363\363\366\325"
+ "\325\335\315\315\325\314\314\325\313\313\324\335\335\344\372\372\374\374"
+ "\374\375\205\374\374\374\7\375\375\375\364\364\366\341\341\346\341\341\345"
+ "\343\343\347\355\355\360\373\373\374\210\375\375\375\5\373\373\373\363\363"
+ "\364\357\357\362\362\362\364\372\372\373\202\375\375\375\1\373\373\374\202"
+ "\367\367\371\4\366\366\367\362\362\364\361\361\363\364\364\364\202\363\363"
+ "\363\11\362\362\362\360\360\361\355\355\357\354\354\356\354\354\355\354\354"
+ "\356\356\355\357\360\360\361\362\362\362\202\363\363\363\23\356\356\357\347"
+ "\347\351\350\350\352\357\357\360\363\363\363\361\361\362\353\353\354\347"
+ "\347\350\355\355\356\363\363\363\362\362\362\356\356\360\362\362\363\366"
+ "\366\367\367\367\370\362\362\364\365\365\367\373\373\374\372\372\373\202"
+ "\373\373\374\5\364\364\366\363\363\365\371\371\372\372\372\374\364\364\367"
+ "\202\370\370\373\12\364\364\370\363\363\367\367\367\373\353\353\360\342\342"
+ "\351\354\354\362\363\363\371\364\364\370\373\373\375\373\373\374\202\372"
+ "\372\374\32\374\374\374\374\374\375\356\356\362\350\350\357\363\363\370\364"
+ "\364\372\367\367\375\363\363\370\340\340\346\347\347\355\374\374\375\372"
+ "\372\373\370\370\371\365\365\365\354\354\356\313\313\322\302\302\310\311"
+ "\311\312\271\271\271\243\243\244\177\222\40\231\263'\261\317.\275\3341\300"
+ "\3403\301\341,\377\276\340#\304\276\340#\15\324\352o\336\357\217\220\224"
+ "\210\206\206\210\231\231\233\243\243\245\253\253\256\270\270\273\306\306"
+ "\310\331\331\334\343\343\345\341\341\345\353\353\356\202\361\361\364\7\364"
+ "\364\367\355\355\361\360\360\364\365\365\371\355\355\361\347\347\354\352"
+ "\352\357\202\362\362\366\20\363\363\367\356\356\362\337\340\346\336\336\345"
+ "\337\337\346\356\356\363\370\370\373\356\356\363\347\347\355\351\351\357"
+ "\350\350\356\340\340\347\350\350\356\372\372\374\362\362\367\363\363\370"
+ "\202\374\374\375\12\371\371\374\372\372\374\366\366\370\333\333\342\317\317"
+ "\330\316\316\327\314\314\327\333\333\342\370\370\372\375\375\375\205\374"
+ "\374\374\7\375\375\375\370\370\371\345\345\352\342\342\347\344\344\351\354"
+ "\354\357\372\372\373\210\375\375\375\17\374\374\374\366\366\370\360\360\362"
+ "\360\360\363\370\370\371\374\374\375\375\375\375\374\374\374\371\371\372"
+ "\367\367\371\370\370\372\367\367\370\366\366\367\370\370\372\374\374\374"
+ "\203\375\375\375\202\374\374\374\202\373\373\374\1\374\374\374\202\375\375"
+ "\375\31\374\374\374\370\370\371\362\362\363\362\362\364\370\370\371\374\374"
+ "\374\374\374\375\367\367\371\361\361\363\362\362\364\372\372\373\375\375"
+ "\375\373\373\374\371\371\372\373\373\374\374\374\375\367\367\370\362\362"
+ "\364\370\370\371\374\374\374\371\371\373\373\373\374\372\372\373\362\362"
+ "\364\364\364\366\202\372\372\374\11\367\367\371\371\371\374\367\367\373\361"
+ "\361\366\363\363\367\366\366\371\347\347\355\341\341\350\355\355\363\202"
+ "\365\365\371\2\373\373\375\373\373\374\202\372\372\374\32\374\374\374\373"
+ "\373\375\356\356\363\354\354\362\362\361\366\363\363\370\365\365\373\361"
+ "\361\367\340\340\347\353\353\360\375\375\375\372\372\373\370\370\371\365"
+ "\365\365\354\354\356\312\312\320\307\307\314\313\313\313\271\271\271\244"
+ "\244\245\177\222\40\227\260'\257\314,\275\3330\300\3372\300\341-\377\276"
+ "\340!\304\276\340!\20\321\351d\336\357\216\224\231\211\204\204\205\230\230"
+ "\231\242\242\245\252\252\255\267\267\272\304\304\307\330\330\333\341\341"
+ "\344\340\340\344\353\353\356\361\361\364\360\360\364\363\363\366\202\355"
+ "\355\361\4\365\365\371\356\356\362\346\346\353\351\351\356\202\362\362\366"
+ "\10\361\361\366\356\356\363\340\340\346\336\336\344\335\335\344\351\351\357"
+ "\367\367\373\360\360\366\202\351\351\357\10\351\350\357\342\342\351\350\350"
+ "\357\372\372\374\362\362\366\361\361\365\374\374\375\375\375\375\202\371"
+ "\371\373\10\371\371\372\344\344\351\321\321\332\317\317\327\317\317\330\331"
+ "\331\340\364\364\367\375\375\375\205\374\374\374\3\375\375\375\373\373\374"
+ "\354\354\360\202\345\345\351\2\353\353\357\367\367\371\211\375\375\375\5"
+ "\373\373\373\363\363\365\360\360\362\364\364\366\373\373\374\202\375\375"
+ "\375\1\373\373\374\202\370\370\372\6\371\371\372\370\370\371\366\366\367"
+ "\367\367\370\372\372\373\374\374\374\206\375\375\375\16\374\374\374\372\372"
+ "\373\365\365\367\361\361\363\362\362\364\370\370\372\374\374\375\375\375"
+ "\375\372\372\373\362\362\364\360\360\362\366\366\370\374\374\375\375\375"
+ "\375\202\373\373\374\31\375\375\375\373\373\374\364\364\365\362\362\365\373"
+ "\373\373\373\373\374\371\371\373\374\374\374\370\370\372\362\362\364\365"
+ "\365\367\374\374\374\372\372\374\371\371\374\373\373\374\365\365\370\360"
+ "\360\364\366\366\371\364\364\367\344\344\352\342\342\350\357\357\364\365"
+ "\365\372\365\365\371\373\373\375\203\372\372\374\3\374\374\375\371\371\373"
+ "\356\356\363\202\356\356\364\25\360\360\365\362\362\370\357\357\365\340\340"
+ "\350\356\356\363\375\375\375\372\372\373\370\370\371\365\365\365\350\350"
+ "\354\311\311\320\314\314\321\313\313\313\271\271\272\244\244\245~\221\40"
+ "\226\256'\256\312.\273\3301\300\3374\300\3400\377\275\337\"\304\275\337\""
+ "4\316\347[\335\356\217\232\240\211\200\200\202\224\224\225\240\240\243\252"
+ "\252\255\265\265\270\302\302\306\326\326\331\342\342\344\340\340\344\352"
+ "\352\355\357\357\363\360\360\363\363\363\366\356\356\362\353\353\357\364"
+ "\364\370\360\360\364\347\347\353\350\350\355\361\361\365\362\362\366\360"
+ "\360\364\356\356\363\340\340\346\336\336\345\335\335\344\345\345\353\365"
+ "\365\372\362\362\367\353\353\361\352\351\357\352\352\357\344\344\353\350"
+ "\350\356\371\371\374\362\362\366\356\356\364\373\373\374\375\375\375\371"
+ "\371\373\366\366\372\372\372\374\354\354\361\326\326\335\321\321\331\320"
+ "\320\331\330\330\337\362\362\365\375\375\375\205\374\374\374\202\375\375"
+ "\375\5\364\364\367\347\347\354\347\347\352\352\352\356\365\365\367\212\375"
+ "\375\375\4\370\370\371\361\361\363\361\361\364\370\370\371\203\375\375\375"
+ "\12\373\373\373\370\370\371\371\371\372\372\372\373\370\370\372\366\366\370"
+ "\365\365\367\366\366\370\370\370\372\372\372\372\202\372\372\373,\371\371"
+ "\372\370\370\371\365\365\367\362\362\364\361\361\364\364\364\366\371\371"
+ "\372\374\374\375\375\375\375\373\373\374\364\364\366\360\360\362\363\363"
+ "\365\373\373\374\375\375\375\374\374\375\373\373\374\374\374\375\375\375"
+ "\375\370\370\371\361\361\364\365\365\367\374\374\374\371\371\373\372\372"
+ "\373\373\373\374\366\366\370\362\362\364\370\370\371\375\375\375\373\373"
+ "\374\373\373\375\371\371\374\362\362\366\357\357\363\367\367\373\357\357"
+ "\363\342\342\347\343\343\352\364\364\370\365\365\372\365\365\371\370\370"
+ "\375\371\371\374\202\372\372\374\32\374\374\375\370\370\371\356\356\363\356"
+ "\356\364\353\353\362\354\354\362\361\361\366\356\356\363\343\343\352\362"
+ "\362\366\375\375\375\372\372\373\370\370\371\365\365\365\344\344\350\312"
+ "\312\320\322\322\325\314\314\314\271\271\272\244\244\245}\221\40\223\255"
+ "'\252\307-\271\3302\277\3403\277\3402\377\273\337!\304\273\337!\24\311\345"
+ "P\334\356\216\243\252\215\200\200\200\223\223\224\240\240\242\251\251\254"
+ "\264\264\267\300\300\304\324\324\327\341\341\343\337\337\343\351\351\354"
+ "\361\361\364\360\360\363\362\362\366\357\357\363\351\351\356\363\363\367"
+ "\361\361\365\202\347\347\354\2\361\361\365\362\362\366\202\357\357\363\4"
+ "\341\341\347\336\336\345\335\335\344\342\342\350\202\363\363\370\24\355\355"
+ "\362\352\352\357\352\352\360\346\346\355\350\350\356\367\367\373\362\362"
+ "\366\353\353\362\371\371\374\375\375\375\372\372\374\364\364\371\372\372"
+ "\374\363\363\365\333\333\343\323\323\333\322\322\332\327\327\336\361\361"
+ "\363\375\375\375\205\374\374\374\202\375\375\375\7\367\367\370\347\347\353"
+ "\342\342\345\345\345\351\360\360\362\371\371\372\371\371\371\202\366\366"
+ "\366\1\371\371\371\202\372\372\372&\371\371\371\367\367\367\365\365\365\363"
+ "\363\364\356\356\360\354\354\357\361\361\363\367\367\370\367\367\367\366"
+ "\366\366\365\365\366\363\363\365\364\364\365\366\366\370\367\367\370\363"
+ "\363\365\361\361\362\356\356\360\355\355\360\357\357\361\360\360\362\361"
+ "\361\362\356\356\360\353\353\356\352\352\354\354\354\356\357\357\360\362"
+ "\362\363\364\364\364\366\366\366\366\366\367\362\362\364\357\357\361\362"
+ "\362\364\371\371\372\375\375\375\373\373\373\370\370\370\202\366\366\366"
+ "\25\363\363\364\355\355\357\354\354\356\367\367\370\372\372\373\371\371\372"
+ "\373\373\374\372\372\373\363\363\365\362\362\363\366\366\370\372\372\372"
+ "\372\372\373\373\373\374\367\367\371\357\357\363\361\361\364\367\367\372"
+ "\352\352\356\340\340\346\345\345\353\202\365\365\372\3\364\363\371\370\370"
+ "\374\371\371\374\202\372\372\374\33\374\374\375\366\366\371\357\357\364\355"
+ "\355\362\351\351\356\351\351\360\357\357\364\354\354\362\345\345\353\366"
+ "\366\371\375\375\375\372\372\373\370\370\371\365\365\365\340\340\345\313"
+ "\313\322\325\325\327\314\314\314\271\271\272\245\245\245|\220!\220\252'\247"
+ "\305-\265\3262\274\3353\275\3374\271\335\"\377\270\335\40\303\270\335\40"
+ "\33\303\342D\333\355\216\255\265\217||}\216\216\221\237\237\242\251\251\253"
+ "\264\264\267\300\300\303\323\323\326\341\341\343\335\335\341\347\347\352"
+ "\361\361\364\360\360\363\362\362\365\361\361\364\350\350\355\361\361\364"
+ "\363\363\367\351\351\356\347\347\354\360\360\364\363\362\367\355\355\362"
+ "\357\357\364\342\342\350\202\336\336\344\26\336\336\345\360\360\365\364\364"
+ "\371\356\356\363\353\353\361\352\352\360\347\347\356\350\350\356\364\364"
+ "\370\365\365\370\351\351\360\367\367\371\375\375\375\373\373\374\364\364"
+ "\371\370\370\372\371\371\373\343\343\352\325\325\335\324\324\334\327\327"
+ "\336\353\353\361\202\374\374\375\205\374\374\374P\371\371\371\303\303\305"
+ "kkl\237\237\241\331\331\334\343\343\346\313\313\314vvxhhj\325\325\327\354"
+ "\354\354\363\363\363\243\243\244\200\200\201yy{\200\200\200\205\205\207\246"
+ "\246\250\344\344\346\317\317\321\205\205\210~}\177xxz||~\276\276\277\353"
+ "\353\355\330\330\331\222\222\224{{}yy{{{~\222\222\224\330\330\331\354\354"
+ "\355\242\241\243\202\202\206vuycceyy{\202\202\205rrt\200\200\201\246\246"
+ "\251\323\323\324\343\343\345\352\352\355\366\366\367\373\373\374\374\374"
+ "\374\266\266\267\212\212\214\200\200\200wwzxx{\241\241\242\346\346\347\364"
+ "\364\365\367\367\371\371\371\373\374\374\374\366\366\370\360\360\362\260"
+ "\260\262\225\226\231\355\355\355\365\365\365\370\370\370\363\363\366\354"
+ "\354\361\364\364\367\365\365\370\345\345\352\337\337\345\352\352\357\367"
+ "\367\372\362\362\367\363\363\371\367\367\373\370\370\374\371\371\374\202"
+ "\372\372\374\32\363\363\370\360\360\365\351\351\357\345\345\353\350\350\356"
+ "\356\356\364\353\353\361\350\350\356\371\371\374\374\374\375\372\372\373"
+ "\370\370\371\365\365\366\334\334\341\320\320\327\330\330\332\314\314\315"
+ "\271\271\272\245\245\245y\216!\214\246&\242\301-\261\3241\271\3343\272\336"
+ "4\265\335#\377\264\334\37\303\264\334\37)\273\3376\331\355\215\271\304\223"
+ "zz{\214\214\216\240\240\241\251\251\253\261\261\266\277\277\302\322\322\325"
+ "\341\341\342\337\337\342\345\345\351\361\361\364\360\360\364\361\361\364"
+ "\362\362\366\350\350\355\355\355\362\364\364\370\353\353\360\347\347\355"
+ "\357\357\363\363\363\367\354\354\361\357\357\364\344\344\352\336\336\344"
+ "\337\337\345\335\335\343\353\353\361\364\364\371\357\357\364\354\354\362"
+ "\353\353\360\351\351\357\351\351\356\362\362\366\367\367\373\350\350\357"
+ "\363\363\367\202\375\375\375\12\365\365\371\363\363\370\373\373\375\353\353"
+ "\360\332\332\341\326\326\336\327\327\336\347\347\354\372\372\374\375\375"
+ "\375\204\374\374\374;\367\367\367\247\247\252//0\1\1\1""889\250\251\253\234"
+ "\234\237AAB\200\200\200\2\2\2NNP\267\267\267\346\346\346sssyyy\13\13\13\11"
+ "\11\12\236\234\235\222\221\221\333\333\334\252\252\252bbb]^]\5\5\5\207\211"
+ "\211\244\243\243\341\341\342\275\275\275kkkCCD\1\1\1\215\215\216\273\273"
+ "\272\277\277\277\347\347\347vvv\223\224\223\36\36\36\5\5\5\305\306\306\262"
+ "\262\262rrqRRR&&&../\242\242\244\340\340\341\361\361\361\371\371\371\372"
+ "\371\372}}|\231\231\230\27\27\30\5\5\5\267\267\266\252\252\252\335\335\336"
+ "\356\356\357\364\364\365\202\372\372\373\7\362\362\365\355\355\360aaa\"#"
+ "\"\277\277\300\350\350\350\360\360\362\202\355\355\361\11\367\367\371\357"
+ "\357\363\341\341\347\340\340\347\356\356\363\367\367\372\360\360\364\362"
+ "\362\370\366\366\373\202\370\370\374\12\371\371\374\370\370\373\363\363\367"
+ "\357\357\364\344\344\353\342\342\351\345\345\353\354\354\363\353\353\361"
+ "\356\356\362\202\374\374\375\20\372\372\373\370\370\371\363\363\364\332\332"
+ "\340\327\327\333\332\332\334\314\314\315\271\271\272\245\245\245v\213\40"
+ "\207\242%\235\274+\254\316/\264\3301\267\3343\262\332$\377\260\331\35\303"
+ "\260\331\35)\263\333'\325\352\210\306\324\225{{|\211\211\213\235\235\240"
+ "\250\250\252\263\263\265\276\276\301\321\321\323\340\340\342\335\335\341"
+ "\343\343\347\361\361\364\361\361\365\362\362\365\363\363\367\351\351\356"
+ "\353\353\357\365\365\370\356\356\362\350\350\355\356\356\362\364\364\370"
+ "\354\354\361\356\356\363\346\346\353\336\336\344\340\340\347\334\334\343"
+ "\346\346\354\363\363\370\360\360\365\355\355\363\354\354\361\352\352\360"
+ "\351\351\357\361\361\365\370\370\375\351\351\357\360\360\365\202\375\375"
+ "\375\12\367\367\372\361\361\365\373\373\374\364\364\367\337\337\347\330\330"
+ "\337\330\330\340\343\343\351\371\371\372\375\375\375\203\374\374\374\15\372"
+ "\372\372\230\230\232223\345\345\346\0\0\0\234\234\235\227\227\230\37\37\40"
+ "\336\336\336\313\313\314\4\4\4OOP\230\230\230\202\331\331\331B\250\250\250"
+ "RRS\4\4\5\247\247\252\277\277\277\325\325\326\336\336\337\261\261\261HHI"
+ "688\307\307\307\305\305\305\334\334\334\346\346\346\274\274\274TTU\6\6\6"
+ "\240\240\240\310\310\310\317\317\320\342\342\343\320\320\320\275\275\275"
+ "667\33\33\34\310\310\311\274\274\274\243\243\244\203\203\203}}{DDD\13\13"
+ "\14\225\224\227\336\336\336\360\357\360\367\366\367\336\335\336\245\245\246"
+ "\"\"#\25\25\25\311\311\311\301\301\301\332\332\332\353\353\354\364\364\366"
+ "\374\374\374\367\367\370\357\356\361\272\272\274[[]\5\5\5}}~\327\327\330"
+ "\345\345\347\350\350\354\357\357\363\370\370\373\351\351\356\340\340\345"
+ "\342\342\350\363\363\366\365\365\370\356\356\362\362\362\370\367\367\373"
+ "\370\370\374\202\367\367\374\6\365\365\372\363\363\370\354\354\361\340\340"
+ "\347\341\341\350\344\344\351\202\354\354\362\1\361\361\365\202\374\374\375"
+ "\20\372\372\373\371\371\371\357\357\361\331\331\340\334\334\337\333\333\334"
+ "\314\314\315\272\272\273\245\245\245r\211\36\203\241$\230\272*\247\316.\257"
+ "\3270\262\3331\257\332&\377\253\330\33\304\253\330\33\27\315\347z\317\342"
+ "\225\205\210\201\206\206\210\232\232\234\250\250\253\262\262\265\275\275"
+ "\300\320\320\322\340\340\342\337\337\342\342\342\345\360\360\363\362\362"
+ "\365\361\361\364\364\364\367\354\354\360\350\350\354\364\364\367\361\361"
+ "\365\350\350\355\355\355\362\364\364\370\202\354\354\361\33\350\350\355\336"
+ "\336\345\341\341\347\335\335\344\341\341\347\360\360\366\360\360\365\356"
+ "\356\364\355\355\363\353\353\361\353\353\360\357\357\364\370\370\373\352"
+ "\352\360\353\353\361\373\373\375\375\375\375\372\372\374\360\360\365\366"
+ "\366\370\371\371\373\346\346\354\332\332\342\331\331\340\341\341\347\365"
+ "\365\371\375\375\375\202\374\374\374T\373\373\373\315\315\315OOQ\352\352"
+ "\352\203\203\203\1\1\2\300\300\303\26\26\27\237\237\236\267\267\270mmn\2"
+ "\2\2\220\220\221\304\304\305\323\323\323\345\345\345\342\342\342sst\11\11"
+ "\11hhk\275\275\275\326\326\326\346\346\347\302\302\303!!!\233\233\233\266"
+ "\266\267\313\313\313\341\341\341\356\356\356\350\350\350YYZ\15\15\16|||\273"
+ "\273\275\321\321\323\344\344\345\347\347\351\313\313\315@@A\40\40!\256\256"
+ "\257\267\267\271\306\306\307\313\313\314\250\250\250kllDCE\24\24\25\260\260"
+ "\260\343\342\343\361\360\361\361\361\361\244\244\245445\33\33\33\250\250"
+ "\252\305\305\306\335\335\336\356\356\360\370\370\372\372\372\373\362\362"
+ "\364\355\355\360~}~zz}\\\\^--,\274\274\275\327\327\332\345\345\347\363\364"
+ "\367\364\364\367\345\345\351\340\340\345\347\347\354\367\367\372\361\361"
+ "\364\354\354\361\362\362\367\367\367\373\370\370\374\366\366\373\366\366"
+ "\372\202\363\363\370\7\345\345\354\335\335\344\336\336\345\343\343\351\355"
+ "\355\363\356\356\364\365\365\370\202\374\374\375\20\372\372\373\371\371\371"
+ "\353\353\356\333\333\341\337\337\344\333\333\334\314\314\315\271\271\272"
+ "\245\245\245o\207\36\200\234\"\222\265(\242\311-\253\324/\256\3270\253\330"
+ "'\377\246\325\31\304\246\325\31\30\304\343g\321\345\223\221\223\206\203\203"
+ "\205\231\231\232\250\250\252\261\261\264\274\274\277\315\315\320\337\337"
+ "\341\340\340\344\341\341\345\357\357\361\363\363\366\360\360\364\364\364"
+ "\367\357\357\363\346\346\353\360\360\364\363\363\367\353\353\360\354\354"
+ "\361\364\364\370\356\356\362\202\352\352\357\6\337\336\345\342\341\350\340"
+ "\340\346\335\335\344\354\354\362\360\360\365\202\356\356\364\22\354\354\363"
+ "\353\353\361\356\356\362\366\366\371\356\356\364\345\345\354\370\370\372"
+ "\375\375\375\374\374\374\361\361\366\357\357\364\372\372\373\357\357\364"
+ "\340\340\346\333\333\342\337\337\345\357\357\364\374\374\375\202\374\374"
+ "\374]\373\373\373\323\323\323\265\265\265\325\325\325\15\15\15TRUHHKnnm\224"
+ "\224\224\241\241\243\31\31\31\36\36\40\216\216\215\267\267\267\326\326\326"
+ "\353\353\353\356\356\356\247\247\247444\31\31\32\276\276\277\327\327\327"
+ "\350\350\350||}++,\305\305\305\277\277\301\326\326\327\355\354\355\367\367"
+ "\367\357\357\357^^`\14\14\14\200\200\200\306\306\307\336\336\337\356\356"
+ "\357\361\361\362\310\310\311DDD\40\40!\262\262\264\312\312\312\335\335\336"
+ "\347\347\347\340\340\340\231\231\231\203\203\204\6\6\7iik\324\323\324\353"
+ "\353\353\362\362\362\237\237\240;;;\32\32\32\245\245\246\314\314\315\343"
+ "\343\345\365\365\366\373\373\374\365\365\367\356\356\360\325\325\327__`Z"
+ "ZZ\206\206\207\14\14\14\213\213\214\311\311\314\341\342\345\366\366\370\356"
+ "\356\362\342\342\350\340\340\346\356\356\362\367\367\372\352\352\360\354"
+ "\354\361\363\363\370\367\367\374\366\366\373\365\365\370\363\363\367\363"
+ "\363\370\361\361\366\337\337\346\332\332\342\334\334\344\342\342\351\356"
+ "\356\364\360\360\364\371\371\373\202\374\374\375\20\372\372\373\370\370\371"
+ "\346\346\353\340\340\345\341\341\346\332\332\334\314\314\315\271\271\271"
+ "\245\245\245l\206\36|\232\"\216\262(\236\307,\247\322.\253\3260\252\327*"
+ "\377\243\324\30\304\243\324\30)\273\337W\320\350\217\234\243\214\201\201"
+ "\202\226\226\231\250\250\251\262\262\264\274\274\276\312\312\316\337\337"
+ "\340\342\342\344\337\337\343\356\356\361\363\363\366\361\361\364\364\364"
+ "\367\362\362\366\346\346\353\354\354\360\365\365\370\356\356\362\354\354"
+ "\361\364\364\370\357\357\364\350\350\355\354\354\361\340\340\347\341\341"
+ "\350\343\343\352\335\335\343\346\346\354\360\360\365\356\356\363\357\357"
+ "\364\356\356\363\354\354\362\355\355\362\364\363\370\363\362\367\343\343"
+ "\352\364\364\370\202\375\375\375\2\367\367\372\354\354\362\202\367\367\372"
+ "\1\345\345\353\202\336\336\345a\353\353\357\372\372\374\374\374\375\374\374"
+ "\374\373\373\373\365\365\365\337\337\337\214\214\215\11\11\12__b^^_xxx\250"
+ "\250\251nmo\3\3\3}}\177\214\214\214\303\303\303\337\337\337\362\362\362\367"
+ "\367\367\351\351\351eff\5\5\5\216\216\217\322\322\322\331\331\331557\201"
+ "\201\201\302\302\303\316\316\317\343\343\344\364\364\365\373\373\374\364"
+ "\364\364]]]\13\13\14\204\204\205\316\316\316\347\347\347\367\367\367\372"
+ "\372\373\323\323\324FFG\37\37\40\266\266\266\323\323\323\353\353\353\366"
+ "\366\366\363\362\363\345\344\345wvw\25\25\26<<=\305\305\305\342\342\342\354"
+ "\354\355\245\245\247<<>\30\30\30\250\250\250\317\317\320\350\350\351\371"
+ "\371\371\367\367\371\356\356\361\356\356\360\223\223\223hgj\241\242\243\210"
+ "\210\211''(NNP\273\273\276\340\341\342\360\360\362\347\347\354\341\341\346"
+ "\344\344\351\364\364\370\362\362\366\350\350\355\355\355\361\364\364\370"
+ "\367\367\373\364\364\370\362\362\366\360\360\364\366\366\372\353\353\357"
+ "\331\331\341\331\331\340\333\333\342\344\344\353\360\360\366\363\363\367"
+ "\372\372\374\202\374\374\375\21\372\372\373\366\366\367\343\343\350\345\345"
+ "\351\342\342\346\331\331\334\313\313\313\271\271\271\245\245\245i\203\35"
+ "x\226!\210\254&\231\302*\244\320.\250\325/\250\325.\240\322\30\377\240\322"
+ "\27\303\240\322\27!\262\332D\317\350\211\252\263\221\200\200\200\223\223"
+ "\225\247\247\250\261\261\264\274\274\277\312\312\314\333\333\336\342\342"
+ "\344\335\335\342\355\355\360\364\364\367\361\361\365\363\363\367\364\364"
+ "\367\350\350\354\350\350\355\365\365\370\361\361\365\354\354\361\363\363"
+ "\367\361\361\365\347\347\355\354\354\361\342\342\350\341\341\347\346\346"
+ "\354\336\336\345\341\341\347\356\356\364\355\355\363\202\357\357\365b\355"
+ "\355\363\356\356\363\361\361\365\365\364\370\343\343\352\356\356\364\374"
+ "\374\375\375\375\375\372\372\374\355\355\363\361\361\366\373\373\374\356"
+ "\356\363\342\342\351\337\337\345\347\346\354\367\367\371\374\374\375\374"
+ "\374\374\373\373\373\370\370\370\342\342\342;;<\35\35\36QQT{{{\236\237\237"
+ "\246\246\247\32\32\32**,\177\177\177\262\262\262\317\317\317\351\351\351"
+ "\367\367\367\373\373\373\363\363\363\210\207\210\22\23\22DDE\306\306\306"
+ "\252\253\253&&&\270\270\270\311\311\311\332\332\332\356\356\356\371\371\372"
+ "\374\374\375\361\361\362ZZ[\13\13\13\216\216\216\317\317\317\350\350\350"
+ "\370\370\370\374\374\374\327\327\327GGH\36\36\37\265\264\265\323\323\324"
+ "\354\354\355\371\371\372\372\372\373\360\360\361~~\177\36\36\37+++\270\271"
+ "\271\330\330\331\342\342\345\254\254\255AAB\25\25\26\244\244\245\317\317"
+ "\320\353\353\354\366\366\367\360\360\362\355\355\360\354\354\356ggg\15\15"
+ "\15YY\\OOQ\16\16\17\17\17\20\243\243\244\331\331\333\345\345\347\342\342"
+ "\346\342\342\350\352\352\357\367\367\371\353\353\360\346\346\354\356\356"
+ "\363\202\365\365\371\14\362\361\366\356\356\364\360\360\364\363\363\370\340"
+ "\340\350\325\325\336\327\327\337\332\332\341\346\346\355\362\362\367\365"
+ "\365\372\373\373\375\202\374\374\375\21\372\372\373\363\363\366\343\343\351"
+ "\347\347\353\340\340\345\327\327\332\313\313\313\271\271\272\244\244\245"
+ "g\201\35u\224!\205\252%\225\276*\240\314-\245\324.\246\325/\237\322\33\377"
+ "\235\321\26\303\235\321\26*\250\3260\315\347\211\271\306\227||\177\216\216"
+ "\221\244\244\245\261\261\263\272\272\274\310\310\312\331\331\334\342\342"
+ "\344\335\335\342\351\351\354\363\363\366\361\361\364\361\361\365\365\365"
+ "\370\354\354\360\345\345\352\361\361\365\363\363\366\355\355\361\361\361"
+ "\365\362\362\366\346\346\354\352\352\357\346\346\353\340\340\346\347\347"
+ "\355\342\342\350\334\334\343\353\353\360\355\355\363\356\356\363\360\360"
+ "\366\357\357\365\356\356\363\357\357\364\364\364\371\347\347\355\346\346"
+ "\354\372\372\373\202\375\375\375\11\365\365\370\353\353\361\371\370\373\365"
+ "\365\371\350\350\356\341\341\350\345\345\352\361\361\365\373\373\374\202"
+ "\374\374\374[\372\372\372\257\260\260\16\16\16\0\0\0\202\202\203\200\200"
+ "\200\270\270\270lmo\3\3\3kkk\234\234\235\275\275\277\333\333\333\360\360"
+ "\360\373\373\373\375\375\375\367\367\367\307\307\307QQR\17\17\20\252\253"
+ "\253YY[bcc\305\305\305\317\317\317\343\343\343\365\365\365\374\374\374\374"
+ "\374\375\361\361\362YYY\13\13\13\220\220\221\317\317\317\350\350\350\370"
+ "\370\370\374\374\374\327\327\327HHI\36\36\37\265\266\267\323\323\324\354"
+ "\354\355\372\372\373\374\374\375\365\365\366\220\217\220\15\15\15""124\267"
+ "\266\267\317\317\321\345\345\347\266\266\266DDE\23\23\24\243\243\245\321"
+ "\321\322\352\352\353\356\356\360\354\354\357\361\361\364\277\277\300@@Af"
+ "ff\260\260\260\252\252\253\217\217\223\6\6\6qqs\313\313\315\327\327\333\336"
+ "\336\343\345\345\352\363\363\367\362\362\366\344\344\351\347\347\355\360"
+ "\360\365\366\366\372\363\363\367\356\356\364\353\353\361\363\363\367\355"
+ "\355\361\330\330\340\324\324\334\326\326\336\333\333\341\354\354\361\363"
+ "\363\370\367\367\372\203\374\374\375\21\372\372\373\357\357\363\345\345\353"
+ "\346\346\352\335\335\342\327\327\332\312\312\313\270\270\271\242\242\244"
+ "e\200\34r\220\40\201\246$\220\272(\234\311,\243\321-\244\323.\236\320\36"
+ "\377\233\317\25\303\233\317\25\25\236\320\33\306\343|\313\335\233\204\206"
+ "\203\212\212\214\240\240\242\260\260\263\272\272\275\307\307\311\326\326"
+ "\331\343\343\344\335\335\341\346\346\352\363\363\365\363\363\366\361\361"
+ "\364\365\365\371\360\360\363\343\343\350\354\354\360\364\364\367\202\357"
+ "\357\363\1\363\363\367\202\350\350\355\12\350\350\356\340\340\346\350\350"
+ "\355\347\347\354\333\333\342\344\344\352\354\354\362\353\352\360\357\357"
+ "\364\357\357\365\202\356\356\363\4\362\362\367\353\353\361\340\340\347\363"
+ "\363\367\202\374\374\374&\372\372\373\353\353\361\357\357\364\371\371\373"
+ "\356\356\363\344\344\352\342\342\350\351\351\357\370\370\371\372\373\374"
+ "\372\372\373\366\366\366efg\1\1\1ddf\200\200\200\262\262\262\256\256\257"
+ "\31\31\32\36\36\35\221\221\222\235\234\237\224\224\225\334\334\334\361\361"
+ "\361\372\372\372\374\374\374\372\372\372\356\356\356{z|\7\7\7cce**,\246\246"
+ "\247\304\304\304\326\326\326\353\353\353\370\370\370\202\374\374\3747\361"
+ "\361\361UUV\14\14\14\220\220\221\316\316\316\347\347\347\367\367\367\373"
+ "\373\373\327\327\327IIJ\36\36\37\265\265\266\322\322\323\353\353\354\370"
+ "\370\371\374\374\374\364\364\364\204\204\205\0\0\0\\\\\\\270\270\272\325"
+ "\325\327\356\356\356\273\273\273HHJ\22\22\22\240\240\241\317\317\317\340"
+ "\340\343\350\350\353\361\361\363\364\364\366\177\177\177\34\34\35\274\274"
+ "\275\314\314\314\271\271\272qqp,,.%%&\261\261\264\312\312\316\332\332\340"
+ "\351\351\356\340\340\342\236\236\240\305\305\310\344\344\352\360\360\363"
+ "\363\363\367\356\356\363\347\347\356\352\352\360\363\363\367\340\340\347"
+ "\202\322\322\332\5\324\324\334\335\335\345\360\360\366\363\363\367\370\370"
+ "\372\203\373\373\374\21\371\371\373\355\355\362\350\350\355\345\345\350\335"
+ "\335\341\326\326\332\310\310\312\265\265\270\237\237\242d\200\34p\217\37"
+ "\200\243$\216\267(\232\306+\240\317-\243\322.\236\321#\377\231\317\25\304"
+ "\231\317\25)\274\337g\320\346\234\224\227\211\207\207\211\233\233\235\257"
+ "\257\260\272\272\274\304\304\306\324\324\327\342\342\343\336\336\342\344"
+ "\344\347\361\361\363\364\364\367\360\360\364\363\363\366\362\362\365\343"
+ "\343\350\346\346\353\362\362\366\360\360\364\357\357\363\363\363\367\351"
+ "\351\356\345\344\352\353\353\360\341\341\347\346\346\354\353\353\360\336"
+ "\336\344\335\335\344\352\352\360\350\350\356\354\354\362\357\357\364\356"
+ "\356\363\355\355\362\356\356\364\357\357\365\336\336\345\351\351\357\203"
+ "\373\373\373%\361\361\365\347\347\355\366\366\371\365\365\371\350\350\356"
+ "\343\343\351\345\345\353\362\362\365\372\372\372\367\367\371\313\313\314"
+ "\34\34\34\32\32\31zz{\237\237\237\276\276\276eeg\6\6\6\247\247\250ffg233"
+ "\215\214\215\325\325\327\355\355\356\370\370\370\373\373\373\372\372\372"
+ "\363\363\363\256\256\256>>>\0\0\0OOP\272\273\273\307\307\307\337\337\337"
+ "\361\361\361\372\372\372\202\373\373\373?\361\361\361RRT\14\14\15\224\224"
+ "\224\315\315\315\346\346\346\366\366\366\372\372\372\341\341\341JJK\34\34"
+ "\35\265\265\266\320\320\320\350\350\350\365\365\365\364\364\364\307\307\311"
+ "\23\23\23\17\17\17\250\250\250\302\302\304\337\337\340\357\357\360\310\310"
+ "\311IIJ\20\20\20\244\244\245\307\307\310\331\331\334\353\353\355\366\366"
+ "\370\336\336\336TTUBBB\301\301\301\277\277\300\271\271\274ZYY\200\200\200"
+ "\10\10\10\220\220\222\276\276\302\325\325\331\343\343\347nnp$$%LLM\341\341"
+ "\345\354\354\360\356\356\361\350\350\355\342\342\351\355\355\362\355\355"
+ "\361\325\325\335\316\316\330\320\320\330\322\322\332\343\343\351\363\363"
+ "\367\362\362\366\367\367\372\371\371\373\202\372\372\373\21\366\366\370\354"
+ "\354\361\346\346\353\341\341\345\334\334\340\325\325\331\305\305\310\263"
+ "\263\266\235\235\237b\177\34n\214\37|\240#\212\264(\226\304,\235\315-\240"
+ "\321.\236\321'\377\227\316\25\304\227\316\25\12\261\332Q\317\347\226\243"
+ "\253\220\202\202\204\226\226\230\254\254\255\270\270\273\303\303\305\322"
+ "\322\324\340\340\341\202\337\337\343\2\356\356\361\364\364\367\202\361\361"
+ "\364\12\364\364\367\346\346\353\341\341\346\354\354\360\361\361\364\356\356"
+ "\362\362\362\366\353\353\360\342\342\347\352\352\357\202\343\343\351\16\355"
+ "\355\363\346\346\353\333\333\342\346\346\354\350\350\355\350\350\356\355"
+ "\355\363\356\356\363\355\355\361\354\354\361\357\357\364\341\341\350\341"
+ "\341\347\367\367\371\202\372\372\372\31\367\367\370\350\350\355\357\357\362"
+ "\370\370\371\357\356\363\345\345\353\344\344\352\354\354\357\367\367\371"
+ "\364\364\366wwy\3\3\4llnqrr\271\271\271\272\272\272\23\23\23\0\0\0VVW,,."
+ "\276\276\276\237\235\237\316\316\321\350\350\351\367\367\367\202\372\372"
+ "\372\22\366\366\366\336\337\336bbc\2\2\2\225\225\226\265\265\265\317\317"
+ "\317\346\346\346\365\365\365\372\372\372\371\371\371\363\363\363\325\325"
+ "\326BBD\4\4\5\230\230\232\306\306\306\340\340\340\202\361\361\361*\310\310"
+ "\311334\0\0\0\204\204\205\302\302\304\317\317\320\313\313\316\224\224\227"
+ "\34\34\34\13\13\13\203\204\204\275\275\276\317\317\320\344\344\345\352\352"
+ "\354\300\301\302BBC\2\1\1\236\236\241\274\274\277\327\327\332\356\356\357"
+ "\360\360\360\252\252\253\15\15\15oop\274\274\275\302\302\305\311\311\313"
+ "\240\240\241\201\200\202\2\2\2""234\263\263\266\321\321\323\325\325\327R"
+ "RR667JJL\333\333\336\345\345\352\346\346\353\202\341\341\347\37\361\361\364"
+ "\340\340\346\317\317\330\316\316\330\317\317\327\326\326\335\353\353\360"
+ "\362\362\366\360\360\364\365\365\371\367\367\372\371\371\373\371\371\372"
+ "\360\360\364\353\353\360\342\342\347\337\337\344\334\334\340\323\323\326"
+ "\301\301\305\261\261\264\232\232\236a~\34k\212\36y\235\"\207\261'\223\301"
+ "*\233\314,\237\321-\240\322,\226\316\25\377\226\316\24\303\226\316\24\34"
+ "\246\3259\314\347\214\263\300\226\200\200\200\221\221\222\245\245\247\267"
+ "\267\270\302\302\304\317\317\321\336\336\337\343\343\346\334\334\341\350"
+ "\350\353\364\364\366\357\357\362\356\356\361\362\362\365\352\352\356\334"
+ "\334\342\344\344\351\357\357\363\355\355\361\356\356\362\355\355\361\340"
+ "\340\345\346\346\353\345\345\353\340\340\345\202\354\354\361\14\336\336\343"
+ "\340\340\345\347\347\354\343\343\351\351\351\356\354\354\361\354\354\360"
+ "\352\351\357\353\353\361\347\347\354\333\333\342\355\355\361\203\370\370"
+ "\370\30\356\356\362\343\343\351\360\360\363\364\364\366\350\350\356\344\344"
+ "\351\346\346\353\361\361\364\362\362\362[[\\222kkk\244\244\244\305\305\305"
+ "\221\221\222\37\37!99:\200\200\201\343\343\343\301\301\301\277\277\277\322"
+ "\322\325\343\343\346\363\363\364\202\370\370\370B\366\366\366\355\355\355"
+ "\210\210\210MMO\263\263\263\276\276\276\327\327\327\354\354\354\366\366\366"
+ "\370\370\370\366\366\366\234\234\234zzzFFG443^^`\214\214\214\322\322\323"
+ "\350\350\351\246\247\250||}AAB:::445}}~\214\214\216yyzNON{{{www\265\265\265"
+ "\306\306\307\332\332\333\351\351\351\222\222\223\201\201\203RQR454]]_\206"
+ "\206\210\317\317\320\316\316\315\204\204\205yyz///acd\230\230\233\275\275"
+ "\301\257\257\261\210\210\211wxy>>?../wwy\261\261\262\324\324\331}}\200EE"
+ "Fnnp\332\332\336\341\341\343\336\336\343\333\333\342\350\350\355\352\352"
+ "\357\322\322\332\202\313\313\323\3\315\315\325\333\333\342\361\361\365\202"
+ "\355\355\362\25\362\362\366\364\364\371\367\367\371\362\362\366\355\355\362"
+ "\351\351\356\336\336\342\335\335\343\333\333\337\316\316\322\276\276\302"
+ "\255\255\261\230\230\232`}\33j\210\35x\231!\204\254%\221\275)\233\311+\237"
+ "\317,\240\320-\377\241\322-\304\241\322-\22\246\3259\313\346\213\311\330"
+ "\243\204\204\201\213\213\214\240\240\241\264\264\265\277\277\302\314\314"
+ "\316\331\331\333\341\341\343\332\332\337\342\342\346\361\361\364\357\357"
+ "\362\353\353\356\355\355\360\353\353\357\202\332\332\337\27\350\350\353\353"
+ "\353\357\352\352\356\353\353\357\336\336\344\336\336\343\345\345\351\335"
+ "\335\343\350\350\354\356\356\362\341\341\347\327\326\336\343\343\351\341"
+ "\341\347\341\341\346\350\350\354\351\351\355\347\347\353\344\344\351\347"
+ "\347\354\331\331\340\337\337\345\362\362\362\202\363\363\363\31\361\361\362"
+ "\342\342\350\341\341\346\360\360\362\353\353\357\343\343\350\341\341\346"
+ "\347\347\352\353\353\354\232\232\232\250\250\250\233\233\233\300\300\300"
+ "\320\320\320\256\255\255~~~\266\266\266\334\334\334\272\272\272\274\274\274"
+ "\317\317\317\336\336\337\346\346\351\353\353\356\360\360\362\202\363\363"
+ "\363\7\355\355\355\271\271\271\214\215\215\267\267\267\313\313\313\336\336"
+ "\336\354\354\354\202\363\363\363T\360\360\360\222\222\222\227\227\227\244"
+ "\244\244\235\235\235\222\222\222\242\242\242\306\306\307\335\335\336\222"
+ "\223\222\244\245\244\270\270\271\273\273\273\271\271\270\266\266\265\267"
+ "\267\267\305\304\304\330\331\331\300\300\300\274\274\274\304\304\305\324"
+ "\324\325\343\343\345\351\351\351\215\215\215\313\313\314\320\321\320\321"
+ "\321\321\311\311\311\256\256\256\315\315\315\267\267\267\260\260\260\324"
+ "\324\324\325\325\325\322\322\322\232\232\231\301\301\303\243\243\245\272"
+ "\272\273\322\322\322\325\325\325\327\327\327\265\265\265\244\244\245\277"
+ "\277\304\303\303\311\301\301\305\325\325\330\326\326\333\330\330\335\321"
+ "\321\327\331\331\337\353\353\357\330\330\337\310\310\321\307\307\316\305"
+ "\305\317\313\313\323\341\341\347\355\355\357\344\344\351\351\351\355\354"
+ "\354\361\356\356\362\357\357\363\354\354\361\352\352\357\341\341\347\327"
+ "\327\334\334\334\341\330\330\332\311\311\316\273\273\275\254\254\257\226"
+ "\226\230\\z\31f\204\33r\224\36\177\246\"\212\270%\224\304(\231\312)\233\314"
+ "*\377\234\316*\305\234\316*\24\274\335s\323\347\247\223\226\212\204\204\206"
+ "\230\230\232\255\255\256\273\273\275\305\305\310\324\324\327\336\336\340"
+ "\331\331\335\333\333\337\353\353\355\352\352\355\350\350\352\347\347\351"
+ "\351\351\353\333\333\337\322\322\327\336\336\342\202\347\347\351,\347\347"
+ "\353\335\335\342\326\326\332\337\337\344\332\332\340\336\336\343\352\352"
+ "\356\344\344\350\322\322\331\330\330\336\336\336\343\331\331\335\337\337"
+ "\345\343\343\347\342\342\346\336\336\344\340\340\347\333\333\340\322\322"
+ "\331\350\350\352\355\355\355\354\354\355\355\355\355\345\345\347\331\331"
+ "\336\344\344\347\352\352\354\342\342\347\335\335\342\336\336\343\343\343"
+ "\346\335\335\335\313\313\315\304\304\306\314\314\314\332\332\332\334\334"
+ "\334\323\323\323\303\303\303\274\274\274\301\301\301\316\316\316\333\333"
+ "\333\346\346\346\203\350\350\352\11\353\354\355\355\355\355\352\352\352\342"
+ "\342\342\327\327\327\317\317\317\326\326\326\341\341\341\352\352\352\202"
+ "\355\355\355S\352\352\352\343\343\343\325\325\325\306\306\306\275\275\275"
+ "\273\273\273\302\302\302\317\317\317\333\333\334\335\335\336\324\324\325"
+ "\305\305\306\275\275\275\272\272\272\274\274\274\276\276\276\300\300\300"
+ "\301\301\301\303\303\303\311\311\312\324\324\325\340\340\340\347\347\350"
+ "\346\346\346\331\331\332\305\305\307\271\271\274\267\267\270\272\272\272"
+ "\303\303\303\317\317\320\332\332\333\331\331\331\313\313\314\267\267\272"
+ "\252\252\255\264\265\267\315\315\316\321\321\325\303\303\306\265\265\270"
+ "\252\252\256\256\256\262\273\273\275\267\267\274\267\267\275\307\307\316"
+ "\326\326\331\332\332\335\326\326\332\317\317\326\313\313\322\335\335\341"
+ "\340\340\345\307\307\317\301\301\310\277\277\307\301\301\310\315\315\324"
+ "\345\345\350\341\341\346\333\333\342\343\343\350\346\346\352\347\347\353"
+ "\346\346\353\347\347\352\345\345\351\326\326\333\322\322\330\330\330\335"
+ "\322\322\325\303\303\307\267\267\272\250\250\253\224\224\226Yv\26a\200\31"
+ "m\216\33y\237\36\203\257\"\215\273$\223\303&\202\226\307&\377\227\310&\304"
+ "\227\310&*\255\323X\314\340\236\243\252\217~~\200\217\217\221\245\245\246"
+ "\265\265\266\301\301\302\314\314\316\331\331\333\327\327\332\323\323\327"
+ "\341\341\344\346\346\347\341\341\344\337\337\342\341\341\343\332\332\335"
+ "\313\313\321\321\321\325\335\335\341\340\340\342\340\340\344\332\332\335"
+ "\315\315\322\325\325\332\326\326\332\323\323\330\341\341\344\342\342\345"
+ "\322\322\330\312\311\320\324\324\331\322\322\326\323\323\330\331\331\335"
+ "\331\331\336\327\327\334\325\325\333\327\327\334\311\311\321\325\325\331"
+ "\203\344\344\344!\342\342\343\330\330\333\322\322\327\340\340\341\340\340"
+ "\343\331\331\335\326\326\332\330\330\334\331\331\334\325\325\326\317\317"
+ "\322\325\325\326\333\333\333\334\334\334\331\331\331\322\322\322\317\317"
+ "\317\322\322\322\331\331\331\337\337\337\342\342\342\344\344\344\343\343"
+ "\344\341\340\342\341\341\343\343\343\344\343\343\343\340\340\340\333\333"
+ "\333\330\330\330\333\333\333\340\340\340\343\343\343\202\344\344\344\4\342"
+ "\342\342\337\337\337\330\330\330\322\322\322\202\315\315\315\7\320\320\320"
+ "\325\325\325\333\333\333\334\334\334\330\330\330\322\322\322\316\316\316"
+ "\204\315\315\315\12\316\316\316\322\322\322\326\326\326\333\333\334\335\335"
+ "\336\332\332\335\324\324\330\320\320\323\315\315\320\315\315\316\202\315"
+ "\315\3157\317\317\320\325\325\326\331\331\331\330\330\331\311\311\314\270"
+ "\270\274\274\274\277\313\313\315\317\317\320\306\306\312\300\300\304\273"
+ "\273\300\276\276\302\310\310\312\301\301\304\263\263\271\274\274\302\314"
+ "\314\322\327\327\332\324\324\331\312\312\320\301\301\310\312\312\321\333"
+ "\333\337\310\310\317\272\272\302\270\270\277\270\270\300\274\274\303\321"
+ "\322\326\335\335\340\322\322\327\324\324\332\332\332\337\334\334\340\335"
+ "\335\341\333\333\340\337\337\343\325\325\332\312\312\320\316\316\323\322"
+ "\322\327\311\311\315\274\274\300\264\264\266\244\244\250\223\223\225Uq\24"
+ "]|\27g\206\31s\227\34\177\246\37\206\262!\214\272\"\217\276#\202\220\300"
+ "$\377\221\301$\303\221\301$3\235\307=\302\330\216\261\275\223zz{\204\204"
+ "\206\230\230\232\252\252\254\270\270\272\303\303\305\317\317\320\322\322"
+ "\324\312\312\315\324\324\327\333\333\336\330\330\333\324\324\327\323\323"
+ "\327\324\324\327\307\307\313\303\303\310\317\317\322\325\325\330\326\326"
+ "\331\324\324\327\305\305\312\306\306\313\317\317\323\310\310\316\323\323"
+ "\327\332\332\333\323\323\325\302\301\307\303\303\311\310\310\315\305\305"
+ "\311\313\313\320\317\317\322\316\316\322\311\311\317\314\314\321\305\305"
+ "\313\301\301\307\325\325\327\331\331\331\330\330\331\331\331\331\327\327"
+ "\327\310\310\316\311\311\316\327\327\330\324\324\327\202\315\315\322\4\320"
+ "\320\323\325\325\326\321\321\323\320\320\323\202\327\327\327\6\325\325\325"
+ "\323\323\323\322\322\322\325\325\325\327\327\327\330\330\330\204\331\331"
+ "\331\10\327\327\331\330\330\331\331\331\331\330\330\330\327\327\327\326\326"
+ "\326\327\327\327\330\330\330\204\331\331\331\3\327\327\327\326\326\326\324"
+ "\324\324\202\322\322\322\2\323\323\323\325\325\325\202\327\327\327\3\326"
+ "\326\326\324\324\324\323\323\323\205\322\322\322\11\322\322\323\322\322\322"
+ "\317\317\322\315\314\320\314\314\317\320\320\322\324\324\325\325\325\325"
+ "\323\323\323\202\322\322\3227\324\324\324\325\325\325\323\323\324\307\307"
+ "\312\274\274\301\301\301\304\316\316\320\314\314\317\302\302\306\274\274"
+ "\300\273\273\300\302\302\305\314\314\320\305\305\310\264\264\272\263\263"
+ "\272\301\301\306\315\315\322\316\316\322\304\304\311\271\271\276\270\270"
+ "\276\315\315\321\307\307\313\262\262\272\257\257\267\256\256\266\260\260"
+ "\270\273\273\302\321\321\324\313\313\317\303\303\310\311\311\316\315\315"
+ "\322\317\317\323\316\316\323\322\322\326\323\323\327\303\303\310\300\300"
+ "\305\306\306\314\307\307\314\276\276\302\265\265\270\256\256\262\240\240"
+ "\242\220\220\223Rn\23Xv\25b\201\27m\220\32w\236\34\200\252\36\205\262\37"
+ "\211\267\40\202\212\272!\377\213\272!\303\213\272!\17\214\273$\256\312o\302"
+ "\324\232\202\204\177}}\177\214\214\216\237\237\240\255\255\257\267\267\272"
+ "\303\303\304\307\307\310\300\300\304\304\304\307\320\320\321\314\314\317"
+ "\202\307\307\312\14\310\310\312\301\301\304\266\266\272\275\275\301\307\307"
+ "\313\311\311\314\311\311\313\276\276\302\267\267\273\300\300\304\275\275"
+ "\301\301\301\305\202\313\313\314\14\275\275\302\263\263\271\274\274\301\271"
+ "\271\275\271\271\277\300\300\304\302\302\305\276\276\303\275\275\302\277"
+ "\277\303\263\263\270\277\277\303\202\313\313\313\16\312\312\313\313\313\313"
+ "\306\306\307\267\267\275\300\300\303\312\312\313\305\305\310\300\300\304"
+ "\301\301\305\307\307\311\312\312\312\306\306\310\307\307\311\312\312\313"
+ "\207\312\312\312\233\313\313\313\1\312\312\313\202\311\311\312\7\307\307"
+ "\311\304\304\306\301\301\304\300\300\303\302\302\304\306\306\310\311\311"
+ "\311\204\313\313\313\1\312\313\313\202\313\313\313\12\311\311\311\273\273"
+ "\300\261\261\265\271\271\275\307\307\311\303\303\306\270\270\275\262\262"
+ "\266\261\261\266\266\266\273\202\303\303\306\13\257\257\264\250\250\260\263"
+ "\263\270\300\300\303\303\303\307\274\274\301\257\257\264\250\250\257\271"
+ "\271\275\302\302\305\255\255\263\203\243\243\252\6\250\250\257\271\271\276"
+ "\305\305\310\266\266\273\266\266\274\275\275\302\202\277\277\304\24\277\277"
+ "\303\307\307\313\277\277\303\261\261\267\267\267\274\274\274\300\272\272"
+ "\276\261\261\266\254\254\261\250\250\253\232\232\235\214\214\215Oi\21Uq\23"
+ "]|\25g\210\27q\226\31{\242\33\200\252\35\202\257\35\202\205\262\36\377\205"
+ "\263\36\304\205\263\36:\234\277R\271\314\220\217\224\201sst\200\200\200\221"
+ "\221\222\236\236\237\247\247\252\263\263\265\271\271\273\264\264\267\262"
+ "\262\265\275\275\300\274\274\276\270\270\273\267\267\272\270\270\272\267"
+ "\267\271\253\253\257\251\251\255\265\265\270\271\271\274\272\272\275\263"
+ "\263\267\252\252\256\256\256\262\262\262\266\257\257\263\272\272\273\274"
+ "\274\274\267\267\271\251\251\255\250\250\255\255\255\261\250\250\254\255"
+ "\255\262\262\262\266\260\260\265\255\255\261\257\257\264\252\252\256\247"
+ "\247\253\267\267\271\273\273\273\272\272\273\273\273\273\272\272\272\261"
+ "\261\264\251\251\255\264\264\266\272\272\272\265\265\270\262\262\266\265"
+ "\265\270\272\272\272\271\271\272\266\266\270\270\270\272\217\272\272\272"
+ "\221\273\273\273\202\272\272\273\2\270\270\272\267\267\272\204\266\266\270"
+ "\2\270\270\272\272\272\272\210\273\273\273\30\266\266\270\252\252\256\243"
+ "\243\251\254\254\260\270\270\271\264\264\266\251\251\255\243\243\250\242"
+ "\242\250\250\250\254\264\264\266\266\266\270\244\244\251\233\233\241\241"
+ "\241\246\255\255\261\264\264\267\260\260\264\244\244\252\231\231\240\243"
+ "\243\251\265\265\270\250\250\254\230\230\237\202\225\225\235\20\227\227\236"
+ "\243\243\251\264\264\267\255\255\261\244\244\251\251\251\255\254\254\261"
+ "\256\256\262\255\255\261\262\262\266\267\267\272\250\250\254\244\244\250"
+ "\253\253\257\255\255\262\252\252\256\202\244\244\247\3\240\240\241\222\222"
+ "\224\206\206\206",
+};
+
diff --git a/src/image_data/bnc_cable.h b/src/image_data/bnc_cable.h
index 756946a..d627072 100644
--- a/src/image_data/bnc_cable.h
+++ b/src/image_data/bnc_cable.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t bnc_cable = {
- 64, 64, 4,
+ 64, 64, 4, 0,
"\224\372\372\372\0\6\371\371\371\0\366\366\366\0\265\265\265\0\356\356\356"
"\0\273\273\273\0\261\260\261\0\202\332\332\332\0\6\311\311\311\0\225\224"
"\225\0\256\253\256\0\315\311\315\0\304\302\304\0\216\215\216\0\214\0\0\0"
diff --git a/src/image_data/clocks_banner.h b/src/image_data/clocks_banner.h
index 46814e5..30debc6 100644
--- a/src/image_data/clocks_banner.h
+++ b/src/image_data/clocks_banner.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t clocks_banner_image = {
- 360, 60, 3,
+ 360, 60, 3, 180,
"\204]y\30\202m\216\33\377\201\221\33\311\201\221\33\6\205\234G\226\244b\200"
"\200\205z{|\206\207\212\227\227\232\202\235\234\237\1\243\242\244\202\235"
"\234\237\2\217\217\222\206\207\212\203\217\217\222\3\206\207\212\200\200"
diff --git a/src/image_data/color_correction_banner.h b/src/image_data/color_correction_banner.h
index 28f24b9..b8a7369 100644
--- a/src/image_data/color_correction_banner.h
+++ b/src/image_data/color_correction_banner.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t color_correction_banner_image = {
- 360, 60, 3,
+ 360, 60, 3, 180,
"\203Qi\22\202i\204\27\377\201\221\34\312\201\221\34\2\214\233Q\232\240f\202"
"\177~\200\11\206\207\211\227\227\231\232\232\237\237\237\240\240\240\244"
"\237\237\240\232\232\237\220\216\223\206\207\211\203\220\216\223\203\206"
diff --git a/src/image_data/configuration_banner.h b/src/image_data/configuration_banner.h
index b5d5403..912d8d7 100644
--- a/src/image_data/configuration_banner.h
+++ b/src/image_data/configuration_banner.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t configuration_banner_image = {
- 360, 60, 3,
+ 360, 60, 3, 180,
"\11S]\21Xc\22`k\23hv\25p\177\27x\206\30}\214\32\200\220\33\200\221\33\307"
"\201\221\33\202\200\220\33\373\201\221\33\35\202\222\40\220\232S\224\235"
"e\202\204{zz{\213\213\214\225\225\226\233\233\234\237\237\241\241\241\242"
diff --git a/src/image_data/crt.h b/src/image_data/crt.h
index 83bce95..145e3c3 100644
--- a/src/image_data/crt.h
+++ b/src/image_data/crt.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t crt_image = {
- 100, 100, 4,
+ 100, 100, 4, 0,
"\377\377\0\377\0\377\377\0\377\0\225\377\0\377\0\25\336\336\337\377\333\333"
"\335\377\330\330\331\377\322\322\324\377\317\317\320\377\312\312\320\377\303"
"\303\310\377\277\277\305\377\275\275\304\377\277\277\305\377\303\303\310\377"
diff --git a/src/image_data/crt_banner.h b/src/image_data/crt_banner.h
index 551a340..ce8c4a0 100644
--- a/src/image_data/crt_banner.h
+++ b/src/image_data/crt_banner.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t crt_banner_image = {
- 360, 60, 3,
+ 360, 60, 3, 180,
"\11S]\21Xc\22`k\23hv\25p\177\27x\206\30}\214\32\200\220\33\200\221\33\222"
"\201\221\33\262\200\221\32\377\201\221\33\36\201\221\33\202\222\40\220\232"
"S\224\235e\202\204{zz{\213\213\214\225\225\226\233\233\234\237\237\241\241"
diff --git a/src/image_data/cursor_banner.h b/src/image_data/cursor_banner.h
index 0e00436..de2e926 100644
--- a/src/image_data/cursor_banner.h
+++ b/src/image_data/cursor_banner.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t cursor_banner_image = {
- 360, 60, 3,
+ 360, 60, 3, 180,
"\11S]\21Xc\22`k\23hv\25p\177\27x\206\30}\214\32\200\220\33\200\221\33\265"
"\201\221\33\1\331\336\272\231\201\221\33\202\201\221\34\202\201\221\33\2"
"\202\222\36\203\223\37\357\201\221\33\35\202\222\40\220\232S\224\235e\202"
diff --git a/src/image_data/dfp.h b/src/image_data/dfp.h
index 7813b00..d5d7b6c 100644
--- a/src/image_data/dfp.h
+++ b/src/image_data/dfp.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t dfp_image = {
- 100, 100, 4,
+ 100, 100, 4, 0,
"\377\377\0\377\0\377\377\0\377\0\213\377\0\377\0\7\337\336\341\377\335\335"
"\336\377\332\332\333\377\322\322\325\377\317\317\321\377\313\312\315\377\310"
"\310\315\377\203\300\300\303\377\5\306\306\311\377\315\314\321\377\324\324"
diff --git a/src/image_data/dfp_banner.h b/src/image_data/dfp_banner.h
index 4c63e4f..462a1be 100644
--- a/src/image_data/dfp_banner.h
+++ b/src/image_data/dfp_banner.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t dfp_banner_image = {
- 360, 60, 3,
+ 360, 60, 3, 180,
"\203Qe\30\203j\206\31\377\202\222\34\311\202\222\34\2\216\235O\226\237h\202"
"}|\177\11\206\206\210\227\227\231\233\233\237\236\236\244\241\241\243\236"
"\236\244\233\233\237\220\217\222\206\206\210\203\220\217\222\203\206\206"
diff --git a/src/image_data/display_device_banner.h b/src/image_data/display_device_banner.h
index 15007ab..d2f988b 100644
--- a/src/image_data/display_device_banner.h
+++ b/src/image_data/display_device_banner.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t display_device_banner_image = {
- 360, 60, 3,
+ 360, 60, 3, 180,
"\203Un\21\202c\177\21\377\200\221\32\312\200\221\32\2\223\237S\231\241k\202"
"~~\202\2\206\206\212\227\226\230\202\233\233\240\1\243\243\244\202\233\233"
"\240\2\217\217\222\206\206\212\203\217\217\222\203\206\206\212\206\217\217"
diff --git a/src/image_data/frame_lock_banner.h b/src/image_data/frame_lock_banner.h
index 90c2cee..009efc2 100644
--- a/src/image_data/frame_lock_banner.h
+++ b/src/image_data/frame_lock_banner.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t frame_lock_banner_image = {
- 360, 60, 3,
+ 360, 60, 3, 180,
"\11S]\21Xc\22`k\23hv\25p\177\27x\206\30}\214\32\200\220\33\200\221\33\226"
"\201\221\33\320\204\223\26\222\204\222\"\1\204\223\26\203\204\222\"\1\204"
"\223\26\203\204\222\"\1\204\223\26\236\204\222\"\245\201\221\33\35\202\222"
diff --git a/src/image_data/glx_banner.h b/src/image_data/glx_banner.h
index 305fe98..faa602e 100644
--- a/src/image_data/glx_banner.h
+++ b/src/image_data/glx_banner.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t glx_banner_image = {
- 360, 60, 3,
+ 360, 60, 3, 180,
"\11S]\21Xc\22`k\23hv\25p\177\27x\206\30}\214\32\200\220\33\200\221\33\377"
"\201\221\33\305\201\221\33\35\202\222\40\220\232S\223\234e\203\205|zz{\213"
"\213\214\225\225\226\233\233\234\237\237\241\241\241\242\237\237\241\234"
diff --git a/src/image_data/gvo_banner_comp_sync_green.h b/src/image_data/gvo_banner_comp_sync_green.h
index 7f63e4c..d1e3c98 100644
--- a/src/image_data/gvo_banner_comp_sync_green.h
+++ b/src/image_data/gvo_banner_comp_sync_green.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t gvo_banner_comp_sync_green_image = {
- 34, 60, 3,
+ 34, 60, 3, 0,
"\242\201\221\33\242\235\257!\242\261\306&\242\301\326,\242\314\340.\242\321"
"\345/\242\324\3462\242\325\3472\304\334\3567\242\335\3578\203\374\374\374"
"\203\373\373\374\205\372\372\373\203\371\371\372\203\370\370\372\202\370"
diff --git a/src/image_data/gvo_banner_comp_sync_grey.h b/src/image_data/gvo_banner_comp_sync_grey.h
index 801a796..dec42be 100644
--- a/src/image_data/gvo_banner_comp_sync_grey.h
+++ b/src/image_data/gvo_banner_comp_sync_grey.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t gvo_banner_comp_sync_grey_image = {
- 34, 60, 3,
+ 34, 60, 3, 0,
"\242\201\221\33\242\235\257!\242\261\306&\242\301\326,\242\314\340.\242\321"
"\345/\242\324\3462\242\325\3472\304\334\3567\242\335\3578\203\374\374\374"
"\203\373\373\374\205\372\372\373\203\371\371\372\203\370\370\372\202\370"
diff --git a/src/image_data/gvo_banner_comp_sync_red.h b/src/image_data/gvo_banner_comp_sync_red.h
index c92087b..b7cdc19 100644
--- a/src/image_data/gvo_banner_comp_sync_red.h
+++ b/src/image_data/gvo_banner_comp_sync_red.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t gvo_banner_comp_sync_red_image = {
- 34, 60, 3,
+ 34, 60, 3, 0,
"\242\201\221\33\242\235\257!\242\261\306&\242\301\326,\242\314\340.\242\321"
"\345/\242\324\3462\242\325\3472\304\334\3567\242\335\3578\203\374\374\374"
"\203\373\373\374\205\372\372\373\203\371\371\372\203\370\370\372\202\370"
diff --git a/src/image_data/gvo_banner_comp_sync_yellow.h b/src/image_data/gvo_banner_comp_sync_yellow.h
index 87126b7..9059195 100644
--- a/src/image_data/gvo_banner_comp_sync_yellow.h
+++ b/src/image_data/gvo_banner_comp_sync_yellow.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t gvo_banner_comp_sync_yellow_image = {
- 34, 60, 3,
+ 34, 60, 3, 0,
"\242\201\221\33\242\235\257!\242\261\306&\242\301\326,\242\314\340.\242\321"
"\345/\242\324\3462\242\325\3472\304\334\3567\242\335\3578\203\374\374\374"
"\203\373\373\374\205\372\372\373\203\371\371\372\203\370\370\372\202\370"
diff --git a/src/image_data/gvo_banner_left.h b/src/image_data/gvo_banner_left.h
index a87539b..c0f6c2a 100644
--- a/src/image_data/gvo_banner_left.h
+++ b/src/image_data/gvo_banner_left.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t gvo_banner_left_image = {
- 70, 60, 3,
+ 70, 60, 3, 0,
"\11S]\21Xc\22`k\23hv\25p\177\27x\206\30}\214\32\200\220\33\200\221\33\275"
"\201\221\33\10`k\25iu\26s\200\31\177\214\33\211\231\35\222\242\37\227\251"
"\40\232\255!\202\234\256!\274\235\257!\11ly\27u\203\32\201\220\34\217\240"
diff --git a/src/image_data/gvo_banner_right.h b/src/image_data/gvo_banner_right.h
index ff6bd93..ce14d88 100644
--- a/src/image_data/gvo_banner_right.h
+++ b/src/image_data/gvo_banner_right.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t gvo_banner_right_image = {
- 174, 60, 3,
+ 174, 60, 3, 0,
"\223\201\221\33\35\202\222\40\220\232S\224\235e\202\204{zz{\213\213\214\225"
"\225\226\233\233\234\237\237\241\241\241\242\237\237\241\234\234\236\220"
"\220\222\212\212\216\216\216\220\222\222\223\221\221\223\212\212\214\203"
diff --git a/src/image_data/gvo_banner_sdi_sync_green.h b/src/image_data/gvo_banner_sdi_sync_green.h
index f8a2e0a..9385919 100644
--- a/src/image_data/gvo_banner_sdi_sync_green.h
+++ b/src/image_data/gvo_banner_sdi_sync_green.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t gvo_banner_sdi_sync_green_image = {
- 26, 60, 3,
+ 26, 60, 3, 0,
"\232\201\221\33\232\235\257!\232\261\306&\232\301\326,\232\314\340.\232\321"
"\345/\232\324\3462\232\325\3472\264\334\3567\232\335\3578\202\374\374\375"
"\203\375\375\375\213\376\376\376\202\375\375\376\204\375\375\375\202\374"
diff --git a/src/image_data/gvo_banner_sdi_sync_grey.h b/src/image_data/gvo_banner_sdi_sync_grey.h
index 556f2f6..bc752c4 100644
--- a/src/image_data/gvo_banner_sdi_sync_grey.h
+++ b/src/image_data/gvo_banner_sdi_sync_grey.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t gvo_banner_sdi_sync_grey_image = {
- 26, 60, 3,
+ 26, 60, 3, 0,
"\232\201\221\33\232\235\257!\232\261\306&\232\301\326,\232\314\340.\232\321"
"\345/\232\324\3462\232\325\3472\264\334\3567\232\335\3578\202\374\374\375"
"\203\375\375\375\213\376\376\376\202\375\375\376\204\375\375\375\202\374"
diff --git a/src/image_data/gvo_banner_sdi_sync_red.h b/src/image_data/gvo_banner_sdi_sync_red.h
index 0894cd2..29479ce 100644
--- a/src/image_data/gvo_banner_sdi_sync_red.h
+++ b/src/image_data/gvo_banner_sdi_sync_red.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t gvo_banner_sdi_sync_red_image = {
- 26, 60, 3,
+ 26, 60, 3, 0,
"\232\201\221\33\232\235\257!\232\261\306&\232\301\326,\232\314\340.\232\321"
"\345/\232\324\3462\232\325\3472\264\334\3567\232\335\3578\202\374\374\375"
"\203\375\375\375\213\376\376\376\202\375\375\376\204\375\375\375\202\374"
diff --git a/src/image_data/gvo_banner_sdi_sync_yellow.h b/src/image_data/gvo_banner_sdi_sync_yellow.h
index b31475d..b1e7a56 100644
--- a/src/image_data/gvo_banner_sdi_sync_yellow.h
+++ b/src/image_data/gvo_banner_sdi_sync_yellow.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t gvo_banner_sdi_sync_yellow_image = {
- 26, 60, 3,
+ 26, 60, 3, 0,
"\232\201\221\33\232\235\257!\232\261\306&\232\301\326,\232\314\340.\232\321"
"\345/\232\324\3462\232\325\3472\264\334\3567\232\335\3578\202\374\374\375"
"\203\375\375\375\213\376\376\376\202\375\375\376\204\375\375\375\202\374"
diff --git a/src/image_data/gvo_banner_vid1_green.h b/src/image_data/gvo_banner_vid1_green.h
index ec2bfea..dc1ec2e 100644
--- a/src/image_data/gvo_banner_vid1_green.h
+++ b/src/image_data/gvo_banner_vid1_green.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t gvo_banner_vid1_green_image = {
- 30, 60, 3,
+ 30, 60, 3, 0,
"\236\201\221\33\236\235\257!\236\261\306&\236\301\326,\236\314\340.\236\321"
"\345/\236\324\3462\236\325\3472\274\334\3567\236\335\3578\2\355\357\341\357"
"\357\363\204\360\360\363\1\360\360\364\204\361\361\364\1\362\362\364\204"
diff --git a/src/image_data/gvo_banner_vid1_grey.h b/src/image_data/gvo_banner_vid1_grey.h
index 3c43908..74bf8e8 100644
--- a/src/image_data/gvo_banner_vid1_grey.h
+++ b/src/image_data/gvo_banner_vid1_grey.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t gvo_banner_vid1_grey_image = {
- 30, 60, 3,
+ 30, 60, 3, 0,
"\236\201\221\33\236\235\257!\236\261\306&\236\301\326,\236\314\340.\236\321"
"\345/\236\324\3462\236\325\3472\274\334\3567\236\335\3578\2\355\357\341\357"
"\357\363\204\360\360\363\1\360\360\364\204\361\361\364\1\362\362\364\204"
diff --git a/src/image_data/gvo_banner_vid1_red.h b/src/image_data/gvo_banner_vid1_red.h
index 6133f09..f16dbde 100644
--- a/src/image_data/gvo_banner_vid1_red.h
+++ b/src/image_data/gvo_banner_vid1_red.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t gvo_banner_vid1_red_image = {
- 30, 60, 3,
+ 30, 60, 3, 0,
"\236\201\221\33\236\235\257!\236\261\306&\236\301\326,\236\314\340.\236\321"
"\345/\236\324\3462\236\325\3472\274\334\3567\236\335\3578\2\355\357\341\357"
"\357\363\204\360\360\363\1\360\360\364\204\361\361\364\1\362\362\364\204"
diff --git a/src/image_data/gvo_banner_vid1_yellow.h b/src/image_data/gvo_banner_vid1_yellow.h
index d988af3..51fa65e 100644
--- a/src/image_data/gvo_banner_vid1_yellow.h
+++ b/src/image_data/gvo_banner_vid1_yellow.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t gvo_banner_vid1_yellow_image = {
- 30, 60, 3,
+ 30, 60, 3, 0,
"\236\201\221\33\236\235\257!\236\261\306&\236\301\326,\236\314\340.\236\321"
"\345/\236\324\3462\236\325\3472\274\334\3567\236\335\3578\2\355\357\341\357"
"\357\363\204\360\360\363\1\360\360\364\204\361\361\364\1\362\362\364\204"
diff --git a/src/image_data/gvo_banner_vid2_green.h b/src/image_data/gvo_banner_vid2_green.h
index 58852c8..19b8311 100644
--- a/src/image_data/gvo_banner_vid2_green.h
+++ b/src/image_data/gvo_banner_vid2_green.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t gvo_banner_vid2_green_image = {
- 26, 60, 3,
+ 26, 60, 3, 0,
"\232\201\221\33\232\235\257!\232\261\306&\232\301\326,\232\314\340.\232\321"
"\345/\232\324\3462\232\325\3472\264\334\3567\232\335\3578\203\366\366\370"
"\1\367\367\370\202\367\367\371\203\370\370\371\202\370\370\372\203\371\371"
diff --git a/src/image_data/gvo_banner_vid2_grey.h b/src/image_data/gvo_banner_vid2_grey.h
index 6e0b8be..5fa5a57 100644
--- a/src/image_data/gvo_banner_vid2_grey.h
+++ b/src/image_data/gvo_banner_vid2_grey.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t gvo_banner_vid2_grey_image = {
- 26, 60, 3,
+ 26, 60, 3, 0,
"\232\201\221\33\232\235\257!\232\261\306&\232\301\326,\232\314\340.\232\321"
"\345/\232\324\3462\232\325\3472\264\334\3567\232\335\3578\203\366\366\370"
"\1\367\367\370\202\367\367\371\203\370\370\371\202\370\370\372\203\371\371"
diff --git a/src/image_data/gvo_banner_vid2_red.h b/src/image_data/gvo_banner_vid2_red.h
index 78929c3..ecdf9cc 100644
--- a/src/image_data/gvo_banner_vid2_red.h
+++ b/src/image_data/gvo_banner_vid2_red.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t gvo_banner_vid2_red_image = {
- 26, 60, 3,
+ 26, 60, 3, 0,
"\232\201\221\33\232\235\257!\232\261\306&\232\301\326,\232\314\340.\232\321"
"\345/\232\324\3462\232\325\3472\264\334\3567\232\335\3578\203\366\366\370"
"\1\367\367\370\202\367\367\371\203\370\370\371\202\370\370\372\203\371\371"
diff --git a/src/image_data/gvo_banner_vid2_yellow.h b/src/image_data/gvo_banner_vid2_yellow.h
index 8a99d29..2bfc745 100644
--- a/src/image_data/gvo_banner_vid2_yellow.h
+++ b/src/image_data/gvo_banner_vid2_yellow.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t gvo_banner_vid2_yellow_image = {
- 26, 60, 3,
+ 26, 60, 3, 0,
"\232\201\221\33\232\235\257!\232\261\306&\232\301\326,\232\314\340.\232\321"
"\345/\232\324\3462\232\325\3472\264\334\3567\232\335\3578\203\366\366\370"
"\1\367\367\370\202\367\367\371\203\370\370\371\202\370\370\372\203\371\371"
diff --git a/src/image_data/help_banner.h b/src/image_data/help_banner.h
index 180ba91..8218a6e 100644
--- a/src/image_data/help_banner.h
+++ b/src/image_data/help_banner.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t help_banner_image = {
- 360, 60, 3,
+ 360, 60, 3, 180,
"\11S]\21Xc\22`k\23hv\25p\177\27x\206\30}\214\32\200\220\33\200\221\33\377"
"\201\221\33\305\201\221\33\35\202\222\40\220\232S\224\235e\202\204{zz{\213"
"\213\214\225\225\226\233\233\234\237\237\241\241\241\242\237\237\241\234"
diff --git a/src/image_data/image.h b/src/image_data/image.h
index be21329..2112c7b 100644
--- a/src/image_data/image.h
+++ b/src/image_data/image.h
@@ -29,6 +29,7 @@ typedef struct {
unsigned int width;
unsigned int height;
unsigned int bytes_per_pixel; /* 3:RGB, 4:RGBA */
+ unsigned int fill_column_index;
char *rle_pixel_data;
} nv_image_t;
diff --git a/src/image_data/led_green.h b/src/image_data/led_green.h
index 1015f47..b70132a 100644
--- a/src/image_data/led_green.h
+++ b/src/image_data/led_green.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t led_green = {
- 16, 16, 4,
+ 16, 16, 4, 0,
"\221\377\377\377\0\15\366\377\374\0\376\377\377\0\377\374\375\0\354\346\346"
"R\305\303\304\234\302\301\311\327\304\301\324\372\277\273\311\327\267\262"
"\266\234\322\307\327R\377\374\377\0\376\377\363\0\373\377\375\0\203\377\377"
diff --git a/src/image_data/led_grey.h b/src/image_data/led_grey.h
index 41218ba..64faa6e 100644
--- a/src/image_data/led_grey.h
+++ b/src/image_data/led_grey.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t led_grey = {
- 16, 16, 4,
+ 16, 16, 4, 0,
"\222\377\377\377\0\13\376\376\376\0\377\377\377\0\346\346\346R\275\275\275"
"\234\260\260\260\327\265\265\265\372\253\253\253\327\252\252\252\234\321"
"\321\321R\377\377\377\0\371\371\371\0\205\377\377\377\0\14\376\376\376\27"
diff --git a/src/image_data/led_red.h b/src/image_data/led_red.h
index f66a900..045394f 100644
--- a/src/image_data/led_red.h
+++ b/src/image_data/led_red.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t led_red = {
- 16, 16, 4,
+ 16, 16, 4, 0,
"\224\377\377\377\0\7\377\376\377J\364\362\365\227\334\330\331\324\325\323"
"\330\372\322\325\336\324\345\352\355\227\371\375\377J\207\377\377\377\0\13"
"\377\376\377\6\370\373\377|\274\313\306\356\326\340\325\377\345\341\326\377"
diff --git a/src/image_data/opengl_banner.h b/src/image_data/opengl_banner.h
index 2eb6e86..12ec48c 100644
--- a/src/image_data/opengl_banner.h
+++ b/src/image_data/opengl_banner.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t opengl_banner_image = {
- 360, 60, 3,
+ 360, 60, 3, 180,
"\1KY\16\203^q\22\202s\206\26\1z\216\27\377\201\221\33\310\201\221\33\2\217"
"\237L\224\233j\202}}\177\10\214\214\217\222\222\224\232\232\235\237\237\243"
"\242\242\244\237\237\243\236\235\237\222\222\224\202\214\214\217\202\222"
diff --git a/src/image_data/rj45_input.h b/src/image_data/rj45_input.h
index 75ea529..4e2dea7 100644
--- a/src/image_data/rj45_input.h
+++ b/src/image_data/rj45_input.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t rj45_input = {
- 20, 28, 4,
+ 20, 28, 4, 0,
"\225666\377\222\0\0\0\0\202666\377\1\0\0\0\0\206ddd\377\204\0\0\0\0\2066"
"66\377\1\0\0\0\0\202666\377\2\0\0\0\0ddd\377\204\0\377\0\377\1ddd\377\204"
"PPP\377\1""666\377\204\236\245\212\377\2""666\377\0\0\0\0\202666\377\2\0"
diff --git a/src/image_data/rj45_output.h b/src/image_data/rj45_output.h
index 95674d8..7aa92d7 100644
--- a/src/image_data/rj45_output.h
+++ b/src/image_data/rj45_output.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t rj45_output = {
- 20, 28, 4,
+ 20, 28, 4, 0,
"\225666\377\222666\0\202666\377\1""666\0\206ddd\377\203\377\377\377\0\1""6"
"66\0\206666\377\1""666\0\202666\377\2""666\0ddd\377\204y\236y\377\1ddd\377"
"\204PPP\377\1""666\377\204\377\314\2\377\2""666\377\377\377\377\0\202666"
diff --git a/src/image_data/rj45_unused.h b/src/image_data/rj45_unused.h
index cb08fe6..a3d01bf 100644
--- a/src/image_data/rj45_unused.h
+++ b/src/image_data/rj45_unused.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t rj45_unused = {
- 20, 28, 4,
+ 20, 28, 4, 0,
"\225666\200\222\0\0\0\0\202666\200\1\0\0\0\0\206666\200\204\0\0\0\0\2066"
"66\200\1\0\0\0\0\202666\200\2\0\0\0\0""666\200\204\0\0\0\0\206666\200\204"
"\0\0\0\0\2""666\200\0\0\0\0\202666\200\2\0\0\0\0""666\200\204\0\0\0\0\1""6"
diff --git a/src/image_data/rotate_left_off.h b/src/image_data/rotate_left_off.h
index e65a9b5..ac3416a 100644
--- a/src/image_data/rotate_left_off.h
+++ b/src/image_data/rotate_left_off.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t rotate_left_off_image = {
- 26, 26, 3,
+ 26, 26, 3, 0,
"\231\230\230\230\177rrr\230\230\230\376\376\376\375\375\375\374\374\374\373"
"\373\373\372\372\372\371\371\371\370\370\370\367\367\367\365\365\365\364"
"\364\364\363\363\363\362\362\362\361\361\361\360\360\360\357\357\357\356"
diff --git a/src/image_data/rotate_left_on.h b/src/image_data/rotate_left_on.h
index c7df6e3..7f9bbe2 100644
--- a/src/image_data/rotate_left_on.h
+++ b/src/image_data/rotate_left_on.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t rotate_left_on_image = {
- 26, 26, 3,
+ 26, 26, 3, 0,
"\231222\177\213\213\213222\306\306\306\304\304\304\302\302\302\300\300\300"
"\277\277\277\275\275\275\273\273\273\271\271\271\267\267\267\265\265\265"
"\264\264\264\262\262\262\260\260\260\256\256\256\254\254\254\252\252\252"
diff --git a/src/image_data/rotate_right_off.h b/src/image_data/rotate_right_off.h
index 426b0cb..e36c405 100644
--- a/src/image_data/rotate_right_off.h
+++ b/src/image_data/rotate_right_off.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t rotate_right_off_image = {
- 26, 26, 3,
+ 26, 26, 3, 0,
"\231\230\230\230\177rrr\230\230\230\376\376\376\375\375\375\374\374\374\373"
"\373\373\372\372\372\371\371\371\370\370\370\367\367\367\365\365\365\364"
"\364\364\363\363\363\362\362\362\361\361\361\360\360\360\357\357\357\356"
diff --git a/src/image_data/rotate_right_on.h b/src/image_data/rotate_right_on.h
index 2f5847e..42f37f7 100644
--- a/src/image_data/rotate_right_on.h
+++ b/src/image_data/rotate_right_on.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t rotate_right_on_image = {
- 26, 26, 3,
+ 26, 26, 3, 0,
"\231222\177\213\213\213222\306\306\306\304\304\304\302\302\302\300\300\300"
"\277\277\277\275\275\275\273\273\273\271\271\271\267\267\267\265\265\265"
"\264\264\264\262\262\262\260\260\260\256\256\256\254\254\254\252\252\252"
diff --git a/src/image_data/rotation_banner.h b/src/image_data/rotation_banner.h
index 69ef080..b85ee76 100644
--- a/src/image_data/rotation_banner.h
+++ b/src/image_data/rotation_banner.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t rotation_banner_image = {
- 360, 60, 3,
+ 360, 60, 3, 180,
"\202N_\30\1ct(\203p\206\26\377\201\221\34\311\201\221\34\6\216\247J\220\232"
"l\201\201\203uty\212\213\215\227\227\230\202\235\236\235\1\243\243\244\202"
"\235\236\235\2\221\221\223\212\213\215\203\221\221\223\1\212\213\215\202"
diff --git a/src/image_data/rotation_orientation_horiz.h b/src/image_data/rotation_orientation_horiz.h
index c78436e..01c6dfd 100644
--- a/src/image_data/rotation_orientation_horiz.h
+++ b/src/image_data/rotation_orientation_horiz.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t rotation_orientation_horiz_image = {
- 120, 90, 3,
+ 120, 90, 3, 0,
"\377\0\0\0\363\0\0\0\35\7\15\20V\220\272t\277\366v\300\365x\301\365y\301"
"\365{\302\365~\303\364\200\303\364\200\304\364\202\305\364\205\305\363\206"
"\306\363\210\307\363\212\307\363\214\310\362\215\310\362\217\311\362\220"
diff --git a/src/image_data/rotation_orientation_horiz_flipped.h b/src/image_data/rotation_orientation_horiz_flipped.h
index fda740c..20ce1d9 100644
--- a/src/image_data/rotation_orientation_horiz_flipped.h
+++ b/src/image_data/rotation_orientation_horiz_flipped.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t rotation_orientation_horiz_flipped_image = {
- 120, 90, 3,
+ 120, 90, 3, 0,
"\377\0\0\0\363\0\0\0\2\2\16\2\27\233\27\216\37\315\37\2\34\237>\26""9\353"
"\340\25""5\375\2\20(\277\1\4\21\204\0\0\0\1\40\240\40\220*\324*\1'\255S\341"
"\34F\375\1\25""5\277\204\0\0\0\2224\3334\342$X\375\204\0\0\0\222>\342>\1"
diff --git a/src/image_data/rotation_orientation_vert.h b/src/image_data/rotation_orientation_vert.h
index 3b1e195..441aba7 100644
--- a/src/image_data/rotation_orientation_vert.h
+++ b/src/image_data/rotation_orientation_vert.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t rotation_orientation_vert_image = {
- 90, 120, 3,
+ 90, 120, 3, 0,
"\377\0\0\0\267\0\0\0\11\12\16\20w\233\265\235\316\360\236\316\360\240\317"
"\360\241\317\360\242\317\360\243\320\357\244\320\357\202\246\321\357\5\247"
"\321\357\250\321\357\250\322\357\251\322\357\252\322\357\202\253\322\357"
diff --git a/src/image_data/rotation_orientation_vert_flipped.h b/src/image_data/rotation_orientation_vert_flipped.h
index a6cc354..5586d04 100644
--- a/src/image_data/rotation_orientation_vert_flipped.h
+++ b/src/image_data/rotation_orientation_vert_flipped.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t rotation_orientation_vert_flipped_image = {
- 90, 120, 3,
+ 90, 120, 3, 0,
"\377\0\0\0\377\0\0\0\222\0\0\0\1\37\246\37\217)\334)\2&\262Q\35M\356\303"
"\34E\375\1\25""4\277\204\0\0\0\221.\337.\1+\271\\\304\40N\375\204\0\0\0\222"
"4\3424\304#W\375\204\0\0\0\2229\3449\1)s\346\303'`\375\204\0\0\0\221>\347"
diff --git a/src/image_data/thermal_banner.h b/src/image_data/thermal_banner.h
index 6ff37f0..ce92342 100644
--- a/src/image_data/thermal_banner.h
+++ b/src/image_data/thermal_banner.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t thermal_banner_image = {
- 360, 60, 3,
+ 360, 60, 3, 180,
"\205c{\31\377\200\221\32\311\200\221\32\3\202\222$\214\232P\227\237k\202"
"}~\177\3\216\217\217\227\227\230\234\236\233\203\243\243\244\2\232\233\240"
"\220\220\225\202\216\217\217\202\220\220\225\1\216\217\217\202\205\207\207"
diff --git a/src/image_data/tv.h b/src/image_data/tv.h
index 957c862..a9a6f60 100644
--- a/src/image_data/tv.h
+++ b/src/image_data/tv.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t tv_image = {
- 100, 100, 4,
+ 100, 100, 4, 0,
"\377\377\0\377\0\377\377\0\377\0\222\377\0\377\0\203\332\332\332\377\202\271"
"\272\274\377\5\252\253\256\377\232\232\237\377\215\215\223\377}}\202\377l"
"lx\377\202]]g\377\7rr\177\377\200\200\215\377\215\215\223\377\232\232\237"
diff --git a/src/image_data/tv_banner.h b/src/image_data/tv_banner.h
index f9fe950..17aa23d 100644
--- a/src/image_data/tv_banner.h
+++ b/src/image_data/tv_banner.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t tv_banner_image = {
- 360, 60, 3,
+ 360, 60, 3, 180,
"\1MV'\203]x\20\202l\212\25\377\201\222\34\311\201\222\34\15\215\231L\224"
"\232j\202\203\206zz\200\212\212\216\221\221\224\232\233\237\237\237\240\240"
"\240\244\237\237\240\232\233\237\221\221\224\212\212\216\203\221\221\224"
diff --git a/src/image_data/xvideo_banner.h b/src/image_data/xvideo_banner.h
index db72142..92166ac 100644
--- a/src/image_data/xvideo_banner.h
+++ b/src/image_data/xvideo_banner.h
@@ -3,7 +3,7 @@
#include "image.h"
static const nv_image_t xvideo_banner_image = {
- 360, 60, 3,
+ 360, 60, 3, 180,
"\204Zr\27\1j\207\30\377\202\222\34\312\202\222\34\7\220\233P\231\243j\200"
"\200\201yy{\214\214\217\222\222\224\234\234\237\203\237\237\243\2\234\234"
"\237\222\222\224\202\214\214\217\202\222\222\224\4\214\214\217\200\200\211"
diff --git a/src/libXNVCtrl/Makefile.inc b/src/libXNVCtrl/Makefile.inc
index d256dbb..d3ecbeb 100644
--- a/src/libXNVCtrl/Makefile.inc
+++ b/src/libXNVCtrl/Makefile.inc
@@ -26,6 +26,7 @@
#
EXTRA_DIST += \
+ Makefile.inc \
NVCtrl.h \
NVCtrlLib.h \
libXNVCtrl.a \
@@ -33,3 +34,6 @@ EXTRA_DIST += \
nv_control.h \
README.LIBXNVCTRL \
Imakefile
+
+dist_list::
+ @ echo $(SRC) $(EXTRA_DIST)
diff --git a/src/libXNVCtrl/NVCtrl.c b/src/libXNVCtrl/NVCtrl.c
index 78fe373..cbb7be6 100644
--- a/src/libXNVCtrl/NVCtrl.c
+++ b/src/libXNVCtrl/NVCtrl.c
@@ -1199,6 +1199,82 @@ Bool XNVCTRLQueryBinaryData (
attribute, ptr, len);
}
+Bool XNVCTRLStringOperation (
+ Display *dpy,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ char *pIn,
+ char **ppOut
+) {
+ XExtDisplayInfo *info = find_display(dpy);
+ xnvCtrlStringOperationReq *req;
+ xnvCtrlStringOperationReply rep;
+ Bool ret;
+ int inSize, outSize, length, slop;
+
+ if (!XextHasExtension(info))
+ return False;
+
+ if (!ppOut)
+ return False;
+
+ *ppOut = NULL;
+
+ XNVCTRLCheckExtension(dpy, info, False);
+ XNVCTRLCheckTargetData(dpy, info, &target_type, &target_id);
+
+ if (pIn) {
+ inSize = strlen(pIn) + 1;
+ } else {
+ inSize = 0;
+ }
+
+ LockDisplay(dpy);
+ GetReq(nvCtrlStringOperation, req);
+
+ req->reqType = info->codes->major_opcode;
+ req->nvReqType = X_nvCtrlStringOperation;
+ req->target_type = target_type;
+ req->target_id = target_id;
+ req->display_mask = display_mask;
+ req->attribute = attribute;
+
+ req->length += ((inSize + 3) & ~3) >> 2;
+ req->num_bytes = inSize;
+
+ if (pIn) {
+ Data(dpy, pIn, inSize);
+ }
+
+ if (!_XReply (dpy, (xReply *) &rep, 0, False)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+
+ length = rep.length;
+ outSize = rep.num_bytes;
+ slop = outSize & 3;
+
+ if (outSize) *ppOut = (char *) Xmalloc(outSize);
+
+ if (!*ppOut) {
+ _XEatData(dpy, length);
+ } else {
+ _XRead(dpy, (char *) *ppOut, outSize);
+ if (slop) _XEatData(dpy, 4-slop);
+ }
+
+ ret = rep.ret;
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ return ret;
+}
+
static Bool wire_to_event (Display *dpy, XEvent *host, xEvent *wire)
{
diff --git a/src/libXNVCtrl/NVCtrl.h b/src/libXNVCtrl/NVCtrl.h
index 86a819c..b015dd7 100644
--- a/src/libXNVCtrl/NVCtrl.h
+++ b/src/libXNVCtrl/NVCtrl.h
@@ -18,6 +18,7 @@
#define NV_CTRL_TARGET_TYPE_X_SCREEN 0
#define NV_CTRL_TARGET_TYPE_GPU 1
#define NV_CTRL_TARGET_TYPE_FRAMELOCK 2
+#define NV_CTRL_TARGET_TYPE_VCSC 3 /* Visual Computing System Controller */
/**************************************************************************/
@@ -55,6 +56,13 @@
*
* F: The attribute may be queried using an NV_CTRL_TARGET_TYPE_FRAMELOCK
* target type via XNVCTRLQueryTargetAttribute().
+ *
+ * X: When Xinerama is enabled, this attribute is kept consistent across
+ * all Physical X Screens; Assignment of this attribute will be
+ * broadcast by the NVIDIA X Driver to all X Screens.
+ *
+ * V: The attribute may be queried using an NV_CTRL_TARGET_TYPE_VCSC
+ * target type via XNVCTRLQueryTargetXXXAttribute().
*
* NOTE: Unless mentioned otherwise, all attributes may be queried using
* an NV_CTRL_TARGET_TYPE_X_SCREEN target type via
@@ -93,7 +101,7 @@
* ratio correct)
*/
-#define NV_CTRL_FLATPANEL_SCALING 2 /* RWD */
+#define NV_CTRL_FLATPANEL_SCALING 2 /* RWDG */
#define NV_CTRL_FLATPANEL_SCALING_DEFAULT 0
#define NV_CTRL_FLATPANEL_SCALING_NATIVE 1
#define NV_CTRL_FLATPANEL_SCALING_SCALED 2
@@ -110,7 +118,7 @@
* 2: disabled (the driver will never dither)
*/
-#define NV_CTRL_FLATPANEL_DITHERING 3 /* RWD */
+#define NV_CTRL_FLATPANEL_DITHERING 3 /* RWDG */
#define NV_CTRL_FLATPANEL_DITHERING_DEFAULT 0
#define NV_CTRL_FLATPANEL_DITHERING_ENABLED 1
#define NV_CTRL_FLATPANEL_DITHERING_DISABLED 2
@@ -121,7 +129,7 @@
* specified display device.
*/
-#define NV_CTRL_DIGITAL_VIBRANCE 4 /* RWD */
+#define NV_CTRL_DIGITAL_VIBRANCE 4 /* RWDG */
/*
@@ -129,7 +137,7 @@
* driving the specified X screen is connected to the computer.
*/
-#define NV_CTRL_BUS_TYPE 5 /* R-- */
+#define NV_CTRL_BUS_TYPE 5 /* R--G */
#define NV_CTRL_BUS_TYPE_AGP 0
#define NV_CTRL_BUS_TYPE_PCI 1
#define NV_CTRL_BUS_TYPE_PCI_EXPRESS 2
@@ -137,11 +145,16 @@
/*
- * NV_CTRL_VIDEO_RAM - returns the amount of video ram on the GPU
- * driving the specified X screen.
+ * NV_CTRL_VIDEO_RAM - returns the total amount of memory available
+ * to the specified GPU (or the GPU driving the specified X
+ * screen). Note: if the GPU supports TurboCache(TM), the value
+ * reported may exceed the amount of video memory installed on the
+ * GPU. The value reported for integrated GPUs may likewise exceed
+ * the amount of dedicated system memory set aside by the system
+ * BIOS for use by the integrated GPU.
*/
-#define NV_CTRL_VIDEO_RAM 6 /* R-- */
+#define NV_CTRL_VIDEO_RAM 6 /* R--G */
/*
@@ -149,7 +162,7 @@
* driving the specified X screen.
*/
-#define NV_CTRL_IRQ 7 /* R-- */
+#define NV_CTRL_IRQ 7 /* R--G */
/*
@@ -157,7 +170,7 @@
* the X server is running.
*/
-#define NV_CTRL_OPERATING_SYSTEM 8 /* R-- */
+#define NV_CTRL_OPERATING_SYSTEM 8 /* R--G */
#define NV_CTRL_OPERATING_SYSTEM_LINUX 0
#define NV_CTRL_OPERATING_SYSTEM_FREEBSD 1
#define NV_CTRL_OPERATING_SYSTEM_SUNOS 2
@@ -169,7 +182,7 @@
* after this setting is applied.
*/
-#define NV_CTRL_SYNC_TO_VBLANK 9 /* RW- */
+#define NV_CTRL_SYNC_TO_VBLANK 9 /* RW-X */
#define NV_CTRL_SYNC_TO_VBLANK_OFF 0
#define NV_CTRL_SYNC_TO_VBLANK_ON 1
@@ -182,7 +195,7 @@
* clients that are started after this setting is applied.
*/
-#define NV_CTRL_LOG_ANISO 10 /* RW- */
+#define NV_CTRL_LOG_ANISO 10 /* RW-X */
/*
@@ -203,7 +216,7 @@
* after this setting is applied.
*/
-#define NV_CTRL_FSAA_MODE 11 /* RW- */
+#define NV_CTRL_FSAA_MODE 11 /* RW-X */
#define NV_CTRL_FSAA_MODE_NONE 0
#define NV_CTRL_FSAA_MODE_2x 1
#define NV_CTRL_FSAA_MODE_2x_5t 2
@@ -223,7 +236,7 @@
* started after this setting is applied.
*/
-#define NV_CTRL_TEXTURE_SHARPEN 12 /* RW- */
+#define NV_CTRL_TEXTURE_SHARPEN 12 /* RW-X */
#define NV_CTRL_TEXTURE_SHARPEN_OFF 0
#define NV_CTRL_TEXTURE_SHARPEN_ON 1
@@ -566,7 +579,7 @@
* after this setting is applied.
*/
-#define NV_CTRL_FORCE_GENERIC_CPU 37 /* RW- */
+#define NV_CTRL_FORCE_GENERIC_CPU 37 /* RW-X */
#define NV_CTRL_FORCE_GENERIC_CPU_DISABLE 0
#define NV_CTRL_FORCE_GENERIC_CPU_ENABLE 1
@@ -580,7 +593,7 @@
* applied.
*/
-#define NV_CTRL_OPENGL_AA_LINE_GAMMA 38 /* RW- */
+#define NV_CTRL_OPENGL_AA_LINE_GAMMA 38 /* RW-X */
#define NV_CTRL_OPENGL_AA_LINE_GAMMA_DISABLE 0
#define NV_CTRL_OPENGL_AA_LINE_GAMMA_ENABLE 1
@@ -606,7 +619,7 @@
* can this be enabled dynamically?
*/
-#define NV_CTRL_FLIPPING_ALLOWED 40 /* RW- */
+#define NV_CTRL_FLIPPING_ALLOWED 40 /* RW-X */
#define NV_CTRL_FLIPPING_ALLOWED_FALSE 0
#define NV_CTRL_FLIPPING_ALLOWED_TRUE 1
@@ -631,7 +644,7 @@
* GPUS, or incorrect texture clamping in certain applications.
*/
-#define NV_CTRL_TEXTURE_CLAMPING 42 /* RW- */
+#define NV_CTRL_TEXTURE_CLAMPING 42 /* RW-X */
#define NV_CTRL_TEXTURE_CLAMPING_EDGE 0
#define NV_CTRL_TEXTURE_CLAMPING_SPEC 1
@@ -658,7 +671,7 @@
* NV_CTRL_FSAA_MODE
*/
-#define NV_CTRL_FSAA_APPLICATION_CONTROLLED 50 /* RW- */
+#define NV_CTRL_FSAA_APPLICATION_CONTROLLED 50 /* RW-X */
#define NV_CTRL_FSAA_APPLICATION_CONTROLLED_ENABLED 1
#define NV_CTRL_FSAA_APPLICATION_CONTROLLED_DISABLED 0
@@ -670,7 +683,7 @@
* NV_CTRL_LOG_ANISO
*/
-#define NV_CTRL_LOG_ANISO_APPLICATION_CONTROLLED 51 /* RW- */
+#define NV_CTRL_LOG_ANISO_APPLICATION_CONTROLLED 51 /* RW-X */
#define NV_CTRL_LOG_ANISO_APPLICATION_CONTROLLED_ENABLED 1
#define NV_CTRL_LOG_ANISO_APPLICATION_CONTROLLED_DISABLED 0
@@ -682,7 +695,7 @@
* newer.
*/
-#define NV_CTRL_IMAGE_SHARPENING 52 /* RWD */
+#define NV_CTRL_IMAGE_SHARPENING 52 /* RWDG */
/*
@@ -690,7 +703,7 @@
* display device.
*/
-#define NV_CTRL_TV_OVERSCAN 53 /* RWD */
+#define NV_CTRL_TV_OVERSCAN 53 /* RWDG */
/*
@@ -698,7 +711,7 @@
* the specified display device.
*/
-#define NV_CTRL_TV_FLICKER_FILTER 54 /* RWD */
+#define NV_CTRL_TV_FLICKER_FILTER 54 /* RWDG */
/*
@@ -706,7 +719,7 @@
* specified display device.
*/
-#define NV_CTRL_TV_BRIGHTNESS 55 /* RWD */
+#define NV_CTRL_TV_BRIGHTNESS 55 /* RWDG */
/*
@@ -714,7 +727,7 @@
* device.
*/
-#define NV_CTRL_TV_HUE 56 /* RWD */
+#define NV_CTRL_TV_HUE 56 /* RWDG */
/*
@@ -722,7 +735,7 @@
* display device.
*/
-#define NV_CTRL_TV_CONTRAST 57 /* RWD */
+#define NV_CTRL_TV_CONTRAST 57 /* RWDG */
/*
@@ -730,7 +743,7 @@
* specified display device.
*/
-#define NV_CTRL_TV_SATURATION 58 /* RWD */
+#define NV_CTRL_TV_SATURATION 58 /* RWDG */
/*
@@ -740,7 +753,7 @@
* the TV attributes be queried to retrieve their new values.
*/
-#define NV_CTRL_TV_RESET_SETTINGS 59 /* -WD */
+#define NV_CTRL_TV_RESET_SETTINGS 59 /* -WDG */
/*
@@ -748,7 +761,7 @@
* of the GPU driving the X screen.
*/
-#define NV_CTRL_GPU_CORE_TEMPERATURE 60 /* R-- */
+#define NV_CTRL_GPU_CORE_TEMPERATURE 60 /* R--G */
/*
@@ -761,9 +774,9 @@
* GPU is throttled to prevent overheating.
*/
-#define NV_CTRL_GPU_CORE_THRESHOLD 61 /* R-- */
-#define NV_CTRL_GPU_DEFAULT_CORE_THRESHOLD 62 /* R-- */
-#define NV_CTRL_GPU_MAX_CORE_THRESHOLD 63 /* R-- */
+#define NV_CTRL_GPU_CORE_THRESHOLD 61 /* R--G */
+#define NV_CTRL_GPU_DEFAULT_CORE_THRESHOLD 62 /* R--G */
+#define NV_CTRL_GPU_MAX_CORE_THRESHOLD 63 /* R--G */
/*
@@ -771,7 +784,7 @@
* immediate neighbourhood of the GPU driving the X screen.
*/
-#define NV_CTRL_AMBIENT_TEMPERATURE 64 /* R-- */
+#define NV_CTRL_AMBIENT_TEMPERATURE 64 /* R--G */
/*
@@ -952,16 +965,16 @@
#define NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_30_00_SMPTE274 26
#define NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_24_00_SMPTE274 27
#define NV_CTRL_GVO_VIDEO_FORMAT_1080PSF_23_98_SMPTE274 28
-#define NV_CTRL_GVO_VIDEO_FORMAT_1080P_30_00_SMPTE372 29
-#define NV_CTRL_GVO_VIDEO_FORMAT_1080P_29_97_SMPTE372 30
-#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_30_00_SMPTE372 31
-#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_29_97_SMPTE372 32
-#define NV_CTRL_GVO_VIDEO_FORMAT_1080P_25_00_SMPTE372 33
-#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_25_00_SMPTE372 34
-#define NV_CTRL_GVO_VIDEO_FORMAT_1080P_24_00_SMPTE372 35
-#define NV_CTRL_GVO_VIDEO_FORMAT_1080P_23_98_SMPTE372 36
-#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_24_00_SMPTE372 37
-#define NV_CTRL_GVO_VIDEO_FORMAT_1080I_23_98_SMPTE372 38
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048P_30_00_SMPTE372 29
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048P_29_97_SMPTE372 30
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048I_60_00_SMPTE372 31
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048I_59_94_SMPTE372 32
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048P_25_00_SMPTE372 33
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048I_50_00_SMPTE372 34
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048P_24_00_SMPTE372 35
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048P_23_98_SMPTE372 36
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048I_48_00_SMPTE372 37
+#define NV_CTRL_GVO_VIDEO_FORMAT_2048I_47_96_SMPTE372 38
/*
* NV_CTRL_GVO_INPUT_VIDEO_FORMAT - indicates the input video format
@@ -1186,7 +1199,7 @@
* has been enabled in the X server (by the user).
*/
-#define NV_CTRL_GPU_OVERCLOCKING_STATE 88 /* RW- */
+#define NV_CTRL_GPU_OVERCLOCKING_STATE 88 /* RW-G */
#define NV_CTRL_GPU_OVERCLOCKING_STATE_NONE 0
#define NV_CTRL_GPU_OVERCLOCKING_STATE_MANUAL 1
@@ -1205,8 +1218,8 @@
* attribute after the set to determine success or failure.
*/
-#define NV_CTRL_GPU_2D_CLOCK_FREQS 89 /* RW- */
-#define NV_CTRL_GPU_3D_CLOCK_FREQS 90 /* RW- */
+#define NV_CTRL_GPU_2D_CLOCK_FREQS 89 /* RW-G */
+#define NV_CTRL_GPU_3D_CLOCK_FREQS 90 /* RW-G */
/*
@@ -1214,8 +1227,8 @@
* and GPU core clocks of the device driving the X screen.
*/
-#define NV_CTRL_GPU_DEFAULT_2D_CLOCK_FREQS 91 /* R-- */
-#define NV_CTRL_GPU_DEFAULT_3D_CLOCK_FREQS 92 /* R-- */
+#define NV_CTRL_GPU_DEFAULT_2D_CLOCK_FREQS 91 /* R--G */
+#define NV_CTRL_GPU_DEFAULT_3D_CLOCK_FREQS 92 /* R--G */
/*
@@ -1223,7 +1236,7 @@
* clocks of the graphics device driving the X screen.
*/
-#define NV_CTRL_GPU_CURRENT_CLOCK_FREQS 93 /* R-- */
+#define NV_CTRL_GPU_CURRENT_CLOCK_FREQS 93 /* R--G */
/*
@@ -1237,7 +1250,7 @@
* optimal clock detection process is unavailable.
*/
-#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS 94 /* R-- */
+#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS 94 /* R--G */
#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_INVALID 0
@@ -1255,7 +1268,7 @@
* optimal clock detection process is unavailable.
*/
-#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION 95 /* -W- */
+#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION 95 /* -W-G */
#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_START 0
#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_CANCEL 1
@@ -1270,7 +1283,7 @@
* optimal clock detection process is unavailable.
*/
-#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE 96 /* R-- */
+#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE 96 /* R--G */
#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE_IDLE 0
#define NV_CTRL_GPU_OPTIMAL_CLOCK_FREQS_DETECTION_STATE_BUSY 1
@@ -2543,7 +2556,6 @@
* stereo drawable is visible.
*/
-
#define NV_CTRL_FORCE_STEREO 220 /* RW- */
#define NV_CTRL_FORCE_STEREO_FALSE 0
#define NV_CTRL_FORCE_STEREO_TRUE 1
@@ -2556,7 +2568,7 @@
* after this setting is applied.
*/
-#define NV_CTRL_IMAGE_SETTINGS 221 /* RW- */
+#define NV_CTRL_IMAGE_SETTINGS 221 /* RW-X */
#define NV_CTRL_IMAGE_SETTINGS_HIGH_QUALITY 0
#define NV_CTRL_IMAGE_SETTINGS_QUALITY 1
#define NV_CTRL_IMAGE_SETTINGS_PERFORMANCE 2
@@ -2567,8 +2579,7 @@
* NV_CTRL_XINERAMA - return whether xinerama is enabled
*/
-
-#define NV_CTRL_XINERAMA 222 /* RW- */
+#define NV_CTRL_XINERAMA 222 /* R--G */
#define NV_CTRL_XINERAMA_OFF 0
#define NV_CTRL_XINERAMA_ON 1
@@ -2589,19 +2600,19 @@
* returns the width of the physical link.
*/
-#define NV_CTRL_BUS_RATE 224 /* R-- */
+#define NV_CTRL_BUS_RATE 224 /* R--G */
/*
* NV_CTRL_SHOW_SLI_HUD - when TRUE, OpenGL will draw information about the
* current SLI mode.
*/
-#define NV_CTRL_SHOW_SLI_HUD 225 /* RW- */
+#define NV_CTRL_SHOW_SLI_HUD 225 /* RW-X */
#define NV_CTRL_SHOW_SLI_HUD_FALSE 0
#define NV_CTRL_SHOW_SLI_HUD_TRUE 1
/*
- * NV_CTRL_XV_SYNC_TO_DISPLAY - this control is valid when twinview and
+ * NV_CTRL_XV_SYNC_TO_DISPLAY - this control is valid when TwinView and
* XVideo Sync To VBlank are enabled.
* It controls which display device will be synched to.
*/
@@ -2739,10 +2750,99 @@
* specified display device.
*/
-#define NV_CTRL_CURRENT_SCANLINE 237 /* R-D */
+#define NV_CTRL_CURRENT_SCANLINE 237 /* R-DG */
+
+
+/*
+ * NV_CTRL_INITIAL_PIXMAP_PLACEMENT - Controls where X pixmaps are initially
+ * created.
+ *
+ * NV_CTRL_INITIAL_PIXMAP_PLACEMENT_FORCE_SYSMEM causes to pixmaps to stay in
+ * system memory.
+ * NV_CTRL_INITIAL_PIXMAP_PLACEMENT_SYSMEM creates pixmaps in system memory
+ * initially, but allows them to migrate to video memory.
+ * NV_CTRL_INITIAL_PIXMAP_PLACEMENT_VIDMEM creates pixmaps in video memory
+ * when enough resources are available.
+ */
+
+#define NV_CTRL_INITIAL_PIXMAP_PLACEMENT 238 /* RW- */
+#define NV_CTRL_INITIAL_PIXMAP_PLACEMENT_FORCE_SYSMEM 0
+#define NV_CTRL_INITIAL_PIXMAP_PLACEMENT_SYSMEM 1
+#define NV_CTRL_INITIAL_PIXMAP_PLACEMENT_VIDMEM 2
+
+
+/*
+ * NV_CTRL_PCI_BUS - Returns the PCI bus number the GPU is using.
+ */
+#define NV_CTRL_PCI_BUS 239 /* R--G */
-#define NV_CTRL_LAST_ATTRIBUTE NV_CTRL_CURRENT_SCANLINE
+
+/*
+ * NV_CTRL_PCI_DEVICE - Returns the PCI device number the GPU is using.
+ */
+
+#define NV_CTRL_PCI_DEVICE 240 /* R--G */
+
+
+/*
+ * NV_CTRL_PCI_FUNCTION - Returns the PCI function number the GPU is using.
+ */
+
+#define NV_CTRL_PCI_FUNCTION 241 /* R--G */
+
+
+/*
+ * NV_CTRL_FRAMELOCK_FPGA_REVISION - Querys the FPGA revision of the
+ * Frame Lock device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetAttribute()
+ * using a NV_CTRL_TARGET_TYPE_FRAMELOCK target.
+ */
+
+#define NV_CTRL_FRAMELOCK_FPGA_REVISION 242 /* R--F */
+
+
+/*
+ * NV_CTRL_MAX_SCREEN_{WIDTH,HEIGHT} - the maximum allowable size, in
+ * pixels, of either the specified X screen (if the target_type of the
+ * query is an X screen), or any X screen on the specified GPU (if the
+ * target_type of the query is a GPU).
+ */
+
+#define NV_CTRL_MAX_SCREEN_WIDTH 243 /* R--G */
+#define NV_CTRL_MAX_SCREEN_HEIGHT 244 /* R--G */
+
+
+/*
+ * NV_CTRL_MAX_DISPLAYS - the maximum number of display devices that
+ * can be driven simultaneously on a GPU (e.g., that can be used in a
+ * MetaMode at once). Note that this does not indicate the maximum
+ * number of bits that can be set in NV_CTRL_CONNECTED_DISPLAYS,
+ * because more display devices can be connected than are actively in
+ * use.
+ */
+
+#define NV_CTRL_MAX_DISPLAYS 245 /* R--G */
+
+
+/*
+ * NV_CTRL_DYNAMIC_TWINVIEW - Returns whether or not the screen
+ * supports dynamic twinview.
+ */
+
+#define NV_CTRL_DYNAMIC_TWINVIEW 246 /* R-- */
+
+
+/*
+ * NV_CTRL_MULTIGPU_DISPLAY_OWNER - Returns the GPU ID of the GPU
+ * that has the display device(s) used for showing the X Screen.
+ */
+
+#define NV_CTRL_MULTIGPU_DISPLAY_OWNER 247 /* R-- */
+
+
+#define NV_CTRL_LAST_ATTRIBUTE NV_CTRL_MULTIGPU_DISPLAY_OWNER
/**************************************************************************/
@@ -2781,7 +2881,7 @@
* which the specified X screen is running.
*/
-#define NV_CTRL_STRING_VBIOS_VERSION 1 /* R-- */
+#define NV_CTRL_STRING_VBIOS_VERSION 1 /* R--G */
/*
@@ -2789,7 +2889,7 @@
* NVIDIA driver version number for the NVIDIA X driver in use.
*/
-#define NV_CTRL_STRING_NVIDIA_DRIVER_VERSION 3 /* R-- */
+#define NV_CTRL_STRING_NVIDIA_DRIVER_VERSION 3 /* R--G */
/*
@@ -2808,7 +2908,7 @@
* specified display device; only valid if the display device is a TV.
*/
-#define NV_CTRL_STRING_TV_ENCODER_NAME 5 /* R-D */
+#define NV_CTRL_STRING_TV_ENCODER_NAME 5 /* R-DG */
/* NV_CTRL_STRING_DDCCI_MISC_TRANSMIT_DISPLAY_DESCRIPTOR -
@@ -2841,35 +2941,44 @@
/*
- * NV_CTRL_STRING_CURRENT_MODELINE - Return the modeline currently
+ * NV_CTRL_STRING_CURRENT_MODELINE - Return the ModeLine currently
* being used by the specified display device.
*
* This attribute may be queried through XNVCTRLQueryTargetStringAttribute()
- * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ * using an NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ *
+ * The ModeLine string may be prepended with a comma-separated list of
+ * "token=value" pairs, separated from the ModeLine string by "::".
+ * This "token=value" syntax is the same as that used in
+ * NV_CTRL_BINARY_DATA_MODELINES
*/
#define NV_CTRL_STRING_CURRENT_MODELINE 9 /* R-DG */
/*
- * NV_CTRL_STRING_ADD_MODELINE - Adds a modeline to the specified
- * display device. The modeline is not added if validation fails.
+ * NV_CTRL_STRING_ADD_MODELINE - Adds a ModeLine to the specified
+ * display device. The ModeLine is not added if validation fails.
*
- * This attribute may be queried through XNVCTRLQueryTargetStringAttribute()
- * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ * The ModeLine string should have the same syntax as a ModeLine in
+ * the X configuration file; e.g.,
+ *
+ * "1600x1200" 229.5 1600 1664 1856 2160 1200 1201 1204 1250 +HSync +VSync
*/
#define NV_CTRL_STRING_ADD_MODELINE 10 /* -WDG */
/*
- * NV_CTRL_STRING_DELETE_MODLEINE - Deletes an existing modeline
+ * NV_CTRL_STRING_DELETE_MODELINE - Deletes an existing ModeLine
* from the specified display device. The currently selected
- * modeline cannot be deleted. (This also means you cannot delete
- * the last modeline.)
+ * ModeLine cannot be deleted. (This also means you cannot delete
+ * the last ModeLine.)
*
- * This attribute may be queried through XNVCTRLQueryTargetStringAttribute()
- * using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ * The ModeLine string should have the same syntax as a ModeLine in
+ * the X configuration file; e.g.,
+ *
+ * "1600x1200" 229.5 1600 1664 1856 2160 1200 1201 1204 1250 +HSync +VSync
*/
#define NV_CTRL_STRING_DELETE_MODELINE 11 /* -WDG */
@@ -2877,36 +2986,244 @@
/*
* NV_CTRL_STRING_CURRENT_METAMODE - Returns the metamode currently
- * being used by the specified X screen.
+ * being used by the specified X screen. The MetaMode string has the
+ * same syntax as the MetaMode X configuration option, as documented
+ * in the NVIDIA driver README.
+ *
+ * The returned string may be prepended with a comma-separated list of
+ * "token=value" pairs, separated from the MetaMode string by "::".
+ * This "token=value" syntax is the same as that used in
+ * NV_CTRL_BINARY_DATA_METAMODES.
*/
#define NV_CTRL_STRING_CURRENT_METAMODE 12 /* R--- */
/*
- * NV_CTRL_STRING_ADD_METAMODE - Adds a metamode to the specified
- * X Screen (or GPU). All modelines referenced in the metamode
- * must already exist for each display device (as returned by the
- * NV_CTRL_BINARY_DATA_MODELINES attribute)
+ * NV_CTRL_STRING_ADD_METAMODE - Adds a MetaMode to the specified
+ * X Screen.
*
- * TwinView must be enabled on the X Screen/GPU to access this attribute.
+ * It is recommended to not use this attribute, but instead use
+ * NV_CTRL_STRING_OPERATION_ADD_METAMODE.
*/
#define NV_CTRL_STRING_ADD_METAMODE 13 /* -W-- */
/*
- * NV_CTRL_STRING_DELETE_METAMODE - Deletes an existing metamode
- * from the specified X Screen (or GPU). The currently selected
- * metamode cannot be deleted. (This also means you cannot delete
- * the last metamode.)
- *
- * TwinView must be enabled on the X Screen/GPU to access this attribute.
+ * NV_CTRL_STRING_DELETE_METAMODE - Deletes an existing MetaMode from
+ * the specified X Screen. The currently selected MetaMode cannot be
+ * deleted. (This also means you cannot delete the last MetaMode).
+ * The MetaMode string should have the same syntax as the MetaMode X
+ * configuration option, as documented in the NVIDIA driver README.
*/
#define NV_CTRL_STRING_DELETE_METAMODE 14 /* -WD-- */
-#define NV_CTRL_STRING_LAST_ATTRIBUTE NV_CTRL_STRING_DELETE_METAMODE
+
+/*
+ * NV_CTRL_STRING_VCSC_PRODUCT_NAME - Querys the product name of the
+ * VCSC device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_PRODUCT_NAME 15 /* R---V */
+
+
+/*
+ * NV_CTRL_STRING_VCSC_PRODUCT_ID - Querys the product ID of the VCSC device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_PRODUCT_ID 16 /* R---V */
+
+
+/*
+ * NV_CTRL_STRING_VCSC_SERIAL_NUMBER - Querys the unique serial number
+ * of the VCSC device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_SERIAL_NUMBER 17 /* R---V */
+
+
+/*
+ * NV_CTRL_STRING_VCSC_BUILD_DATE - Querys the date of the VCSC device.
+ * the returned string is in the following format: "Week.Year"
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_BUILD_DATE 18 /* R---V */
+
+
+/*
+ * NV_CTRL_STRING_VCSC_FIRMWARE_VERSION - Querys the firmware version
+ * of the VCSC device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_FIRMWARE_VERSION 19 /* R---V */
+
+
+/*
+ * NV_CTRL_STRING_VCSC_FIRMWARE_REVISION - Querys the firmware revision
+ * of the VCSC device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_FIRMWARE_REVISION 20 /* R---V */
+
+
+/*
+ * NV_CTRL_STRING_VCSC_HARDWARE_VERSION - Querys the hardware version
+ * of the VCSC device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_HARDWARE_VERSION 21 /* R---V */
+
+
+/*
+ * NV_CTRL_STRING_VCSC_HARDWARE_REVISION - Querys the hardware revision
+ * of the VCSC device.
+ *
+ * This attribute must be queried through XNVCTRLQueryTargetStringAttribute()
+ * using a NV_CTRL_TARGET_TYPE_VCSC target.
+ */
+
+#define NV_CTRL_STRING_VCSC_HARDWARE_REVISION 22 /* R---V */
+
+
+/*
+ * NV_CTRL_STRING_MOVE_METAMODE - Moves a MetaMode to the specified
+ * index location. The MetaMode must already exist in the X Screen's
+ * list of MetaModes (as returned by the NV_CTRL_BINARY_DATA_METAMODES
+ * attribute). If the index is larger than the number of MetaModes in
+ * the list, the MetaMode is moved to the end of the list. The
+ * MetaMode string should have the same syntax as the MetaMode X
+ * configuration option, as documented in the NVIDIA driver README.
+
+ * The MetaMode string must be prepended with a comma-separated list
+ * of "token=value" pairs, separated from the MetaMode string by "::".
+ * Currently, the only valid token is "index", which indicates where
+ * in the MetaMode list the MetaMode should be moved to.
+ *
+ * Other tokens may be added in the future.
+ *
+ * E.g.,
+ * "index=5 :: CRT-0: 1024x768 @1024x768 +0+0"
+ */
+
+#define NV_CTRL_STRING_MOVE_METAMODE 23 /* -W-- */
+
+
+
+/*
+ * NV_CTRL_STRING_VALID_HORIZ_SYNC_RANGES - returns the valid
+ * horizontal sync ranges used to perform mode validation for the
+ * specified display device. The ranges are in the same format as the
+ * "HorizSync" X config option:
+ *
+ * "horizsync-range may be a comma separated list of either discrete
+ * values or ranges of values. A range of values is two values
+ * separated by a dash."
+ *
+ * The values are in kHz.
+ *
+ * Additionally, the string may be prepended with a comma-separated
+ * list of "token=value" pairs, separated from the HorizSync string by
+ * "::". Valid tokens:
+ *
+ * Token Value
+ * "source" "edid" - HorizSync is from the display device's EDID
+ * "xconfig" - HorizSync is from the "HorizSync" entry in
+ * the Monitor section of the X config file
+ * "option" - HorizSync is from the "HorizSync" NVIDIA X
+ * config option
+ * "twinview" - HorizSync is from the "SecondMonitorHorizSync"
+ * NVIDIA X config option
+ * "builtin" - HorizSync is from NVIDIA X driver builtin
+ * default values
+ *
+ * Additional tokens and/or values may be added in the future.
+ *
+ * Example: "source=edid :: 30.000-62.000"
+ */
+
+#define NV_CTRL_STRING_VALID_HORIZ_SYNC_RANGES 24 /* R-DG */
+
+
+/*
+ * NV_CTRL_STRING_VALID_VERT_REFRESH_RANGES - returns the valid
+ * vertical refresh ranges used to perform mode validation for the
+ * specified display device. The ranges are in the same format as the
+ * "VertRefresh" X config option:
+ *
+ * "vertrefresh-range may be a comma separated list of either discrete
+ * values or ranges of values. A range of values is two values
+ * separated by a dash."
+ *
+ * The values are in Hz.
+ *
+ * Additionally, the string may be prepended with a comma-separated
+ * list of "token=value" pairs, separated from the VertRefresh string by
+ * "::". Valid tokens:
+ *
+ * Token Value
+ * "source" "edid" - VertRefresh is from the display device's EDID
+ * "xconfig" - VertRefresh is from the "VertRefresh" entry in
+ * the Monitor section of the X config file
+ * "option" - VertRefresh is from the "VertRefresh" NVIDIA X
+ * config option
+ * "twinview" - VertRefresh is from the "SecondMonitorVertRefresh"
+ * NVIDIA X config option
+ * "builtin" - VertRefresh is from NVIDIA X driver builtin
+ * default values
+ *
+ * Additional tokens and/or values may be added in the future.
+ *
+ * Example: "source=edid :: 50.000-75.000"
+ */
+
+#define NV_CTRL_STRING_VALID_VERT_REFRESH_RANGES 25 /* R-DG */
+
+
+/*
+ * NV_CTRL_STRING_XINERAMA_SCREEN_INFO - returns the physical X Screen's
+ * initial position and size (in absolute coordinates) within the Xinerama
+ * desktop as the "token=value" string: "x=#, y=#, width=#, height=#"
+ *
+ * Querying this attribute returns FALSE if NV_CTRL_XINERAMA is not
+ * NV_CTRL_XINERAMA_ON.
+ */
+
+#define NV_CTRL_STRING_XINERAMA_SCREEN_INFO 26 /* R--- */
+
+
+/*
+ * NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER - used to specify the
+ * order that display devices will be returned via Xinerama when
+ * TwinViewXineramaInfo is enabled. Follows the same syntax as the
+ * TwinViewXineramaInfoOrder X config option.
+ */
+
+#define NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER 27 /* RW-- */
+
+#define NV_CTRL_STRING_LAST_ATTRIBUTE NV_CTRL_STRING_TWINVIEW_XINERAMA_INFO_ORDER
/**************************************************************************/
@@ -2939,13 +3256,43 @@
/*
* NV_CTRL_BINARY_DATA_MODELINES - Returns a display device's supported
- * modelines. Modelines are returned in a buffer, separated by a single
- * \0 and terminated by two consecuitive \0's like so:
+ * ModeLines. ModeLines are returned in a buffer, separated by a single
+ * '\0' and terminated by two consecutive '\0' s like so:
*
- * "Modeline 1\0Modeline 2\0Modeline 3\0Last Modeline\0\0"
+ * "ModeLine 1\0ModeLine 2\0ModeLine 3\0Last ModeLine\0\0"
*
* This attribute may be queried through XNVCTRLQueryTargetBinaryData()
* using a NV_CTRL_TARGET_TYPE_GPU or NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ *
+ * Each ModeLine string may be prepended with a comma-separated list
+ * of "token=value" pairs, separated from the ModeLine string with a
+ * "::". Valid tokens:
+ *
+ * Token Value
+ * "source" "xserver" - the ModeLine is from the core X server
+ * "xconfig" - the ModeLine was specified in the X config file
+ * "builtin" - the NVIDIA driver provided this builtin ModeLine
+ * "vesa" - this is a VESA standard ModeLine
+ * "edid" - the ModeLine was in the display device's EDID
+ * "nv-control" - the ModeLine was specified via NV-CONTROL
+ *
+ * "xconfig-name" - for ModeLines that were specified in the X config
+ * file, this is the name the X config file
+ * gave for the ModeLine.
+ *
+ * Note that a ModeLine can have several sources; the "source" token
+ * can appear multiple times in the "token=value" pairs list.
+ * Additional source values may be specified in the future.
+ *
+ * Additional tokens may be added in the future, so it is recommended
+ * that any token parser processing the returned string from
+ * NV_CTRL_BINARY_DATA_MODELINES be implemented to gracefully ignore
+ * unrecognized tokens.
+ *
+ * E.g.,
+ *
+ * "source=xserver, source=vesa, source=edid :: "1024x768_70" 75.0 1024 1048 1184 1328 768 771 777 806 -HSync -VSync"
+ * "source=xconfig, xconfig-name=1600x1200_60.00 :: "1600x1200_60_0" 161.0 1600 1704 1880 2160 1200 1201 1204 1242 -HSync +VSync"
*/
#define NV_CTRL_BINARY_DATA_MODELINES 1 /* R-DG */
@@ -2953,10 +3300,47 @@
/*
* NV_CTRL_BINARY_DATA_METAMODES - Returns an X Screen's supported
- * metamodes. Metamodes are returned in a buffer separated by a single
- * \0 and terminated by two consecuitive \0's like so:
+ * MetaModes. MetaModes are returned in a buffer separated by a
+ * single '\0' and terminated by two consecutive '\0' s like so:
*
* "MetaMode 1\0MetaMode 2\0MetaMode 3\0Last MetaMode\0\0"
+ *
+ * The MetaMode string should have the same syntax as the MetaMode X
+ * configuration option, as documented in the NVIDIA driver README.
+
+ * Each MetaMode string may be prepended with a comma-separated list
+ * of "token=value" pairs, separated from the MetaMode string with
+ * "::". Currently, valid tokens are:
+ *
+ * Token Value
+ * "id" <number> - the id of this MetaMode; this is stored in
+ * the Vertical Refresh field, as viewed
+ * by the XRandR and XF86VidMode X *
+ * extensions.
+ *
+ * "switchable" "yes"/"no" - whether this MetaMode may be switched to via
+ * ctrl-alt-+/-; Implicit MetaModes (see
+ * the "IncludeImplicitMetaModes" X
+ * config option), for example, are not
+ * normally made available through
+ * ctrl-alt-+/-.
+ *
+ * "source" "xconfig" - the MetaMode was specified in the X
+ * config file.
+ * "implicit" - the MetaMode was implicitly added; see the
+ * "IncludeImplicitMetaModes" X config option
+ * for details.
+ * "nv-control" - the MetaMode was added via the NV-CONTROL X
+ * extension to the currently running X server.
+ *
+ * Additional tokens may be added in the future, so it is recommended
+ * that any token parser processing the returned string from
+ * NV_CTRL_BINARY_DATA_METAMODES be implemented to gracefully ignore
+ * unrecognized tokens.
+ *
+ * E.g.,
+ *
+ * "id=50, switchable=yes, source=xconfig :: CRT-0: 1024x768 @1024x768 +0+0"
*/
#define NV_CTRL_BINARY_DATA_METAMODES 2 /* R-D- */
@@ -2978,6 +3362,7 @@
#define NV_CTRL_BINARY_DATA_XSCREENS_USING_GPU 3 /* R-DG */
+
/*
* NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN - Returns the list of GPUs
* currently in use by the given X screen.
@@ -2990,6 +3375,7 @@
#define NV_CTRL_BINARY_DATA_GPUS_USED_BY_XSCREEN 4 /* R--- */
+
/*
* NV_CTRL_BINARY_DATA_GPUS_USING_FRAMELOCK - Returns the list of
* GPUs currently connected to the given frame lock board.
@@ -3006,8 +3392,153 @@
#define NV_CTRL_BINARY_DATA_GPUS_USING_FRAMELOCK 5 /* R-DF */
+
+/*
+ * NV_CTRL_BINARY_DATA_DISPLAY_VIEWPORT - Returns the Display Device's
+ * viewport box into the given X Screen (in X Screen coordinates.)
+ *
+ * The format of the returned data is:
+ *
+ * 4 CARD32 Offset X
+ * 4 CARD32 Offset Y
+ * 4 CARD32 Width
+ * 4 CARD32 Height
+ */
+
+#define NV_CTRL_BINARY_DATA_DISPLAY_VIEWPORT 6 /* R-DG */
+
+
#define NV_CTRL_BINARY_DATA_LAST_ATTRIBUTE \
- NV_CTRL_BINARY_DATA_GPUS_USING_FRAMELOCK
+ NV_CTRL_BINARY_DATA_DISPLAY_VIEWPORT
+
+
+/**************************************************************************/
+
+/*
+ * String Operation Attributes:
+ *
+ * These attributes are used with the XNVCTRLStringOperation()
+ * function; a string is specified as input, and a string is returned
+ * as output.
+ *
+ * Unless otherwise noted, all attributes can be operated upon using
+ * an NV_CTRL_TARGET_TYPE_X_SCREEN target.
+ */
+
+
+/*
+ * NV_CTRL_STRING_OPERATION_ADD_METAMODE - provide a MetaMode string
+ * as input, and returns a string containing comma-separated list of
+ * "token=value" pairs as output. Currently, the only output token is
+ * "id", which indicates the id that was assigned to the MetaMode.
+ *
+ * All ModeLines referenced in the MetaMode must already exist for
+ * each display device (as returned by the
+ * NV_CTRL_BINARY_DATA_MODELINES attribute).
+ *
+ * The MetaMode string should have the same syntax as the MetaMode X
+ * configuration option, as documented in the NVIDIA driver README.
+ *
+ * The input string can optionally be prepended with a string of
+ * comma-separated "token=value" pairs, separated from the MetaMode
+ * string by "::". Currently, the only valid token is "index" which
+ * indicates the insertion index for the MetaMode.
+ *
+ * E.g.,
+ *
+ * Input: "index=5 :: 1600x1200+0+0, 1600x1200+1600+0"
+ * Output: "id=58"
+ *
+ * which causes the MetaMode to be inserted at position 5 in the
+ * MetaMode list (all entries after 5 will be shifted down one slot in
+ * the list), and the X server's containing mode stores 58 as the
+ * VRefresh, so that the MetaMode can be uniquely identifed through
+ * XRandR and XF86VidMode.
+ */
+
+#define NV_CTRL_STRING_OPERATION_ADD_METAMODE 0
+
+
+/*
+ * NV_CTRL_STRING_OPERATION_GTF_MODELINE - provide as input a string
+ * of comma-separated "token=value" pairs, and returns a ModeLine
+ * string, computed using the GTF formula using the parameters from
+ * the input string. Valid tokens for the input string are "width",
+ * "height", and "refreshrate".
+ *
+ * E.g.,
+ *
+ * Input: "width=1600, height=1200, refreshrate=60"
+ * Output: "160.96 1600 1704 1880 2160 1200 1201 1204 1242 -HSync +VSync"
+ *
+ * This operation does not have any impact on any display device's
+ * modePool, and the ModeLine is not validated; it is simply intended
+ * for generating ModeLines.
+ */
+
+#define NV_CTRL_STRING_OPERATION_GTF_MODELINE 1
+
+
+/*
+ * NV_CTRL_STRING_OPERATION_CVT_MODELINE - provide as input a string
+ * of comma-separated "token=value" pairs, and returns a ModeLine
+ * string, computed using the CVT formula using the parameters from
+ * the input string. Valid tokens for the input string are "width",
+ * "height", "refreshrate", and "reduced-blanking". The
+ * "reduced-blanking" argument can be "0" or "1", to enable or disable
+ * use of reduced blanking for the CVT formula.
+ *
+ * E.g.,
+ *
+ * Input: "width=1600, height=1200, refreshrate=60, reduced-blanking=1"
+ * Output: "130.25 1600 1648 1680 1760 1200 1203 1207 1235 +HSync -VSync"
+ *
+ * This operation does not have any impact on any display device's
+ * modePool, and the ModeLine is not validated; it is simply intended
+ * for generating ModeLines.
+ */
+
+#define NV_CTRL_STRING_OPERATION_CVT_MODELINE 2
+
+
+/*
+ * NV_CTRL_STRING_OPERATION_BUILD_MODEPOOL - build a ModePool for the
+ * specified display device on the specified target (either an X
+ * screen or a GPU). This is typically used to generate a ModePool
+ * for a display device on a GPU on which no X screens are present.
+ *
+ * Currently, a display device's ModePool is static for the life of
+ * the X server, so XNVCTRLStringOperation will return FALSE if
+ * requested to build a ModePool on a display device that already has
+ * a ModePool.
+ *
+ * The string input to BUILD_MODEPOOL may be NULL. If it is not NULL,
+ * then it is interpreted as a double-semicolon ("::") separated list
+ * of "option=value" pairs, where the options and the syntax of their
+ * values are the X configuration options that impact the behavior of
+ * modePool construction; namely:
+ *
+ * "ModeValidation"
+ * "HorizSync"
+ * "VertRefresh"
+ * "FlatPanelProperties"
+ * "TVStandard"
+ * "ExactModeTimingsDVI"
+ * "UseEdidFreqs"
+ *
+ * An example input string might look like:
+ *
+ * "ModeValidation=NoVesaModes :: HorizSync=50-110 :: VertRefresh=50-150"
+ *
+ * This request currently does not return a string.
+ */
+
+#define NV_CTRL_STRING_OPERATION_BUILD_MODEPOOL 3 /* DG */
+
+
+#define NV_CTRL_STRING_OPERATION_LAST_ATTRIBUTE \
+ NV_CTRL_STRING_OPERATION_BUILD_MODEPOOL
+
/**************************************************************************/
@@ -3049,6 +3580,9 @@
* ATTRIBUTE_TYPE_GPU - Attribute is valid for GPU target types.
* ATTRIBUTE_TYPE_FRAMELOCK - Attribute is valid for Frame Lock target types.
* ATTRIBUTE_TYPE_X_SCREEN - Attribute is valid for X Screen target types.
+ * ATTRIBUTE_TYPE_XINERAMA - Attribute will be made consistent for all
+ * X Screens when the Xinerama extension is enabled.
+ *
*
* See 'Key to Integer Attribute "Permissions"' at the top of this
* file for a description of what these permission bits mean.
@@ -3067,6 +3601,8 @@
#define ATTRIBUTE_TYPE_GPU 0x08
#define ATTRIBUTE_TYPE_FRAMELOCK 0x10
#define ATTRIBUTE_TYPE_X_SCREEN 0x20
+#define ATTRIBUTE_TYPE_XINERAMA 0x40
+#define ATTRIBUTE_TYPE_VCSC 0x80
typedef struct _NVCTRLAttributeValidValues {
int type;
diff --git a/src/libXNVCtrl/NVCtrlLib.h b/src/libXNVCtrl/NVCtrlLib.h
index 318e978..75b07ad 100644
--- a/src/libXNVCtrl/NVCtrlLib.h
+++ b/src/libXNVCtrl/NVCtrlLib.h
@@ -661,6 +661,25 @@ Bool XNVCTRLQueryTargetBinaryData (
/*
+ * XNVCTRLStringOperation -
+ *
+ * Takes a string as input and returns a Xmalloc'ed string as output.
+ * Returns True on success and False on failure.
+ */
+
+Bool XNVCTRLStringOperation (
+ Display *dpy,
+ int target_type,
+ int target_id,
+ unsigned int display_mask,
+ unsigned int attribute,
+ char *pIn,
+ char **ppOut
+);
+
+
+
+/*
* XNVCtrlSelectNotify -
*
* This enables/disables receiving of NV-CONTROL events. The type
diff --git a/src/libXNVCtrl/libXNVCtrl.a b/src/libXNVCtrl/libXNVCtrl.a
index 9ec60d2..3b9c342 100644
--- a/src/libXNVCtrl/libXNVCtrl.a
+++ b/src/libXNVCtrl/libXNVCtrl.a
Binary files differ
diff --git a/src/libXNVCtrl/nv_control.h b/src/libXNVCtrl/nv_control.h
index e595918..012f397 100644
--- a/src/libXNVCtrl/nv_control.h
+++ b/src/libXNVCtrl/nv_control.h
@@ -6,7 +6,7 @@
#define NV_CONTROL_NAME "NV-CONTROL"
#define NV_CONTROL_MAJOR 1
-#define NV_CONTROL_MINOR 10
+#define NV_CONTROL_MINOR 12
#define X_nvCtrlQueryExtension 0
#define X_nvCtrlIsNv 1
@@ -33,7 +33,8 @@
#define X_nvCtrlQueryGvoColorConversion 22
#define X_nvCtrlSelectTargetNotify 23
#define X_nvCtrlQueryTargetCount 24
-#define X_nvCtrlLastRequest (X_nvCtrlQueryTargetCount + 1)
+#define X_nvCtrlStringOperation 25
+#define X_nvCtrlLastRequest (X_nvCtrlStringOperation + 1)
/* Define 32 bit floats */
@@ -609,6 +610,32 @@ typedef struct {
#define sz_xnvCtrlSelectNotifyReq 12
typedef struct {
+ CARD8 reqType;
+ CARD8 nvReqType;
+ CARD16 length B16;
+ CARD16 target_id B16; /* X screen number or GPU number */
+ CARD16 target_type B16; /* X screen or GPU */
+ CARD32 display_mask B32;
+ CARD32 attribute B32;
+ CARD32 num_bytes B32; /* Length of string */
+} xnvCtrlStringOperationReq;
+#define sz_xnvCtrlStringOperationReq 20
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ CARD8 padb1;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 ret B32;
+ CARD32 num_bytes B32; /* Length of string */
+ CARD32 padl4 B32;
+ CARD32 padl5 B32;
+ CARD32 padl6 B32;
+ CARD32 padl7 B32;
+} xnvCtrlStringOperationReply;
+#define sz_xnvCtrlStringOperationReply 32
+
+typedef struct {
union {
struct {
BYTE type;
diff --git a/src/libXNVCtrlAttributes/Makefile.inc b/src/libXNVCtrlAttributes/Makefile.inc
index 257cc7f..7c2a87c 100644
--- a/src/libXNVCtrlAttributes/Makefile.inc
+++ b/src/libXNVCtrlAttributes/Makefile.inc
@@ -34,5 +34,9 @@ SRC += \
NvCtrlAttributesXrandr.c
EXTRA_DIST += \
+ Makefile.inc \
NvCtrlAttributes.h \
NvCtrlAttributesPrivate.h
+
+dist_list::
+ @ echo $(SRC) $(EXTRA_DIST)
diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributes.c b/src/libXNVCtrlAttributes/NvCtrlAttributes.c
index 5cea7c5..172acf0 100644
--- a/src/libXNVCtrlAttributes/NvCtrlAttributes.c
+++ b/src/libXNVCtrlAttributes/NvCtrlAttributes.c
@@ -299,6 +299,163 @@ int NvCtrlGetXrandrEventBase(NvCtrlAttributeHandle *handle)
} /* NvCtrlGetXrandrEventBase() */
+/*
+ * NvCtrlGetServerVendor() - return the server vendor
+ * information string associated with this
+ * NvCtrlAttributeHandle.
+ */
+
+char *NvCtrlGetServerVendor(NvCtrlAttributeHandle *handle)
+{
+ NvCtrlAttributePrivateHandle *h;
+
+ if (!handle) return NULL;
+
+ h = (NvCtrlAttributePrivateHandle *) handle;
+
+ if (!h->dpy) return NULL;
+ return ServerVendor(h->dpy);
+
+} /* NvCtrlGetServerVendor() */
+
+
+/*
+ * NvCtrlGetVendorRelease() - return the server vendor
+ * release number associated with this NvCtrlAttributeHandle.
+ */
+
+int NvCtrlGetVendorRelease(NvCtrlAttributeHandle *handle)
+{
+ NvCtrlAttributePrivateHandle *h;
+
+ if (!handle) return -1;
+
+ h = (NvCtrlAttributePrivateHandle *) handle;
+
+ if (!h->dpy) return -1;
+ return VendorRelease(h->dpy);
+
+} /* NvCtrlGetVendorRelease() */
+
+
+/*
+ * NvCtrlGetScreenCount() - return the number of (logical)
+ * X Screens associated with this NvCtrlAttributeHandle.
+ */
+
+int NvCtrlGetScreenCount(NvCtrlAttributeHandle *handle)
+{
+ NvCtrlAttributePrivateHandle *h;
+
+ if (!handle) return -1;
+
+ h = (NvCtrlAttributePrivateHandle *) handle;
+
+ if (!h->dpy) return -1;
+ return ScreenCount(h->dpy);
+
+} /* NvCtrlGetScreenCount() */
+
+
+/*
+ * NvCtrlGetProtocolVersion() - Returns the majoy version
+ * number of the X protocol (server).
+ */
+
+int NvCtrlGetProtocolVersion(NvCtrlAttributeHandle *handle)
+{
+ NvCtrlAttributePrivateHandle *h;
+
+ if (!handle) return -1;
+
+ h = (NvCtrlAttributePrivateHandle *) handle;
+
+ if (!h->dpy) return -1;
+ return ProtocolVersion(h->dpy);
+
+} /* NvCtrlGetProtocolVersion() */
+
+
+/*
+ * NvCtrlGetProtocolRevision() - Returns the revision number
+ * of the X protocol (server).
+ */
+
+int NvCtrlGetProtocolRevision(NvCtrlAttributeHandle *handle)
+{
+ NvCtrlAttributePrivateHandle *h;
+
+ if (!handle) return -1;
+
+ h = (NvCtrlAttributePrivateHandle *) handle;
+
+ if (!h->dpy) return -1;
+ return ProtocolRevision(h->dpy);
+
+} /* NvCtrlGetProtocolRevision() */
+
+
+/*
+ * NvCtrlGetScreenWidthMM() - return the width (in Millimeters) of the
+ * screen associated with this NvCtrlAttributeHandle.
+ */
+
+int NvCtrlGetScreenWidthMM(NvCtrlAttributeHandle *handle)
+{
+ NvCtrlAttributePrivateHandle *h;
+
+ if (!handle) return -1;
+
+ h = (NvCtrlAttributePrivateHandle *) handle;
+
+ if (h->target_type != NV_CTRL_TARGET_TYPE_X_SCREEN) return -1;
+
+ return DisplayWidthMM(h->dpy, h->target_id);
+
+} /* NvCtrlGetScreenWidthMM() */
+
+
+/*
+ * NvCtrlGetScreenHeightMM() - return the height (in Millimeters) of the
+ * screen associated with this NvCtrlAttributeHandle.
+ */
+
+int NvCtrlGetScreenHeightMM(NvCtrlAttributeHandle *handle)
+{
+ NvCtrlAttributePrivateHandle *h;
+
+ if (!handle) return -1;
+
+ h = (NvCtrlAttributePrivateHandle *) handle;
+
+ if (h->target_type != NV_CTRL_TARGET_TYPE_X_SCREEN) return -1;
+
+ return DisplayHeightMM(h->dpy, h->target_id);
+
+} /* NvCtrlGetScreenHeightMM() */
+
+
+/*
+ * NvCtrlGetScreenPlanes() - return the number of planes (the depth)
+ * of the screen associated with this NvCtrlAttributeHandle.
+ */
+
+int NvCtrlGetScreenPlanes(NvCtrlAttributeHandle *handle)
+{
+ NvCtrlAttributePrivateHandle *h;
+
+ if (!handle) return -1;
+
+ h = (NvCtrlAttributePrivateHandle *) handle;
+
+ if (h->target_type != NV_CTRL_TARGET_TYPE_X_SCREEN) return -1;
+
+ return DisplayPlanes(h->dpy, h->target_id);
+
+} /* NvCtrlGetScreenPlanes() */
+
+
+
ReturnStatus NvCtrlQueryTargetCount(NvCtrlAttributeHandle *handle,
int target_type,
int *val)
@@ -550,6 +707,26 @@ NvCtrlGetBinaryAttribute(NvCtrlAttributeHandle *handle,
} /* NvCtrlGetBinaryAttribute() */
+ReturnStatus
+NvCtrlStringOperation(NvCtrlAttributeHandle *handle,
+ unsigned int display_mask, int attr,
+ char *ptrIn, char **ptrOut)
+{
+ NvCtrlAttributePrivateHandle *h;
+
+ h = (NvCtrlAttributePrivateHandle *) handle;
+
+ if ((attr >= 0) && (attr <= NV_CTRL_STRING_OPERATION_LAST_ATTRIBUTE)) {
+ if (!h->nv) return NvCtrlMissingExtension;
+ return NvCtrlNvControlStringOperation(h, display_mask, attr, ptrIn,
+ ptrOut);
+ }
+
+ return NvCtrlNoAttribute;
+
+} /* NvCtrlStringOperation() */
+
+
char *NvCtrlAttributesStrError(ReturnStatus status)
{
switch (status) {
@@ -610,3 +787,12 @@ NvCtrlXrandrSetScreenMode (NvCtrlAttributeHandle *handle,
return NvCtrlXrandrSetScreenMagicMode
((NvCtrlAttributePrivateHandle *)handle, width, height, refresh);
} /* NvCtrlXrandrSetScreenMode() */
+
+
+ReturnStatus
+NvCtrlXrandrGetScreenMode (NvCtrlAttributeHandle *handle,
+ int *width, int *height, int *refresh)
+{
+ return NvCtrlXrandrGetScreenMagicMode
+ ((NvCtrlAttributePrivateHandle *)handle, width, height, refresh);
+} /* NvCtrlXrandrGetScreenMode() */
diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributes.h b/src/libXNVCtrlAttributes/NvCtrlAttributes.h
index 08f958d..3cdad09 100644
--- a/src/libXNVCtrlAttributes/NvCtrlAttributes.h
+++ b/src/libXNVCtrlAttributes/NvCtrlAttributes.h
@@ -265,6 +265,14 @@ int NvCtrlGetScreenWidth(NvCtrlAttributeHandle *handle);
int NvCtrlGetScreenHeight(NvCtrlAttributeHandle *handle);
int NvCtrlGetEventBase(NvCtrlAttributeHandle *handle);
int NvCtrlGetXrandrEventBase(NvCtrlAttributeHandle *handle);
+char *NvCtrlGetServerVendor(NvCtrlAttributeHandle *handle);
+int NvCtrlGetVendorRelease(NvCtrlAttributeHandle *handle);
+int NvCtrlGetProtocolVersion(NvCtrlAttributeHandle *handle);
+int NvCtrlGetProtocolRevision(NvCtrlAttributeHandle *handle);
+int NvCtrlGetScreenCount(NvCtrlAttributeHandle *handle);
+int NvCtrlGetScreenWidthMM(NvCtrlAttributeHandle *handle);
+int NvCtrlGetScreenHeightMM(NvCtrlAttributeHandle *handle);
+int NvCtrlGetScreenPlanes(NvCtrlAttributeHandle *handle);
ReturnStatus NvCtrlGetColorAttributes (NvCtrlAttributeHandle *handle,
float contrast[3],
@@ -390,6 +398,18 @@ NvCtrlGetBinaryAttribute(NvCtrlAttributeHandle *handle,
unsigned char **data, int *len);
/*
+ * NvCtrlStringOperation() - Performs the string operation associated
+ * with the specified attribute, where valid values are the
+ * NV_CTRL_STRING_OPERATION_* #defines in NVCtrl.h. If 'ptrOut'
+ * is specified, (string) result information is returned.
+ */
+
+ReturnStatus
+NvCtrlStringOperation(NvCtrlAttributeHandle *handle,
+ unsigned int display_mask, int attr,
+ char *ptrIn, char **ptrOut);
+
+/*
* NvCtrl[SG]etGvoColorConversion() - get and set the color conversion
* matrix and offset used in the Graphics to Video Out (GVO)
* extension. These should only be used if the NV_CTRL_GVO_SUPPORTED
@@ -416,4 +436,8 @@ ReturnStatus
NvCtrlXrandrSetScreenMode (NvCtrlAttributeHandle *handle,
int width, int height, int refresh);
+ReturnStatus
+NvCtrlXrandrGetScreenMode (NvCtrlAttributeHandle *handle,
+ int *width, int *height, int *refresh);
+
#endif /* __NVCTRL_ATTRIBUTES__ */
diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributesGlx.c b/src/libXNVCtrlAttributes/NvCtrlAttributesGlx.c
index 08a40b6..9d99c39 100644
--- a/src/libXNVCtrlAttributes/NvCtrlAttributesGlx.c
+++ b/src/libXNVCtrlAttributes/NvCtrlAttributesGlx.c
@@ -137,6 +137,7 @@ static Bool open_libgl(void)
if ( !__libGL ) {
__libGL = (__libGLInfo *) calloc(1, sizeof(__libGLInfo));
if ( !__libGL ) {
+ error_str = "Could not allocate memory.";
goto fail;
}
}
@@ -152,6 +153,7 @@ static Bool open_libgl(void)
/* We are the first to open the library */
__libGL->handle = dlopen("libGL.so.1", RTLD_LAZY);
if ( !__libGL->handle ) {
+ error_str = dlerror();
goto fail;
}
diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributesNvControl.c b/src/libXNVCtrlAttributes/NvCtrlAttributesNvControl.c
index 32177e8..e0929ac 100644
--- a/src/libXNVCtrlAttributes/NvCtrlAttributesNvControl.c
+++ b/src/libXNVCtrlAttributes/NvCtrlAttributesNvControl.c
@@ -174,7 +174,7 @@ NvCtrlNvControlGetStringAttribute (NvCtrlAttributePrivateHandle *h,
return NvCtrlNoAttribute;
-} /* NvCtrlGetStringAttribute() */
+} /* NvCtrlNvControlGetStringAttribute() */
ReturnStatus
@@ -235,6 +235,26 @@ NvCtrlNvControlGetBinaryAttribute(NvCtrlAttributePrivateHandle *h,
ReturnStatus
+NvCtrlNvControlStringOperation(NvCtrlAttributePrivateHandle *h,
+ unsigned int display_mask, int attr,
+ char *ptrIn, char **ptrOut)
+{
+ if (attr <= NV_CTRL_STRING_OPERATION_LAST_ATTRIBUTE) {
+ if (XNVCTRLStringOperation (h->dpy, h->target_type,
+ h->target_id, display_mask,
+ attr, ptrIn, ptrOut)) {
+ return NvCtrlSuccess;
+ } else {
+ return NvCtrlAttributeNotAvailable;
+ }
+ }
+
+ return NvCtrlNoAttribute;
+
+} /* NvCtrlNvControlStringOperation() */
+
+
+ReturnStatus
NvCtrlSetGvoColorConversion(NvCtrlAttributeHandle *handle,
float colorMatrix[3][3],
float colorOffset[3],
diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributesPrivate.h b/src/libXNVCtrlAttributes/NvCtrlAttributesPrivate.h
index 314234d..43841e9 100644
--- a/src/libXNVCtrlAttributes/NvCtrlAttributesPrivate.h
+++ b/src/libXNVCtrlAttributes/NvCtrlAttributesPrivate.h
@@ -58,7 +58,7 @@
/* minimum required version for the NV-CONTROL extension */
#define NV_MINMAJOR 1
-#define NV_MINMINOR 9
+#define NV_MINMINOR 11
/* minimum required version for the XF86VidMode extension */
@@ -205,6 +205,10 @@ NvCtrlXrandrSetAttribute (NvCtrlAttributePrivateHandle *, int, int);
ReturnStatus
NvCtrlXrandrSetScreenMagicMode (NvCtrlAttributePrivateHandle *, int, int, int);
+ReturnStatus
+NvCtrlXrandrGetScreenMagicMode (NvCtrlAttributePrivateHandle *, int *, int *,
+ int *);
+
/* Generic attribute functions */
@@ -235,6 +239,12 @@ ReturnStatus
NvCtrlNvControlGetBinaryAttribute(NvCtrlAttributePrivateHandle *h,
unsigned int display_mask, int attr,
unsigned char **data, int *len);
+
+ReturnStatus
+NvCtrlNvControlStringOperation (NvCtrlAttributePrivateHandle *h,
+ unsigned int display_mask, int attr,
+ char *ptrIn, char **ptrOut);
+
ReturnStatus
NvCtrlXvGetAttribute (NvCtrlAttributePrivateHandle *, int, int *);
diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributesXrandr.c b/src/libXNVCtrlAttributes/NvCtrlAttributesXrandr.c
index 29b0412..60c3d78 100644
--- a/src/libXNVCtrlAttributes/NvCtrlAttributesXrandr.c
+++ b/src/libXNVCtrlAttributes/NvCtrlAttributesXrandr.c
@@ -42,17 +42,26 @@
#include "msg.h"
#include "parse.h"
+/* Make sure we are compiling with XRandR version 1.1 or greater */
+#define MIN_RANDR_MAJOR 1
+#define MIN_RANDR_MINOR 1
+#if (RANDR_MAJOR < MIN_RANDR_MAJOR) || ((RANDR_MAJOR == MIN_RANDR_MAJOR) && (RANDR_MINOR < MIN_RANDR_MINOR))
+#error XRandR version 1.1 or greater is required.
+#endif
typedef struct __libXrandrInfoRec {
/* libXrandr.so library handle */
void *handle;
int ref_count; /* # users of the library */
-
-
+
+
/* XRandR functions used */
Bool (* XRRQueryExtension)
(Display *dpy, int *event_base, int *error_base);
+
+ Status (* XRRQueryVersion)
+ (Display *dpy, int *major_versionp, int *minor_versionp);
void (* XRRSelectInput)
(Display *dpy, Window window, int mask);
@@ -62,6 +71,9 @@ typedef struct __libXrandrInfoRec {
SizeID (* XRRConfigCurrentConfiguration)
(XRRScreenConfiguration *config, Rotation *rotation);
+
+ short (* XRRConfigCurrentRate)
+ (XRRScreenConfiguration *config);
Rotation (* XRRConfigRotations)
(XRRScreenConfiguration *config, Rotation *rotation);
@@ -104,6 +116,7 @@ static Bool open_libxrandr(void)
if ( !__libXrandr ) {
__libXrandr = (__libXrandrInfo *) calloc(1, sizeof(__libXrandrInfo));
if ( !__libXrandr ) {
+ error_str = "Could not allocate memory.";
goto fail;
}
}
@@ -118,6 +131,7 @@ static Bool open_libxrandr(void)
/* We are the first to open the library */
__libXrandr->handle = dlopen("libXrandr.so.2", RTLD_LAZY);
if ( !__libXrandr->handle ) {
+ error_str = dlerror();
goto fail;
}
@@ -127,6 +141,10 @@ static Bool open_libxrandr(void)
NV_DLSYM(__libXrandr->handle, "XRRQueryExtension");
if ((error_str = dlerror()) != NULL) goto fail;
+ __libXrandr->XRRQueryVersion =
+ NV_DLSYM(__libXrandr->handle, "XRRQueryVersion");
+ if ((error_str = dlerror()) != NULL) goto fail;
+
__libXrandr->XRRSelectInput =
NV_DLSYM(__libXrandr->handle, "XRRSelectInput");
if ((error_str = dlerror()) != NULL) goto fail;
@@ -139,6 +157,10 @@ static Bool open_libxrandr(void)
NV_DLSYM(__libXrandr->handle, "XRRConfigCurrentConfiguration");
if ((error_str = dlerror()) != NULL) goto fail;
+ __libXrandr->XRRConfigCurrentRate =
+ NV_DLSYM(__libXrandr->handle, "XRRConfigCurrentRate");
+ if ((error_str = dlerror()) != NULL) goto fail;
+
__libXrandr->XRRConfigRotations =
NV_DLSYM(__libXrandr->handle, "XRRConfigRotations");
if ((error_str = dlerror()) != NULL) goto fail;
@@ -249,6 +271,8 @@ NvCtrlInitXrandrAttributes (NvCtrlAttributePrivateHandle *h)
NvCtrlXrandrAttributes * xrandr = NULL;
XRRScreenConfiguration *sc;
Rotation rotation, rotations;
+ int ver_major;
+ int ver_minor;
/* Check parameters */
@@ -285,6 +309,15 @@ NvCtrlInitXrandrAttributes (NvCtrlAttributePrivateHandle *h)
goto fail;
}
+ /* Verify server version of the XRandR extension */
+ if ( !__libXrandr->XRRQueryVersion(h->dpy, &(ver_major), &(ver_minor)) ||
+ ((ver_major < MIN_RANDR_MAJOR) ||
+ ((ver_major == MIN_RANDR_MAJOR) &&
+ (ver_minor < MIN_RANDR_MINOR)))) {
+ XSync(h->dpy, False);
+ XSetErrorHandler(old_error_handler);
+ goto fail;
+ }
/* Register to receive XRandR events */
__libXrandr->XRRSelectInput(h->dpy, RootWindow(h->dpy, h->target_id),
@@ -564,3 +597,58 @@ NvCtrlXrandrSetScreenMagicMode (NvCtrlAttributePrivateHandle *h,
return NvCtrlError;
} /* NvCtrlXrandrSetScreenMagicMode */
+
+
+
+/******************************************************************************
+ *
+ * Gets XRandR size and refresh rate.
+ *
+ ****/
+
+ReturnStatus
+NvCtrlXrandrGetScreenMagicMode (NvCtrlAttributePrivateHandle *h,
+ int *width, int *height, int *magic_ref_rate)
+{
+ XRRScreenConfiguration *sc;
+ Rotation cur_rotation;
+ int nsizes;
+ XRRScreenSize *sizes;
+ int cur_size;
+ short cur_rate;
+
+
+ /* Validate */
+ if ( !h || !h->dpy || h->target_type != NV_CTRL_TARGET_TYPE_X_SCREEN ) {
+ return NvCtrlBadHandle;
+ }
+
+ if ( !h->xrandr || !__libXrandr ) {
+ return NvCtrlMissingExtension;
+ }
+
+
+ /* Get current screen configuration information */
+ sc = __libXrandr->XRRGetScreenInfo(h->dpy, RootWindow(h->dpy,
+ h->target_id));
+ if ( !sc ) {
+ return NvCtrlError;
+ }
+ cur_size = __libXrandr->XRRConfigCurrentConfiguration(sc, &cur_rotation);
+ cur_rate = __libXrandr->XRRConfigCurrentRate(sc);
+ sizes = __libXrandr->XRRConfigSizes(sc, &nsizes);
+ if (cur_size >= nsizes) {
+ __libXrandr->XRRFreeScreenConfigInfo(sc);
+ return NvCtrlError;
+ }
+
+
+ /* Get the width & height from the size information */
+ *width = sizes[cur_size].width;
+ *height = sizes[cur_size].height;
+ *magic_ref_rate = (int)cur_rate;
+
+ __libXrandr->XRRFreeScreenConfigInfo(sc);
+ return NvCtrlSuccess;
+
+} /* NvCtrlXrandrGetScreenMagicMode */
diff --git a/src/libXNVCtrlAttributes/NvCtrlAttributesXv.c b/src/libXNVCtrlAttributes/NvCtrlAttributesXv.c
index 5d061d6..07ede41 100644
--- a/src/libXNVCtrlAttributes/NvCtrlAttributesXv.c
+++ b/src/libXNVCtrlAttributes/NvCtrlAttributesXv.c
@@ -79,6 +79,7 @@ static Bool open_libxv(void)
if ( !__libXv ) {
__libXv = (__libXvInfo *) calloc(1, sizeof(__libXvInfo));
if ( !__libXv ) {
+ error_str = "Could not allocate memory.";
goto fail;
}
}
@@ -94,6 +95,7 @@ static Bool open_libxv(void)
/* We are the first to open the library */
__libXv->handle = dlopen("libXv.so.1", RTLD_LAZY);
if ( __libXv->handle == NULL ) {
+ error_str = dlerror();
goto fail;
}
diff --git a/src/msg.c b/src/msg.c
index 002f2b4..a176cd2 100644
--- a/src/msg.c
+++ b/src/msg.c
@@ -23,6 +23,7 @@
*/
#include "msg.h"
+#include "command-line.h"
#include <stdio.h>
#include <stdarg.h>
@@ -35,6 +36,8 @@
#include <sys/termios.h>
#endif
+extern int __verbosity;
+
static void format(FILE*, const char*, char *);
static int get_terminal_width(void);
@@ -49,10 +52,14 @@ do { \
/*
* nv_error_msg() - print an error message, nicely formatted using the
* format() function.
+ *
+ * This function should be used for all errors.
*/
void nv_error_msg(const char *fmt, ...)
{
+ if (__verbosity < VERBOSITY_ERROR) return;
+
fprintf(stderr, "\n");
NV_FORMAT(stderr, "ERROR: ", fmt);
@@ -66,10 +73,14 @@ void nv_error_msg(const char *fmt, ...)
/*
* nv_warning_msg() - print a warning message, nicely formatted using
* the format() function.
+ *
+ * This function should be used for all warnings.
*/
void nv_warning_msg(const char *fmt, ...)
{
+ if (__verbosity < VERBOSITY_WARNING) return;
+
fprintf(stdout, "\n");
NV_FORMAT(stdout, "WARNING: ", fmt);
@@ -81,8 +92,28 @@ void nv_warning_msg(const char *fmt, ...)
/*
+ * nv_info_msg() - print an info message, nicely formatted using
+ * the format() function.
+ *
+ * This function should be used to display verbose information.
+ */
+
+void nv_info_msg(const char *prefix, const char *fmt, ...)
+{
+ if (__verbosity < VERBOSITY_ALL) return;
+
+ NV_FORMAT(stdout, prefix, fmt);
+
+} /* nv_info_msg() */
+
+
+
+/*
* nv_msg() - print a message, nicely formatted using the format()
* function.
+ *
+ * This function should be used to display messages independent
+ * of the verbosity level.
*/
void nv_msg(const char *prefix, const char *fmt, ...)
@@ -159,7 +190,7 @@ static void format(FILE *stream, const char *prefix,
if (b <= a) {
b = a;
- while (!isspace(*b)) b++;
+ while (*b && !isspace(*b)) b++;
}
}
diff --git a/src/msg.h b/src/msg.h
index f8eb7ae..e710f9f 100644
--- a/src/msg.h
+++ b/src/msg.h
@@ -30,6 +30,7 @@
void nv_error_msg(const char*, ...);
void nv_warning_msg(const char*, ...);
+void nv_info_msg(const char*, const char*, ...);
void nv_msg(const char*, const char*, ...);
/*
diff --git a/src/nvidia-settings.c b/src/nvidia-settings.c
index 79e6f75..7a9d2e9 100644
--- a/src/nvidia-settings.c
+++ b/src/nvidia-settings.c
@@ -39,9 +39,11 @@ int main(int argc, char **argv)
ConfigProperties conf;
ParsedAttribute *p;
CtrlHandles *h;
- NvCtrlAttributeHandle **handles;
+ NvCtrlAttributeHandle **screen_handles = NULL;
+ NvCtrlAttributeHandle **gpu_handles = NULL;
+ NvCtrlAttributeHandle **vcsc_handles = NULL;
Options *op;
- int ret, i, num_handles;
+ int ret, i, num_screen_handles, num_gpu_handles, num_vcsc_handles;
/*
* initialize the ui
@@ -69,16 +71,24 @@ int main(int argc, char **argv)
p = nv_parsed_attribute_init();
+ /* initialize the ConfigProperties */
+
+ init_config_properties(&conf);
+
/* upload the data from the config file */
- ret = nv_read_config_file(op->config, op->ctrl_display, p, &conf);
+ if (!op->no_load) {
+ ret = nv_read_config_file(op->config, op->ctrl_display, p, &conf);
+ } else {
+ ret = 1;
+ }
/*
* if the user requested that we only load the config file, then
* exit now
*/
- if (op->load) {
+ if (op->only_load) {
return ret ? 0 : 1;
}
@@ -91,25 +101,58 @@ int main(int argc, char **argv)
}
/*
- * pull the screens' handles out of the CtrlHandles so that we can
+ * pull the screen and gpu handles out of the CtrlHandles so that we can
* pass them to the gui
*/
- num_handles = h->targets[X_SCREEN_TARGET].n;
-
- if (num_handles) {
- handles = malloc(num_handles * sizeof(NvCtrlAttributeHandle *));
-
- for (i = 0; i < num_handles; i++) {
- handles[i] = h->targets[X_SCREEN_TARGET].t[i].h;
+ num_screen_handles = h->targets[X_SCREEN_TARGET].n;
+
+ if (num_screen_handles) {
+ screen_handles =
+ malloc(num_screen_handles * sizeof(NvCtrlAttributeHandle *));
+ if (screen_handles) {
+ for (i = 0; i < num_screen_handles; i++) {
+ screen_handles[i] = h->targets[X_SCREEN_TARGET].t[i].h;
+ }
+ } else {
+ num_screen_handles = 0;
+ }
+ }
+
+ num_gpu_handles = h->targets[GPU_TARGET].n;
+
+ if (num_gpu_handles) {
+ gpu_handles =
+ malloc(num_gpu_handles * sizeof(NvCtrlAttributeHandle *));
+ if (gpu_handles) {
+ for (i = 0; i < num_gpu_handles; i++) {
+ gpu_handles[i] = h->targets[GPU_TARGET].t[i].h;
+ }
+ } else {
+ num_gpu_handles = 0;
+ }
+ }
+
+ num_vcsc_handles = h->targets[VCSC_TARGET].n;
+
+ if (num_vcsc_handles) {
+ vcsc_handles =
+ malloc(num_vcsc_handles * sizeof(NvCtrlAttributeHandle *));
+ if (vcsc_handles) {
+ for (i = 0; i < num_vcsc_handles; i++) {
+ vcsc_handles[i] = h->targets[VCSC_TARGET].t[i].h;
+ }
+ } else {
+ num_vcsc_handles = 0;
}
- } else {
- handles = NULL;
}
/* pass control to the gui */
- ctk_main(handles, num_handles, p, &conf);
+ ctk_main(screen_handles, num_screen_handles,
+ gpu_handles, num_gpu_handles,
+ vcsc_handles, num_vcsc_handles,
+ p, &conf);
/* write the configuration file */
@@ -117,7 +160,8 @@ int main(int argc, char **argv)
/* cleanup */
- if (handles) free(handles);
+ if (screen_handles) free(screen_handles);
+ if (gpu_handles) free(gpu_handles);
nv_free_ctrl_handles(h);
nv_parsed_attribute_free(p);
diff --git a/src/parse.c b/src/parse.c
index d681736..121279b 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -59,7 +59,7 @@ static char *nv_strndup(char *s, int n);
#define D NV_PARSER_TYPE_VALUE_IS_DISPLAY
#define A NV_PARSER_TYPE_NO_QUERY_ALL
#define Z NV_PARSER_TYPE_NO_ZERO_VALUE
-
+#define H NV_PARSER_TYPE_100Hz
AttributeTableEntry attributeTable[] = {
@@ -87,6 +87,7 @@ AttributeTableEntry attributeTable[] = {
{ "TwinView", NV_CTRL_TWINVIEW, 0 },
{ "ConnectedDisplays", NV_CTRL_CONNECTED_DISPLAYS, 0 },
{ "EnabledDisplays", NV_CTRL_ENABLED_DISPLAYS, 0 },
+ { "AssociatedDisplays", NV_CTRL_ASSOCIATED_DISPLAY_DEVICES, N|D },
{ "ProbeDisplays", NV_CTRL_PROBE_DISPLAYS, A },
{ "ForceGenericCpu", NV_CTRL_FORCE_GENERIC_CPU, 0 },
{ "GammaCorrectedAALines", NV_CTRL_OPENGL_AA_LINE_GAMMA, 0 },
@@ -100,7 +101,13 @@ AttributeTableEntry attributeTable[] = {
{ "CursorShadowBlue", NV_CTRL_CURSOR_SHADOW_BLUE, 0 },
{ "FSAAAppControlled", NV_CTRL_FSAA_APPLICATION_CONTROLLED, 0 },
{ "LogAnisoAppControlled", NV_CTRL_LOG_ANISO_APPLICATION_CONTROLLED,0 },
- { "RefreshRate", NV_CTRL_REFRESH_RATE, 0 },
+ { "RefreshRate", NV_CTRL_REFRESH_RATE, N|H },
+ { "InitialPixmapPlacement",NV_CTRL_INITIAL_PIXMAP_PLACEMENT, N },
+ { "PCIBus", NV_CTRL_PCI_BUS, N },
+ { "PCIDevice", NV_CTRL_PCI_DEVICE, N },
+ { "PCIFunc", NV_CTRL_PCI_FUNCTION, N },
+ { "DynamicTwinview", NV_CTRL_DYNAMIC_TWINVIEW, N },
+ { "MultiGpuDisplayOwner", NV_CTRL_MULTIGPU_DISPLAY_OWNER, N },
{ "FrameLockMaster", NV_CTRL_FRAMELOCK_MASTER, N|F|G|D },
{ "FrameLockSlaves", NV_CTRL_FRAMELOCK_SLAVES, N|F|G|D },
@@ -121,6 +128,7 @@ AttributeTableEntry attributeTable[] = {
{ "FrameLockSyncRate", NV_CTRL_FRAMELOCK_SYNC_RATE, N|F|G },
{ "FrameLockTiming", NV_CTRL_FRAMELOCK_TIMING, N|F|G },
{ "FrameLockMasterable", NV_CTRL_FRAMELOCK_MASTERABLE, N|F|G },
+ { "FrameLockFPGARevision", NV_CTRL_FRAMELOCK_FPGA_REVISION, N|F|G },
{ "Brightness", BRIGHTNESS_VALUE|ALL_CHANNELS, N|C|G },
{ "RedBrightness", BRIGHTNESS_VALUE|RED_CHANNEL, C|G },
@@ -170,7 +178,8 @@ AttributeTableEntry attributeTable[] = {
#undef P
#undef D
#undef A
-
+#undef Z
+#undef H
/*
* When new integer attributes are added to NVCtrl.h, an entry should
@@ -179,7 +188,7 @@ AttributeTableEntry attributeTable[] = {
* about.
*/
-#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_REFRESH_RATE
+#if NV_CTRL_LAST_ATTRIBUTE != NV_CTRL_MULTIGPU_DISPLAY_OWNER
#warning "Have you forgotten to add a new integer attribute to attributeTable?"
#endif
@@ -212,7 +221,14 @@ TargetTypeEntry targetTypeTable[] = {
NV_CTRL_TARGET_TYPE_FRAMELOCK, /* nvctrl */
ATTRIBUTE_TYPE_FRAMELOCK, /* permission_bit */
NV_FALSE }, /* uses_display_devices */
-
+
+ { "VCSC", /* name */
+ "vcsc", /* parsed_name */
+ VCSC_TARGET, /* target_index */
+ NV_CTRL_TARGET_TYPE_VCSC, /* nvctrl */
+ ATTRIBUTE_TYPE_VCSC, /* permission_bit */
+ NV_FALSE }, /* uses_display_devices */
+
{ NULL, NULL, 0, 0, 0 },
};
@@ -330,7 +346,7 @@ int nv_parse_attribute_string(const char *str, int query, ParsedAttribute *a)
a->val |= strtol((tmp + 1), &tmp, 10) & 0xffff;
} else {
/* all other attributes are integer */
- a->val = strtol(s, &tmp, 10);
+ a->val = strtol(s, &tmp, 0);
}
if (tmp && (s != tmp)) a->flags |= NV_PARSER_HAS_VAL;
diff --git a/src/parse.h b/src/parse.h
index d12c7b6..99b420c 100644
--- a/src/parse.h
+++ b/src/parse.h
@@ -52,6 +52,7 @@
#define NV_PARSER_TYPE_VALUE_IS_DISPLAY (1<<22)
#define NV_PARSER_TYPE_NO_QUERY_ALL (1<<23)
#define NV_PARSER_TYPE_NO_ZERO_VALUE (1<<24)
+#define NV_PARSER_TYPE_100Hz (1<<25)
#define NV_PARSER_ASSIGNMENT 0
#define NV_PARSER_QUERY 1
@@ -138,7 +139,8 @@ extern AttributeTableEntry attributeTable[];
#define X_SCREEN_TARGET 0
#define GPU_TARGET 1
#define FRAMELOCK_TARGET 2
-#define MAX_TARGET_TYPES 3
+#define VCSC_TARGET 3
+#define MAX_TARGET_TYPES 4
diff --git a/src/query-assign.c b/src/query-assign.c
index 2ff1de4..1784486 100644
--- a/src/query-assign.c
+++ b/src/query-assign.c
@@ -356,6 +356,11 @@ static int process_attribute_queries(int num, char **queries,
continue;
}
+ if (nv_strcasecmp(queries[query], "vcscs")) {
+ query_all_targets(display_name, VCSC_TARGET);
+ continue;
+ }
+
/* call the parser to parse queries[query] */
@@ -673,7 +678,7 @@ static void print_valid_values(char *name, uint32 flags,
if (n == 0) sprintf(c, "None");
- nv_msg(INDENT, "'%s' can use the following target types: %s",
+ nv_msg(INDENT, "'%s' can use the following target types: %s.",
name, str);
#undef INDENT
@@ -683,6 +688,52 @@ static void print_valid_values(char *name, uint32 flags,
/*
+ * print_queried_value() - print the attribute value that we queried
+ * from NV-CONTROL
+ */
+
+static void print_queried_value(CtrlHandleTarget *t,
+ NVCTRLAttributeValidValuesRec *v,
+ int val,
+ uint32 flags,
+ char *name,
+ uint32 mask,
+ const char *indent)
+{
+ char d_str[64], val_str[64], *tmp_d_str;
+
+ /* assign val_str */
+
+ if (flags & NV_PARSER_TYPE_100Hz) {
+ snprintf(val_str, 64, "%.2f Hz", ((float) val) / 100.0);
+ } else if (v->type == ATTRIBUTE_TYPE_BITMASK) {
+ snprintf(val_str, 64, "0x%08x", val);
+ } else if (flags & NV_PARSER_TYPE_PACKED_ATTRIBUTE) {
+ snprintf(val_str, 64, "%d,%d", val >> 16, val & 0xffff);
+ } else {
+ snprintf(val_str, 64, "%d", val);
+ }
+
+ /* append the display device name, if necessary */
+
+ if (v->permissions & ATTRIBUTE_TYPE_DISPLAY) {
+ tmp_d_str = display_device_mask_to_display_device_name(mask);
+ snprintf(d_str, 64, "; display device: %s", tmp_d_str);
+ free(tmp_d_str);
+ } else {
+ d_str[0] = '\0';
+ }
+
+ /* print the string */
+
+ nv_msg(indent, "Attribute '%s' (%s%s): %s.",
+ name, t->name, d_str, val_str);
+
+} /* print_queried_value() */
+
+
+
+/*
* query_all() - loop through all screens, and query all attributes
* for those screens. The current attribute values for all display
* devices on all screens are printed, along with the valid values for
@@ -698,24 +749,9 @@ static int query_all(const char *display_name)
uint32 mask;
ReturnStatus status;
AttributeTableEntry *a;
- char *tmp_d_str;
- const char *fmt, *fmt_display;
NVCTRLAttributeValidValuesRec valid;
CtrlHandles *h;
CtrlHandleTarget *t;
-
- static const char *__fmt_str_int =
- "Attribute '%s' (screen: %s): %d.";
- static const char *__fmt_str_int_display =
- "Attribute '%s' (screen: %s; display: %s): %d.";
- static const char *__fmt_str_hex =
- "Attribute '%s' (screen: %s): 0x%08x.";
- static const char *__fmt_str_hex_display =
- "Attribute '%s' (screen: %s; display: %s): 0x%08x.";
- static const char *__fmt_str_packed_int =
- "Attribute '%s' (screen: %s): %d,%d.";
- static const char *__fmt_str_packed_int_display =
- "Attribute '%s' (screen: %s; display: %s): %d,%d.";
h = nv_alloc_ctrl_handles(display_name);
@@ -777,55 +813,20 @@ static int query_all(const char *display_name)
NvCtrlAttributesStrError(status));
goto exit_bit_loop;
}
-
- if (valid.type == ATTRIBUTE_TYPE_BITMASK) {
- fmt = __fmt_str_hex;
- fmt_display = __fmt_str_hex_display;
- } else if (a->flags & NV_PARSER_TYPE_PACKED_ATTRIBUTE) {
- fmt = __fmt_str_packed_int;
- fmt_display = __fmt_str_packed_int_display;
- } else {
- fmt = __fmt_str_int;
- fmt_display = __fmt_str_int_display;
- }
+ print_queried_value(t, &valid, val, a->flags,
+ a->name, mask, INDENT);
+
+ print_valid_values(a->name, a->flags, valid);
+
+ nv_msg(NULL,"");
+
if (valid.permissions & ATTRIBUTE_TYPE_DISPLAY) {
-
- tmp_d_str =
- display_device_mask_to_display_device_name(mask);
-
- if (a->flags & NV_PARSER_TYPE_PACKED_ATTRIBUTE) {
- nv_msg(INDENT, fmt_display, a->name,
- t->name, tmp_d_str,
- val >> 16, val & 0xffff);
- } else {
- nv_msg(INDENT, fmt_display, a->name,
- t->name, tmp_d_str, val);
- }
-
- free(tmp_d_str);
-
- print_valid_values(a->name, a->flags, valid);
-
- nv_msg(NULL,"");
-
continue;
-
- } else {
- if (a->flags & NV_PARSER_TYPE_PACKED_ATTRIBUTE) {
- nv_msg(INDENT, fmt, a->name, t->name,
- val >> 16, val & 0xffff);
- } else {
- nv_msg(INDENT, fmt, a->name, t->name, val);
- }
-
- print_valid_values(a->name, a->flags, valid);
-
- nv_msg(NULL,"");
-
- /* fall through to exit_bit_loop */
}
+ /* fall through to exit_bit_loop */
+
exit_bit_loop:
bit = 25; /* XXX force us out of the display device loop */
@@ -918,6 +919,13 @@ static int query_all_targets(const char *display_name, const int target_index)
product_name = malloc(32);
snprintf(product_name, 32, "G-Sync %d", i);
+ } else if (target_index == VCSC_TARGET) {
+
+ status = NvCtrlGetStringAttribute
+ (t->h, NV_CTRL_STRING_VCSC_PRODUCT_NAME, &product_name);
+
+ if (status != NvCtrlSuccess) product_name = strdup("Unknown");
+
} else {
/* for X_SCREEN_TARGET or GPU_TARGET, query the product name */
@@ -1023,14 +1031,9 @@ static int process_parsed_attribute_internal(CtrlHandleTarget *t,
NvCtrlAttributesStrError(status));
return NV_FALSE;
} else {
- if (a->flags & NV_PARSER_TYPE_PACKED_ATTRIBUTE) {
- nv_msg(" ", "Attribute '%s' (%s%s): %d,%d.",
- a->name, t->name, str,
- a->val >> 16, a->val & 0xffff);
- } else {
- nv_msg(" ", "Attribute '%s' (%s%s): %d.",
- a->name, t->name, str, a->val);
- }
+
+ print_queried_value(t, &valid, a->val, a->flags, a->name, d, " ");
+
print_valid_values(a->name, a->flags, valid);
}
}
diff --git a/src/xpm_data/Makefile.inc b/src/xpm_data/Makefile.inc
index d50561d..3221772 100644
--- a/src/xpm_data/Makefile.inc
+++ b/src/xpm_data/Makefile.inc
@@ -26,10 +26,11 @@
#
EXTRA_DIST += \
+ Makefile.inc \
blue_xpm.h \
green_xpm.h \
- mini_xpm.h \
red_xpm.h \
- rgb_xpm.h \
- x11_xpm.h
+ rgb_xpm.h
+dist_list::
+ @ echo $(SRC) $(EXTRA_DIST)
diff --git a/src/xpm_data/mini_xpm.h b/src/xpm_data/mini_xpm.h
deleted file mode 100644
index c834b98..0000000
--- a/src/xpm_data/mini_xpm.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* XPM */
-static const char * mini_xpm[] = {
-"16 14 9 1",
-" c None",
-". c #FFFFFF",
-"+ c #848201",
-"@ c #000000",
-"# c #C0BDC0",
-"$ c #848284",
-"% c #CECBC6",
-"& c #B9E313",
-"* c #D6CFC6",
-"......+++++++++@",
-"......+++++++++@",
-"...#$@.%#++++++@",
-"..$$#.++..+++++@",
-".@$.$@..+&.#+++@",
-"$@.@$.+.&+.&+++@",
-"$@.@$.+++.*++++@",
-".@$#@#+%.&+%..+@",
-".#@$#@*&++..#++@",
-"..#@$#++..%++++@",
-"....$$..#++++++@",
-"......+++++++++@",
-"......+++++++++@",
-"$$$$$$@@@@@@@@@@"};
diff --git a/src/xpm_data/x11_xpm.h b/src/xpm_data/x11_xpm.h
deleted file mode 100644
index 4eb3862..0000000
--- a/src/xpm_data/x11_xpm.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* XPM */
-static const char * x11_xpm[] = {
-"14 14 50 1",
-" c None",
-". c #5E5E5E",
-"+ c #000000",
-"@ c #2C2C2C",
-"# c #F4F4F4",
-"$ c #FFFFFF",
-"% c #787878",
-"& c #454545",
-"* c #2B2B2B",
-"= c #616161",
-"- c #AAAAAA",
-"; c #232323",
-"> c #EFEFEF",
-", c #D5D5D5",
-"' c #0B0B0B",
-") c #9F9F9F",
-"! c #D3D3D3",
-"~ c #191919",
-"{ c #D0D0D0",
-"] c #A0A0A0",
-"^ c #0A0A0A",
-"/ c #D4D4D4",
-"( c #A2A2A2",
-"_ c #FEFEFE",
-": c #F3F3F3",
-"< c #515151",
-"[ c #6C6C6C",
-"} c #F2F2F2",
-"| c #6A6A6A",
-"1 c #818181",
-"2 c #414141",
-"3 c #FAFAFA",
-"4 c #090909",
-"5 c #666666",
-"6 c #1F1F1F",
-"7 c #E3E3E3",
-"8 c #3B3B3B",
-"9 c #5C5C5C",
-"0 c #0F0F0F",
-"a c #7A7A7A",
-"b c #444444",
-"c c #777777",
-"d c #ABABAB",
-"e c #EEEEEE",
-"f c #CFCFCF",
-"g c #A1A1A1",
-"h c #535353",
-"i c #6B6B6B",
-"j c #828282",
-"k c #404040",
-".++@#$$$$$$$%&",
-"#*++=$$$$$$-;>",
-"$,'++)$$$$!~{$",
-"$$]++^/$$>*($$",
-"$$_=++@:_<[$$$",
-"$$$}*++|123$$$",
-"$$$$,4+567$$$$",
-"$$$$38904,$$$$",
-"$$$$abc++*}$$$",
-"$$$d;e:@++=_$$",
-"$$/~f$$/^++]$$",
-"$>@g$$$$)++',$",
-"_hi$$$$$$=++*#",
-"jk3$$$$$$#@++."};