Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  gtkaccelgroup.c

  Sprache: C
 

/* GTK - The GIMP Toolkit
 * Copyright (C) 1998, 2001 Tim Janik
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 */


/*
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
 */


#include "config.h"
#include <string.h>
#include <stdlib.h>

#include "gtkaccelgroup.h"
#include "gtkaccelgroupprivate.h"
#include <glib/gi18n-lib.h>
#include "gtkmarshalers.h"
#include "gtkprivate.h"

/* --- functions --- */
/**
 * gtk_accelerator_valid:
 * @keyval: a GDK keyval
 * @modifiers: modifier mask
 *
 * Determines whether a given keyval and modifier mask constitute
 * a valid keyboard accelerator.
 *
 * For example, the `GDK_KEY_a` keyval plus `GDK_CONTROL_MASK` mask is valid,
 * and matches the Ctrl+a accelerator. But, you can't, for instance, use
 * the `GDK_KEY_Control_L` keyval as an accelerator.
 *
 * Returns: true if the accelerator is valid
 */

gboolean
gtk_accelerator_valid (guint           keyval,
                       GdkModifierType modifiers)
{
  static const guint invalid_accelerator_vals[] = {
    GDK_KEY_Shift_L, GDK_KEY_Shift_R, GDK_KEY_Shift_Lock,
    GDK_KEY_Caps_Lock, GDK_KEY_ISO_Lock, GDK_KEY_Control_L,
    GDK_KEY_Control_R, GDK_KEY_Meta_L, GDK_KEY_Meta_R,
    GDK_KEY_Alt_L, GDK_KEY_Alt_R, GDK_KEY_Super_L, GDK_KEY_Super_R,
    GDK_KEY_Hyper_L, GDK_KEY_Hyper_R, GDK_KEY_ISO_Level3_Shift,
    GDK_KEY_ISO_Next_Group, GDK_KEY_ISO_Prev_Group,
    GDK_KEY_ISO_First_Group, GDK_KEY_ISO_Last_Group,
    GDK_KEY_Mode_switch, GDK_KEY_Num_Lock, GDK_KEY_Multi_key,
    GDK_KEY_Scroll_Lock, GDK_KEY_Sys_Req,
    GDK_KEY_Tab, GDK_KEY_ISO_Left_Tab, GDK_KEY_KP_Tab,
    GDK_KEY_First_Virtual_Screen, GDK_KEY_Prev_Virtual_Screen,
    GDK_KEY_Next_Virtual_Screen, GDK_KEY_Last_Virtual_Screen,
    GDK_KEY_Terminate_Server, GDK_KEY_AudibleBell_Enable,
    0
  };
  static const guint invalid_unmodified_vals[] = {
    GDK_KEY_Up, GDK_KEY_Down, GDK_KEY_Left, GDK_KEY_Right,
    GDK_KEY_KP_Up, GDK_KEY_KP_Down, GDK_KEY_KP_Left, GDK_KEY_KP_Right,
    0
  };
  const guint *ac_val;

  modifiers &= GDK_MODIFIER_MASK;

  if (keyval <= 0xFF)
    return keyval >= 0x20;

  ac_val = invalid_accelerator_vals;
  while (*ac_val)
    {
      if (keyval == *ac_val++)
        return FALSE;
    }

  if (!modifiers)
    {
      ac_val = invalid_unmodified_vals;
      while (*ac_val)
        {
          if (keyval == *ac_val++)
            return FALSE;
        }
    }

  return TRUE;
}

static inline gboolean
is_alt (const char *string)
{
  return ((string[0] == '<') &&
          (string[1] == 'a' || string[1] == 'A') &&
          (string[2] == 'l' || string[2] == 'L') &&
          (string[3] == 't' || string[3] == 'T') &&
          (string[4] == '>'));
}

static inline gboolean
is_ctl (const char *string)
{
  return ((string[0] == '<') &&
          (string[1] == 'c' || string[1] == 'C') &&
          (string[2] == 't' || string[2] == 'T') &&
          (string[3] == 'l' || string[3] == 'L') &&
          (string[4] == '>'));
}

static inline gboolean
is_ctrl (const char *string)
{
  return ((string[0] == '<') &&
          (string[1] == 'c' || string[1] == 'C') &&
          (string[2] == 't' || string[2] == 'T') &&
          (string[3] == 'r' || string[3] == 'R') &&
          (string[4] == 'l' || string[4] == 'L') &&
          (string[5] == '>'));
}

static inline gboolean
is_shft (const char *string)
{
  return ((string[0] == '<') &&
          (string[1] == 's' || string[1] == 'S') &&
          (string[2] == 'h' || string[2] == 'H') &&
          (string[3] == 'f' || string[3] == 'F') &&
          (string[4] == 't' || string[4] == 'T') &&
          (string[5] == '>'));
}

static inline gboolean
is_shift (const char *string)
{
  return ((string[0] == '<') &&
          (string[1] == 's' || string[1] == 'S') &&
          (string[2] == 'h' || string[2] == 'H') &&
          (string[3] == 'i' || string[3] == 'I') &&
          (string[4] == 'f' || string[4] == 'F') &&
          (string[5] == 't' || string[5] == 'T') &&
          (string[6] == '>'));
}

static inline gboolean
is_control (const char *string)
{
  return ((string[0] == '<') &&
          (string[1] == 'c' || string[1] == 'C') &&
          (string[2] == 'o' || string[2] == 'O') &&
          (string[3] == 'n' || string[3] == 'N') &&
          (string[4] == 't' || string[4] == 'T') &&
          (string[5] == 'r' || string[5] == 'R') &&
          (string[6] == 'o' || string[6] == 'O') &&
          (string[7] == 'l' || string[7] == 'L') &&
          (string[8] == '>'));
}

static inline gboolean
is_meta (const char *string)
{
  return ((string[0] == '<') &&
          (string[1] == 'm' || string[1] == 'M') &&
          (string[2] == 'e' || string[2] == 'E') &&
          (string[3] == 't' || string[3] == 'T') &&
          (string[4] == 'a' || string[4] == 'A') &&
          (string[5] == '>'));
}

