/* * BRLTTY - A background process providing access to the console screen (when in * text mode) for a blind person using a refreshable braille display. * * Copyright (C) 1995-2021 by The BRLTTY Developers. * * BRLTTY comes with ABSOLUTELY NO WARRANTY. * * This is free software, placed under the terms of the * GNU Lesser General Public License, as published by the Free Software * Foundation; either version 2.1 of the License, or (at your option) any * later version. Please see the file LICENSE-LGPL for details. * * Web Page: http://brltty.app/ * * This software is maintained by Dave Mielke . */ #include "prologue.h" #include "log.h" #include "profile.h" #include "datafile.h" #include "file.h" #include "utf8.h" typedef struct { const ProfileDescriptor *profile; char **values; } ProfileActivationData; static int processPropertyAssignment ( DataFile *file, const DataString *name, char **value, const ProfileActivationData *pad ) { unsigned int index; for (index=0; indexprofile->properties.count; index+=1) { if (isKeyword(pad->profile->properties.array[index].name, name->characters, name->length)) { char **v = &pad->values[index]; if (*v) { reportDataError(file, "property assigned more than once: %s:%.*"PRIws, pad->profile->category, name->length, name->characters); free(*v); } *v = *value; *value = NULL; return 1; } } reportDataError(file, "unknown property: %s:%.*"PRIws, pad->profile->category, name->length, name->characters); return 1; } static DATA_OPERANDS_PROCESSOR(processPropertyOperands) { const ProfileActivationData *pad = data; int ok = 1; DataString name; if (getDataString(file, &name, 0, "property name")) { DataString value; if (getDataString(file, &value, 0, "property value")) { char *v = getUtf8FromWchars(value.characters, value.length, NULL); if (v) { if (!processPropertyAssignment(file, &name, &v, pad)) ok = 0; if (v) free(v); } else { ok = 0; } } } return ok; } static DATA_OPERANDS_PROCESSOR(processProfileOperands) { BEGIN_DATA_DIRECTIVE_TABLE DATA_NESTING_DIRECTIVES, DATA_VARIABLE_DIRECTIVES, DATA_CONDITION_DIRECTIVES, {.name=NULL, .processor=processPropertyOperands}, END_DATA_DIRECTIVE_TABLE return processDirectiveOperand(file, &directives, "profile directive", data); } char * makeProfilePath (const ProfileDescriptor *profile, const char *directory, const char *name) { char *subdirectory = makePath(directory, PROFILES_SUBDIRECTORY); if (subdirectory) { char *file = makeFilePath(subdirectory, name, profile->extension); free(subdirectory); if (file) return file; } return NULL; } static int changeProperty (const ProfileProperty *property, const char *value) { if (property->change) { if (!value) value = *property->defaultValue; if (property->change(value)) { return 1; } } return 0; } static int changeProperties (const ProfileDescriptor *profile, char **values) { int ok = !profile->begin || profile->begin(); if (ok) { const ProfileProperty *const start = profile->properties.array; const ProfileProperty *const end = start + profile->properties.count; const ProfileProperty *property = start; while (property < end) { char *value = values? values[property - start]: NULL; if (!changeProperty(property, value)) ok = 0; if (value) free(value); property += 1; } if (profile->end && !profile->end()) ok = 0; } return ok; } int activateProfile (const ProfileDescriptor *profile, const char *directory, const char *name) { int ok = 0; if (setBaseDataVariables(NULL)) { char *path; if ((path = makeProfilePath(profile, directory, name))) { ProfileActivationData pad = { .profile = profile }; if ((pad.values = malloc(ARRAY_SIZE(pad.values, profile->properties.count)))) { for (unsigned int index=0; indexproperties.count; index+=1) { pad.values[index] = NULL; } const DataFileParameters parameters = { .processOperands = processProfileOperands, .data = &pad }; if (processDataFile(path, ¶meters)) { if (changeProperties(profile, pad.values)) { ok = 1; } } free(pad.values); } else { logMallocError(); } free(path); } } return ok; } int deactivateProfile (const ProfileDescriptor *profile) { return changeProperties(profile, NULL); }