home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 184.lha / Edimap / edimap.c < prev    next >
C/C++ Source or Header  |  1988-04-28  |  25KB  |  1,019 lines

  1. /* EDIMAP Un éditeur de table de clavier
  2.  *
  3.  *    Version 1.0 de Septembre 1988 par Gilles Gamesh
  4.  *
  5.  *
  6.  * Ce programme se compile sous Aztec 3.6 avec le makefile suivant :
  7.  *
  8.  * CFLAGS = +Iedimap.inc +l +x3
  9.  *
  10.  * OBJS    = edimap.o lit_map.o
  11.  * # ----------------------------------------------------------------
  12.  * edimap            : $(OBJS)
  13.  *     ln -o $@ $(OBJS) -lc32
  14.  *
  15.  * edimap.inc            : edimap.h
  16.  *     cc -A +Hedimap.inc edimap.h +l +x3
  17.  * 
  18.  * edimap.o            : edimap.c gadgets.h func.h edimap.inc
  19.  *
  20.  * lit_map.o            : lit_map.c func.h edimap.inc
  21.  *
  22.  *
  23.  * Le code n'est peut-être pas du meilleur C mais il marche, certaines
  24.  * étrangetées peuvent être du à mon incompréhension de certains points
  25.  * de la table ou à certains bugs du système.
  26.  *
  27.  *
  28.  */
  29.  
  30.  
  31. #include "edimap.h"
  32. #include "gadgets.h"
  33. #include "func.h"
  34.  
  35. char usage[] = "\tEdimap v1.0\nUsage: Edimap keymap_name";
  36.  
  37. /*-----------------------------------------------------------------*/
  38. void main(argc, argv)
  39. int argc;
  40. UBYTE *argv[];
  41. {
  42.  
  43.   struct FileHandle *f_in;
  44.   UWORD *pword;
  45.   int taille, i;
  46.   ULONG longtab, nb_str;
  47.   ULONG *pnb_str, *deb_p_str;
  48.   ULONG Class;
  49.   USHORT Code, Qualifier;
  50.   BOOL encore = TRUE, flgraw = TRUE, flgsave = FALSE;
  51.   struct Gadget   *pMGad;
  52.   USHORT pMGadID;
  53.  
  54.     if (argc == 2)
  55.     {   if (argv[1][0] == '?') { puts(usage); exit(); }
  56.         else
  57.             strncpy(nom,argv[1],31);
  58.     }
  59.     else { puts(usage); exit(); }
  60.  
  61.     if ((buf_p = (struct P_String *)AllocMem(sizeof(struct P_String)*P_SIZE,
  62.                         MEMF_CLEAR)) == NULL)
  63.     {   printf(pas_de_place);
  64.         exit(1);
  65.     }
  66.     if ((buffer = (struct P_String *)AllocMem(sizeof(struct P_String)*P_SIZE,
  67.                         MEMF_CLEAR)) == NULL)
  68.     {   printf(pas_de_place);
  69.         goto error1;
  70.     }
  71.     if ((alstrflag = (UBYTE *)AllocMem(sizeof(UBYTE)*P_SIZE,
  72.                         MEMF_CLEAR)) == NULL)
  73.     {   printf(pas_de_place);
  74.         goto error2;
  75.     }
  76.  
  77. /*printf("filebuf %lx\n",filebuf);*/
  78.     if ((f_in = Open(nom,MODE_OLDFILE)) == NULL)
  79.     {  printf("Je ne peux trouver le fichier %s\n",nom); 
  80.        goto error3;
  81.     }
  82.  
  83.     taille = Seek(f_in,0L,OFFSET_END);
  84.     taille = Seek(f_in,0L,OFFSET_BEGINNING);
  85. /*    printf("taille %d\n",taille);*/
  86.     if (taille == 0L)
  87.     {   printf("Fichier vide\n");
  88.     goto error3bis;
  89.     }
  90.  
  91.     if ((filebuf = (UBYTE *)AllocMem(taille+1,0L)) == NULL)
  92.     {   printf(pas_de_place);
  93.     goto error3bis;
  94.     }
  95.  
  96.     if (Read(f_in,filebuf,taille) <= NULL)
  97.     {  printf("Je ne peux lire ce fichier\n"); 
  98.     goto error4;
  99.     }
  100.  
  101.     if ((IntuitionBase = (struct IntuitionBase *)
  102.         OpenLibrary("intuition.library", 0L)) == NULL) goto error4;
  103.     if ((GfxBase = (struct GfxBase *)
  104.         OpenLibrary("graphics.library", 0L)) == NULL) goto error5;
  105.  
  106.     if (!(window = (struct Window *)OpenWindow(&newWindow)))
  107.     {  printf("Je ne peux ouvrir la fenètre\n"); 
  108.     goto error6;
  109.     }
  110.     wRPort = window->RPort;
  111. /*printf("taille %x,1er %lx\n",taille,*((LONG *)filebuf));*/
  112.     if (lit_table())
  113.     { printf("Ce n'est pas une table de clavier\n");
  114.       goto error7;
  115.     }
  116.     question.IText =(UBYTE *)MTapez;
  117.     PrintIText(wRPort,&question,0L,0L);
  118.  
  119.     while (encore == TRUE)
  120.     {  Wait(1 << window->UserPort->mp_SigBit);
  121.        while (Message = (struct IntuiMessage *)GetMsg(window->UserPort))
  122.        {  Class = Message->Class;
  123.           Code = Message->Code;
  124.       Qualifier = Message->Qualifier;
  125.           ReplyMsg(Message);
  126.           pMGad   = (struct Gadget *)Message->IAddress;
  127.           pMGadID = pMGad->GadgetID;
  128.   
  129.       if (!(flgraw) && !(flgsave))
  130.       { question.IText =(UBYTE *)BlancLigne;
  131.         PrintIText(wRPort,&question,0L,0L);
  132.       }
  133.       switch (Class)
  134.       {  case RAWKEY :
  135.         if ((Code < 0x60) && flgraw)
  136.         {   flgraw = FALSE; flgsave = FALSE;
  137.             question.IText =(UBYTE *)BlancLigne;
  138.             PrintIText(wRPort,&question,0L,0L);
  139.             if (etape == MAL_FINI)
  140.             {  etape = 0;
  141.                question.IText =(UBYTE *)BlancLigne;
  142.                PrintIText(wRPort,&question,100L,100L);
  143.             }
  144.             affichegad(ON);
  145.  
  146.             LoType = (Code<0x40) ? TRUE : FALSE;
  147.             key_rel = (Code<0x40) ? Code : Code-0x40;
  148.             key_abs = Code;
  149.             initkey();
  150.             decodekey();
  151.             ajustgad(qual);
  152.         }
  153.         break;
  154.  
  155.              case GADGETUP:
  156.         switch (pMGadID)
  157.              {
  158.                   case G_SHIFT:
  159.              modifyGad(KCF_SHIFT,G_SHIFT);
  160.                      break;
  161.  
  162.                   case G_CTRL:
  163.              modifyGad(KCF_CONTROL,G_CTRL);
  164.                      break;
  165.  
  166.                   case G_ALT:
  167.              modifyGad(KCF_ALT,G_ALT);
  168.                      break;
  169.  
  170.                   case G_DEAD:
  171.              priorGad(KCF_DEAD,KCF_STRING);
  172.                      break;
  173.  
  174.                   case G_STRING:
  175.              priorGad(KCF_STRING,KCF_DEAD);
  176.                      break;
  177.  
  178.                   case G_OK:        /* OK */
  179.                  ajustkey();
  180.              if (invalide)
  181.              {  CopyMem(txt_err[-invalide-1],MErreur+POS_ERR,3L);
  182.             question.IText =(UBYTE *)MErreur;
  183.             PrintIText(wRPort,&question,0L,0L);
  184.             invalide = FAUX;
  185.             break;
  186.              }
  187.              modifie = TRUE;
  188.                   case G_ABORT:      /* RESET */
  189.              question.IText =(UBYTE *)MTapez;
  190.              PrintIText(wRPort,&question,0L,0L);
  191.              flgraw = TRUE;
  192.              affichegad(OFF);
  193.                      break;
  194.  
  195.                   case G_SAVE:
  196.              flgraw = FALSE; flgsave = TRUE;
  197.              etape=NOM_DU_FICHIER; quel_noms();
  198.              break;
  199.  
  200.                   case G_NOM:
  201.              PrintIText(wRPort,&Blanc_Txt,0L,TNSTRG);
  202.              if (etape == NOM_DU_FICHIER)
  203.              {  etape=NOM_DE_LA_TABLE;
  204.             quel_noms();
  205.              }
  206.              else if (etape == NOM_DE_LA_TABLE)
  207.              {    etape=ECRITURE;
  208.             quel_noms();
  209.              }
  210.              if (etape >= FINI)
  211.              {  if (etape == FINI) etape = 0;
  212.             question.IText =(UBYTE *)MFClose;
  213.             PrintIText(wRPort,&question,0L,0L);
  214.             flgraw = TRUE;
  215.             OnGadget(&SaveGad,window,0L);
  216.             OffGadget(&OkGad,window,0L); /* pour rafraichir */
  217.              }
  218.              break;
  219.         }
  220.         break;
  221.  
  222.          case CLOSEWINDOW :
  223.         if (modifie) 
  224.         { question.IText =(UBYTE *)MSortie;
  225.           PrintIText(wRPort,&question,0L,0L);
  226.           modifie = FALSE;
  227.         }
  228.         else
  229.           encore = FALSE;
  230.         }
  231.     }
  232.     }
  233.  
  234. error7:
  235.     CloseWindow(window); 
  236. error6:
  237.     CloseLibrary(GfxBase);
  238. error5:
  239.     CloseLibrary(IntuitionBase);
  240. error4:
  241.     FreeMem(filebuf,taille+1);
  242. error3bis:
  243.     Close(f_in);
  244. error3: 
  245.     FreeMem((char *)alstrflag,(long)sizeof(UBYTE)*P_SIZE);
  246. error2: 
  247.     FreeMem((char *)buffer,(long)sizeof(struct P_String)*P_SIZE);
  248. error1: 
  249.     FreeMem((char *)buf_p,(long)sizeof(struct P_String)*P_SIZE);
  250. }
  251. /*----------------------------------------*/
  252. /* Cette fonction sélecte les 'qualifier gadgets' et ajoute les
  253.  * 'string gadgets' conormément aux flags passés en argument
  254.  */
  255. void ajustgad(flg)
  256. UBYTE flg;
  257. {
  258.     UBYTE vanille = (flg == KC_VANILLA);
  259.  
  260.     strdead = qual & (KCF_DEAD | KCF_STRING);
  261.  
  262.     AddGadget(window,&StringGad[b_N],-1L);
  263.  
  264.     if (flg & KCF_SHIFT)
  265.     {   selectGad(&TogGad[G_SHIFT],G_SHIFT,ON);
  266.     AddGadget(window,&StringGad[b_S],-1L);
  267.     }
  268.     else if (flg & KCF_CONTROL && flg & KCF_ALT) AddGadget(window,&StringGad[b_CA],-1L);
  269.  
  270.     if (flg & KCF_ALT)
  271.     {   selectGad(&TogGad[G_ALT],G_ALT,ON);
  272.     AddGadget(window,&StringGad[b_A],-1L);
  273.     }
  274.     if (flg & KCF_CONTROL)
  275.     {   selectGad(&TogGad[G_CTRL],G_CTRL,ON);
  276.     if (!(vanille)) AddGadget(window,&StringGad[b_C],-1L);
  277.     }
  278.     if (flg & KCF_SHIFT && flg & KCF_ALT) AddGadget(window,&StringGad[b_SA],-1L);
  279.     if (flg & KCF_CONTROL && flg & KCF_SHIFT && !(vanille))
  280.     {   AddGadget(window,&StringGad[b_CS],-1L);
  281.     }
  282.  
  283.     if ((flg & KC_VANILLA)==KC_VANILLA) 
  284.     {   if (strdead)
  285.     { AddGadget(window,&StringGad[b_CSA],-1L);
  286.           AddGadget(window,&StringGad[b_CA],-1L);
  287.     }
  288.     else
  289.     { AffGadget(&StringGad[b_C],b_C);
  290.       AffGadget(&StringGad[b_CS],b_CS);
  291.     }
  292.     }
  293.     RefreshGadgets(&StringGad[b_N],window,0L);
  294.     if (flg & KCF_DEAD)
  295.     {   selectGad(&TogGad[G_DEAD],G_DEAD,ON);
  296.     selectGad(&TogGad[G_STRING],G_STRING,OFF);
  297.     }
  298.     if (flg & KCF_STRING)
  299.     {   selectGad(&TogGad[G_STRING],G_STRING,ON);
  300.     selectGad(&TogGad[G_DEAD],G_DEAD,OFF);
  301.     }
  302.  
  303. }
  304. /*----------------------------------------*/
  305. /* Cette fonction affiche l'image d'un pseudo 'string gadget' */
  306.  
  307. AffGadget(unGadget,code)
  308. struct Gadget *unGadget;
  309. int code;
  310. {
  311.     static struct IntuiText unText =  {3,0,JAM1,LSTRG};/* init debut */
  312.  
  313.     unText.TopEdge = unGadget->TopEdge;
  314.     unText.IText = unGadget->GadgetText->IText;
  315.     PrintIText(wRPort,&unText,-LSTRG+4L,0L);
  316.     unText.IText = StrBuf[code];
  317.     PrintIText(wRPort,&unText,0L,0L);
  318. }
  319. /*----------------------------------------*/
  320. /* Cette fonction effaces tous les 'string gadgets' */
  321.  
  322. void deleteSgadgets(onoff)
  323. BOOL onoff;
  324. {
  325.    int i;
  326.     for (i=b_N; i<=b_CSA; i++) RemoveGadget(window,&StringGad[i]);
  327.     if (!(onoff))
  328.     {  for (i=b_N; i<=b_CSA; i++)
  329.            StrBuf[i][0] = '\0';
  330.     }
  331.     for (i=b_N; i<=b_CSA; i++)
  332.         PrintIText(wRPort,&Blanc_Txt,0L,TSTRG+HSTRG*i);
  333. }
  334. /*----------------------------------------*/
  335. /* Change les selections de gadgets entre le mode édition et commande */
  336.  
  337. affichegad(onoff)
  338. BOOL onoff;
  339. {
  340.    int i;
  341.     if (onoff)
  342.     { cleargadgets();
  343.       OnGadget(&AbortGad,window,0L);
  344.       OffGadget(&SaveGad,window,0L);
  345.       OnGadget(&OkGad,window,0L);
  346. /*      RefreshGadgets(&OkGad,window,0L);*/
  347.     }
  348.     else
  349.     { cleargadgets();
  350.       deleteSgadgets(OFF);
  351.       OffGadget(&AbortGad,window,0L);
  352.       OnGadget(&SaveGad,window,0L);
  353.       OffGadget(&OkGad,window,0L);
  354.       for (i=G_SHIFT; i<=G_DEAD; i++) selectGad(&TogGad[i],i,OFF);
  355. /*      RefreshGadgets(&OkGad,window,0L);*/
  356.     }
  357.       
  358. }
  359. /*----------------------------------------*/
  360. /* efface les gadgets de l'écran */
  361.  
  362. cleargadgets()
  363. {    SetAPen(window->RPort,0L);
  364.     RectFill(window->RPort,LGAD-10L,HEIGHT+BGAD-2L,WIDTH-20L,HEIGHT-2L);
  365.     SetAPen(window->RPort,1L);
  366. }
  367. /*----------------------------------------*/
  368. /* sélecte ou déselecte un gadget, un certaine gymnastique a été
  369.  * nécessaire à cause d'un bug qui bascule l'affichage du fond d'un
  370.  * 'toggle gadget' à chaque refresh
  371.  */
  372.  
  373. void selectGad(pGad,pos,onoff)
  374. struct Gadget *pGad;
  375. BOOL onoff;
  376. int pos;
  377. {
  378.    int deja_selecte = 0;
  379.     RemoveGadget(window,pGad);
  380.     deja_selecte = pGad->Flags & SELECTED;
  381.     if (onoff)
  382.     { if (!(deja_selecte))
  383.       { pGad->Flags |= SELECTED;
  384.         RefreshGList(pGad,window,0L,1L);
  385.       }
  386.      }
  387.     else
  388.     { if (deja_selecte)
  389.       { RefreshGList(pGad,window,0L,1L);/* eteint centre */
  390.         pGad->Flags &= ~SELECTED;
  391.         RefreshGList(pGad,window,0L,1L);/* eteint bordure */
  392.       }
  393.     }
  394.     AddGadget(window,pGad,(long)(pos+3));
  395. }
  396. /*----------------------------------------*/
  397. /* Si STRING pas DEAD et vice versa */
  398.  
  399. void priorGad(gadoui,gadnon)
  400. ULONG gadoui, gadnon;
  401. {   UWORD i;
  402.     qual &= ~(gadnon);
  403.     if (qual & gadoui)
  404.        qual &= ~(gadoui);
  405.     else
  406.        qual |= gadoui;
  407.  
  408.     deleteSgadgets(OFF);
  409. /*    for (i=b_N; i<=b_CSA; ++i) StrBuf[i][0] = 0;*/
  410.     ajustgad(qual);
  411. }
  412. /*----------------------------------------*/
  413. /* on a cliqué et sélecté le gadget du type 'type' */
  414.  
  415. void modifyGad(un_qual,type)
  416. ULONG un_qual;
  417. int type;
  418. {
  419.     int flg;
  420.  
  421.     deleteSgadgets(ON);
  422.     flg = TogGad[type].Flags;
  423.     qual &= ~(un_qual);
  424.     if (flg == SELECTED) qual |= un_qual;
  425.     StrBuf[b_CSA][0] = 0;
  426.     switch(un_qual)
  427.     { case KCF_SHIFT:
  428.         StrBuf[b_S][0] = 0;
  429.         StrBuf[b_CS][0] = 0;
  430.         StrBuf[b_SA][0] = 0;
  431.         break;
  432.  
  433.       case KCF_CONTROL:
  434.         StrBuf[b_C][0] = 0;
  435.         StrBuf[b_CA][0] = 0;
  436.         StrBuf[b_CS][0] = 0;
  437.         break;
  438.  
  439.       case KCF_ALT:
  440.         StrBuf[b_A][0]= 0;
  441.         StrBuf[b_SA][0] = 0;
  442.         StrBuf[b_CA][0] = 0;
  443.         break;
  444.     }
  445.     ajustgad(qual);
  446. }
  447. /*----------------------------------------*/
  448. /* on ajuste le codage de la touche aux valeurs demandées */
  449.  
  450. void ajustkey()
  451. {
  452.   UBYTE strcode[257];    /*buffer où on encode la touche */
  453.   int nb, i;
  454.  
  455. /*printf("j'ajuste la key %x\n",key_abs);*/
  456.     nb = encodekey(strcode);
  457.     if (invalide) return;
  458.  
  459.     if (alstrflag[key_abs]) /* si on a alloue un buffer a la touche */
  460.     {   free(buf_p[key_abs].p); /* on le libere */
  461.         alstrflag[key_abs] = 0;
  462.     }
  463.     buf_p[key_abs].l = 0;
  464.     buf_p[key_abs].p = NULL;
  465.  
  466.     if (nb)    /* c'est string ou dead */
  467.     {   buf_p[key_abs].p = (UBYTE *)calloc(nb,1);
  468.         buf_p[key_abs].l = nb;
  469.         alstrflag[key_abs] = TRUE; /* marque buffer alloue */
  470.         CopyMem(strcode,buf_p[key_abs].p,(long)nb);
  471.     }
  472.     else
  473.     {   for (i=0; i<4 ;++i) Tkey.trad[i] = strcode[i];
  474.         if (LoType)
  475.         {  keymap.km_LoKeyMap[key_rel] = Tkey.longtrad ;    
  476.         }
  477.         else
  478.         {  keymap.km_HiKeyMap[key_rel] = Tkey.longtrad ;    
  479.         }
  480.     }
  481.     if (LoType)
  482.     {  keymap.km_LoKeyMapTypes[key_rel] = qual;
  483.        setbitqual(keymap.km_LoCapsable,key_rel,caps);
  484.        getbitqual(keymap.km_LoRepeatable,key_rel,repet);
  485.     }
  486.     else
  487.     {  keymap.km_HiKeyMapTypes[key_rel] = qual;
  488.        setbitqual(keymap.km_HiCapsable,key_rel,caps);
  489.        getbitqual(keymap.km_HiRepeatable,key_rel,repet);
  490.     }
  491. }
  492. /*----------------------------------------*/
  493. /* on initialise le codage initial de la touche */
  494.  
  495. void initkey()
  496. {
  497.     if (LoType)
  498.     { qual = keymap.km_LoKeyMapTypes[key_rel] ;
  499.       strdead = qual & (KCF_DEAD | KCF_STRING);
  500.       if (strdead)
  501.           Tkey.str = (UBYTE *)(buf_p[key_abs].p);
  502.       else
  503.           Tkey.longtrad = keymap.km_LoKeyMap[key_rel] ;    
  504.       caps = getbitqual(keymap.km_LoCapsable,key_rel);
  505.       repet = getbitqual(keymap.km_LoRepeatable,key_rel);
  506.     }
  507.     else
  508.     { qual = keymap.km_HiKeyMapTypes[key_rel] ;
  509.       strdead = qual & (KCF_DEAD | KCF_STRING);
  510.       if (strdead)
  511.           Tkey.str = (UBYTE *)(buf_p[key_abs].p);
  512.       else
  513.           Tkey.longtrad = keymap.km_HiKeyMap[key_rel] ;
  514.       caps = getbitqual(keymap.km_HiCapsable,key_rel);
  515.       repet = getbitqual(keymap.km_HiRepeatable,key_rel);
  516.     }
  517. }
  518. /*----------------------------------------*/
  519. /* on retourne le qualifier de la touche k */
  520.  
  521. getbitqual(table,k)
  522. UBYTE *table;
  523. USHORT k;
  524. {  UBYTE n;
  525.     n = table[k/8];
  526.     return(n & (1 << (k%8)));
  527. }
  528. /*----------------------------------------*/
  529. /* on modifie le qualifier de la touche k */
  530.  
  531. void setbitqual(table,k,onoff)
  532. UBYTE *table;
  533. USHORT k;
  534. BOOL onoff;
  535. {  UBYTE n;
  536.     n = table[k/8];
  537.     table[k/8] = onoff ? (n | (1 << (k%8))) : (n & (~(1 << (k%8))));
  538. }
  539. /*----------------------------------------*/
  540. /* on affiche le codage de la touche selectée */
  541.  
  542. void decodekey()
  543. {
  544.   UBYTE *p, *pi;
  545.   USHORT i;
  546.  
  547.     p = pi = Tkey.str;
  548.  
  549.     if (!(qual)) decodele(b_N,Tkey.trad,0);
  550.     else if (qual & KCF_DEAD)    /* dead */
  551.     { decodedead(pi,p,b_N); p += 2;
  552.       for (i=b_S; i<=b_CSA; i++)
  553.       { if ((qual & i) == i)
  554.           decodedead(pi,p,i); p += 2;
  555.       }
  556.     }
  557.     else if (qual & KCF_STRING)    /* string */
  558.     { decodestr(pi,p,b_N,KCF_STRING); p += 2;
  559.       for (i=b_S; i<=b_CSA; i++)
  560.       { if ((qual & i) == i)
  561.           decodestr(pi,p,i,KCF_STRING); p += 2;
  562.       }
  563.     }
  564.     else
  565.     { decodele(b_N,Tkey.trad,0);
  566.       if    (qual == KCF_SHIFT) decodele(b_S,Tkey.trad,1);    
  567.       else if (qual == KCF_ALT) decodele(b_A,Tkey.trad,1);
  568.       else if (qual == KCF_CONTROL) decodele(b_C,Tkey.trad,1);
  569.       else if (qual == (KCF_CONTROL+KCF_ALT))
  570.       {  decodele(b_A,Tkey.trad,1);
  571.          decodele(b_C,Tkey.trad,2);
  572.          decodele(b_CA,Tkey.trad,3);
  573.       }
  574.       else if (qual == (KCF_CONTROL+KCF_SHIFT))
  575.       {  decodele(b_S,Tkey.trad,1);
  576.          decodele(b_C,Tkey.trad,2);
  577.          decodele(b_CS,Tkey.trad,3);
  578.       }
  579.       else if ((qual & (KCF_SHIFT+KCF_ALT)) == (KCF_SHIFT+KCF_ALT))
  580.       {  decodele(b_S,Tkey.trad,1);
  581.          decodele(b_A,Tkey.trad,2);
  582.          decodele(b_SA,Tkey.trad,3);
  583.       }
  584.       if (qual == KC_VANILLA)
  585.       {  decodele(b_C,Tkey.trad,4);
  586.          decodele(b_CS,Tkey.trad,5);
  587.       }
  588.     }
  589. }
  590. /*-------------------------------------------*/
  591. /* on decode le contenu de la touche pour le qualifier 'cod' */
  592.  
  593. void decodele(cod,k,n)
  594. UBYTE *k;
  595. int cod,n;
  596. {
  597.    UBYTE b, *p;
  598.  
  599.     p = StrBuf[cod];
  600.     b = k[3-n%4];
  601.     if (n==7) b = *k;
  602.     else if (n>3) b &= 0x9f;
  603.     if (b & 0x60) {*p++ = '\''; *p++ = b; *p++ = '\''; *p = '\0';}
  604.     else sprintf(p,"%02x",b);
  605. }
  606. /*-------------------------------------------*/
  607. /* on decode le string de la touche pour le qualifier 'cod' pour une
  608.  * chaine ou une dead(able) key (flag dans diag)
  609.  */
  610.  
  611. void decodestr(deb,k,cod,diac)
  612. UBYTE *deb, *k;
  613. int cod;
  614. ULONG diac;
  615. {
  616.   UBYTE *p, *s, n;
  617.   char flgaff = '\0';
  618.   USHORT i;
  619.  
  620.     s = StrBuf[cod];
  621.     n = *k;
  622.     p = deb + *(k+1);
  623.  
  624.     for (i=0; i<n; i++, p++)
  625.     { if (*p & 0x60) /* affichable */
  626.       { if (!(flgaff)) /* pas dans un string */
  627.         { if (*p != '"' && *p != '\'' ) /* si 1er car n'est pas " ou ' */
  628.             *s++ = flgaff = '\'';        /* on met ' */
  629.           else      
  630.             *s++ = flgaff = *p ^ 0x05;  /* sinon l'autre */
  631.         }
  632.         else if (*p == '"' || *p == '\'' )
  633.         { *s++ = flgaff; *s++ = ','; flgaff = *p ^ 0x05; *s++ = flgaff;
  634.         }
  635.         *s++ = *p;
  636.       }
  637.       else
  638.       { if (flgaff)
  639.         { *s++ = flgaff; *s++ = ',';
  640.           flgaff = '\0';
  641.         }
  642.         if (*p == 0x9b) { strcpy(s,"<CSI>,"); s += 6;}
  643.         else { sprintf(s,"%02x",*p); s += 2; *s++ = ',';}
  644.       }
  645.     }
  646.  
  647.     if (flgaff) *s++ = flgaff;
  648.     else --s;
  649.  
  650.     if (diac == KCF_DEAD)
  651.     { *s++ = ','; *s++ = '(';
  652.       for (i=0; i<5; i++) *s++ = *p++;
  653.       *s++ = ')';
  654.     }
  655.     *s = '\0';
  656. }
  657. /*-------------------------------------------*/
  658. /* on decode une dead(able) key */
  659.  
  660. void decodedead(deb,p,cod)
  661. UBYTE *deb, *p;
  662. int cod;
  663. {
  664.     if (*p == 0) decodele(cod,++p,7);
  665.     else if (*p == DPF_MOD) decodestr(deb,p,cod,KCF_DEAD);
  666.     else if (*p == DPF_DEAD) decodeacc(deb,p,cod);
  667. }
  668. /*-------------------------------------------*/
  669. /* on décode les accents des 'dead key' */
  670.  
  671. void decodeacc(deb,p,cod)
  672. UBYTE *deb, *p;
  673. int cod;
  674. {
  675.    UBYTE *s;
  676.    static UBYTE accent[] = {0xb4, 0x60, 0x5e, 0x7e, 0xa8};
  677.  
  678.     s = StrBuf[cod];
  679.     *s++ = '(';
  680.     *s++ = accent[(*(p+1) & 7)-1];
  681.     *s++ = ')'; *s = '\0';
  682. }
  683.  
  684. /*----------------------------------------*/
  685. /* on encode la touche conformément aux souhaits de l'utilisateur */
  686.  
  687. int encodekey(strcode)
  688. UBYTE *strcode;
  689. {
  690.   UBYTE *pstr, *p;
  691.   USHORT i;
  692.   short n;
  693.   UBYTE vanille;
  694.  
  695.     invalide = FAUX; /* a priori pas d'erreur */
  696.     for (i = 0; i<256 ; ++i) strcode[i] = 0;
  697.     pstr = strcode;
  698.     vanille = qual & KC_VANILLA;
  699.     if (!(qual)) encodele(b_N,pstr,0); /* si qual=0 touche Normale */
  700.     else if (strdead = qual & (KCF_DEAD | KCF_STRING))    /* dead */
  701.     { for (n=1, i=b_S; i<=b_CSA; i++)
  702.           if ((qual & i) == i) n++;    /* calcule offset */
  703.       p = pstr + 2*n;
  704.       { for (i=b_N; i<=b_CSA; i++)
  705.         { if ((qual & i) == i)
  706.           encodestr(i,&pstr,&p,strcode);
  707.         }
  708.       }
  709.     n = p - strcode;
  710.     }
  711.     else
  712.     { encodele(b_N,pstr,0);
  713.       if    (qual == KCF_SHIFT) encodele(b_S,pstr,1);    
  714.       else if (qual == KCF_ALT) encodele(b_A,pstr,1);
  715.       else if (qual == KCF_CONTROL) encodele(b_C,pstr,1);
  716.       else if (qual == (KCF_CONTROL+KCF_ALT))
  717.       {  encodele(b_A,pstr,1);
  718.          encodele(b_C,pstr,2);
  719.          encodele(b_CA,pstr,3);
  720.       }
  721.       else if (qual == (KCF_CONTROL+KCF_SHIFT))
  722.       {  encodele(b_S,pstr,1);
  723.          encodele(b_C,pstr,2);
  724.          encodele(b_CS,pstr,3);
  725.       }
  726.       else if ((qual & (KCF_SHIFT+KCF_ALT)) == (KCF_SHIFT+KCF_ALT))
  727.       {  encodele(b_S,pstr,1);
  728.          encodele(b_A,pstr,2);
  729.          encodele(b_SA,pstr,3);
  730.       }
  731. /*      if (qual == KC_VANILLA)
  732.       {  encodele(b_C,pstr,4);
  733.          encodele(b_CS,pstr,5);
  734.       }
  735. */
  736.     }
  737.  
  738.     return (strdead ? n : 0);
  739. }
  740. /*-------------------------------------------*/
  741. /* on encode le string demandé et vérifie sa validité */
  742.  
  743. void encodestr(cod,plong,ptexte,pdeb)
  744. int cod;
  745. UBYTE **plong,    /* la ou on va mettre la longueur du string */
  746.       **ptexte,    /* la ou on met le texte du string */
  747.       *pdeb;    /* buffer d'encodage */
  748.  
  749. {
  750.     UBYTE *p, c;
  751.     int nb=0 , off, invacode;
  752.     int tampon;
  753.     
  754.     invacode = -(cod+1);
  755.     p = StrBuf[cod]; /* string a coder */
  756.     off = *ptexte - pdeb;
  757.  
  758.     if (strdead == KCF_STRING)
  759.     {
  760.       nb = form(p,*ptexte,'s');
  761.       *(*plong)++ = nb; *(*plong)++ = off; 
  762.       *ptexte += nb;
  763.     }
  764.     else    /* dead or deadeable */
  765.     { if (*p == '(') /* dead */
  766.       { if (p[2] == ')') /* dead key */
  767.         { *(*plong)++ = DPF_DEAD;
  768.           if ((tampon = queldead(p[1])) == ERROR)
  769.           { invalide = invacode;
  770.         return;
  771.           }
  772.           else
  773.           { *(*plong)++ = tampon;
  774.         return;
  775.           }
  776.         }
  777.         else /* ne doit pas commencer par parenthese */
  778.         { invalide = invacode;
  779.           return;
  780.         }
  781.       }
  782.       else if (strlen(p) > 3) /* deadable */
  783.       { nb=form(p,*ptexte,'d') ; /* le code de reference */
  784.         *(*plong)++ = DPF_MOD; *(*plong)++ = off; 
  785.         *ptexte += nb;
  786.       }
  787.       else /* caractère normal */
  788.       { *(*plong)++ = 0; 
  789.         nb=form(p,*plong,'c'); ++(*plong);
  790.       }
  791.     }
  792.     if (nb < 0) invalide = invacode;
  793.     return;
  794. }
  795. /*-------------------------------------------*/
  796. /* on recherche le type d'accent demandé */
  797.  
  798. queldead(c)
  799. UBYTE c;
  800. {
  801.     switch(c)
  802.     { case 0xB4:
  803.       case '\'':    return(1);
  804.       case '`':    return(2);
  805.       case '^':    return(3);
  806.       case '~':    return(4);
  807.       case 0xA8:
  808.       case '"':    return(5);
  809.       default:    return(ERROR);
  810.     }
  811. }
  812. /*-------------------------------------------*/
  813. /* on encode sur 4 bytes les codes demandés
  814.  * on met en k le code traduit demande pour cod avec decalage n 
  815.  * si n > 3 control (shift) pour vanilla (n'est plus utilisé)
  816.  */  
  817. void encodele(cod,k,n)
  818. UBYTE *k;
  819. int cod,n;
  820. {
  821.    UBYTE b, *p;
  822.    int nb, invacode;
  823.  
  824.     invacode = -(cod+1);
  825.     p = StrBuf[cod];
  826.     if ((nb = form(p,&b,'c')) < 0) {invalide = invacode; return;}
  827. /*    if (n>3) b &= 0x9f;
  828.     k[3-n%4] = b;
  829. */
  830.     k[3-n] = b;
  831.     return;
  832. }
  833. /*-------------------------------------------*/
  834. /* deformatte string s en d avec specifs f */
  835. /* 'c' copie le car 'x' ou dont le code ascii hexa est donné 
  836.  * 'd' copie le car et les 5 dead-codes suivants entre () ')'
  837.  * 'a' parse un string de la forme  41,<CSI>,'m toto',0D,0A
  838.  */
  839. form(s,d,f)
  840. UBYTE *s, *d;
  841. char f;
  842. {
  843.     char strin = '\0';
  844.     int b=0;
  845.     UBYTE *memd;
  846.     short i;
  847.  
  848.     memd = d;
  849.     switch(f)
  850.     { case 'c':
  851.         if (*s == '\'')
  852.         { *d++ = *++s; ++s;
  853.           if (*s++ != '\'') return ERROR;
  854.         }
  855.         else
  856.         { b = axtoi(&s);
  857.           if (b < 256) *d++ = b;
  858.           else return ERROR;
  859.         }
  860.         while (*s == ' ') ++s; /* des blancs sont authorises a la fin */
  861.         if (*s) return ERROR;  /* mais rien d'autre */
  862.         break;
  863.  
  864.       case 'd' :
  865.         if (*s == '\'')
  866.         { *d++ = *++s; ++s;
  867.           if (*s++ != '\'') return ERROR;
  868.         }
  869.         else
  870.         { b = axtoi(&s);
  871.           if (b < 256) *d++ = b;
  872.           else return ERROR;
  873.         }
  874.         while (*s == ' ') ++s;
  875.         if (*s++ != ',') return ERROR;
  876.  
  877.         while (*s == ' ') ++s;
  878.         if (*s++ == '(')
  879.         { for (i=0; i<5; i++) *d++ = *s++;
  880.           if (*s++ != ')') return ERROR;
  881.         }
  882.         else return ERROR;
  883.         while (*s == ' ') ++s; /* des blancs sont authorises a la fin */
  884.         if (*s) return ERROR;  /* mais rien d'autre */
  885.         break;
  886.  
  887.       case 'a':
  888.         break;
  889.  
  890.       case 's':
  891.         --s;    /* predecremente pour pouvoir incrementer */
  892.         while (*(++s)) 
  893.           switch(*s)
  894.           { case '\'':
  895.         case '"':
  896.           if (strin == *s) strin = '\0';
  897.           else if (!(strin)) strin = *s;
  898.           else *d++ = *s;
  899.           break;
  900.             case ',':
  901.           if (!(strin)) break;
  902.           else *d++ = *s;
  903.           break;
  904.             default:
  905.           if (strin)
  906.             *d++ = *s;
  907.           else
  908.           { if (!(strncmp(s,"<CSI>",4)))
  909.             {    *d++ = 0x9b;
  910.             s += 4;
  911.             }
  912.             else
  913.             { b = axtoi(&s);
  914.               while (*s == ' ') ++s;
  915.               if (*s && (*s != ',')) return ERROR;
  916.               --s;    /* pour tester le 0 au coup suivant */
  917.               if (b < 256 && b >= 0) *d++ = b;
  918.               else return (ERROR);
  919.             }
  920.           }
  921.           break;
  922.           }
  923.     }
  924.     return (strin ? ERROR : d-memd);
  925. }
  926. /*------------------------------------------ */
  927. /* traduit une chaine hexa en un entier */
  928.  
  929. axtoi(pp)
  930. char **pp;
  931. {
  932.     char *p;
  933.     int i = 0;
  934.  
  935.     p = *pp;
  936.     while (isspace(*p)) p++;
  937.     while (isxdigit(*p))
  938.     { i = i * 16 +(isdigit(*p) ? *p - '0' : (*p & 0x5f) - 55);
  939.       p++;
  940.     }
  941.     *pp = p;
  942.     return i;
  943. }
  944. /*------------------------------------------ */
  945. /* gère la demande des noms de fichier et de table */
  946.  
  947. quel_noms()
  948. {
  949.     UBYTE *p;
  950.     int l;
  951.  
  952.     question.IText =(UBYTE *)BlancLigne;
  953.     PrintIText(wRPort,&question,0L,0L);
  954.  
  955.       switch(etape)
  956.       { case NOM_DU_FICHIER:
  957.         OffGadget(&SaveGad,window,0L);
  958.         cleargadgets();
  959.          question.IText =(UBYTE *)"Nom du fichier à sauver ?";
  960.         PrintIText(wRPort,&question,0L,0L);
  961.         if (p=index(nom,'.'))
  962.           l = p-nom;
  963.         else
  964.           l = strlen(nom);
  965.  
  966.         strncpy(NomStrBuf,nom,l); NomStrBuf[l]='\0';
  967.         strcat(NomStrBuf,".map");
  968.         Nom_strinfo.BufferPos = l+4;
  969.         AddGadget(window,&NomGad,-1L);
  970.         RefreshGadgets(&NomGad,window,0L);
  971.         ActivateGadget(&NomGad,window,0L);
  972.         break;
  973.  
  974.     case NOM_DE_LA_TABLE:
  975.         RemoveGadget(window,&NomGad);
  976.         if (*NomStrBuf == 0) goto inval;
  977.  
  978.         strcpy(nom_fich,NomStrBuf);
  979.          question.IText =(UBYTE *)"Nom de la table de clavier ?";
  980.         PrintIText(wRPort,&question,0L,0L);
  981.         if (p=index(NomStrBuf,'.'))
  982.         { l = p-NomStrBuf;
  983.           *p = '\0';
  984.         }
  985.         else
  986.           l = strlen(NomStrBuf);
  987.  
  988.         Nom_strinfo.BufferPos = l;
  989.         AddGadget(window,&NomGad,-1L);
  990.         RefreshGadgets(&NomGad,window,0L);
  991.         ActivateGadget(&NomGad,window,0L);
  992.         break;
  993.  
  994.     case ECRITURE:
  995.         RemoveGadget(window,&NomGad);
  996.         if (*NomStrBuf == 0)
  997.             { question.IText =(UBYTE *)"Nom INVALIDE,";
  998.           goto inval;
  999.         }
  1000.  
  1001.         if (ecr_table(nom_fich,NomStrBuf))
  1002.             { question.IText =(UBYTE *)"Pb d'écriture,";
  1003.           goto inval;
  1004.         }
  1005.         modifie = FALSE;
  1006.         etape = FINI;
  1007.         break;
  1008.     }
  1009.     return;
  1010.  
  1011. inval:
  1012.     PrintIText(wRPort,&question,100L,100L);
  1013.     question.IText =(UBYTE *)"le fichier N'est PAS sauvé";
  1014.     PrintIText(wRPort,&question,220L,100L);
  1015.     etape = MAL_FINI;
  1016.     return;
  1017. }
  1018.  
  1019.