static inline gboolean
is_super (const char *string)
{
  return ((string[0] == '<') &&
          (string[1] == 's' || string[1] == 'S') &&
          (string[2] == 'u' || string[2] == 'U') &&
          (string[3] == 'p' || string[3] == 'P') &&
          (string[4] == 'e' || string[4] == 'E') &&
          (string[5] == 'r' || string[5] == 'R') &&
          (string[6] == '>'));
}

static inline gboolean
is_hyper (const char *string)
{
  return ((string[0] == '<') &&
          (string[1] == 'h' || string[1] == 'H') &&
          (string[2] == 'y' || string[2] == 'Y') &&
          (string[3] == 'p' || string[3] == 'P') &&
          (string[4] == 'e' || string[4] == 'E') &&
          (string[5] == 'r' || string[5] == 'R') &&
          (string[6] == '>'));
}

static inline gboolean
is_primary (const char *string)
{
  return ((string[0] == '<') &&
          (string[1] == 'p' || string[1] == 'P') &&
          (string[2] == 'r' || string[2] == 'R') &&
          (string[3] == 'i' || string[3] == 'I') &&
          (string[4] == 'm' || string[4] == 'M') &&
          (string[5] == 'a' || string[5] == 'A') &&
          (string[6] == 'r' || string[6] == 'R') &&
          (string[7] == 'y' || string[7] == 'Y') &&
          (string[8] == '>'));
}

static inline gboolean
is_keycode (const char *string)
{
  return (string[0] == '0' &&
          string[1] == 'x' &&
          g_ascii_isxdigit (string[2]) &&
          g_ascii_isxdigit (string[3]));
}

/**
 * gtk_accelerator_parse_with_keycode:
 * @accelerator: string representing an accelerator
 * @display: (nullable): the `GdkDisplay` to look up @accelerator_codes in
 * @accelerator_key: (out) (optional): return location for accelerator keyval
 * @accelerator_codes: (out) (array zero-terminated=1) (transfer full) (optional):
 *   return location for accelerator keycodes
 * @accelerator_mods: (out) (optional): return location for accelerator
 *   modifier mask
 *
 * Parses a string representing an accelerator.
 *
 * This is similar to [func@Gtk.accelerator_parse] but handles keycodes as
 * well. This is only useful for system-level components, applications should
 * use [func@Gtk.accelerator_parse] instead.
 *
 * If @accelerator_codes is given and the result stored in it is non-%NULL,
 * the result must be freed with g_free().
 *
 * If a keycode is present in the accelerator and no @accelerator_codes
 * is given, the parse will fail.
 *
 * If the parse fails, @accelerator_key, @accelerator_mods and
 * @accelerator_codes will be set to 0 (zero).
 *
 * Returns: true if parsing succeeded
 */

gboolean
gtk_accelerator_parse_with_keycode (const char      *accelerator,
                                    GdkDisplay      *display,
                                    guint           *accelerator_key,
                                    guint          **accelerator_codes,
                                    GdkModifierType *accelerator_mods)
{
  guint keyval;
  GdkModifierType mods;
  int len;
  gboolean error;

  if (accelerator_key)
    *accelerator_key = 0;
  if (accelerator_mods)
    *accelerator_mods = 0;
  if (accelerator_codes)
    *accelerator_codes = NULL;

  g_return_val_if_fail (accelerator != NULL, FALSE);

  if (!display)
    display = gdk_display_get_default ();

  error = FALSE;
  keyval = 0;
  mods = 0;
  len = strlen (accelerator);
  while (len)
    {
      if (*accelerator == '<')
        {
          if (len >= 9 && is_primary (accelerator))
            {
              accelerator += 9;
              len -= 9;
              mods |= GDK_CONTROL_MASK;
            }
          else if (len >= 9 && is_control (accelerator))
            {
              accelerator += 9;
              len -= 9;
              mods |= GDK_CONTROL_MASK;
            }
          else if (len >= 7 && is_shift (accelerator))
            {
              accelerator += 7;
              len -= 7;
              mods |= GDK_SHIFT_MASK;
            }
          else if (len >= 6 && is_shft (accelerator))
            {
              accelerator += 6;
              len -= 6;
              mods |= GDK_SHIFT_MASK;
            }
          else if (len >= 6 && is_ctrl (accelerator))
            {
              accelerator += 6;
              len -= 6;
              mods |= GDK_CONTROL_MASK;
            }
          else if (len >= 5 && is_ctl (accelerator))
            {
              accelerator += 5;
              len -= 5;
              mods |= GDK_CONTROL_MASK;
            }
          else if (len >= 5 && is_alt (accelerator))
            {
              accelerator += 5;
              len -= 5;
              mods |= GDK_ALT_MASK;
            }
          else if (len >= 6 && is_meta (accelerator))
            {
              accelerator += 6;
              len -= 6;
              mods |= GDK_META_MASK;
            }
          else if (len >= 7 && is_hyper (accelerator))
            {
              accelerator += 7;
              len -= 7;
              mods |= GDK_HYPER_MASK;
            }
          else if (len >= 7 && is_super (accelerator))
            {
              accelerator += 7;
              len -= 7;
              mods |= GDK_SUPER_MASK;
            }
          else
            {
              char last_ch;

              last_ch = *accelerator;
              while (last_ch && last_ch != '>')
                {
                  accelerator += 1;
                  len -= 1;
                  last_ch = *accelerator;
                }

              if (!last_ch)
                {
                  /* The opened '<' has never been closed with '>' */
                  error = TRUE;
                  goto out;
                }
            }
        }
      else
        {
          if (len >= 4 && is_keycode (accelerator))
            {
               char keystring[5];
               char *endptr;
               int tmp_keycode;

               memcpy (keystring, accelerator, 4);
               keystring [4] = '\000';

               tmp_keycode = strtol (keystring, &endptr, 16);

               if (endptr == NULL || *endptr != '\000')
                 {
                   error = TRUE;
                   goto out;
                 }
               else if (accelerator_codes != NULL)
                 {
                   /* 0x00 is an invalid keycode too. */
                   if (tmp_keycode == 0)
                     {
                       error = TRUE;
                       goto out;
                     }
                   else
                     {
                       *accelerator_codes = g_new0 (guint, 2);
                       (*accelerator_codes)[0] = tmp_keycode;
                     }
                 }
               else
                 {
                   /* There was a keycode in the string, but
                    * we cannot store it, so we have an error */

                   error = TRUE;
                   goto out;
                 }
            }
          else
            {
              keyval = gdk_keyval_from_name (accelerator);
              if (keyval == GDK_KEY_VoidSymbol)
                {
                  error = TRUE;
                  goto out;
                }
            }

          if (keyval && accelerator_codes != NULL)
            {
              GdkKeymapKey *keys;
              int n_keys, i, j;

              if (!gdk_display_map_keyval (display, keyval, &keys, &n_keys))
                {
                  /* Not in keymap */
                  error = TRUE;
                  goto out;
                }
              else
                {
                  *accelerator_codes = g_new0 (guint, n_keys + 1);

                  /* Prefer level-0 group-0 keys to modified keys */
                  for (i = 0, j = 0; i < n_keys; ++i)
                    {
                      if (keys[i].level == 0 && keys[i].group == 0)
                        (*accelerator_codes)[j++] = keys[i].keycode;
                    }

                  /* No level-0 group-0 keys? Find in the whole group-0 */
                  if (j == 0)
                    {
                      for (i = 0, j = 0; i < n_keys; ++i)
                        {
                          if (keys[i].group == 0)
                            (*accelerator_codes)[j++] = keys[i].keycode;
                        }
                    }

                  /* Still nothing? Try in other groups */
                  if (j == 0)
                    {
                      for (i = 0, j = 0; i < n_keys; ++i)
                        (*accelerator_codes)[j++] = keys[i].keycode;
                    }

                  if (j == 0)
                    {
                      g_clear_pointer (accelerator_codes, g_free);
                      /* Not in keymap */
                      error = TRUE;
                      goto out;
                    }
                  g_free (keys);
                }
            }

          accelerator += len;
          len -= len;
        }
    }

out:
  if (error)
    keyval = mods = 0;

  if (accelerator_key)
    *accelerator_key = gdk_keyval_to_lower (keyval);
  if (accelerator_mods)
    *accelerator_mods = mods;

  return !error;
}

