//
// GNU gettext message generator for the CUPS PPD Compiler.
//
// This program is used to generate a dummy source file containing all of
// the standard media and sample driver strings.  The results are picked up
// by GNU gettext and placed in the CUPS message catalog.
//
// Copyright © 2020-2024 by OpenPrinting.
// Copyright 2008-2014 by Apple Inc.
//
// Licensed under Apache License v2.0.  See the file "LICENSE" for more information.
//
// Usage:
//
//   ./genstrings >sample.c
//

//
// Include necessary headers...
//

#include "ppdc-private.h"
#include <unistd.h>


//
// Local functions...
//

static void	add_ui_strings(ppdcDriver *d, ppdcCatalog *catalog);
static void	write_cstring(const char *s);


//
// 'main()' - Main entry for the PPD compiler.
//

int					// O - Exit status
main(void)
{
  ppdcSource	*src;			// PPD source file data
  ppdcCatalog	*catalog;		// Catalog to hold all of the UI strings


  // Make sure we are in the right place...
  if (access("../data", 0) || access("sample.drv", 0))
  {
    puts("You must run genstrings from the ppdc directory.");
    return (1);
  }

  // Load the sample drivers...
  ppdcSource::add_include("../data");

  src     = new ppdcSource("sample.drv");
  catalog = new ppdcCatalog(NULL);

  catalog->add_message("ISOLatin1");
  catalog->add_message("English");

  // Add the media size strings...
  ppdcMediaSize	*size;			// Current media size

  for (size = (ppdcMediaSize *)src->sizes->first();
       size;
       size = (ppdcMediaSize *)src->sizes->next())
    catalog->add_message(size->text->value);

  // Then collect all of the UI strings from the sample drivers...
  ppdcDriver	*d;			// Current driver

  for (d = (ppdcDriver *)src->drivers->first();
       d;
       d = (ppdcDriver *)src->drivers->next())
    add_ui_strings(d, catalog);

  // Finally, write all of the strings...
  ppdcMessage *message;

  for (message = (ppdcMessage *)catalog->messages->first();
       message;
       message = (ppdcMessage *)catalog->messages->next())
    write_cstring(message->id->value);

  src->release();
  catalog->release();

  // Return with no errors.
  return (0);
}


//
// 'add_ui_strings()' - Add all UI strings from the driver.
//

static void
add_ui_strings(ppdcDriver  *d,		// I - Driver data
               ppdcCatalog *catalog)	// I - Message catalog
{
  // Add the make/model/language strings...
  catalog->add_message(d->manufacturer->value);
  catalog->add_message(d->model_name->value);

  // Add the group/option/choice strings...
  ppdcGroup	*g;			// Current group
  ppdcOption	*o;			// Current option
  ppdcChoice	*c;			// Current choice

  for (g = (ppdcGroup *)d->groups->first();
       g;
       g = (ppdcGroup *)d->groups->next())
  {
    if (!g->options->count)
      continue;

    if (_cups_strcasecmp(g->name->value, "General"))
      catalog->add_message(g->text->value);

    for (o = (ppdcOption *)g->options->first();
         o;
	 o = (ppdcOption *)g->options->next())
    {
      if (!o->choices->count)
        continue;

      if (o->text->value && strcmp(o->name->value, o->text->value))
        catalog->add_message(o->text->value);
      else
        catalog->add_message(o->name->value);

      for (c = (ppdcChoice *)o->choices->first();
           c;
	   c = (ppdcChoice *)o->choices->next())
	if (c->text->value && strcmp(c->name->value, c->text->value))
          catalog->add_message(c->text->value);
        else
          catalog->add_message(c->name->value);
    }
  }

  // Add profile and preset strings...
  ppdcAttr *a;				// Current attribute
  for (a = (ppdcAttr *)d->attrs->first();
       a;
       a = (ppdcAttr *)d->attrs->next())
  {
    if (a->text->value && a->text->value[0] &&
        (a->localizable ||
	 !strncmp(a->name->value, "Custom", 6) ||
         !strncmp(a->name->value, "ParamCustom", 11) ||
         !strcmp(a->name->value, "APCustomColorMatchingName") ||
         !strcmp(a->name->value, "APPrinterPreset") ||
         !strcmp(a->name->value, "cupsICCProfile") ||
         !strcmp(a->name->value, "cupsIPPReason") ||
         !strcmp(a->name->value, "cupsMarkerName")))
    {
      catalog->add_message(a->text->value);

      if ((a->localizable && a->value->value[0]) ||
          !strcmp(a->name->value, "cupsIPPReason"))
        catalog->add_message(a->value->value);
    }
    else if (!strncmp(a->name->value, "Custom", 6) ||
             !strncmp(a->name->value, "ParamCustom", 11))
      catalog->add_message(a->name->value);
  }
}


//
// 'write_cstring()' - Write a translation string as a valid C string to stdout.
//

static void
write_cstring(const char *s)		/* I - String to write */
{
  fputs("_(\"", stdout);
  if (s)
  {
    while (*s)
    {
      if (*s == '\\')
        fputs("\\\\", stdout);
      else if (*s == '\"')
        fputs("\\\"", stdout);
      else if (*s == '\t')
        fputs("\\t", stdout);
      else if (*s == '\n')
        fputs("\\n", stdout);
      else
        putchar(*s);

      s ++;
    }
  }
  puts("\");");
}
