Ticket #13828: 0001-Implement-new-setlocale-command.patch

File 0001-Implement-new-setlocale-command.patch, 4.3 KB (added by KeyboardFire, 6 years ago)
  • new file src/bin/setlocale.cpp

    From a4bee04efbcc0ff898e9e450f379e94e51ca1847 Mon Sep 17 00:00:00 2001
    From: KeyboardFire <andy@keyboardfire.com>
    Date: Sun, 3 Dec 2017 10:59:45 -0600
    Subject: [PATCH] Implement new `setlocale' command
    
    This is a command line tool that serves the same purpose as the "Locale"
    application under preferences. It allows the user to set the system
    locale with syntax similar to the following:
    
      setlocale en
      setlocale en us -v posix
      setlocale bs -s cyrl
      setlocale bs ba -s cyrl
    
    It also supports the -l flag to list all available locales.
    
    In the future, the setlocale utility should support all the features
    available from the GUI application.
    ---
     src/bin/setlocale.cpp | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++
     1 file changed, 131 insertions(+)
     create mode 100644 src/bin/setlocale.cpp
    
    diff --git a/src/bin/setlocale.cpp b/src/bin/setlocale.cpp
    new file mode 100644
    index 0000000000..f25baadb5e
    - +  
     1/*
     2 * Copyright 2017 Haiku, Inc. All rights reserved.
     3 * Distributed under the terms of the MIT License.
     4 *
     5 * Authors:
     6 *      Andrew Tockman, andy@keyboardfire.com
     7 */
     8
     9#include <stdio.h>
     10#include <stdlib.h>
     11#include <string.h>
     12
     13#include <Font.h>
     14#include <Locale.h>
     15#include <LocaleRoster.h>
     16#include <MutableLocaleRoster.h>
     17#include <String.h>
     18
     19using BPrivate::MutableLocaleRoster;
     20
     21bool matches(const char* a, const char* b)
     22{
     23    if (a == NULL && b == NULL)
     24        return true;
     25    if (a == NULL || b == NULL)
     26        return false;
     27    return !strcasecmp(a, b);
     28}
     29
     30
     31int main(int argc, char **argv)
     32{
     33    const char* queryCode = NULL;
     34    const char* queryCountry = NULL;
     35    const char* queryScript = NULL;
     36    const char* queryVariant = NULL;
     37    bool list = false, err = false;
     38
     39    // parse command line
     40    for (int i = 1; i < argc; ++i) {
     41        if (*argv[i] == '-') {
     42            // parse a command line flag
     43            if (!strcmp(argv[i], "--list"))
     44                list = true;
     45            else if (argv[i][1] && !argv[i][2]) {
     46                // found a single character flag
     47                if (argv[i][1] == 'l')
     48                    list = true;
     49                else if (argv[i][1] == 's')
     50                    queryScript = argv[++i];
     51                else if (argv[i][1] == 'v')
     52                    queryVariant = argv[++i];
     53                else {
     54                    err = true;
     55                    break;
     56                }
     57            } else
     58                err = false; // unknown flag
     59        } else if (queryCode == NULL)
     60            // bare argument; fill up code and then country, erroring on
     61            // anything more than two arguments
     62            queryCode = argv[i];
     63        else if (queryCountry == NULL)
     64            queryCountry = argv[i];
     65        else {
     66            err = true;
     67            break;
     68        }
     69    }
     70
     71    // check for proper command line, requiring exactly one of list or query
     72    if (err || ((queryCode == NULL) ^ list)) {
     73        fprintf(stderr,
     74            "Usage:\n"
     75            "  setlocale -l|--list\n"
     76            "  setlocale language [country] [-s script] [-v variant]\n");
     77        return 1;
     78    }
     79
     80    // query for all available languages
     81    BMessage languages;
     82    BLocaleRoster::Default()->GetAvailableLanguages(&languages);
     83
     84    const char* id;
     85    for (int32 i = 0; languages.FindString("language", i, &id) == B_OK; ++i) {
     86        BLanguage* language;
     87        if (BLocaleRoster::Default()->GetLanguage(id, &language) == B_OK) {
     88            // extract all the relevant information about the language
     89            BString name;
     90            language->GetNativeName(name);
     91            const char* code = language->Code();
     92            const char* country = language->CountryCode();
     93            const char* script = language->ScriptCode();
     94            const char* variant = language->Variant();
     95
     96            // if we're listing, print the information
     97            if (list)
     98                printf("%s\t%s\t%s\t%s\t%s\n",
     99                    code,
     100                    country ? country : "",
     101                    script ? script : "",
     102                    variant ? variant : "",
     103                    name.String());
     104            else if (!strcasecmp(code, queryCode)
     105                && matches(country, queryCountry)
     106                && matches(script, queryScript)
     107                && matches(variant, queryVariant)) {
     108                // found a match! set the new locale
     109                BMessage preferred;
     110                preferred.AddString("language", id);
     111                MutableLocaleRoster::Default()->
     112                    SetPreferredLanguages(&preferred);
     113                printf("Locale successfully set to %s\n", name.String());
     114                delete language;
     115                return 0;
     116            }
     117
     118            delete language;
     119        } else
     120            fprintf(stderr, "Failed to get BLanguage for %s\n", id);
     121    }
     122
     123    // if we've gotten this far and the -l flag wasn't passed, the requested
     124    // locale wasn't found
     125    if (!list) {
     126        fprintf(stderr, "Locale not found\n");
     127        return 1;
     128    }
     129
     130    return 0;
     131}