/**
 * gtk_accelerator_parse:
 * @accelerator: string representing an accelerator
 * @accelerator_key: (out) (optional): return location for accelerator keyval
 * @accelerator_mods: (out) (optional): return location for accelerator
 *   modifier mask
 *
 * Parses a string representing an accelerator.
 *
 * The format looks like `<Control>a` or `<Shift><Alt>F1`.
 *
 * The parser is fairly liberal and allows lower or upper case, and also
 * abbreviations such as `<Ctl>` and `<Ctrl>`.
 *
 * Key names are parsed using [func@Gdk.keyval_from_name]. For character keys
 * the name is not the symbol, but the lowercase name, e.g. one would use
 * `<Ctrl>minus` instead of `<Ctrl>-`.
 *
 * Modifiers are enclosed in angular brackets `<>`, and match the
 * [flags@Gdk.ModifierType] mask:
 *
 * - `<Shift>` for `GDK_SHIFT_MASK`
 * - `<Ctrl>` for `GDK_CONTROL_MASK`
 * - `<Alt>` for `GDK_ALT_MASK`
 * - `<Meta>` for `GDK_META_MASK`
 * - `<Super>` for `GDK_SUPER_MASK`
 * - `<Hyper>` for `GDK_HYPER_MASK`
 *
 * If the parse operation fails, @accelerator_key and @accelerator_mods will
 * be set to 0 (zero).
 *
 * Returns: whether parsing succeeded
 */

gboolean
gtk_accelerator_parse (const char      *accelerator,
                       guint           *accelerator_key,
                       GdkModifierType *accelerator_mods)
{
  return gtk_accelerator_parse_with_keycode (accelerator, NULL, accelerator_key, NULL, accelerator_mods);
}

/**
 * gtk_accelerator_name_with_keycode:
 * @display: (nullable): a `GdkDisplay`
 * @accelerator_key: accelerator keyval
 * @keycode: accelerator keycode
 * @accelerator_mods: accelerator modifier mask
 *
 * Converts an accelerator keyval and modifier mask
 * into a string that can be parsed by [func@Gtk.accelerator_parse_with_keycode].
 *
 * This is similar to [func@Gtk.accelerator_name] but handling keycodes.
 * This is only useful for system-level components, applications
 * should use [func@Gtk.accelerator_name] instead.
 *
 * Returns: a newly allocated accelerator name.
 */

char *
gtk_accelerator_name_with_keycode (GdkDisplay      *display,
                                   guint            accelerator_key,
                                   guint            keycode,
                                   GdkModifierType  accelerator_mods)
{
  char *gtk_name;

  gtk_name = gtk_accelerator_name (accelerator_key, accelerator_mods);

  if (!accelerator_key)
    {
      char *name;
      name = g_strdup_printf ("%s0x%02x", gtk_name, keycode);
      g_free (gtk_name);
      return name;
    }

  return gtk_name;
}

/**
 * gtk_accelerator_name:
 * @accelerator_key: accelerator keyval
 * @accelerator_mods: accelerator modifier mask
 *
 * Converts an accelerator keyval and modifier mask into a string
 * that can be parsed by [func@Gtk.accelerator_parse].
 *
 * For example, if you pass in `GDK_KEY_q` and `GDK_CONTROL_MASK`,
 * this function returns `<Control>q`.
 *
 * If you need to display accelerators in the user interface,
 * see [func@Gtk.accelerator_get_label].
 *
 * Returns: (transfer full): a newly-allocated accelerator name
 */

char *
gtk_accelerator_name (guint           accelerator_key,
                      GdkModifierType accelerator_mods)
{
  static const struct {
    guint mask;
    const char *text;
  } mask_text[] = {
    { GDK_SHIFT_MASK,   "<Shift>"   },
    { GDK_CONTROL_MASK, "<Control>" },
    { GDK_ALT_MASK,     "<Alt>"     },
    { GDK_META_MASK,    "<Meta>"    },
    { GDK_SUPER_MASK,   "<Super>"   },
    { GDK_HYPER_MASK,   "<Hyper>"   }
  };
  const char *keyval_name;
  GString *result;
  gsize i;

  accelerator_mods &= GDK_MODIFIER_MASK;

  keyval_name = gdk_keyval_name (gdk_keyval_to_lower (accelerator_key));
  if (keyval_name == NULL)
    keyval_name = "";

  if (accelerator_mods == 0)
    return g_strdup (keyval_name);

  result = g_string_new (NULL);

  for (i = 0; i < G_N_ELEMENTS (mask_text); i++)
    {
      if (accelerator_mods & mask_text[i].mask)
        g_string_append (result, mask_text[i].text);
    }

  if (keyval_name)
    g_string_append (result, keyval_name);

  return g_string_free_and_steal (result);
}

