diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c index c2814d4..74c8d66 100644 --- a/hw/xfree86/modes/xf86Crtc.c +++ b/hw/xfree86/modes/xf86Crtc.c @@ -432,6 +433,7 @@ extern XF86ConfigPtr xf86configptr; typedef enum { OPTION_PREFERRED_MODE, + OPTION_ZOOM_MODES, OPTION_POSITION, OPTION_BELOW, OPTION_RIGHT_OF, @@ -450,6 +452,7 @@ typedef enum { static OptionInfoRec xf86OutputOptions[] = { {OPTION_PREFERRED_MODE, "PreferredMode", OPTV_STRING, {0}, FALSE }, + {OPTION_ZOOM_MODES, "ZoomModes", OPTV_STRING, {0}, FALSE }, {OPTION_POSITION, "Position", OPTV_STRING, {0}, FALSE }, {OPTION_BELOW, "Below", OPTV_STRING, {0}, FALSE }, {OPTION_RIGHT_OF, "RightOf", OPTV_STRING, {0}, FALSE }, @@ -1453,6 +1456,73 @@ preferredMode(ScrnInfoPtr pScrn, xf86OutputPtr output) return preferred_mode; } +/** identify a token + * args + * src[] the string with zero or more tokens, e.g. "tok0 tok1". + * buf[] used to store a '\0' terminated copy of the first token. + * return + * a pointer into src[] at the token terminating character, or + * NULL if no token is found. + */ +static const char * +gettoken(const char *src, char *buf) +{ + const char *token, *next, *delim = " \t"; + int skip, len; + + if (!src) + return NULL; + + skip = strspn(src, delim); + token = &src[skip]; + + /* Support for backslash escaped delimiters could be implemented here. */ + len = strcspn(token, delim); + if (buf) { + strncpy(buf, token, len); + buf[len] = '\0'; + } + + /* token[0] != '\0' <==> len > 0 */ + next = len ? &token[len] : NULL; + + return next; +} + +static int +processZoomModes(xf86OutputPtr output) +{ + const char *zoom_modes; + int count = 0; + + /* Check for a user configured zoom mode list + * e.g. Option "ZoomModes" "1600x1200 1280x1024 1280x1024 640x480" + */ + zoom_modes = xf86GetOptValString(output->options, OPTION_ZOOM_MODES); + + if (zoom_modes) { + int bufsiz = strlen(zoom_modes) + 1; + char buf[bufsiz]; + const char *next; + + next = gettoken(zoom_modes, buf); + while (next) { + DisplayModePtr mode; + + for (mode = output->probed_modes; mode; mode = mode->next) + if (!strcmp(buf, mode->name) && !(mode->type & M_T_USERDEF)) { + mode->type |= M_T_USERDEF; + break; + } + + count++; + next = gettoken(next, buf); + } + } + + return count; +} + static void GuessRangeFromModes(MonPtr mon, DisplayModePtr mode) { @@ -1734,7 +1804,6 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) /* Check for a configured preference for a particular mode */ preferred_mode = preferredMode(scrn, output); - if (preferred_mode) { for (mode = output->probed_modes; mode; mode = mode->next) @@ -1752,12 +1821,15 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) mode->prev = NULL; output->probed_modes = mode; } - mode->type |= (M_T_PREFERRED|M_T_USERPREF); + mode->type |= (M_T_USERPREF|M_T_PREFERRED); break; } } } - + + /* Ctrl+Alt+Keypad-{Plus,Minus} zoom mode M_T_USERDEF */ + processZoomModes(output); + output->initial_rotation = xf86OutputInitialRotation (output); if (debug_modes) {