19decb2cdStsutsui/* $NetBSD: x68kConfig.c,v 1.8 2025/06/22 22:32:14 tsutsui Exp $ */
2ba64b02eStsutsui/*-------------------------------------------------------------------------
3ba64b02eStsutsui * Copyright (c) 1996 Yasushi Yamasaki
4ba64b02eStsutsui * All rights reserved.
5ba64b02eStsutsui *
6ba64b02eStsutsui * Redistribution and use in source and binary forms, with or without
7ba64b02eStsutsui * modification, are permitted provided that the following conditions
8ba64b02eStsutsui * are met:
9ba64b02eStsutsui * 1. Redistributions of source code must retain the above copyright
10ba64b02eStsutsui *    notice, this list of conditions and the following disclaimer.
11ba64b02eStsutsui * 2. Redistributions in binary form must reproduce the above copyright
12ba64b02eStsutsui *    notice, this list of conditions and the following disclaimer in the
13ba64b02eStsutsui *    documentation and/or other materials provided with the distribution.
14ba64b02eStsutsui *
15ba64b02eStsutsui * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16ba64b02eStsutsui * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17ba64b02eStsutsui * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18ba64b02eStsutsui * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19ba64b02eStsutsui * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20ba64b02eStsutsui * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21ba64b02eStsutsui * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22ba64b02eStsutsui * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23ba64b02eStsutsui * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24ba64b02eStsutsui * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25ba64b02eStsutsui *-----------------------------------------------------------------------*/
26ba64b02eStsutsui
27ba64b02eStsutsui#include <stdarg.h>
28ba64b02eStsutsui#include "x68k.h"
29ba64b02eStsutsui#include "opaque.h"
30ba64b02eStsutsui
31ba64b02eStsutsuistatic PixmapFormatRec *x68kFormat = NULL;
32ba64b02eStsutsuistatic PixmapFormatRec defaultFormat = {
33ba64b02eStsutsui	1,
34ba64b02eStsutsui	1,
35ba64b02eStsutsui	BITMAP_SCANLINE_PAD
36ba64b02eStsutsui};
37ba64b02eStsutsuistatic X68kScreenRec x68kScreen[X68K_FB_TYPES];
38ba64b02eStsutsuistatic X68kFbProcRec x68kFbProc[X68K_FB_TYPES];
39ba64b02eStsutsui
409decb2cdStsutsuistatic int x68kKbdType = X68K_KB_STANDARD;
419decb2cdStsutsui
42ba64b02eStsutsui/*-------------------------------------------------------------------------
43ba64b02eStsutsui * function "x68kGetScreenRec"
44ba64b02eStsutsui *
45ba64b02eStsutsui *  purpose:  get corresponding screen record
46ba64b02eStsutsui *  argument: (int)sindex       : screen index
47ba64b02eStsutsui *  returns:  (X68kScreenRec *) : X68k dependent screen record
48ba64b02eStsutsui *-----------------------------------------------------------------------*/
49ba64b02eStsutsuiX68kScreenRec *
50ba64b02eStsutsuix68kGetScreenRec(int sindex)
51ba64b02eStsutsui{
52ba64b02eStsutsui    return &x68kScreen[sindex];
53ba64b02eStsutsui}
54ba64b02eStsutsui
55ba64b02eStsutsui/*-------------------------------------------------------------------------
56ba64b02eStsutsui * function "x68kGetScreenRecByType"
57ba64b02eStsutsui *
58ba64b02eStsutsui *  purpose:  search screen record by type
59ba64b02eStsutsui *  argument: (int)type         : screen type
60ba64b02eStsutsui *  returns:  (X68kScreenRec *) : X68k dependent screen record
61ba64b02eStsutsui *-----------------------------------------------------------------------*/
62ba64b02eStsutsuiX68kScreenRec *
63ba64b02eStsutsuix68kGetScreenRecByType(int type)
64ba64b02eStsutsui{
65ba64b02eStsutsui    int i;
66ab290810Stsutsui
67ba64b02eStsutsui    for (i = 0; i < X68K_FB_TYPES; i++) {
68ba64b02eStsutsui        if (x68kScreen[i].type == type)
69ba64b02eStsutsui            return &x68kScreen[i];
70ba64b02eStsutsui    }
71ba64b02eStsutsui    return NULL;
72ba64b02eStsutsui}
73ba64b02eStsutsui
74ba64b02eStsutsui/*-------------------------------------------------------------------------
75ba64b02eStsutsui * function "x68kGetFbProcRec"
76ba64b02eStsutsui *
77ba64b02eStsutsui *  purpose:  get corresponding frame buffer procedure record
78ba64b02eStsutsui *  argument: (int)sindex       : screen index
79ba64b02eStsutsui *  returns:  (X68kFbProcRec *) : frame buffer procedure record
80ba64b02eStsutsui *-----------------------------------------------------------------------*/
81ba64b02eStsutsuiX68kFbProcRec *
82ba64b02eStsutsuix68kGetFbProcRec(int sindex)
83ba64b02eStsutsui{
84ba64b02eStsutsui    return &x68kFbProc[sindex];
85ba64b02eStsutsui}
86ba64b02eStsutsui
87ba64b02eStsutsui/*-------------------------------------------------------------------------
88ba64b02eStsutsui * function "x68kRegisterPixmapFormats"
89ba64b02eStsutsui *
90ba64b02eStsutsui *  purpose:  register pixmap formats into ScreenInfo struct
91ba64b02eStsutsui *  argument: (ScreenInfo *)pScreenInfo
92ba64b02eStsutsui *  returns:  nothing
93ba64b02eStsutsui *-----------------------------------------------------------------------*/
94ba64b02eStsutsuivoid
95ba64b02eStsutsuix68kRegisterPixmapFormats(ScreenInfo *pScreenInfo)
96ba64b02eStsutsui{
97ba64b02eStsutsui    /* supports only one pixmap format for each screen type */
98ba64b02eStsutsui    pScreenInfo->numPixmapFormats = 1;
99ba64b02eStsutsui    pScreenInfo->formats[0] = defaultFormat;
100ba64b02eStsutsui
101ba64b02eStsutsui    if (x68kFormat)
102ba64b02eStsutsui	pScreenInfo->formats[pScreenInfo->numPixmapFormats++] = *x68kFormat;
103ba64b02eStsutsui}
104ba64b02eStsutsui
1059decb2cdStsutsui/*-------------------------------------------------------------------------
1069decb2cdStsutsui * function "x68kGetKbdType"
1079decb2cdStsutsui *
1089decb2cdStsutsui *  purpose:  get keyboard map type specified in the config file
1099decb2cdStsutsui *  argument: none
1109decb2cdStsutsui *  returns:  (int) : keyboard type
1119decb2cdStsutsui *-----------------------------------------------------------------------*/
1129decb2cdStsutsuiint
1139decb2cdStsutsuix68kGetKbdType(void)
1149decb2cdStsutsui{
1159decb2cdStsutsui    return x68kKbdType;
1169decb2cdStsutsui}
1179decb2cdStsutsui
118ba64b02eStsutsui/*-------------------------------------------------------------------------
119ba64b02eStsutsui * function "x68kConfig"
120ba64b02eStsutsui *
121ba64b02eStsutsui *  purpose:  process general configuration by reading "X68kConfig" file
122b65a0881Stsutsui *            <X11_LIBDIR> is the default location of this file
123ba64b02eStsutsui *  argument: nothing
124ba64b02eStsutsui *  returns:  the number of screens
125ba64b02eStsutsui *-----------------------------------------------------------------------*/
126ba64b02eStsutsuiconst char *hostConfigFilename = "/etc/X68kConfig";
127ba64b02eStsutsuiconst char *siteConfigFilename = X11_LIBDIR "/X68kConfig";
128ba64b02eStsutsuiconst char *configFilename = NULL;
129ba64b02eStsutsuistatic FILE *config;
13015b0c026Stsutsuistatic char modeSet = FALSE;
131ba64b02eStsutsui
132ba64b02eStsutsuistatic int parseCommand(void);
13315b0c026Stsutsuistatic void logConfig(void);
134ba64b02eStsutsui
135ba64b02eStsutsuiint
136ba64b02eStsutsuix68kConfig(void)
137ba64b02eStsutsui{
13815b0c026Stsutsui    MessageType filefrom = X_DEFAULT;
13915b0c026Stsutsui
14015b0c026Stsutsui    if (configFilename) {
141ba64b02eStsutsui	config = fopen(configFilename, "r");
14215b0c026Stsutsui	filefrom = X_CMDLINE;
14315b0c026Stsutsui    } else {
144ba64b02eStsutsui	configFilename = hostConfigFilename;
145ba64b02eStsutsui	config = fopen(configFilename, "r");
146ba64b02eStsutsui	if (config == NULL) {
147ba64b02eStsutsui	    configFilename = siteConfigFilename;
148ba64b02eStsutsui	    config = fopen(configFilename, "r");
149ba64b02eStsutsui	}
150ba64b02eStsutsui    }
151ba64b02eStsutsui    if (config == NULL)
152ba64b02eStsutsui	FatalError("Can't open X68kConfig file");
15315b0c026Stsutsui
15415b0c026Stsutsui    LogMessage(filefrom, "Using config file: \"%s\"\n", configFilename);
15515b0c026Stsutsui
156ba64b02eStsutsui    while (parseCommand())
157ba64b02eStsutsui        ;
158ba64b02eStsutsui    fclose(config);
159ba64b02eStsutsui    if (!modeSet)
160ba64b02eStsutsui        FatalError("No mode set.");
16115b0c026Stsutsui    logConfig();
162ba64b02eStsutsui    return 1;
163ba64b02eStsutsui}
164ba64b02eStsutsui
165ba64b02eStsutsui
166ba64b02eStsutsui/*-------------------------------------------------------------------------
167ba64b02eStsutsui *                       X68KConfig parsing part
168ba64b02eStsutsui *-----------------------------------------------------------------------*/
16915b0c026Stsutsuistatic void parseError(int line, const char *str, ...);
170ba64b02eStsutsui
171ba64b02eStsutsuienum TokenType {
172ba64b02eStsutsui    TOKEN_EOF,
173ba64b02eStsutsui    TOKEN_SYMBOL,
174ba64b02eStsutsui    TOKEN_LITERAL,
175ba64b02eStsutsui    TOKEN_OPEN_PARENTHESIS,
176ba64b02eStsutsui    TOKEN_CLOSE_PARENTHESIS
177ba64b02eStsutsui};
178ba64b02eStsutsui
179ba64b02eStsutsuitypedef struct {
180ba64b02eStsutsui    enum TokenType type;
181ba64b02eStsutsui    int line;
182ba64b02eStsutsui    union {
183ba64b02eStsutsui        char *symbol;
184ba64b02eStsutsui        int literal;
185ba64b02eStsutsui    } content;
186ba64b02eStsutsui} Token;
187ba64b02eStsutsui
188ba64b02eStsutsui/*-------------------------------------------------------------------------
189ba64b02eStsutsui * function "getToken"
190ba64b02eStsutsui *
191ba64b02eStsutsui *  purpose:  cut out a token from configration file stream
192ba64b02eStsutsui *  argument: nothing
193ba64b02eStsutsui *  returns:  (Token *)  : cut token
194ba64b02eStsutsui *-----------------------------------------------------------------------*/
195ba64b02eStsutsuistatic Token *
196ba64b02eStsutsuigetToken(void)
197ba64b02eStsutsui{
198ba64b02eStsutsui    int c;
199ba64b02eStsutsui    static int line = 1;
200ba64b02eStsutsui    Token *ret;
201ab290810Stsutsui
202d998ab55Stsutsui    ret = malloc(sizeof(Token));
203ba64b02eStsutsui    if (ret == NULL)
204ba64b02eStsutsui        FatalError("Out of memory");
205ba64b02eStsutsui    while (TRUE) {
206ba64b02eStsutsui        /* slip white spaces */
207ba64b02eStsutsui        do {
208ba64b02eStsutsui            c = fgetc(config);
209ba64b02eStsutsui            if (c == '\n')
210ba64b02eStsutsui                line++;
211ba64b02eStsutsui        } while (isspace(c));
212ba64b02eStsutsui        if (c != ';')
213ba64b02eStsutsui            break;
214ba64b02eStsutsui        /* skip a comment */
215ba64b02eStsutsui        do {
216ba64b02eStsutsui            c = fgetc(config);
217ba64b02eStsutsui        } while (c != '\n');
218ba64b02eStsutsui        line++;
219ba64b02eStsutsui    }
220ba64b02eStsutsui    ret->line = line;
221ba64b02eStsutsui    if (c == EOF) {
222ba64b02eStsutsui        ret->type = TOKEN_EOF;
223ba64b02eStsutsui        return ret;
224ba64b02eStsutsui    }
225ba64b02eStsutsui    /* is a symbol? */
226ba64b02eStsutsui    if (isalpha(c)) {
227ba64b02eStsutsui        int i = 0;
228d998ab55Stsutsui        ret->content.symbol = malloc(32 * sizeof(char));
229ba64b02eStsutsui        if (ret->content.symbol == NULL)
230ba64b02eStsutsui            FatalError("Out of memory");
231ba64b02eStsutsui        do {
232ba64b02eStsutsui            if (i < 31)
233ba64b02eStsutsui                ret->content.symbol[i++] = c;
234ba64b02eStsutsui            c = fgetc(config);
235ba64b02eStsutsui        } while (isalnum(c) || c == '_');
236ba64b02eStsutsui        ungetc(c, config);
237ba64b02eStsutsui        ret->content.symbol[i] = '\0';
238ba64b02eStsutsui        ret->type = TOKEN_SYMBOL;
239ba64b02eStsutsui        return ret;
240ba64b02eStsutsui    }
241ba64b02eStsutsui    /* is a literal number? */
242ba64b02eStsutsui    if (isdigit(c)) {
243ba64b02eStsutsui        char tmp[32];
244ba64b02eStsutsui        int i = 0;
245ba64b02eStsutsui        do {
246ba64b02eStsutsui            if (i < 31)
247ba64b02eStsutsui                tmp[i++] = c;
248ba64b02eStsutsui            c = fgetc(config);
249ba64b02eStsutsui        } while (isdigit(c));
250ba64b02eStsutsui        ungetc(c, config);
251ba64b02eStsutsui        tmp[i] = '\0';
252ba64b02eStsutsui        if (sscanf(tmp, "%d", &ret->content.literal) != 1)
253ba64b02eStsutsui            parseError(line, "illegal literal value");
254ba64b02eStsutsui        ret->type = TOKEN_LITERAL;
255ba64b02eStsutsui        return ret;
256ba64b02eStsutsui    }
257ba64b02eStsutsui    /* others */
258ba64b02eStsutsui    switch(c) {
259ba64b02eStsutsui        case '(':
260ba64b02eStsutsui            ret->type = TOKEN_OPEN_PARENTHESIS;
261ba64b02eStsutsui            break;
262ba64b02eStsutsui        case ')':
263ba64b02eStsutsui            ret->type = TOKEN_CLOSE_PARENTHESIS;
264ba64b02eStsutsui            break;
265ba64b02eStsutsui        default:
266ba64b02eStsutsui            parseError(line, NULL);
267ba64b02eStsutsui    }
268ba64b02eStsutsui    return ret;
269ba64b02eStsutsui}
270ba64b02eStsutsui
271ba64b02eStsutsuitypedef struct {
272ba64b02eStsutsui    const char *symbol;
273ba64b02eStsutsui    void (*proc)(int argc, Token **argv);
274ba64b02eStsutsui} Command;
275ba64b02eStsutsui
276ba64b02eStsutsuistatic void parseModeDef(int argc, Token **argv);
277ba64b02eStsutsuistatic void parseMouse(int argc, Token **argv);
278ba64b02eStsutsuistatic void parseKeyboard(int argc, Token **argv);
279ba64b02eStsutsuistatic void parseMode(int argc, Token **argv);
280ba64b02eStsutsui
28115b0c026Stsutsuistatic const Command command[] = {
282ba64b02eStsutsui    { "ModeDef", parseModeDef },
283ba64b02eStsutsui    { "Mouse", parseMouse },
284ba64b02eStsutsui    { "Keyboard", parseKeyboard },
285ba64b02eStsutsui    { "Mode", parseMode },
286ba64b02eStsutsui};
287ab290810Stsutsui#define NCOMMANDS (sizeof(command)/sizeof(command[0]))
288ba64b02eStsutsui
28915b0c026Stsutsuistatic const char *x68kTypeStr[] = {
29015b0c026Stsutsui	[X68K_FB_NULL]    = NULL,
29115b0c026Stsutsui	[X68K_FB_TEXT]    = "Text",
29215b0c026Stsutsui	[X68K_FB_GRAPHIC] = "Graphic",
29315b0c026Stsutsui};
29415b0c026Stsutsui#define NTYPES (sizeof(x68kTypeStr) / sizeof(x68kTypeStr[0]))
29515b0c026Stsutsui
29615b0c026Stsutsuistatic const char *x68kClassStr[] = {
29715b0c026Stsutsui	[StaticGray]  = "StaticGray",
29815b0c026Stsutsui	[GrayScale]   = "GrayScale",
29915b0c026Stsutsui	[StaticColor] = "StaticColor",
30015b0c026Stsutsui	[PseudoColor] = "PseudoColor",
30115b0c026Stsutsui	[TrueColor]   = "TrueColor",
30215b0c026Stsutsui	[DirectColor] = "DirectColor",
30315b0c026Stsutsui};
30415b0c026Stsutsui#define NCLASSES (sizeof(x68kClassStr) / sizeof(x68kClassStr[0]))
30515b0c026Stsutsui#define ClassInvalid	(-1)
30615b0c026Stsutsui
307ba64b02eStsutsui/*-------------------------------------------------------------------------
308ba64b02eStsutsui * function "parseCommand"
309ba64b02eStsutsui *
310ba64b02eStsutsui *  purpose:  parse generic command. every command parsing departs here.
311ba64b02eStsutsui *  argument: nothing
312ba64b02eStsutsui *  returns:  (int) : FALSE if there's no rest
313ba64b02eStsutsui *                    TRUE  otherwise
314ba64b02eStsutsui *-----------------------------------------------------------------------*/
315ba64b02eStsutsuistatic int
316ba64b02eStsutsuiparseCommand(void)
317ba64b02eStsutsui{
318ba64b02eStsutsui    Token **argv = 0, *token;
319ba64b02eStsutsui    int argc = 0;
320ba64b02eStsutsui    int i;
321ab290810Stsutsui
322ba64b02eStsutsui    token = getToken();
323ba64b02eStsutsui    if (token->type == TOKEN_EOF)
324ba64b02eStsutsui        return FALSE;
325ba64b02eStsutsui    if (token->type != TOKEN_OPEN_PARENTHESIS)
326ba64b02eStsutsui        parseError(token->line, "missing parenthesis");
327a2ab6c90Stsutsui    free(token);
328ba64b02eStsutsui
329ba64b02eStsutsui    /* get command name and arguments */
330ba64b02eStsutsui    while (TRUE) {
331ba64b02eStsutsui        token = getToken();
332ba64b02eStsutsui        if (token->type == TOKEN_EOF)
333ba64b02eStsutsui            parseError(token->line, "reached EOF");
334ba64b02eStsutsui        if (token->type == TOKEN_CLOSE_PARENTHESIS) {
335a2ab6c90Stsutsui            free(token);
336ba64b02eStsutsui            break;
337ba64b02eStsutsui        }
338ba64b02eStsutsui        argc++;
339d998ab55Stsutsui        argv = realloc(argv, sizeof(Token *) * argc);
340ba64b02eStsutsui        if (argv == NULL)
341ba64b02eStsutsui            FatalError("Out of memory");
342ba64b02eStsutsui        argv[argc-1] = token;
343ba64b02eStsutsui    }
344ba64b02eStsutsui    if (argc == 0)
345ba64b02eStsutsui        return TRUE;
346ba64b02eStsutsui
347ba64b02eStsutsui    /* call corresponding command procedure */
348ba64b02eStsutsui    if (argv[0]->type != TOKEN_SYMBOL)
349ba64b02eStsutsui        parseError(argv[0]->line, "command name required");
350ba64b02eStsutsui    for (i = 0; i < NCOMMANDS; i++) {
351ba64b02eStsutsui        if (strcasecmp(command[i].symbol, argv[0]->content.symbol) == 0) {
352ba64b02eStsutsui            /* parse command */
353ab290810Stsutsui            command[i].proc(argc, argv);
354ba64b02eStsutsui            break;
355ba64b02eStsutsui        }
356ba64b02eStsutsui    }
357ba64b02eStsutsui    if (i == NCOMMANDS)
358ba64b02eStsutsui        parseError(argv[0]->line, "unknown command `%s'",
359ba64b02eStsutsui                   argv[0]->content.symbol);
360ba64b02eStsutsui
361ba64b02eStsutsui    /* free arguments */
362ba64b02eStsutsui    for (i = 0; i < argc; i++) {
363ba64b02eStsutsui        if (argv[i]->type == TOKEN_SYMBOL)
364a2ab6c90Stsutsui            free(argv[i]->content.symbol);
365a2ab6c90Stsutsui        free(argv[i]);
366ba64b02eStsutsui    }
367a2ab6c90Stsutsui    free(argv);
368ba64b02eStsutsui    return TRUE;
369ba64b02eStsutsui}
370ba64b02eStsutsui
371ba64b02eStsutsui/*-------------------------------------------------------------------------
372ba64b02eStsutsui * function "checkArguments"
373ba64b02eStsutsui *
374ba64b02eStsutsui *  purpose:  examine the number of arguments and the type of each
375ba64b02eStsutsui *            argument.
376ba64b02eStsutsui *  argument: (int)n                 : correct number of arguments
37715b0c026Stsutsui *            (const enum TokenType *)type : table of types
378ba64b02eStsutsui *            (int)argc_m1           : actual number of arguments
379ba64b02eStsutsui *            (Token **)argv         : command and arguments
380ba64b02eStsutsui *  returns:  nothing
381ba64b02eStsutsui *-----------------------------------------------------------------------*/
382ba64b02eStsutsuistatic void
38315b0c026StsutsuicheckArguments(int n, const enum TokenType *type, int argc_m1, Token **argv)
384ba64b02eStsutsui{
385ba64b02eStsutsui    int i;
386ab290810Stsutsui
387ba64b02eStsutsui    if (argc_m1 < n)
388ba64b02eStsutsui        parseError(argv[0]->line, "too few arguments to command `%s'",
389ba64b02eStsutsui                   argv[0]->content.symbol);
390ba64b02eStsutsui    if (argc_m1 > n)
391ba64b02eStsutsui        parseError(argv[0]->line, "too many arguments to command `%s'",
392ba64b02eStsutsui                   argv[0]->content.symbol);
393ba64b02eStsutsui    for (i = 0; i < n; i++) {
394ba64b02eStsutsui        if (argv[i+1]->type != type[i])
395ba64b02eStsutsui            parseError(argv[i+1]->line,
396ba64b02eStsutsui                       "type mismatch. argument %d to command `%s'",
397ba64b02eStsutsui                       i+1, argv[0]->content.symbol);
398ba64b02eStsutsui    }
399ba64b02eStsutsui}
400ba64b02eStsutsui
401ba64b02eStsutsuitypedef struct _Mode {
402ba64b02eStsutsui    struct _Mode *next;
40315b0c026Stsutsui    const char *name;
404ba64b02eStsutsui    int type;
405ba64b02eStsutsui    int depth;
406ba64b02eStsutsui    int class;
407ba64b02eStsutsui    int width, height;
408ba64b02eStsutsui    X68kFbReg reg;
409ba64b02eStsutsui} Mode;
410ba64b02eStsutsui
41115b0c026Stsutsuistatic Mode *modeList = NULL;
41215b0c026Stsutsuistatic Mode *modeChosen;
413ba64b02eStsutsui
414ba64b02eStsutsui/*-------------------------------------------------------------------------
415ba64b02eStsutsui * function "parseModeDef"
416ba64b02eStsutsui *
417ba64b02eStsutsui *  purpose:  define a mode
418ba64b02eStsutsui *  argument: (int)argc, (Token **)argv : command and arguments
419ba64b02eStsutsui *  returns:  nothing
420ba64b02eStsutsui *-----------------------------------------------------------------------*/
421ba64b02eStsutsuistatic void
422ba64b02eStsutsuiparseModeDef(int argc, Token **argv)
423ba64b02eStsutsui{
42415b0c026Stsutsui    const enum TokenType argtype[] = {
425ba64b02eStsutsui        /* name       type          depth          class      */
426ba64b02eStsutsui        TOKEN_SYMBOL, TOKEN_SYMBOL, TOKEN_LITERAL, TOKEN_SYMBOL,
427ba64b02eStsutsui        /* width       height       */
428ba64b02eStsutsui        TOKEN_LITERAL, TOKEN_LITERAL,
429ba64b02eStsutsui        /* register values */
430ba64b02eStsutsui        TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL,
431ba64b02eStsutsui        TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL,
432ba64b02eStsutsui        TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL
433ba64b02eStsutsui    };
434ba64b02eStsutsui    Mode *mode;
435ba64b02eStsutsui    char *symbol;
43615b0c026Stsutsui    int type, class, width, height;
437ab290810Stsutsui
438ba64b02eStsutsui    checkArguments(18, argtype, argc-1, argv);
439ba64b02eStsutsui
440d998ab55Stsutsui    mode = malloc(sizeof(Mode));
441ba64b02eStsutsui    if (mode == NULL)
442ba64b02eStsutsui        FatalError("Out of memory");
443ba64b02eStsutsui    mode->name = strdup(argv[1]->content.symbol);
444ab290810Stsutsui
445ba64b02eStsutsui    /* parse frame buffer type */
446ba64b02eStsutsui    symbol = argv[2]->content.symbol;
44715b0c026Stsutsui    mode->type = X68K_FB_NULL;
44815b0c026Stsutsui    for (type = 1; type < NTYPES; type++) {
44915b0c026Stsutsui        if (strcasecmp(x68kTypeStr[type], symbol) == 0) {
45015b0c026Stsutsui            mode->type = type;
45115b0c026Stsutsui            break;
45215b0c026Stsutsui        }
45315b0c026Stsutsui    }
45415b0c026Stsutsui    if (mode->type == X68K_FB_NULL)
45515b0c026Stsutsui        parseError(argv[2]->line, "unknown frame buffer type `%s'", symbol);
45615b0c026Stsutsui
457ba64b02eStsutsui    mode->depth = argv[3]->content.literal;
458ab290810Stsutsui
459ba64b02eStsutsui    /* parse frame buffer class */
460ba64b02eStsutsui    symbol = argv[4]->content.symbol;
46115b0c026Stsutsui    mode->class = ClassInvalid;
46215b0c026Stsutsui    for (class = 0; class < NCLASSES; class++) {
46315b0c026Stsutsui	if (strcasecmp(x68kClassStr[class], symbol) == 0) {
46415b0c026Stsutsui            mode->class = class;
46515b0c026Stsutsui            break;
46615b0c026Stsutsui	}
46715b0c026Stsutsui    }
46815b0c026Stsutsui    if (mode->class == ClassInvalid)
46915b0c026Stsutsui        parseError(argv[4]->line, "unknown frame buffer class `%s'", symbol);
47015b0c026Stsutsui
471ba64b02eStsutsui    width = mode->width = argv[5]->content.literal;
472ba64b02eStsutsui    height = mode->height = argv[6]->content.literal;
473ab290810Stsutsui
474ba64b02eStsutsui    /* examine whether type, depth, class, width, and height are
475ba64b02eStsutsui       a legal combination or not, and then set mode registers */
47615b0c026Stsutsui    switch (type) {
477ba64b02eStsutsui        case X68K_FB_TEXT:
478ba64b02eStsutsui            if (mode->depth == 1 && class == StaticGray &&
479ba64b02eStsutsui                width <= 1024 && height <= 1024) {
480ba64b02eStsutsui                mode->reg.videoc.r1 = 0x21e4;
481ba64b02eStsutsui                mode->reg.videoc.r2 = 0x0020;
482ba64b02eStsutsui                goto legal;
483ba64b02eStsutsui            }
484ba64b02eStsutsui            break;
485ba64b02eStsutsui        case X68K_FB_GRAPHIC:
486ba64b02eStsutsui            switch (mode->depth) {
487ba64b02eStsutsui                case 4:
488ba64b02eStsutsui                    if ( (class == StaticGray || class == PseudoColor) &&
489ba64b02eStsutsui                         width <= 1024 && height <= 1024 ) {
490ba64b02eStsutsui                        mode->reg.videoc.r1 = 0x21e4;
491ba64b02eStsutsui                        mode->reg.videoc.r2 = 0x0010;
492ba64b02eStsutsui                        goto legal;
493ba64b02eStsutsui                    }
494ba64b02eStsutsui                    break;
495ba64b02eStsutsui                case 8:
496ba64b02eStsutsui                    if (class == PseudoColor &&
497ba64b02eStsutsui                        width <= 512 && height <= 512) {
498ba64b02eStsutsui                        mode->reg.videoc.r1 = 0x21e4;
499ba64b02eStsutsui                        mode->reg.videoc.r2 = 0x0003;
500ba64b02eStsutsui                        goto legal;
501ba64b02eStsutsui                    }
502ba64b02eStsutsui                    break;
503ba64b02eStsutsui                case 15:
504ba64b02eStsutsui                    if (class == TrueColor &&
505ba64b02eStsutsui                        width <= 512 && height <= 512) {
506ba64b02eStsutsui                        mode->reg.videoc.r1 = 0x21e4;
507ba64b02eStsutsui                        mode->reg.videoc.r2 = 0x000f;
508ba64b02eStsutsui                        goto legal;
509ba64b02eStsutsui                    }
510ba64b02eStsutsui                    break;
511ba64b02eStsutsui            }
512ba64b02eStsutsui            break;
513ba64b02eStsutsui    }
514ba64b02eStsutsui    parseError(argv[0]->line, "illegal combination of mode parameters");
515ba64b02eStsutsui  legal:
516ba64b02eStsutsui
517ba64b02eStsutsui    /* store register values */
518ba64b02eStsutsui    mode->reg.crtc.r00 = argv[7]->content.literal;
519ba64b02eStsutsui    mode->reg.crtc.r01 = argv[8]->content.literal;
520ba64b02eStsutsui    mode->reg.crtc.r02 = argv[9]->content.literal;
521ba64b02eStsutsui    mode->reg.crtc.r03 = argv[10]->content.literal;
522ba64b02eStsutsui    mode->reg.crtc.r04 = argv[11]->content.literal;
523ba64b02eStsutsui    mode->reg.crtc.r05 = argv[12]->content.literal;
524ba64b02eStsutsui    mode->reg.crtc.r06 = argv[13]->content.literal;
525ba64b02eStsutsui    mode->reg.crtc.r07 = argv[14]->content.literal;
526ba64b02eStsutsui    mode->reg.crtc.r08 = argv[15]->content.literal;
527ba64b02eStsutsui    mode->reg.crtc.r20 = argv[16]->content.literal;
528ba64b02eStsutsui    mode->reg.videoc.r0 = argv[17]->content.literal;
529ba64b02eStsutsui    mode->reg.dotClock = argv[18]->content.literal;
530ba64b02eStsutsui
531ba64b02eStsutsui    /* set scroll registers to zero */
532ba64b02eStsutsui    mode->reg.crtc.r12 = 0;    mode->reg.crtc.r13 = 0;
533ba64b02eStsutsui    mode->reg.crtc.r14 = 0;    mode->reg.crtc.r15 = 0;
534ba64b02eStsutsui    mode->reg.crtc.r16 = 0;    mode->reg.crtc.r17 = 0;
535ba64b02eStsutsui    mode->reg.crtc.r18 = 0;    mode->reg.crtc.r19 = 0;
536ab290810Stsutsui
537ba64b02eStsutsui    /* add new mode to linked mode list */
538ba64b02eStsutsui    mode->next = modeList;
539ba64b02eStsutsui    modeList = mode;
540ba64b02eStsutsui}
541ba64b02eStsutsui
542ba64b02eStsutsui/*-------------------------------------------------------------------------
543ba64b02eStsutsui * function "parseMode"
544ba64b02eStsutsui *
545ba64b02eStsutsui *  purpose:  choose a mode from predefined modes
546ba64b02eStsutsui *  argument: (int)argc, (Token **)argv : command and arguments
547ba64b02eStsutsui *  returns:  nothing
548ba64b02eStsutsui *-----------------------------------------------------------------------*/
549ba64b02eStsutsuistatic void
550ba64b02eStsutsuiparseMode(int argc, Token **argv)
551ba64b02eStsutsui{
55215b0c026Stsutsui    const enum TokenType argtype[]= { TOKEN_SYMBOL };
553ba64b02eStsutsui    Mode *mode;
554ba64b02eStsutsui
555ba64b02eStsutsui    checkArguments(1, argtype, argc-1, argv);
556ba64b02eStsutsui
557ba64b02eStsutsui    /* search mode to set from mode list */
558ba64b02eStsutsui    for (mode = modeList; mode != NULL; mode = mode->next) {
559ba64b02eStsutsui        if (strcmp(mode->name, argv[1]->content.symbol) == 0)
560ba64b02eStsutsui            break;
561ba64b02eStsutsui    }
562ba64b02eStsutsui    if (mode == NULL)
563ba64b02eStsutsui        parseError(argv[1]->line, "undefined mode `%s'",
564ba64b02eStsutsui                   argv[1]->content.symbol);
565ba64b02eStsutsui
566ba64b02eStsutsui    x68kScreen[0].type = mode->type;
567ba64b02eStsutsui    x68kScreen[0].depth = mode->depth;
568ba64b02eStsutsui    x68kScreen[0].class = mode->class;
569ba64b02eStsutsui    x68kScreen[0].dpi = 75;
570ba64b02eStsutsui    x68kScreen[0].x68kreg = mode->reg;
571ba64b02eStsutsui    x68kScreen[0].scr_width = mode->width;
572ba64b02eStsutsui    x68kScreen[0].scr_height = mode->height;
573ab290810Stsutsui
574ba64b02eStsutsui    switch (mode->type) {
575ba64b02eStsutsui        /* for TVRAM frame buffer */
576ba64b02eStsutsui        case X68K_FB_TEXT:
577ba64b02eStsutsui            x68kFbProc[0].open = x68kTextOpen;
578ba64b02eStsutsui            x68kFbProc[0].init = x68kTextInit;
579ba64b02eStsutsui            x68kFbProc[0].close = x68kTextClose;
580ba64b02eStsutsui            x68kScreen[0].fb_width = 1024;
581ba64b02eStsutsui            x68kScreen[0].fb_height = 1024;
582ba64b02eStsutsui            break;
583ba64b02eStsutsui        /* for GVRAM frame buffer */
584ba64b02eStsutsui        case X68K_FB_GRAPHIC:
585ba64b02eStsutsui            x68kFbProc[0].open = x68kGraphOpen;
586ba64b02eStsutsui            x68kFbProc[0].init = x68kGraphInit;
587ba64b02eStsutsui            x68kFbProc[0].close = x68kGraphClose;
588d998ab55Stsutsui	    x68kFormat = malloc (sizeof(PixmapFormatRec));
589ba64b02eStsutsui	    x68kFormat->scanlinePad = BITMAP_SCANLINE_PAD;
590ba64b02eStsutsui            x68kFormat->bitsPerPixel = 16;
591ba64b02eStsutsui            switch (mode->depth) {
592ba64b02eStsutsui                case 4:
593ba64b02eStsutsui                    x68kFormat->depth = 4;
594ba64b02eStsutsui                    x68kScreen[0].fb_width = 1024;
595ba64b02eStsutsui                    x68kScreen[0].fb_height = 1024;
596ba64b02eStsutsui                    break;
597ba64b02eStsutsui                case 8:
598ba64b02eStsutsui                    x68kFormat->depth = 8;
599ba64b02eStsutsui                    x68kScreen[0].fb_width = 512;
600ba64b02eStsutsui                    x68kScreen[0].fb_height = 512;
601ba64b02eStsutsui                    break;
602ba64b02eStsutsui                case 15:
603ba64b02eStsutsui                    x68kFormat->depth = 15;
604ba64b02eStsutsui                    x68kScreen[0].fb_width = 512;
605ba64b02eStsutsui                    x68kScreen[0].fb_height = 512;
606ba64b02eStsutsui            }
607ba64b02eStsutsui    }
608ba64b02eStsutsui    modeSet = TRUE;
60915b0c026Stsutsui    modeChosen = mode;
610ba64b02eStsutsui}
611ba64b02eStsutsui
612ba64b02eStsutsui/*-------------------------------------------------------------------------
613ba64b02eStsutsui * function "parseMouse"
614ba64b02eStsutsui *
615ba64b02eStsutsui *  purpose:  set mouse attribute.
616ba64b02eStsutsui *  argument: (int)argc, (Token **)argv : command and arguments
617ba64b02eStsutsui *  returns:  nothing
618ba64b02eStsutsui *-----------------------------------------------------------------------*/
619ba64b02eStsutsuistatic void
620ba64b02eStsutsuiparseMouse(int argc, Token **argv)
621ba64b02eStsutsui{
62215b0c026Stsutsui    const enum TokenType argtype[] = { TOKEN_SYMBOL };
623ab290810Stsutsui
624ba64b02eStsutsui    checkArguments(1, argtype, argc-1, argv);
625ba64b02eStsutsui    /* only `standard' mouse allowed */
626ba64b02eStsutsui    if (strcasecmp("standard", argv[1]->content.symbol) != 0)
627ba64b02eStsutsui        parseError(argv[1]->line, "unknown mouse type `%s'",
628ba64b02eStsutsui                   argv[1]->content.symbol);
629ba64b02eStsutsui}
630ba64b02eStsutsui
631ba64b02eStsutsui/*-------------------------------------------------------------------------
632ba64b02eStsutsui * function "parseKeyboard"
633ba64b02eStsutsui *
634ba64b02eStsutsui *  purpose:  select keyboard map
635ba64b02eStsutsui *  argument: (int)argc, (Token **)argv : command and arguments
636ba64b02eStsutsui *  returns:  nothing
637ba64b02eStsutsui *-----------------------------------------------------------------------*/
638ba64b02eStsutsuistatic void
639ba64b02eStsutsuiparseKeyboard(int argc, Token **argv)
640ba64b02eStsutsui{
64115b0c026Stsutsui    const enum TokenType argtype[] = { TOKEN_SYMBOL };
642ab290810Stsutsui
643ba64b02eStsutsui    checkArguments(1, argtype, argc-1, argv);
644ba64b02eStsutsui    if (strcasecmp("standard", argv[1]->content.symbol) == 0) {
645ba64b02eStsutsui        x68kKeySyms = &jisKeySyms;
6469decb2cdStsutsui        x68kKbdType = X68K_KB_STANDARD;
647ba64b02eStsutsui    } else if (strcasecmp("ascii", argv[1]->content.symbol) == 0) {
648ba64b02eStsutsui        x68kKeySyms = &asciiKeySyms;
6499decb2cdStsutsui        x68kKbdType = X68K_KB_ASCII;
650ab290810Stsutsui    } else
651ba64b02eStsutsui        parseError(argv[1]->line, "unknown keyboard type `%s'",
652ba64b02eStsutsui                   argv[1]->content.symbol);
653ba64b02eStsutsui}
654ba64b02eStsutsui
655ba64b02eStsutsui/*-------------------------------------------------------------------------
656ba64b02eStsutsui * function "parseError"
657ba64b02eStsutsui *
65815b0c026Stsutsui *  purpose:  print error message to log and stderr and abort Xserver.
65915b0c026Stsutsui *  argument: (int)line         : the line in which some error was detected
66015b0c026Stsutsui *            (const char *)str : error message
661ba64b02eStsutsui *  returns:  nothing
662ba64b02eStsutsui *-----------------------------------------------------------------------*/
66315b0c026Stsutsuistatic void
664ba64b02eStsutsuiparseError(int line, const char *str, ...)
665ba64b02eStsutsui{
666ba64b02eStsutsui    va_list arglist;
667ab290810Stsutsui
66815b0c026Stsutsui    LogMessageVerb(X_ERROR, 0, "parse error in %s at line %d",
66915b0c026Stsutsui        configFilename, line);
670ba64b02eStsutsui    if (str != NULL) {
67115b0c026Stsutsui        LogMessageVerb(X_NONE, 0, ":\n\t");
672ba64b02eStsutsui	va_start(arglist, str);
67315b0c026Stsutsui	LogVMessageVerb(X_NONE, 0, str, arglist);
674ba64b02eStsutsui	va_end(arglist);
67515b0c026Stsutsui    }
67615b0c026Stsutsui    LogMessageVerb(X_NONE, 0, "\n");
67715b0c026Stsutsui    FatalError("Error in X68k server config file. Exiting.\n");
67815b0c026Stsutsui}
67915b0c026Stsutsui
68015b0c026Stsutsui/*-------------------------------------------------------------------------
68115b0c026Stsutsui * function "logConfig"
68215b0c026Stsutsui *
68315b0c026Stsutsui *  purpose:  print specified config settings to log.
68415b0c026Stsutsui *  argument: nothing
68515b0c026Stsutsui *  returns:  nothing
68615b0c026Stsutsui *-----------------------------------------------------------------------*/
68715b0c026Stsutsuistatic void
68815b0c026StsutsuilogConfig(void)
68915b0c026Stsutsui{
69015b0c026Stsutsui
69115b0c026Stsutsui    LogMessage(X_CONFIG, "Using specified mode: \"%s\"\n", modeChosen->name);
69215b0c026Stsutsui    LogMessage(X_CONFIG, "Type: %s, Class: %s, Size: %dx%d, Depth: %d\n",
69315b0c026Stsutsui        x68kTypeStr[modeChosen->type], x68kClassStr[modeChosen->class],
69415b0c026Stsutsui        modeChosen->width, modeChosen->height, modeChosen->depth);
69515b0c026Stsutsui    LogMessage(X_CONFIG, "Keyboard: %s\n",
6969decb2cdStsutsui        x68kKbdType == X68K_KB_ASCII ? "ascii" : "standard");
69715b0c026Stsutsui    LogMessage(X_CONFIG, "Mouse: %s\n", "standard");
698ba64b02eStsutsui}
699ba64b02eStsutsui
700ba64b02eStsutsui/* EOF x68kConfig.c */
701