/**
 * gtk_accelerator_get_label_with_keycode:
 * @display: (nullable): a `GdkDisplay`
 * @accelerator_key: accelerator keyval
 * @keycode: accelerator keycode
 * @accelerator_mods: accelerator modifier mask
 *
 * Converts an accelerator keyval and modifier mask
 * into a string that can be displayed to the user.
 *
 * The string may be translated.
 *
 * This function is similar to [func@Gtk.accelerator_get_label],
 * but handling keycodes. This is only useful for system-level
 * components, applications should use [func@Gtk.accelerator_get_label]
 * instead.
 *
 * Returns: (transfer full): a newly-allocated string representing the accelerator
 */

char *
gtk_accelerator_get_label_with_keycode (GdkDisplay      *display,
                                        guint            accelerator_key,
                                        guint            keycode,
                                        GdkModifierType  accelerator_mods)
{
  char *gtk_label;

  gtk_label = gtk_accelerator_get_label (accelerator_key, accelerator_mods);

  if (!accelerator_key)
    {
      char *label;
      label = g_strdup_printf ("%s0x%02x", gtk_label, keycode);
      g_free (gtk_label);
      return label;
    }

  return gtk_label;
}

/* Underscores in key names are better displayed as spaces
 * E.g., Page_Up should be Page Up.
 *
 * Some keynames also have prefixes that are not suitable
 * for display, e.g XF86AudioMute, so strip those out, too.
 *
 * This function is only called on untranslated keynames,
 * so no need to be UTF-8 safe.
 */

static void
append_without_underscores (GString    *s,
                            const char *str)
{
  const char *p;

  if (g_str_has_prefix (str, "XF86"))
    p = str + 4;
  else if (g_str_has_prefix (str, "ISO_"))
    p = str + 4;
  else
    p = str;

  for ( ; *p; p++)
    {
      if (*p == '_')
        g_string_append_c (s, ' ');
      else
        g_string_append_c (s, *p);
    }
}

/* On Mac, if the key has symbolic representation (e.g. arrow keys),
 * append it to gstring and return TRUE; otherwise return FALSE.
 * See http://docs.info.apple.com/article.html?path=Mac/10.5/en/cdb_symbs.html
 * for the list of special keys. */

static gboolean
append_keyval_symbol (guint    accelerator_key,
                      GString *gstring)
{
#ifdef GDK_WINDOWING_MACOS
  switch (accelerator_key)
  {
  case GDK_KEY_Return:
    /* U+21A9 LEFTWARDS ARROW WITH HOOK */
    g_string_append (gstring, "\xe2\x86\xa9");
    return TRUE;

  case GDK_KEY_ISO_Enter:
    /* U+2324 UP ARROWHEAD BETWEEN TWO HORIZONTAL BARS */
    g_string_append (gstring, "\xe2\x8c\xa4");
    return TRUE;

  case GDK_KEY_Left:
    /* U+2190 LEFTWARDS ARROW */
    g_string_append (gstring, "\xe2\x86\x90");
    return TRUE;

  case GDK_KEY_Up:
    /* U+2191 UPWARDS ARROW */
    g_string_append (gstring, "\xe2\x86\x91");
    return TRUE;

  case GDK_KEY_Right:
    /* U+2192 RIGHTWARDS ARROW */
    g_string_append (gstring, "\xe2\x86\x92");
    return TRUE;

  case GDK_KEY_Down:
    /* U+2193 DOWNWARDS ARROW */
    g_string_append (gstring, "\xe2\x86\x93");
    return TRUE;

  case GDK_KEY_Page_Up:
    /* U+21DE UPWARDS ARROW WITH DOUBLE STROKE */
    g_string_append (gstring, "\xe2\x87\x9e");
    return TRUE;

  case GDK_KEY_Page_Down:
    /* U+21DF DOWNWARDS ARROW WITH DOUBLE STROKE */
    g_string_append (gstring, "\xe2\x87\x9f");
    return TRUE;

  case GDK_KEY_Home:
    /* U+2196 NORTH WEST ARROW */
    g_string_append (gstring, "\xe2\x86\x96");
    return TRUE;

  case GDK_KEY_End:
    /* U+2198 SOUTH EAST ARROW */
    g_string_append (gstring, "\xe2\x86\x98");
    return TRUE;

  case GDK_KEY_Escape:
    /* U+238B BROKEN CIRCLE WITH NORTHWEST ARROW */
    g_string_append (gstring, "\xe2\x8e\x8b");
    return TRUE;

  case GDK_KEY_BackSpace:
    /* U+232B ERASE TO THE LEFT */
    g_string_append (gstring, "\xe2\x8c\xab");
    return TRUE;

  case GDK_KEY_Delete:
    /* U+2326 ERASE TO THE RIGHT */
    g_string_append (gstring, "\xe2\x8c\xa6");
    return TRUE;

  default:
    return FALSE;
  }
#else /* !GDK_WINDOWING_MACOS */
  return FALSE;
#endif
}

static void
append_separator (GString *string)
{
#ifndef GDK_WINDOWING_MACOS
  g_string_append (string, "+");
#else
  /* no separator on quartz */
#endif
}

/**
 * gtk_accelerator_get_label:
 * @accelerator_key: accelerator keyval
 * @accelerator_mods: accelerator modifier mask
 *
 * Converts an accelerator keyval and modifier mask into a string
 * which can be used to represent the accelerator to the user.
 *
 * Returns: (transfer full): a newly-allocated string representing the accelerator
 */

char *
gtk_accelerator_get_label (guint           accelerator_key,
                           GdkModifierType accelerator_mods)
{
  GString *gstring;

  gstring = g_string_new (NULL);

  gtk_accelerator_print_label (gstring, accelerator_key, accelerator_mods);

  return g_string_free (gstring, FALSE);
}

