Logo Search packages:      
Sourcecode: kbd version File versions  Download package

kdmapop.c

/*
 * kdmapop.c - export getscrnmap(), loadscrnmap(),
 *                    loaduniscrnmap(), loadunimap()
 *
 * Hide the ioctl use in this file.
 */
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <linux/kd.h>
#include "kdmapop.h"
#include "nls.h"
#include "version.h"

/*
 * Linux pre-0.96 defined GIO_SCRNMAP, PIO_SCRNMAP:
      typedef char scrnmap_t;
      #define E_TABSZ         256
      #define GIO_SCRNMAP     0x4B40
      #define PIO_SCRNMAP     0x4B41
 * and Linux 0.99.14y first implemented them.
 * Usage:
      scrnmap_t map[E_TABSZ];
      ioctl(fd,GIO_SCRNMAP,map);
      ioctl(fd,PIO_SCRNMAP,map);
 * to read or write the kernel translation table that is
 * applied to user application output before displaying.
 *
 * Before 1.3.1, the character set was completely undetermined,
 * and if the font was in an order different from the character
 * set in use, the user screen map was used to map application
 * codes to font indices. (To be more precise: there were four
 * translation tables, and this ioctl would get/set the fourth
 * table, while the other three tables are built-in and constant.)
 */
int
getscrnmap(int fd, char *map) {
      if (ioctl(fd,GIO_SCRNMAP,map)) {
            perror("GIO_SCRNMAP");
            return -1;
      }
      return 0;
}

int
loadscrnmap(int fd, char *map) {
      if (ioctl(fd,PIO_SCRNMAP,map)) {
            perror("PIO_SCRNMAP");
            return -1;
      }
      return 0;
}

/*
 * Linux 1.3.1 introduces GIO_UNISCRNMAP, PIO_UNISCRNMAP:
      #define GIO_UNISCRNMAP  0x4B69
      #define PIO_UNISCRNMAP  0x4B6A
 * Usage:
      unsigned short umap[E_TABSZ];
      ioctl(fd,GIO_UNISCRNMAP,umap);
      ioctl(fd,PIO_UNISCRNMAP,umap);
 * to read or write the kernel translation table that is
 * applied to user application output before displaying.
 * (When the console is not in utf8 mode.)
 *
 * The idea is that the umap values are 16-bit unicode (ucs2)
 * values, and that the fonts will have an index giving the
 * unicode value for each glyph, so that the kernel can match up
 * application codes to font positions.
      #define UNI_DIRECT_BASE 0xF000
      #define UNI_DIRECT_MASK 0x01FF
 * For compatibility, and for fonts without table, the unicode
 * values 0xF000+n, 0 <= n <= 0x01FF, acts as direct font indices.
 * In the new scheme, the old PIO_SCRNMAP fills the kernel umap
 * table with such direct-to-font values.
 */
      
int
getuniscrnmap(int fd, unsigned short *map) {
      if (ioctl(fd,GIO_UNISCRNMAP,map)) {
            perror("GIO_UNISCRNMAP");
            return -1;
      }
      return 0;
}

int
loaduniscrnmap(int fd, unsigned short *map) {
      if (ioctl(fd,PIO_UNISCRNMAP,map)) {
            perror("PIO_UNISCRNMAP");
            return -1;
      }
      return 0;
}

/*
 * Linux 1.1.63 introduces GIO_UNIMAP, PIO_UNIMAP, PIO_UNIMAPCLR:
      #define GIO_UNIMAP     0x4B66
      #define PIO_UNIMAP     0x4B67
      #define PIO_UNIMAPCLR  0x4B68
 * And Linux 1.1.92 implements them.
 * Usage:
      struct unimapinit {
            unsigned short advised_hashsize;
            unsigned short advised_hashstep;
            unsigned short advised_hashlevel;
      } ui;
      ioctl(fd, PIO_UNIMAPCLR, &ui);
 * to clear the unimap table and advise about the kind of
 * hash setup appropriate to what one is going to load
 * (with 0 for "don't care").
      struct unipair {
              unsigned short unicode;
            unsigned short fontpos;
      };
      struct unimapdesc {
            unsigned short entry_ct;
            struct unipair *entries;
      } ud;
      ioctl(fd, PIO_UNIMAP, &ud);
      ioctl(fd, GIO_UNIMAP, &ud);
 * to add the indicated pairs to the kernel unimap table
 * or to read the kernel unimap table, where in the latter case
 * ud.entry_ct indicated the room available.
 *
 * In Linux 1.3.28 the hash table was replaced by a 3-level
 * paged table, so the contents of a struct unimapinit are
 * no longer meaningful.
 *
 * Linux 2.6.1 makes GIO_UNIMAP, PIO_UNIMAP, PIO_UNIMAPCLR per-vt
 * so that fd no longer is random.
 */
int
getunimap(int fd, struct unimapdesc *ud0) {
      struct unimapdesc ud;
      int ct;

      ud.entry_ct = 0;
      ud.entries = 0;
      if (ioctl(fd, GIO_UNIMAP, &ud)) {
            if(errno != ENOMEM || ud.entry_ct == 0) {
                  perror("GIO_UNIMAP(0)");
                  return -1;
            }
            ct = ud.entry_ct;
            ud.entries = (struct unipair *)
                  malloc(ct * sizeof(struct unipair));
            if (ud.entries == NULL) {
                  fprintf(stderr, _("%s: out of memory\n"), progname);
                  return -1;
            }
            if (ioctl(fd, GIO_UNIMAP, &ud)) {
                  perror("GIO_UNIMAP");
                  return -1;
            }
            if (ct != ud.entry_ct)
                  fprintf(stderr,
                        _("strange... ct changed from %d to %d\n"),
                        ct, ud.entry_ct);
            /* someone could change the unimap between our
               first and second ioctl, so the above errors
               are not impossible */
      }
      *ud0 = ud;
      return 0;
}

int
loadunimap(int fd, struct unimapinit *ui, struct unimapdesc *ud) {
      struct unimapinit advice;

      if (ui)
            advice = *ui;
      else {
            advice.advised_hashsize = 0;
            advice.advised_hashstep = 0;
            advice.advised_hashlevel = 0;
      }
 again:
      if (ioctl(fd, PIO_UNIMAPCLR, &advice)) {
#ifdef ENOIOCTLCMD
            if (errno == ENOIOCTLCMD) {
                  fprintf(stderr,
                        _("It seems this kernel is older than 1.1.92\n"
                          "No Unicode mapping table loaded.\n"));
            } else
#endif
            perror("PIO_UNIMAPCLR");
            return -1;
      }
      if (ud == NULL)
            return 0;

      if (ioctl(fd, PIO_UNIMAP, ud)) {
            if (errno == ENOMEM && advice.advised_hashlevel < 100) {
                  advice.advised_hashlevel++;
                  goto again;
            }
            perror("PIO_UNIMAP");
            return -1;
      }

      return 0;
}

Generated by  Doxygen 1.6.0   Back to index