void
gtk_accelerator_print_label (GString        *gstring,
                             guint           accelerator_key,
                             GdkModifierType accelerator_mods)
{
  gboolean seen_mod = FALSE;
  gunichar ch;

  if (accelerator_mods & GDK_SHIFT_MASK)
    {
#ifndef GDK_WINDOWING_MACOS
      /* This is the text that should appear next to menu accelerators
       * that use the shift key. If the text on this key isn't typically
       * translated on keyboards used for your language, don't translate
       * this.
       */

      g_string_append (gstring, C_("keyboard label""Shift"));
#else
      /* U+21E7 UPWARDS WHITE ARROW */
      g_string_append (gstring, "⇧");
#endif
      seen_mod = TRUE;
    }

  if (accelerator_mods & GDK_CONTROL_MASK)
    {
      if (seen_mod)
        append_separator (gstring);

#ifndef GDK_WINDOWING_MACOS
      /* This is the text that should appear next to menu accelerators
       * that use the control key. If the text on this key isn't typically
       * translated on keyboards used for your language, don't translate
       * this.
       */

      g_string_append (gstring, C_("keyboard label""Ctrl"));
#else
      /* U+2303 UP ARROWHEAD */
      g_string_append (gstring, "⌃");
#endif
      seen_mod = TRUE;
    }

  if (accelerator_mods & GDK_ALT_MASK)
    {
      if (seen_mod)
        append_separator (gstring);

#ifndef GDK_WINDOWING_MACOS
      /* This is the text that should appear next to menu accelerators
       * that use the alt key. If the text on this key isn't typically
       * translated on keyboards used for your language, don't translate
       * this.
       */

      g_string_append (gstring, C_("keyboard label""Alt"));
#else
      /* U+2325 OPTION KEY */
      g_string_append (gstring, "⌥");
#endif
      seen_mod = TRUE;
    }

  if (accelerator_mods & GDK_SUPER_MASK)
    {
      if (seen_mod)
        append_separator (gstring);

      /* This is the text that should appear next to menu accelerators
       * that use the super key. If the text on this key isn't typically
       * translated on keyboards used for your language, don't translate
       * this.
       */

      g_string_append (gstring, C_("keyboard label""Super"));
      seen_mod = TRUE;
    }

  if (accelerator_mods & GDK_HYPER_MASK)
    {
      if (seen_mod)
        append_separator (gstring);

      /* This is the text that should appear next to menu accelerators
       * that use the hyper key. If the text on this key isn't typically
       * translated on keyboards used for your language, don't translate
       * this.
       */

      g_string_append (gstring, C_("keyboard label""Hyper"));
      seen_mod = TRUE;
    }

  if (accelerator_mods & GDK_META_MASK)
    {
      if (seen_mod)
        append_separator (gstring);

#ifndef GDK_WINDOWING_MACOS
      /* This is the text that should appear next to menu accelerators
       * that use the meta key. If the text on this key isn't typically
       * translated on keyboards used for your language, don't translate
       * this.
       */

      g_string_append (gstring, C_("keyboard label""Meta"));
#else
      g_string_append (gstring, "⌘");
#endif
      seen_mod = TRUE;
    }

  ch = gdk_keyval_to_unicode (accelerator_key);
  if (ch && (ch == ' ' || g_unichar_isgraph (ch)))
    {
      if (seen_mod)
        append_separator (gstring);

      if (accelerator_key >= GDK_KEY_KP_Space &&
          accelerator_key <= GDK_KEY_KP_9)
        {
          /* Translators: "KP" means "numeric key pad". This string will
           * be used in accelerators such as "Ctrl+Shift+KP 1" in menus,
           * and therefore the translation needs to be very short.
           */

          g_string_append (gstring, C_("keyboard label""KP"));
          g_string_append (gstring, " ");
        }

      switch (ch)
        {
        case ' ':
          g_string_append (gstring, C_("keyboard label""Space"));
          break;
        case '\\':
          g_string_append (gstring, C_("keyboard label""Backslash"));
          break;
        default:
          g_string_append_unichar (gstring, g_unichar_toupper (ch));
          break;
        }
    }
  else if (!append_keyval_symbol (accelerator_key, gstring))
    {
      const char *tmp;

      tmp = gdk_keyval_name (gdk_keyval_to_lower (accelerator_key));
      if (tmp != NULL)
        {
          if (seen_mod)
            append_separator (gstring);

          if (tmp[0] != 0 && tmp[1] == 0)
            g_string_append_c (gstring, g_ascii_toupper (tmp[0]));
          else
            {
              const char *str;
              str = g_dpgettext2 (GETTEXT_PACKAGE, "keyboard label", tmp);
              if (str == tmp)
                append_without_underscores (gstring, tmp);
              else
                g_string_append (gstring, str);
            }
        }
    }
}

/* See https://www.w3.org/TR/uievents-key/#named-key-attribute-values for the
 * list of WAI-ARIA named key attribute values. */

static const gchar *
keyval_get_accessible_name (guint accelerator_key)
{
  switch (accelerator_key)
  {
    case GDK_KEY_Alt_L:
    case GDK_KEY_Alt_R:
      return "Alt";

    case GDK_KEY_Mode_switch:
    case GDK_KEY_ISO_Level3_Shift:
    case GDK_KEY_ISO_Level3_Latch:
    case GDK_KEY_ISO_Level3_Lock:
    case GDK_KEY_ISO_Level5_Shift:
    case GDK_KEY_ISO_Level5_Latch:
    case GDK_KEY_ISO_Level5_Lock:
      return "AltGraph";

    case GDK_KEY_Caps_Lock:
      return "CapsLock";

    case GDK_KEY_Control_L:
    case GDK_KEY_Control_R:
      return "Control";

    /* Firefox treats these as "Alt" */
    case GDK_KEY_Meta_L:
    case GDK_KEY_Meta_R:
      return "Meta";

    case GDK_KEY_Num_Lock:
      return "NumLock";

    case GDK_KEY_Scroll_Lock:
      return "ScrollLock";

    case GDK_KEY_Shift_L:
    case GDK_KEY_Shift_R:
    case GDK_KEY_Shift_Lock:
      return "Shift";

    /* Firefox treats these as "Meta" */
    case GDK_KEY_Super_L:
    case GDK_KEY_Super_R:
      return "Super";

    /* Firefox treats these as "Meta" */
    case GDK_KEY_Hyper_L:
    case GDK_KEY_Hyper_R:
      return "Hyper";

    case GDK_KEY_Return:
    case GDK_KEY_KP_Enter:
    case GDK_KEY_ISO_Enter:
    case GDK_KEY_3270_Enter:
      return "Enter";

    case GDK_KEY_Tab:
    case GDK_KEY_ISO_Left_Tab:
    case GDK_KEY_KP_Tab:
      return "Tab";

    case GDK_KEY_Down:
    case GDK_KEY_KP_Down:
      return "ArrowDown";

    case GDK_KEY_Left:
    case GDK_KEY_KP_Left:
      return "ArrowLeft";

    case GDK_KEY_Right:
    case GDK_KEY_KP_Right:
      return "ArrowRight";

    case GDK_KEY_Up:
    case GDK_KEY_KP_Up:
      return "ArrowUp";

    case GDK_KEY_End:
    case GDK_KEY_KP_End:
      return "End";

    case GDK_KEY_Home:
    case GDK_KEY_KP_Home:
      return "Home";

    case GDK_KEY_Page_Down:
    case GDK_KEY_KP_Page_Down:
      return "PageDown";

    case GDK_KEY_Page_Up:
    case GDK_KEY_KP_Page_Up:
      return "PageUp";

    case GDK_KEY_BackSpace:
      return "Backspace";

    case GDK_KEY_Clear:
      return "Clear";

    case GDK_KEY_Copy:
      return "Copy";

    case GDK_KEY_3270_CursorSelect:
      return "CrSel";

    case GDK_KEY_Cut:
      return "Cut";

    case GDK_KEY_Delete:
    case GDK_KEY_KP_Delete:
      return "Delete";

    case GDK_KEY_3270_EraseEOF:
      return "EraseEof";

    case GDK_KEY_3270_ExSelect:
      return "ExSel";

    case GDK_KEY_Insert:
    case GDK_KEY_KP_Insert:
      return "Insert";

    case GDK_KEY_Paste:
      return "Paste";

    case GDK_KEY_Redo:
      return "Redo";

    case GDK_KEY_Undo:
      return "Undo";

    case GDK_KEY_3270_Attn:
      return "Attn";

    case GDK_KEY_Cancel:
      return "Cancel";

    case GDK_KEY_Menu:
      return "ContextMenu";

    case GDK_KEY_Escape:
      return "Escape";

    case GDK_KEY_Execute:
      return "Execute";

    case GDK_KEY_Find:
      return "Find";

    case GDK_KEY_Help:
      return "Help";

    case GDK_KEY_Pause:
    case GDK_KEY_Break:
      return "Pause";

    case GDK_KEY_3270_Play:
      return "Play";

    case GDK_KEY_Select:
      return "Select";

    case GDK_KEY_ZoomIn:
      return "ZoomIn";

    case GDK_KEY_ZoomOut:
      return "ZoomOut";

    case GDK_KEY_MonBrightnessDown:
      return "BrightnessDown";

    case GDK_KEY_MonBrightnessUp:
      return "BrightnessUp";

    case GDK_KEY_Eject:
      return "Eject";

    case GDK_KEY_LogOff:
      return "LogOff";

    case GDK_KEY_PowerDown:
    case GDK_KEY_PowerOff:
      return "PowerOff";

    case GDK_KEY_3270_PrintScreen:
    case GDK_KEY_Print:
    case GDK_KEY_Sys_Req:
      return "PrintScreen";

    case GDK_KEY_Hibernate:
      return "Hibernate";

    case GDK_KEY_Standby:
    case GDK_KEY_Suspend:
    case GDK_KEY_Sleep:
      return "Standby";

    case GDK_KEY_WakeUp:
      return "WakeUp";

    case GDK_KEY_MultipleCandidate:
      return "AllCandidates";

    case GDK_KEY_Eisu_Shift:
    case GDK_KEY_Eisu_toggle:
      return "Alphanumeric";

    case GDK_KEY_Codeinput:
      return "CodeInput";

    case GDK_KEY_Multi_key:
      return "Compose";

    case GDK_KEY_Henkan:
      return "Convert";

    case GDK_KEY_dead_grave:
    case GDK_KEY_dead_acute:
    case GDK_KEY_dead_circumflex:
    case GDK_KEY_dead_tilde:
    case GDK_KEY_dead_macron:
    case GDK_KEY_dead_breve:
    case GDK_KEY_dead_abovedot:
    case GDK_KEY_dead_diaeresis:
    case GDK_KEY_dead_abovering:
    case GDK_KEY_dead_doubleacute:
    case GDK_KEY_dead_caron:
    case GDK_KEY_dead_cedilla:
    case GDK_KEY_dead_ogonek:
    case GDK_KEY_dead_iota:
    case GDK_KEY_dead_voiced_sound:
    case GDK_KEY_dead_semivoiced_sound:
    case GDK_KEY_dead_belowdot:
    case GDK_KEY_dead_hook:
    case GDK_KEY_dead_horn:
    case GDK_KEY_dead_stroke:
    case GDK_KEY_dead_abovecomma:
    case GDK_KEY_dead_abovereversedcomma:
    case GDK_KEY_dead_doublegrave:
    case GDK_KEY_dead_belowring:
    case GDK_KEY_dead_belowmacron:
    case GDK_KEY_dead_belowcircumflex:
    case GDK_KEY_dead_belowtilde:
    case GDK_KEY_dead_belowbreve:
    case GDK_KEY_dead_belowdiaeresis:
    case GDK_KEY_dead_invertedbreve:
    case GDK_KEY_dead_belowcomma:
    case GDK_KEY_dead_currency:
    case GDK_KEY_dead_a:
    case GDK_KEY_dead_A:
    case GDK_KEY_dead_e:
    case GDK_KEY_dead_E:
    case GDK_KEY_dead_i:
    case GDK_KEY_dead_I:
    case GDK_KEY_dead_o:
    case GDK_KEY_dead_O:
    case GDK_KEY_dead_u:
    case GDK_KEY_dead_U:
    case GDK_KEY_dead_small_schwa:
    case GDK_KEY_dead_capital_schwa:
    case GDK_KEY_dead_greek:
      return "Dead";

    case GDK_KEY_ISO_First_Group:
      return "GroupFirst";

    case GDK_KEY_ISO_Last_Group:
      return "GroupLast";

    case GDK_KEY_ISO_Next_Group:
      return "GroupNext";

    case GDK_KEY_ISO_Prev_Group:
      return "GroupPrevious";

    case GDK_KEY_Muhenkan:
      return "NonConvert";

    case GDK_KEY_PreviousCandidate:
      return "PreviousCandidate";

    case GDK_KEY_SingleCandidate:
      return "SingleCandidate";

    case GDK_KEY_Hankaku:
      return "Hankaku";

    case GDK_KEY_Hiragana:
      return "Hiragana";

    case GDK_KEY_Hiragana_Katakana:
      return "HiraganaKatakana";

    case GDK_KEY_Kana_Lock:
    case GDK_KEY_Kana_Shift:
      return "KanaMode";

    case GDK_KEY_Kanji:
      return "KanjiMode";

    case GDK_KEY_Katakana:
      return "Katakana";

    case GDK_KEY_Romaji:
      return "Romaji";

    case GDK_KEY_Zenkaku:
      return "Zenkaku";

    case GDK_KEY_Zenkaku_Hankaku:
      return "ZenkakuHankaku";

    case GDK_KEY_F1:
    case GDK_KEY_KP_F1:
      return "F1";

    case GDK_KEY_F2:
    case GDK_KEY_KP_F2:
      return "F2";

    case GDK_KEY_F3:
    case GDK_KEY_KP_F3:
      return "F3";

    case GDK_KEY_F4:
    case GDK_KEY_KP_F4:
      return "F4";

    case GDK_KEY_F5:
      return "F5";

    case GDK_KEY_F6:
      return "F6";

    case GDK_KEY_F7:
      return "F7";

    case GDK_KEY_F8:
      return "F8";

    case GDK_KEY_F9:
      return "F9";

    case GDK_KEY_F10:
      return "F10";

    case GDK_KEY_F11:
      return "F11";

    case GDK_KEY_F12:
      return "F12";

    case GDK_KEY_F13:
      return "F13";

    case GDK_KEY_F14:
      return "F14";

    case GDK_KEY_F15:
      return "F15";

    case GDK_KEY_F16:
      return "F16";

    case GDK_KEY_F17:
      return "F17";

    case GDK_KEY_F18:
      return "F18";

    case GDK_KEY_F19:
      return "F19";

    case GDK_KEY_F20:
      return "F20";

    case GDK_KEY_F21:
      return "F21";

    case GDK_KEY_F22:
      return "F22";

    case GDK_KEY_F23:
      return "F23";

    case GDK_KEY_F24:
      return "F24";

    case GDK_KEY_F25:
      return "F25";

    case GDK_KEY_F26:
      return "F26";

    case GDK_KEY_F27:
      return "F27";

    case GDK_KEY_F28:
      return "F28";

    case GDK_KEY_F29:
      return "F29";

    case GDK_KEY_F30:
      return "F30";

    case GDK_KEY_F31:
      return "F31";

    case GDK_KEY_F32:
      return "F32";

    case GDK_KEY_F33:
      return "F33";

    case GDK_KEY_F34:
      return "F34";

    case GDK_KEY_F35:
      return "F35";

    case GDK_KEY_Close:
      return "Close";

    case GDK_KEY_MailForward:
      return "MailForward";

    case GDK_KEY_Reply:
      return "MailReply";

    case GDK_KEY_Send:
      return "MailSend";

    case GDK_KEY_AudioForward:
      return "MediaFastForward";

    case GDK_KEY_AudioPause:
      return "MediaPause";

    case GDK_KEY_AudioPlay:
      return "MediaPlay";

    case GDK_KEY_AudioRecord:
      return "MediaRecord";

    case GDK_KEY_AudioRewind:
      return "MediaRewind";

    case GDK_KEY_AudioStop:
      return "MediaStop";

    case GDK_KEY_AudioNext:
      return "MediaTrackNext";

    case GDK_KEY_AudioPrev:
      return "MediaTrackPrevious";

    case GDK_KEY_New:
      return "New";

    case GDK_KEY_Open:
      return "Open";

    case GDK_KEY_Save:
      return "Save";

    case GDK_KEY_Spell:
      return "SpellCheck";

    case GDK_KEY_AudioLowerVolume:
      return "AudioVolumeDown";

    case GDK_KEY_AudioRaiseVolume:
      return "AudioVolumeUp";

    case GDK_KEY_AudioMute:
      return "AudioVolumeMute";

    case GDK_KEY_Calculator:
      return "LaunchCalculator";

    case GDK_KEY_Calendar:
      return "LaunchCalendar";

    case GDK_KEY_Mail:
      return "LaunchMail";

    case GDK_KEY_CD:
    case GDK_KEY_Video:
    case GDK_KEY_AudioMedia:
      return "LaunchMediaPlayer";

    case GDK_KEY_Music:
      return "LaunchMusicPlayer";

    case GDK_KEY_MyComputer:
    case GDK_KEY_Explorer:
      return "LaunchMyComputer";

    case GDK_KEY_ScreenSaver:
      return "LaunchScreenSaver";

    case GDK_KEY_Excel:
      return "LaunchSpreadsheet";

    case GDK_KEY_WWW:
      return "LaunchWebBrowser";

    case GDK_KEY_WebCam:
      return "LaunchWebCam";

    case GDK_KEY_Word:
      return "LaunchWordProcessor";

    case GDK_KEY_Launch0:
      return "LaunchApplication1";

    case GDK_KEY_Launch1:
      return "LaunchApplication2";

    case GDK_KEY_Launch2:
      return "LaunchApplication3";

    case GDK_KEY_Launch3:
      return "LaunchApplication4";

    case GDK_KEY_Launch4:
      return "LaunchApplication5";

    case GDK_KEY_Launch5:
      return "LaunchApplication6";

    case GDK_KEY_Launch6:
      return "LaunchApplication7";

    case GDK_KEY_Launch7:
      return "LaunchApplication8";

    case GDK_KEY_Launch8:
      return "LaunchApplication9";

    case GDK_KEY_Launch9:
      return "LaunchApplication10";

    case GDK_KEY_LaunchA:
      return "LaunchApplication11";

    case GDK_KEY_LaunchB:
      return "LaunchApplication12";

    case GDK_KEY_LaunchC:
      return "LaunchApplication13";

    case GDK_KEY_LaunchD:
      return "LaunchApplication14";

    case GDK_KEY_LaunchE:
      return "LaunchApplication15";

    case GDK_KEY_LaunchF:
      return "LaunchApplication16";

    case GDK_KEY_Back:
      return "BrowserBack";

    case GDK_KEY_Forward:
      return "BrowserForward";

    case GDK_KEY_HomePage:
      return "BrowserHome";

    case GDK_KEY_Refresh:
    case GDK_KEY_Reload:
      return "BrowserRefresh";

    case GDK_KEY_Search:
      return "BrowserSearch";

    case GDK_KEY_Stop:
      return "BrowserStop";

    case GDK_KEY_Red:
      return "ColorF0Red";

    case GDK_KEY_Green:
      return "ColorF1Green";

    case GDK_KEY_Yellow:
      return "ColorF2Yellow";

    case GDK_KEY_Blue:
      return "ColorF3Blue";

    case GDK_KEY_BrightnessAdjust:
      return "Dimmer";

    case GDK_KEY_AudioRandomPlay:
      return "RandomToggle";

    case GDK_KEY_Subtitle:
      return "Subtitle";

    case GDK_KEY_Next_VMode:
      return "VideoModeNext";

    default:
      return NULL;
  }
}

static gboolean
append_keyval_accessible_graph (guint    accelerator_key,
                                GString *gstring)
{
  gunichar ch;

  ch = gdk_keyval_to_unicode (accelerator_key);
  if (ch == ' ')
    {
      /* The [WAI-ARIA](https://www.w3.org/TR/wai-aria/#aria-keyshortcuts)
       * reference states that "Space" is used for the spacebar.
       */

      g_string_append (gstring, "Space");
      return TRUE;
    }
  else if (ch && g_unichar_isgraph (ch))
    {
      g_string_append_unichar (gstring, g_unichar_toupper (ch));
      return TRUE;
    }
  else
    {
      return FALSE;
    }
}

/* See https://www.w3.org/TR/uievents-key/#named-key-attribute-values for the
 * list of WAI-ARIA named key attribute values. */

static gboolean
append_keyval_accessible_name (guint    accelerator_key,
                               GString *gstring)
{
  const gchar *name;

  name = keyval_get_accessible_name (accelerator_key);
  if (name != NULL)
    {
      g_string_append (gstring, name);
      return TRUE;
    }

    return FALSE;
}
/**
 * gtk_accelerator_get_accessible_label:
 * @accelerator_key: accelerator keyval
 * @accelerator_mods: accelerator modifier mask
 *
 * Generates an accessible description of an accelerator.
 *
 * This function is similar to [func@Gtk.accelerator_get_label] but it is meant
 * for accessibility layers labels rather than user-facing labels. The output
 * of this function is fit for [enum@Gtk.AccessibleProperty.KEY_SHORTCUTS].
 *
 * For more information, see the [WAI-ARIA](https://www.w3.org/TR/wai-aria/#aria-keyshortcuts)
 * reference.
 *
 * Returns: (transfer full): a newly-allocated string representing the accelerator
 *
 * Since: 4.22
 */

char *
gtk_accelerator_get_accessible_label (guint           accelerator_key,
                                      GdkModifierType accelerator_mods)
{
  GString *gstring;
  gboolean seen_mod = FALSE;

  gstring = g_string_new (NULL);

  if (accelerator_mods & GDK_SHIFT_MASK)
    {
      g_string_append (gstring, "Shift");
      seen_mod = TRUE;
    }

  if (accelerator_mods & GDK_CONTROL_MASK)
    {
      if (seen_mod)
        g_string_append (gstring, "+");

      g_string_append (gstring, "Control");
      seen_mod = TRUE;
    }

  if (accelerator_mods & GDK_ALT_MASK)
    {
      if (seen_mod)
        g_string_append (gstring, "+");

      g_string_append (gstring, "Alt");
      seen_mod = TRUE;
    }

  if (accelerator_mods & GDK_SUPER_MASK)
    {
      if (seen_mod)
        g_string_append (gstring, "+");

      /* According to the [WAI-ARIA](https://www.w3.org/TR/uievents-key/#:~:text="Super")
       * reference, "Super" is considered a legacy key and its support isn't
       * required. */

      g_string_append (gstring, "Super");
      seen_mod = TRUE;
    }

  if (accelerator_mods & GDK_HYPER_MASK)
    {
      if (seen_mod)
        g_string_append (gstring, "+");

      /* According to the [WAI-ARIA](https://www.w3.org/TR/uievents-key/#:~:text="Hyper")
       * reference, "Hyper" is considered a legacy key and its support isn't
       * required. */

      g_string_append (gstring, "Hyper");
      seen_mod = TRUE;
    }

  if (accelerator_mods & GDK_META_MASK)
    {
      if (seen_mod)
        g_string_append (gstring, "+");

      g_string_append (gstring, "Meta");
      seen_mod = TRUE;
    }

  if (seen_mod)
    g_string_append (gstring, "+");

  if (!append_keyval_accessible_name (accelerator_key, gstring) &&
      !append_keyval_accessible_graph (accelerator_key, gstring))
    {
      g_string_append (gstring, "Unidentified");
    }

  return g_string_free (gstring, FALSE);
}

/**
 * gtk_accelerator_get_default_mod_mask:
 *
 * Gets the modifier mask.
 *
 * The modifier mask determines which modifiers are considered significant
 * for keyboard accelerators. This includes all keyboard modifiers except
 * for `GDK_LOCK_MASK`.
 *
 * Returns: the modifier mask for accelerators
 */

GdkModifierType
gtk_accelerator_get_default_mod_mask (void)
{
  return GDK_CONTROL_MASK|GDK_SHIFT_MASK|GDK_ALT_MASK|
         GDK_SUPER_MASK|GDK_HYPER_MASK|GDK_META_MASK;
}

Messung V0.5 in Prozent
C=99 H=93 G=95

¤ Dauer der Verarbeitung: 0.29 Sekunden  (vorverarbeitet am  2026-07-03) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik