KeyboardEx.cpp

Parent Previous Next

/*

* *********************************

  Nico78 - French Forum Arduino

* *********************************

  KeyboardEx.cpp

* *********************************

  Code permettant d'utiliser la langue française pour l'émulation du clavier sur Arduino

  Prend en charge tous les caractères du clavier physique, ainsi que les clés mortes (dead keys)

  soit l'ensemble des caractères suivant:

  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

  €£¤§¨°²µÀÂÃÄÈÊËÌÎÏÑÒÔÕÖÙÛÜàâãäçèéêëìîïñòôõöùûüÿ

* *********************************

 Copyright (c) 2015, Arduino LLC

 Original code (pre-library): Copyright (c) 2011, Peter Barrett

 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.1 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, write to the Free Software

 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

*/


#include "KeyboardEx.h"


//#define DEBUG         // Affiche le nom des fonctions seulement

//#define DEBUG_R       // Affiche le nom de la variable ainsi que sa valeur qui est renvoyée par la fonction

//#define DEBUG_L1      // affiche le nom de la variable ainsi que sa valeur pour le debug Level 1

//#define DEBUG_L2      // affiche le nom de la variable ainsi que sa valeur pour le debug Level 2

//#define DEBUG_L3      // affiche le nom de la variable ainsi que sa valeur pour le debug Level 3


#ifdef DEBUG

#define D_SERIALBEGIN(...) Serial.begin(__VA_ARGS__)

#define D_PRINT(...) Serial.print(__VA_ARGS__)

#define D_PRINTLN(...) Serial.println(__VA_ARGS__)

#define D_PRINTF(...) Serial.print(F(__VA_ARGS__))

#define D_PRINTLNF(...) Serial.println(F(__VA_ARGS__)) //Printing text using the F macro

#define D_DELAY(...) delay(__VA_ARGS__)

#define D_PROC_(a)                        \

 Serial.println();                       \

 Serial.print(F("\t ---> Fonction [ ")); \

 Serial.println(#a " ]");

#else

#define SERIALBEGIN(...) //blank line

#define D_PRINT(...)     //blank line

#define D_PRINTLN(...)   //blank line

#define D_PRINTF(...)    //blank line

#define D_PRINTLNF(...)  //blank line

#define D_DELAY(...)     //blank line

#define D_PROC_(a)       //blank line

#endif


#ifdef DEBUG_R

#define D_PROC_R(a, b)                                   \

 Serial.println();                                      \

 Serial.print(F("\t\t ---> Retour de la Fonction [ ")); \

 Serial.print(#a "] -> ");                              \

 Serial.print(#b " = ");                                \

 Serial.println(b)

#else

#define D_PROC_R(a, b) //blank line

#endif


#ifdef DEBUG_L1

#define D_PROC_L1(a, b)           \

 Serial.println();               \

 Serial.print(F("\t\t L1 > [")); \

 Serial.print(a);                \

 Serial.print(F("] \t-> "));     \

 Serial.print(#b " = ");         \

 Serial.println(b)

#else

#define D_PROC_L1(a, b) //blank line

#endif


#ifdef DEBUG_L2

#define D_PROC_L2(a, b)           \

 Serial.println();               \

 Serial.print(F("\t\t L2 > [")); \

 Serial.print(a);                \

 Serial.print(F("]\t\-> "));     \

 Serial.print(#b " = ");         \

 Serial.println(b)

#else

#define D_PROC_L2(a, b) //blank line

#endif


#ifdef DEBUG_L3

#define D_PROC_L3(a, b)           \

 Serial.println();               \

 Serial.print(F("\t\t L3 > [")); \

 Serial.print(a);                \

 Serial.print(F("]\t\-> "));     \

 Serial.print(#b " = ");         \

 Serial.println(b)

#else

#define D_PROC_L3(a, b) //blank line

#endif


//================================================================================

//================================================================================

//  Keyboard


//#define _ID_KEYBOARD 0x01

//

//static const uint8_t _hidReportDescriptor[] PROGMEM = {

//

//  //  Keyboard

//  0x05, 0x01, // USAGE_PAGE (Generic Desktop)  // 47

//  0x09, 0x06, // USAGE (Keyboard)

//  0xa1, 0x01, // COLLECTION (Application)

//  0x85, _ID_KEYBOARD, //   REPORT_ID (1)

//  0x05, 0x07, //   USAGE_PAGE (Keyboard)

//

//  0x19, 0xe0, //   USAGE_MINIMUM (Keyboard LeftControl)

//  0x29, 0xe7, //   USAGE_MAXIMUM (Keyboard Right GUI)

//  0x15, 0x00, //   LOGICAL_MINIMUM (0)

//  0x25, 0x01, //   LOGICAL_MAXIMUM (1)

//  0x95, 0x08, //   REPORT_COUNT (8)

//  0x75, 0x01, //   REPORT_SIZE (1)

//  0x81, 0x02, //   INPUT (Data,Var,Abs)

//

//  0x95, 0x01, //   REPORT_COUNT (1)

//  0x75, 0x08, //   REPORT_SIZE (8)

//  0x81, 0x03, //   INPUT (Cnst,Var,Abs)

//

//  0x95, 0x06, //   REPORT_COUNT (6)

//  0x75, 0x08, //   REPORT_SIZE (8)

//  0x15, 0x00, //   LOGICAL_MINIMUM (0)

//  0x25, 0x65, //   LOGICAL_MAXIMUM (101)

//

//  0x05, 0x07, //   USAGE_PAGE (Keyboard)

//  0x19, 0x00, //   USAGE_MINIMUM (Reserved (no event indicated))

//  0x29, 0x73, //   USAGE_MAXIMUM (Keyboard Application)

//  0x81, 0x00, //   INPUT (Data,Array)

//  0xc0,       // END_COLLECTION

//};


Keyboard_::Keyboard_(void)

{

 this->_tempo = 5;

 this->_NB_decimale = (_nbdecimale);

 this->_Notation_decimale = '\0'; // point du pavé numérique par défaut

 this->_prefix[0] = '\0';

 this->OS = None;

}


void Keyboard_::begin(Adafruit_USBD_HID &usb, uint8_t ID_KEYBOARD)

{

 _tinyUSB = &usb;

 _ID_KEYBOARD = ID_KEYBOARD;

}


void Keyboard_::end(void)

{

}


size_t Keyboard_::setOS(_OS myOS /* myOS=None */)

{

 this->OS = myOS;

 return this->OS;

}


void Keyboard_::sendReport(KeyReport *keys)

{

 //HID().SendReport(_ID_KEYBOARD, keys, sizeof(KeyReport));

 this->_tinyUSB->keyboardReport(this->_ID_KEYBOARD, keys->modifiers, keys->keys);

 delay(this->_tempo);

}


#define _SHIFT (uint8_t)(0x80) // SHIFT

#define _ALT (uint8_t)(0x40) // ALTGR


// Déclaration des Scancodes pour les Dead Key FR

#define _CIRCUMFLEX_ACCENT (uint8_t)(0x2F)      // ^   0x2F   47

#define _DIAERESIS (uint8_t)(0x2F | _SHIFT)     // ¨   0xAF  175

#define _GRAVE_ACCENT (uint8_t)(0x24 | _ALT)    // `   0x64  100

#define _TILDE (uint8_t)(0x1F | _ALT)           // ~   0x5F   95


// La valeur FirstDoubleOctet changera suivant le layout afin d'optimiser l'espace occupé dans la mémore flash

#define FirstDoubleOctet (uint8_t)(192)


// Declaration du tableau des Scancodes Dead Key FR

const uint8_t _deadkey[] = {_CIRCUMFLEX_ACCENT, _DIAERESIS, _GRAVE_ACCENT, _TILDE};


const uint8_t _asciimapEx[] PROGMEM =

{

 //        0x00,                // NUL  Reserved do not change

 //        0x00,                // SOH

 //        0x00,                // STX

 //        0x00,                // ETX

 //        0x00,                // EOT

 //        0x00,                // ENQ

 //        0x00,                // ACK

 //        0x00,                // BEL

 //        0x2A,                // BS   Backspace   8

 //        0x2B,                // TAB  Tab         9

 //        0x28,                // LF   Line Feed  10

 //        0x00,                // VT

 //        0x00,                // FF

 //        0x28,                // CR   Enter      13

 //        0x00,                // SO

 //        0x00,                // SI

 //        0x00,                // DEL

 //        0x00,                // DC1

 //        0x00,                // DC2

 //        0x00,                // DC3

 //        0x00,                // DC4     20

 //        0x00,                // NAK

 //        0x00,                // SYN

 //        0x00,                // ETB

 //        0x00,                // CAN

 //        0x00,                // EM

 //        0x00,                // SUB

 //        0x00,                // ESC

 //        0x00,                // FS

 //        0x00,                // GS

 //        0x00,                // RS     30

 //        0x00,                // US

 0x2C,      // ' '   Espace   32

 0x38,      // !

 0x20,      // "

 0x20 | _ALT, // #

 0x30,      // $

 0x34 | _SHIFT, // %

 0x1E,      // &

 0x21,      // '


 //40 (0x28)

 0x22,      // (

 0x2D,      // )

 0x32,      // *

 0x2E | _SHIFT, // +

 0x10,      // ,

 0x23,      // -

 0x36 | _SHIFT, // .

 0x37 | _SHIFT, // /

 0x27 | _SHIFT, // 0

 0x1E | _SHIFT, // 1


 // 50 (0x32)

 0x1F | _SHIFT, // 2

 0x20 | _SHIFT, // 3

 0x21 | _SHIFT, // 4

 0x22 | _SHIFT, // 5

 0x23 | _SHIFT, // 6

 0x24 | _SHIFT, // 7

 0x25 | _SHIFT, // 8

 0x26 | _SHIFT, // 9

 0x37,      // :

 0x36,      // ;


 // 60 (0x3C)

 0x03,      // <         // la valeur devrait être 0x64, la fonction pressEx_ procède à la modification

 0x2E,      // =

 0x03 | _SHIFT, // >         // la valeur devrait être 0x64|Shift, la fonction pressEx_ procède à la modification

 0x10 | _SHIFT, // ?

 0x27 | _ALT, // @

 0x14 | _SHIFT, // A

 0x05 | _SHIFT, // B

 0x06 | _SHIFT, // C

 0x07 | _SHIFT, // D

 0x08 | _SHIFT, // E


 // 70 (0x46)

 0x09 | _SHIFT, // F

 0x0A | _SHIFT, // G

 0x0B | _SHIFT, // H

 0x0C | _SHIFT, // I

 0x0D | _SHIFT, // J

 0x0E | _SHIFT, // K

 0x0F | _SHIFT, // L

 0x33 | _SHIFT, // M

 0x11 | _SHIFT, // N

 0x12 | _SHIFT, // O


 // 80 (0x50)

 0x13 | _SHIFT, // P

 0x04 | _SHIFT, // Q

 0x15 | _SHIFT, // R

 0x16 | _SHIFT, // S

 0x17 | _SHIFT, // T

 0x18 | _SHIFT, // U

 0x19 | _SHIFT, // V

 0x1D | _SHIFT, // W

 0x1B | _SHIFT, // X

 0x1C | _SHIFT, // Y


 // 90 (0x5A)

 0x1A | _SHIFT,          // Z

 0x22 | _ALT,          // [

 0x25 | _ALT,          // antislash

 0x2D | _ALT,          // ]

 _CIRCUMFLEX_ACCENT, // ^

 0x25,               // _

 _GRAVE_ACCENT,      // `

 0x14,               // a

 0x05,               // b

 0x06,               // c


 // 100

 0x07, // d

 0x08, // e

 0x09, // f

 0x0A, // g

 0x0B, // h

 0x0C, // i

 0x0D, // j

 0x0E, // k

 0x0F, // l

 0x33, // m


 // 110

 0x11, // n

 0x12, // o

 0x13, // p

 0x04, // q

 0x15, // r

 0x16, // s

 0x17, // t

 0x18, // u

 0x19, // v

 0x1D, // w


 // 120

 0x1B,      // x

 0x1C,      // y

 0x1A,      // z

 0x21 | _ALT, // {

 0x23 | _ALT, // |

 0x2E | _ALT, // }

 _TILDE,    // ~

 0xFF,      // DEL  127    Pas de caractère

 0x08 | _ALT, //  0x80       €€

 0xFF,      //  0x81       Pas de caractère (HOP)


 // 130

 0x00, //  0x82       ‚

 0x00, //  0x83       ƒ

 0x00, //  0x84       „

 0x00, //  0x85       …

 0x00, //  0x86       †

 0x00, //  0x87       ‡

 0x00, //  0x88       ˆ

 0x00, //  0x89       ‰

 0x00, //  0x8A       Š

 0x00, //  0x8B       ‹


 // 140

 0x00, //  0x8C       Œ

 0xFF, //  0x8D       Pas de caractère   

 0x00, //  0x8E       Ž Ž

 0xFF, //  0x8F       Pas de caractère

 0xFF, //  0x90       Pas de caractère      

 0x00, //  0x91       ‘

 0x00, //  0x92       ’

 0x00, //  0x93       “

 0x00, //  0x94       ”

 0x00, //  0x95       •


 // 150

 0x00, //  0x96       —

 0x00, //  0x97       —

 0x00, //  0x98       ˜

 0x00, //  0x99       ™

 0x00, //  0x9A       š

 0x00, //  0x9B       ›

 0x00, //  0x9C       œ

 0xFF, //  0x9D       Pas de caractère 

 0x00, //  0x9E       ž

 0x00, //  0x9F       Ÿ


 // 160

 0x00,       //  0xA0       Espace insécable

 0x00,       //  0xA1       ¡

 0x00,       //  0xA2       ¢

 0x30 | _SHIFT,  //  0xA3       £

 0x30 | _ALT,  //  0xA4       ¤

 0x00,       //  0xA5       ¥

 0x00,       //  0xA6       ¦

 0x38 | _SHIFT,  //  0xA7       §

 _DIAERESIS, //  0xA8       ¨

 0x00,       //  0xA9       ©


 // 170

 0x00,      //  0xAA       ª

 0x00,      //  0xAB       «

 0x00,      //  0xAC       ¬

 0x00,      //  0xAD       ­

 0x00,      //  0xAE       ®

 0x00,      //  0xAF       ¯

 0x2D | _SHIFT, //  0xB0       °

 0x00,      //  0xB1       ±

 0x35,      //  0xB2       ²

 0x00,      //  0xB3       ³


 // 180

 0x00,      //  0xB4       ´

 0x32 | _SHIFT, //  0xB5       µ

 0x00,      //  0xB6       ¶

 0x00,      //  0xB7       ·

 0x00,      //  0xB8       ¸

 0x00,      //  0xB9       ¹

 0x00,      //  0xBA       º

 0x00,      //  0xBB       »

 0x00,      //  0xBC       ¼

 0x00,      //  0xBD       ½


 // 190

 0x00, //  0xBE       ¾

 0x00, //  0xBF       ¿


 // Double Byte begin at 192

 _GRAVE_ACCENT, (0x14 | _SHIFT),      //  0xC0       À

 0x00, 0x00,                      //  0xC1       Á

 _CIRCUMFLEX_ACCENT, (0x14 | _SHIFT), //  0xC2       Â

 _TILDE, (0x14 | _SHIFT),             //  0xC3       Ã

 _DIAERESIS, (0x14 | _SHIFT),         //  0xC4       Ä

 0x00, 0x00,                      //  0xC5       Å

 0x00, 0x00,                      //  0xC6       Æ

 0x00, 0x00,                      //  0xC7       Ç


 //200

 _GRAVE_ACCENT, (0x08 | _SHIFT),      //  0xC8       È

 0x00, 0x00,                      //  0xC9       É

 _CIRCUMFLEX_ACCENT, (0x08 | _SHIFT), //  0xCA       Ê

 _DIAERESIS, (0x08 | _SHIFT),         //  0xCB       Ë

 _GRAVE_ACCENT, (0x0C | _SHIFT),      //  0xCC       Ì

 0x00, 0x00,                      //  0xCD       Í

 _CIRCUMFLEX_ACCENT, (0x0C | _SHIFT), //  0xCE       Î

 _DIAERESIS, (0x0C | _SHIFT),         //  0xCF       Ï

 0x00, 0x00,                      //  0xD0       Ð

 _TILDE, (0x11 | _SHIFT),             //  0xD1       Ñ


 // 210

 _GRAVE_ACCENT, (0x12 | _SHIFT),      //  0xD2       Ò

 0x00, 0x00,                      //  0xD3       Ó

 _CIRCUMFLEX_ACCENT, (0x12 | _SHIFT), //  0xD4       Ô

 _TILDE, (0x12 | _SHIFT),             //  0xD5       Õ

 _DIAERESIS, (0x12 | _SHIFT),         //  0xD6       Ö

 0x00, 0x00,                      //  0xD7       ×

 0x00, 0x00,                      //  0xD8       Ø

 _GRAVE_ACCENT, (0x18 | _SHIFT),      //  0xD9       Ù

 0x00, 0x00,                      //  0xDA       Ú

 _CIRCUMFLEX_ACCENT, (0x18 | _SHIFT), //  0xDB       Û


 // 220

 _DIAERESIS, (0x18 | _SHIFT),  //  0xDC       Ü

 0x00, 0x00,               //  0xDD       Ý

 0x00, 0x00,               //  0xDE       Þ

 0x00, 0x00,               //  0xDF       ß

 0x27, 0x00,               //  0xE0       à

 0x00, 0x00,               //  0xE1       á

 _CIRCUMFLEX_ACCENT, 0x14, //  0xE2       â

 _TILDE, 0x14,             //  0xE3       ã

 _DIAERESIS, 0x14,         //  0xE4       ä

 0x00, 0x00,               //  0xE5       å


 // 230

 0x00, 0x00,               //  0xE6       æ

 0x26, 0x00,               //  0xE7       ç

 0x24, 0x00,               //  0xE8       è

 0x1F, 0x00,               //  0xE9       é

 _CIRCUMFLEX_ACCENT, 0x08, //  0xEA       ê

 _DIAERESIS, 0x08,         //  0xEB       ë

 _GRAVE_ACCENT, 0x0C,      //  0xEC       ì

 0x00, 0x00,               //  0xED       í

 _CIRCUMFLEX_ACCENT, 0x0C, //  0xEE       î

 _DIAERESIS, 0x0C,         //  0xEF       ï


 // 240

 0x00, 0x00,               //  0xF0       ð

 _TILDE, 0x11,             //  0xF1       ñ

 _GRAVE_ACCENT, 0x12,      //  0xF2       ò

 0x00, 0x00,               //  0xF3       ó

 _CIRCUMFLEX_ACCENT, 0x12, //  0xF4       ô

 _TILDE, 0x12,             //  0xF5       õ

 _DIAERESIS, 0x12,         //  0xF6       ö

 0x00, 0x00,               //  0xF7       ÷

 0x00, 0x00,               //  0xF8       ø

 0x34, 0x00,               //  0xF9       ù


 // 250

 0x00, 0x00,               //  0xFA       ú

 _CIRCUMFLEX_ACCENT, 0x18, //  0xFB       û

 _DIAERESIS, 0x18,         //  0xFC       ü

 0x00, 0x00,               //  0xFD       ý

 0x00, 0x00,               //  0xFE       þ

 _DIAERESIS, 0x1C,         //  0xFF       ÿ

};


//uint8_t USBPutChar(uint8_t c);



/*

  pressEx_(...)

  option = 0 -> pour les appels ou l'argument est une touche (par défaut, appel venant de print...)

  option = _Keycode (1) -> pour les appels ou l'argument est un keycode (Raw Keycode)

*/

uint8_t Keyboard_::pressEx_(uint8_t k, const uint8_t option /*option=0*/)

{

 D_PROC_("pressEx_()");

 uint8_t i;


 if (!k)

 {

   return 0;

 }


 if (!option)

 {

   D_PROC_L3("pressEx_( , print)", option);

   if (k & 0x80)

   {

     _keyReport.modifiers |= 0x02; // the left shift modifier

     k &= 0x7F;

   }

   if (k & 0x40)

   {

     _keyReport.modifiers |= 0x40; // the right AltGr modifier

     k &= 0x3F;

   }

   if (k == 0x03)

   { // special case 0x64

     k = 0x64;

   }

 }

 else

 {

   D_PROC_L3("pressEx_( , keycode)", option);

   if ((k > 0xDF) && (k < 0xE8))

   {

     _keyReport.modifiers |= (1 << (k - 0xE0));

     k = 0;

   }

 }


 if (k)

 {

   if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&

       _keyReport.keys[2] != k && _keyReport.keys[3] != k &&

       _keyReport.keys[4] != k && _keyReport.keys[5] != k)

   {


     for (i = 0; i < 6; i++)

     {

       if (_keyReport.keys[i] == 0x00)

       {

         _keyReport.keys[i] = k;

         break;

       }

     }

     if (i == 6)

     {

       return 0;

     }

   }

 }

 D_PROC_L3("pressEx_()", _keyReport.modifiers);

 D_PROC_L3("pressEx_()", _keyReport.keys[0]);

 D_PROC_L3("pressEx_()", _keyReport.keys[1]);

 D_PROC_L3("pressEx_()", _keyReport.keys[2]);

 D_PROC_L3("pressEx_()", _keyReport.keys[3]);

 D_PROC_L3("pressEx_()", _keyReport.keys[4]);

 D_PROC_L3("pressEx_()", _keyReport.keys[5]);

 sendReport(&_keyReport);

 return 1;

}


/*

  releaseEx_(...)

  option = 0 -> pour les appels ou l'argument est une touche (par défaut, appel venant de print...)

  option = _Keycode (1) -> pour les appels ou l'argument est un keycode (Voir l'énumération))

*/

uint8_t Keyboard_::releaseEx_(uint8_t k, const uint8_t option /*option=0*/)

{

 D_PROC_("releaseEx_()");

 uint8_t i;


 if (!k)

 {

   return 0;

 }


 if (!option)

 {

   D_PROC_L3("releaseEx_( , print)", option);

   if (k & 0x80)

   {

     _keyReport.modifiers &= ~(0x02); // the left shift modifier

     k &= 0x7F;

   }

   if (k & 0x40)

   {

     _keyReport.modifiers &= ~(0x40); // the right AltGr modifier

     k &= 0x3F;

   }

   if (k == 0x03)

   { // special case 0x64

     k = 0x64;

   }

 }

 else

 {

   D_PROC_L3("releaseEx_( , keycode)", option);

   if ((k > 0xDF) && (k < 0xE8))

   {

     _keyReport.modifiers &= ~(1 << (k - 0xE0));

     k = 0;

   }

 }


 if (k)

 {

   for (i = 0; i < 6; i++)

   {

     if (0 != k && _keyReport.keys[i] == k)

     {

       _keyReport.keys[i] = 0x00;

       break;

     }

   }


   if (i == 6)

   {

     return 0;

   }

 }

 D_PROC_L3("releaseEx_()", _keyReport.modifiers);

 D_PROC_L3("releaseEx_()", _keyReport.keys[0]);

 D_PROC_L3("releaseEx_()", _keyReport.keys[1]);

 D_PROC_L3("releaseEx_()", _keyReport.keys[2]);

 D_PROC_L3("releaseEx_()", _keyReport.keys[3]);

 D_PROC_L3("releaseEx_()", _keyReport.keys[4]);

 D_PROC_L3("releaseEx_()", _keyReport.keys[5]);

 sendReport(&_keyReport);

 return 1;

}


void Keyboard_::releaseAll(void)

{

 D_PROC_("releaseAll()");

 _keyReport.keys[0] = 0;

 _keyReport.keys[1] = 0;

 _keyReport.keys[2] = 0;

 _keyReport.keys[3] = 0;

 _keyReport.keys[4] = 0;

 _keyReport.keys[5] = 0;

 _keyReport.modifiers = 0;

 sendReport(&_keyReport);

 D_PROC_L3("releaseAll()", 0);

}


/*

  setDelay(...)

  Ajuster la temporisation afin que tous les caractères s'affichent correctement suivant l'OS

*/

size_t Keyboard_::setDelay(const uint8_t &tempo)

{ // Valeur du delay de 0 à 100

 D_PROC_("setDelay()");

 if (tempo < 5)

   this->_tempo = 5;

 if (tempo > 100)

   this->_tempo = 100;

 this->_tempo = tempo;


 D_PROC_R("setDelay()", this->_tempo);

 return this->_tempo;

}


/*

  Récupérer les infos sur le caractère suite à l'appel de la fonction setAlign(...)

*/

const char *Keyboard_::getCharacter(void)

{

 D_PROC_("getCharacter()");

 // méthode plus rapide et économique que memcpy

 uint8_t i = sizeof(this->_infoUtf8.utf8);

 while (i--)

 {

   *(this->_infoUtf8.copieUtf8 + i) = *(this->_infoUtf8.utf8 + i);

 }

 D_PROC_R("getCharacter()", this->_infoUtf8.copieUtf8);

 return this->_infoUtf8.copieUtf8;

}


/*

  Récupérer les infos sur le caractère suite à l'appel de la fonction setAlign(...)

*/

size_t Keyboard_::isLayout()

{

 D_PROC_("isLayout()");

 D_PROC_R("isLayout()", this->_infoUtf8.isLayout);

 return this->_infoUtf8.isLayout; // Le clavier peut t'il l'afficher, valeur 0 ou 1

}


/*

  Récupérer les infos sur le caractère suite à l'appel de la fonction setAlign(...)

*/

size_t Keyboard_::isSimpleKey()

{

 D_PROC_("isSimpleKey()");

 if (this->_infoUtf8.isDeadKey > 1) // key1 est un dead key, valeur 0 si faux, 1 (dead key simple) ou 2 (dead key composé)

 {

   D_PROC_R("isSimpleKey(", 0);

   return 0;

 }

 D_PROC_R("isSimpleKey()", 1);

 return 1;

}


/*

  Récupérer les infos sur le caractère suite à l'appel de la fonction setAlign(...)

*/

size_t Keyboard_::isComposeKey()

{

 D_PROC_("isComposeKey()");

 if (this->_infoUtf8.isDeadKey > 1) // key1 est un dead key, valeur 0 si faux, 1 (dead key simple) ou 2 (dead key composé)

 {

   D_PROC_R("isComposeKey()", 1);

   return 1;

 }

 D_PROC_R("isComposeKey()", 0);

 return 0;

}


/*

  Récupérer les infos sur le caractère suite à l'appel de la fonction setAlign(...)

*/

size_t Keyboard_::isDeadKey()

{

 D_PROC_("isDeadKey()");

 D_PROC_R("isDeadKey()", this->_infoUtf8.isDeadKey);

 return this->_infoUtf8.isDeadKey; // key1 est un dead key, valeur 0 si faux, 1 si dead key seul ou 2 si dead key composé

}


/*

  Récupérer les infos sur le caractère suite à l'appel de la fonction setAlign(...)

*/

size_t Keyboard_::isAltCode()

{

 D_PROC_("isAltCode(");

 D_PROC_R("isAltCode()", this->_infoUtf8.isLayout);

 return (!(this->_infoUtf8.isLayout)); // Le clavier peut t'il l'afficher, valeur 0 ou 1

}


/*

  Récupérer les infos sur le caractère suite à l'appel de la fonction setAlign(...)

*/

size_t Keyboard_::nbByte()

{

 D_PROC_("nbByte(");

 D_PROC_R("nbByte()", this->_infoUtf8.nbByte);

 return this->_infoUtf8.nbByte; // Nombre d'octets composant le caractère UTF8, valeur de 1 à 4 octets

}


/*

  Récupérer les infos sur le caractère suite à l'appel de la fonction setAlign(...)

*/

size_t Keyboard_::isAsciiEx()

{

 D_PROC_("isAsciiEx()");

 D_PROC_R("isAsciiEx()", this->_infoUtf8.isAsciiEx);

 return this->_infoUtf8.isAsciiEx; // Valeur Ascii étendu du caractère UTF8 sur 8 Bit

}


/*

  Récupérer les infos sur le caractère suite à l'appel de la fonction setAlign(...)

*/

size_t Keyboard_::asciiEx()

{

 D_PROC_("asciiEx()");

 D_PROC_R("asciiEx()", this->_infoUtf8.isAsciiEx);

 return this->_infoUtf8.asciiEx; // Valeur Ascii étendu du caractère UTF8 sur 8 Bit

}


/*

  Récupérer les infos sur le caractère suite à l'appel de la fonction setAlign(...)

*/

size_t Keyboard_::scancode()

{

 D_PROC_("scancode()");

 D_PROC_R("scancode()", (this->_infoUtf8.key1 << 8) | this->_infoUtf8.key2);

 return ((this->_infoUtf8.key1 << 8) | this->_infoUtf8.key2); // Scancode du caractère sur 2 Byte

}


/*

 getKeyEx(...)

 keyEx_error = 0,        // si erreur

 keyEx_simpleKey = 1     // si touche simple ou dead key seul

 keyEx_composeKey = 2    // si touche composée

 keyEx_deadKey = 4       // si dead key

 keyEx_isLayout = 8      // si le clavier le gère

*/

size_t Keyboard_::getKeyEx(uint8_t asciiEx)

{

 D_PROC_("getKeyEx()");

 D_PROC_R("getKeyEx()", asciiEx);


 uint8_t key1 = 0, key2 = 0;


 if (asciiEx == 0x09)

 { // TAB

   return (keyEx_isLayout | keyEx_simpleKey);

 }

 else if (asciiEx == 0x0D)

 { // RETURN

   return (keyEx_isLayout | keyEx_simpleKey);

 }

 else if (asciiEx < 32)

 { //  le clavier ne le gère pas;

   return keyEx_error;

 }

 else

 {

   if (asciiEx < FirstDoubleOctet)

   { // 1 octet à traiter

     size_t indiceTableau = asciiEx - 32;

     key1 = pgm_read_byte(_asciimapEx + indiceTableau);

   }

   else

   { // 1 à 2 octets à traiter

     size_t indiceTableau = (((asciiEx - FirstDoubleOctet) * 2) + (FirstDoubleOctet - 32));

     key1 = pgm_read_byte(_asciimapEx + indiceTableau);

     if (key1 != 0 || key1 != 0xFF)

     {

       key2 = pgm_read_byte(_asciimapEx + indiceTableau + 1);

     }

   }


   if (key1 == 0)

   { // Le caractère existe mais le clavier ne le gère pas

     return keyEx_simpleKey;

   }

   if (key1 == 0xFF)

   {

     return keyEx_error; //  Le caractère n'existe pas;

   }


   if (key1 && !key2)

   {

     if (isDeadKey_(key1))

     {

       return (keyEx_isLayout | keyEx_simpleKey | keyEx_deadKey);

     }

     else

     {

       return (keyEx_isLayout | keyEx_simpleKey);

     }

   }

   else

   {

     return (keyEx_isLayout | keyEx_composeKey | keyEx_deadKey);

   }

 }

}


/*

  Test afin de détecter si la touche est un dead key

  Pour afficher un dead key seul, il faut ajouter l'appui sur la touche Espace.

*/

uint8_t Keyboard_::isDeadKey_(const uint8_t k)

{

 D_PROC_("isDeadKey_()");

 uint8_t ret = 0;

 for (uint8_t i = 0; i < sizeof(_deadkey); ++i)

 {

   if (_deadkey[i] == k)

   {

     ret = 1;

     break;

   }

 }

 D_PROC_R("isDeadKey_()", ret);

 return ret;

}


/*

  Converti un caractère UTF8 en caractère ASCII étendu (codage CP1252)

*/

uint8_t Keyboard_::convertUtf8ToAscii_(const uint8_t &NBoctets, const uint8_t *pointer)

{

 D_PROC_("convertUtf8ToAscii_()");

 uint8_t asciiEx = 0;


 switch (NBoctets)

 {

   case 0x01:

     asciiEx = *(pointer); // Ascii 32 to 127

     break;


   case 0x02:

     if (*(pointer) == 0xC2)

     {

       asciiEx = *(pointer + 1);

       break;

     }

     else if (*(pointer) == 0xC3)

     {

       asciiEx = (*(pointer + 1) | 0xC0);

       break;

     }

     else if (*(pointer) == 0xC5)

     {

       switch (*(pointer + 1))

       {

         case 0xA0:

           asciiEx = 0x8A; // Š

           break;

         case 0x92:

           asciiEx = 0x8C; // Œ

           break;

         case 0xBD:

           asciiEx = 0x8E; // Ž

           break;

         case 0xA1:

           asciiEx = 0x9A; // š

           break;

         case 0x93:

           asciiEx = 0x9C; // œ

           break;

         case 0xBE:

           asciiEx = 0x9E; // ž

           break;

         case 0xB8:

           asciiEx = 0x9F; // Ÿ

           break;

         default:

           break;

       }

       break;

     }

     else if (*(pointer) == 0xC6 && *(pointer + 1) == 0x92)

     {

       asciiEx = 0x83; // ƒ

       break;

     }

     else if (*(pointer) == 0xCB && *(pointer + 1) == 0x86)

     {

       asciiEx = 0x88; // ˆ

       break;

     }

     else if (*(pointer) == 0xCB && *(pointer + 1) == 0x9C)

     {

       asciiEx = 0x98; // ~

       break;

     }


   case 0x03:

     if (*(pointer) == 0xE2 && *(pointer + 1) == 0x82 && *(pointer + 2) == 0xAC)

     { // traitement du signe €

       asciiEx = 0x80;

       break;

     }

     else if (*(pointer) == 0xE2 && *(pointer + 1) == 0x84 && *(pointer + 2) == 0xA2)

     { // traitement du signe ™

       asciiEx = 0x99;

       break;

     }

     else if (*(pointer) == 0xE2 && *(pointer + 1) == 0x80)

     {

       switch (*(pointer + 2))

       {

         case 0x93:

           asciiEx = 0x96; // –

           break;

         case 0x94:

           asciiEx = 0x97; // —

           break;

         case 0x98:

           asciiEx = 0x91; // ‘

           break;

         case 0x99:

           asciiEx = 0x92; // ’

           break;

         case 0x9A:

           asciiEx = 0x82; // ‚

           break;

         case 0x9C:

           asciiEx = 0x93; // “

           break;

         case 0x9D:

           asciiEx = 0x94; // ”

           break;

         case 0x9E:

           asciiEx = 0x84; // „

           break;

         case 0xA0:

           asciiEx = 0x86; // †

           break;

         case 0xA1:

           asciiEx = 0x87; // ‡

           break;

         case 0xA2:

           asciiEx = 0x95; // •

           break;

         case 0xA6:

           asciiEx = 0x85; // …

           break;

         case 0xB0:

           asciiEx = 0x89; // ‰

           break;

         case 0xB9:

           asciiEx = 0x8B; // ‹

           break;

         case 0xBA:

           asciiEx = 0x9B; // ›

           break;

         default:

           break;

       }

     }

 }

 D_PROC_R("convertUtf8ToAscii_()", asciiEx);

 return (asciiEx);

}


/*

  Converti un caractère UTF8 en caractère UNICODE

*/

uint32_t Keyboard_::UTF8_to_CodePoint_(const uint8_t *buffer, const size_t &size)

{

 D_PROC_("UTF8_to_CodePoint_()");

 uint32_t unicode = 0;

 uint8_t octet1, octet2, octet3, octet4;


 octet1 = *buffer & 0xFF;


 if (!octet1 || !size)

   return 0;


 if (octet1 < 0x80)

 { // résultat sur 1 octet

   unicode = octet1;

   //align = 1;

 }

 else if ((octet1 > 0xBF) && (octet1 < 0xE0))

 { // résultat sur 2 octets

   if (!(size > 1))

   {

     return 0;

   }

   octet2 = *(buffer + 1) & 0xFF;

   if ((octet2 & B11000000) != B10000000)

     return 0;

   unicode = (octet1 & B00011111);

   unicode = (unicode << 6);

   unicode = unicode | (octet2 & B00111111);

   //align = 2;

 }

 else if ((octet1 > 0xDF) && (octet1 < 0xF0))

 { // résultat sur 3 octets

   if (!(size > 2))

   {

     return 0;

   }

   octet2 = *(buffer + 1) & 0xFF;

   octet3 = *(buffer + 2) & 0xFF;

   if ((octet2 & B11000000) != B10000000)

     return 0;

   if ((octet3 & B11000000) != B10000000)

     return 0;

   unicode = (octet1 & B00001111);

   unicode = (unicode << 6);

   unicode = unicode | (octet2 & B00111111);

   unicode = (unicode << 6);

   unicode = unicode | (octet3 & B00111111);

   //align = 3;

 }

 else if ((octet1 > 0xEF) && (octet1 < 0xF8))

 { // résultat sur 4 octets

   if (!(size > 3))

   {

     return 0;

   }

   octet2 = *(buffer + 1) & 0xFF;

   octet3 = *(buffer + 2) & 0xFF;

   octet4 = *(buffer + 3) & 0xFF;

   if ((octet2 & B11000000) != B10000000)

     return 0;

   if ((octet3 & B11000000) != B10000000)

     return 0;

   if ((octet4 & B11000000) != B10000000)

     return 0;

   unicode = (octet1 & B00000111);

   unicode = (unicode << 6);

   unicode = unicode | (octet2 & B00111111);

   unicode = (unicode << 6);

   unicode = unicode | (octet3 & B00111111);

   unicode = (unicode << 6);

   unicode = unicode | (octet4 & B00111111);

   //align = 4;

 }


 //i = i + align - 1;

 D_PROC_R("UTF8_to_CodePoint_()", unicode);

 return unicode;

}


/*

  flashMemoryUTF8_(...)

  option = _For_Print (32) (par défaut) avec releaseAll

  option = _For_AltCode (64)

  option = _Return (4) ajout de la touche return

*/

size_t Keyboard_::flashMemoryUTF8_(const __FlashStringHelper *ifsh, const uint8_t option /* option = _For_Print */)

{

 D_PROC_("flashMemoryUTF8_()");

 uint8_t k, align = 0, ret = 1;

 size_t NbCharacter = 0, i = 0;


 // laisser uint8_t et non char

 uint8_t utf8[5] = {

   0,

 };

 PGM_P p = reinterpret_cast<PGM_P>(ifsh);

 while (1)

 {

   utf8[0] = 0;

   utf8[1] = 0;

   utf8[2] = 0;

   utf8[3] = 0;

   utf8[0] = pgm_read_byte(p + i);

   if (!utf8[0])

   {

     break;

   }

   if ((utf8[0] & 0x80) == 0)

   { // 1 octet

     align = 1;

   }

   else if ((utf8[0] & 0xE0) == 0xC0)

   { // 2 octets

     align = 2;

   }

   else if ((utf8[0] & 0xF0) == 0xE0)

   { // 3 octets

     align = 3;

   }

   else if ((utf8[0] & 0xF8) == 0xF0)

   { // 4 octets

     align = 4;

   }

   else

   {

     ret = 0;

     break;

   }

   for (k = 1; k < align; ++k)

   {

     utf8[k] = pgm_read_byte(p + i + k);

     if (!utf8[k])

     {

       ret = 0;

       break;

     }

   }

   if (option & _For_AltCode)

   {

     if (this->OS == Windows) {

       if (!altcodeBuffer_(utf8, strlen((char *)utf8)))

       {

         ret = 0;

         break;

       }

     } else {

       ret = 0;

       break;

     }

   }

   else if (option & _For_Print)

   {

     if (!printBuffer_(utf8, strlen((char *)utf8)))

     {

       ret = 0;

       break;

     }

   }

   i += align;

   NbCharacter += 1;

 }

 if (option & _Return)

 {

   ret &= pressEx_(TINY_KEY_RETURN);

   releaseAll();

 }


 D_PROC_R("flashMemoryUTF8_()", NbCharacter);

 if (ret)

 {

   return NbCharacter;

 }

 return 0;

}


/*

  Permet de traiter les caractères un par un avec l'encodage UTF8

  et de copier toutes les infos dans la variable infoUtf8

*/

size_t Keyboard_::setAlign_(const uint8_t *buffer, size_t &i)

{

 D_PROC_("setAlign_()");

 uint8_t key1, key2, key3, key4, align = 0;

 uint16_t indiceTableau;


 key1 = 0, key2 = 0, key3 = 0, key4 = 0;

 key1 = *(buffer + i);


 D_PROC_R("setAlign_()", *(buffer + i));


 this->_infoUtf8.isAsciiEx = 0;

 this->_infoUtf8.nbByte = 0;

 this->_infoUtf8.asciiEx = 0;

 this->_infoUtf8.isLayout = 0;

 this->_infoUtf8.isDeadKey = 0;

 this->_infoUtf8.key1 = 0;

 this->_infoUtf8.key2 = 0;

 memset(this->_infoUtf8.utf8, 0, sizeof(this->_infoUtf8.utf8));


 if (key1 != 0)

 {


   if ((key1 & 0x80) == 0)

   { // 1 octet

     align = 1;

   }

   else if ((key1 & 0xE0) == 0xC0)

   { // 2 octets

     key2 = *(buffer + i + 1);

     if (key2 != 0)

     {

       align = 2;

     }

   }

   else if ((key1 & 0xF0) == 0xE0)

   { // 3 octets

     key2 = *(buffer + i + 1);

     key3 = *(buffer + i + 2);

     if (key2 != 0 && key3 != 0)

     {

       align = 3;

     }

   }

   else if ((key1 & 0xF8) == 0xF0)

   { // 4 octets

     key2 = *(buffer + i + 1);

     key3 = *(buffer + i + 2);

     key4 = *(buffer + i + 3);

     if (key2 != 0 && key3 != 0 && key4 != 0)

     {

       align = 4;

     }

   }

 }


 if (align)

 {

   //D_PROC_R("setAlign_()", align);

   //D_PROC_R("setAlign_()", i);

   //D_PROC_R("setAlign_()", *(buffer + i));


   strncpy(this->_infoUtf8.utf8, (char *)(buffer + i), align);

   this->_infoUtf8.nbByte = align;

   this->_infoUtf8.asciiEx = convertUtf8ToAscii_(align, (buffer + i));


   key4 = 1;

   if (this->_infoUtf8.asciiEx)

   {

     this->_infoUtf8.isAsciiEx = 1;

     if (this->_infoUtf8.asciiEx == 0x09)

     {

       key1 = TINY_KEY_TAB, key2 = 0;

     }

     else if (this->_infoUtf8.asciiEx == 0x0D)

     {

       key1 = TINY_KEY_RETURN, key2 = 0;

     }

     else if (this->_infoUtf8.asciiEx == 0x0A)

     {

       key1 = TINY_KEY_RETURN, key2 = 0;

     }

     else if (this->_infoUtf8.asciiEx > 31)

     {

       if (this->_infoUtf8.asciiEx < FirstDoubleOctet)

       { // 1 octet à traiter

         indiceTableau = this->_infoUtf8.asciiEx - 32;

         key1 = pgm_read_byte(_asciimapEx + indiceTableau);

         key2 = 0;

       }

       else

       { // 1 à 2 octets à traiter

         indiceTableau = (((this->_infoUtf8.asciiEx - FirstDoubleOctet) * 2) + (FirstDoubleOctet - 32));

         key1 = pgm_read_byte(_asciimapEx + indiceTableau);

         key2 = pgm_read_byte(_asciimapEx + indiceTableau + 1);

       }

     }

     else

     {

       key1 = 0, key2 = 0, key4 = 0;

     }


     if (key1 == 0xFF)

     { // La valeur ASCII ne correspond pas à un caractère

       key1 = 0, key2 = 0, key4 = 0;

     }


     if (key1 != 0)

     {

       this->_infoUtf8.isLayout = 1;

       this->_infoUtf8.key1 = key1;

       this->_infoUtf8.key2 = key2;

       if (isDeadKey_(key1))

       {

         if (key2 == 0)

         {

           this->_infoUtf8.isDeadKey = 1;

         }

         else

         {

           this->_infoUtf8.isDeadKey = 2;

         }

       }

     }

   }


   i += align - 1;

 }


 D_PROC_R("setAlign_()", this->_infoUtf8.utf8);

 D_PROC_R("setAlign_()", this->_infoUtf8.isLayout);

 D_PROC_R("setAlign_()", this->_infoUtf8.key1);

 D_PROC_R("setAlign_()", this->_infoUtf8.key2);

 D_PROC_R("setAlign_()", this->_infoUtf8.asciiEx);

 D_PROC_R("setAlign_()", key4);

 D_PROC_R("setAlign_()", align);


 if (align && key4)

 {

   return 1;

 }

 return 0;

}


size_t Keyboard_::setAlign(const char *str, size_t &i)

{

 return setAlign_((const uint8_t *)str, i);

}


size_t Keyboard_::setAlign(const String &s, size_t &i)

{

 return setAlign_((const uint8_t *)s.c_str(), i);

}


/*

  printScancode_(...)

  option = _Print (0) (par défaut) avec releaseAll

  option = _Press (1)

  option = _Release (2)

  option = _PressAndRelease (3) (press et release sans releaseAll)

  Pas d'option (ln), gérer dans la fonction printScancodeln directement

*/

uint8_t Keyboard_::printScancode_(const uint8_t &key1, const uint8_t &key2, const uint8_t option /*option = _Print*/)

{

 D_PROC_("printScancode_()");

 D_PROC_R("printScancode_()", key1);

 D_PROC_R("printScancode_()", key2);

 D_PROC_R("printScancode_()", option);


 uint8_t ret = 1;


 if (!key1)

 {

   return 0;

 }


 if (option & _Press)

 { // press

   ret &= pressEx_(key1);

   if (key2)

   {

     ret &= pressEx_(key2);

   }

 }

 if (option & _Release)

 { // release

   ret = releaseEx_(key1);

   if (key2)

   {

     ret &= releaseEx_(key2);

   }

 }

 if (!(option & _PressAndRelease))

 { // print

   ret &= pressEx_(key1);

   releaseAll();

   if (key2)

   {

     ret &= pressEx_(key2);

     releaseAll();

   }

   else

   {

     if (isDeadKey_(key1))

     {

       ret &= pressEx_(TINY_KEY_SPACE, _Keycode);

       releaseAll();

     }

   }

 }

 D_PROC_R("printScancode_()", ret);

 return ret;

}


/*

  printBuffer_(...)

  option = _Print (0) (par défaut) avec releaseAll

  option = _Press (1)

  option = _Release (2)

  option = _PressAndRelease (3) (press et release sans releaseAll)

  option = _Return (4) ajout de la touche return

*/

size_t Keyboard_::printBuffer_(const uint8_t *buffer, const size_t &size, const uint8_t option /*option = _Print*/)

{

 D_PROC_("printBuffer_()");

 uint8_t ret = 1;

 uint32_t unicode;

 size_t NbCharacter = 0;


 if (buffer == NULL || size == 0 || *buffer == 0)

 {

   return 0;

 }


 for (size_t i = 0; i < size; ++i)

 {

   if (!setAlign_(buffer, i))

   {

     ret = 0;

     break;

   }


   if (!(i < size))

   {

     ret = 0;

     break;

   }


   if (this->_infoUtf8.isLayout)

   {

     if (this->_infoUtf8.asciiEx == 0x0A)

     {

       continue;

     }

     ret &= printScancode_(this->_infoUtf8.key1, this->_infoUtf8.key2, option);

   }

   else

   {

     if (!(option & _PressAndRelease))

     { // La fonction altunicode ne doit fonctionner que pour print(ln)

       if (this->OS == Windows)

       {

         if (this->_infoUtf8.asciiEx)

         {

           ret &= altCP1252Win_(this->_infoUtf8.asciiEx);

           D_PROC_L2("printBuffer_()->ltCP1252Win", this->_infoUtf8.asciiEx);

         }

         else

         {

           unicode = UTF8_to_CodePoint_((const uint8_t *)this->_infoUtf8.utf8, strlen(this->_infoUtf8.utf8));

           ret &= altcodePointWin_(unicode);

           D_PROC_L2("printBuffer_()->UTF8_to_CodePoint", unicode);

         }

       }

       else

       {

         ret = 0;

       }

     }

     else

     {

       ret = 0;

     }

   }


   NbCharacter += 1;


   if (option & _PressAndRelease)

   { // Si press ou release

     //      if (key2) { // si key2 est différent de 0

     //        ret = 0; // on signale une erreur

     //      }

     D_PROC_("printBuffer_() ------ break");

     break; // important, sortir pour press ou release

   }

 }


 if (option == _Return)

 { // == et non & car fonctionne seulement en association avec print

   ret &= pressEx_(TINY_KEY_RETURN);

   releaseAll();

 }


 D_PROC_R("printBuffer_()", NbCharacter);


 if (ret)

 {

   return NbCharacter;

 }

 return 0;

}


/*

  printAsciiBufferEx_(...)

  option = _Print (0) (par défaut) avec releaseAll

  option = _Press (1)

  option = _Release (2)

  option = _PressAndRelease (3) (press et release sans releaseAll)

  option = _Return (4) ajout de la touche return

*/

size_t Keyboard_::printAsciiBufferEx_(const uint8_t *buffer, const size_t &size, const uint8_t option /* option = _Print */)

{

 D_PROC_("printAsciiBufferEx_()");

 size_t NbCharacter = 0, indiceTableau;

 uint8_t ret = 1, key1 = 0, key2 = 0, asciiEx;


 if (buffer == NULL || size == 0 || *buffer == 0)

 {

   return 0;

 }


 for (size_t i = 0; i < size; ++i)

 {

   asciiEx = *(buffer + i);


   if (asciiEx == 0x09)

   { // TAB

     ret &= printScancode_(TINY_KEY_TAB, 0, option);

   }

   else if (asciiEx == 0x0D)

   { // RETURN

     ret &= printScancode_(TINY_KEY_RETURN, 0, option);

   }

   else if (asciiEx == 0x0A)

   { // Line Feed

     continue;

   }

   else if (asciiEx > 31)

   {

     if (asciiEx < FirstDoubleOctet)

     { // 1 octet à traiter

       indiceTableau = asciiEx - 32;

       key1 = pgm_read_byte(_asciimapEx + indiceTableau);

       key2 = 0;

     }

     else

     { // 1 à 2 octets à traiter

       indiceTableau = (((asciiEx - FirstDoubleOctet) * 2) + (FirstDoubleOctet - 32));

       key1 = pgm_read_byte(_asciimapEx + indiceTableau);

       key2 = pgm_read_byte(_asciimapEx + indiceTableau + 1);

     }

     if (key1 == 0xFF)

     { // Le caractère n'existe pas

       ret = 0;

       break;

     }

     // Rajouter le test si window

     if (key1)

     { // Le clavier gère ce caractère

       ret &= printScancode_(key1, key2, option);

     }

     else

     { // Le clavier ne gère pas ce caractère

       if (!(option & _PressAndRelease))

       { // doit fonctionner seulement pour print(ln)

         if (this->OS == Windows)

         {

           ret &= altCP1252Win_(asciiEx);

         } else {

           ret = 0;

           break;

         }

       }

     }

   }

   else

   {

     ret = 0;

     break;

   }


   NbCharacter += 1;


   D_PROC_L3("[printAsciiBufferEx_]", NbCharacter);

   D_PROC_L3("[printAsciiBufferEx_]", asciiEx);

   D_PROC_L3("[printAsciiBufferEx_]", key1);

   D_PROC_L3("[printAsciiBufferEx_]", key2);


   if (option & _PressAndRelease)

   { // Si press ou release

     //      if (key2) { // si key2 est différent de 0

     //        ret = 0; // on signale une erreur

     //      }

     break; // important, sortir pour press ou release

   }

 }


 if (option == _Return)

 { // == et non & car fonctionne seulement en association avec print

   ret &= pressEx_(TINY_KEY_RETURN);

   releaseAll();

 }


 D_PROC_L1("printAsciiBufferEx_()", NbCharacter);


 if (ret)

 {

   return NbCharacter;

 }

 return 0;

}


/*

  altCP1252Win_(...)

  option = _No_Return (0)

  option = _Return (4) ajout de la touche return

*/

uint8_t Keyboard_::altCP1252Win_(const uint8_t &asciiEx, const uint8_t option /* option = _No_Return */)

{

 D_PROC_("altCP1252Win_()");

 uint8_t ret = 1, decal;

 char DecToAscii[5] = {'0', '0', '0', '0', '\0'};

 // u -> unsigned int

 sprintf(DecToAscii, "%u", asciiEx);

 decal = (sizeof(DecToAscii) - strlen(DecToAscii) - 1);

 DecToAscii[0] = '0', DecToAscii[1] = '0', DecToAscii[2] = '0';

 sprintf(DecToAscii + decal, "%u", asciiEx);


 if (asciiEx == 0x09)

 {

   ret &= pressEx_(TINY_KEY_TAB);

   releaseAll();

 }

 else if (asciiEx == 0x0D)

 {

   ret &= pressEx_(TINY_KEY_RETURN);

   releaseAll();

 }

 else if (asciiEx == 0x0A)

 {

   // nothing

 }

 else if (asciiEx < 32 || asciiEx == 127 || asciiEx == 129 || asciiEx == 141 || asciiEx == 143 || asciiEx == 144 || asciiEx == 157)

 {

   return 0;

 }

 else

 {

   //      ret &= pressEx_(TINY_KEY_LEFT_ALT, _Keycode);

   //      if (!(keypadBuffer_((const uint8_t *)DecToAscii, 4, 3))) {

   //        ret = 0;

   //      }

   //      ret &= releaseEx_(TINY_KEY_LEFT_ALT, _Keycode);

   // ou

   ret &= altcodeOptimize_(DecToAscii, strlen(DecToAscii));

 }


 if (option == _Return)

 {

   ret &= pressEx_(TINY_KEY_KEYPAD_ENTER, _Keycode);

   releaseAll();

 }


 D_PROC_L1("altCP1252Win_()", ret);

 return ret;

}


/*

  altcodePointWin_(...)

  option = _No_Return (0)

  option = _Return (4) ajout de la touche return

*/

uint8_t Keyboard_::altcodePointWin_(const uint32_t &unicode, const uint8_t option /* option = _No_Return */)

{

 D_PROC_("altcodePointWin_()");

 uint8_t ret = 1;

 char DecToAscii[7 + 1] = {

   '\0',

 };


 if (unicode > 0x10FFFF)

 { // -> 1114111

   return 0;

 }


 sprintf(DecToAscii, "%lu", unicode);

 ret &= pressEx_(TINY_KEY_ALT_LEFT, _Keycode);

 //  if (!keypadBuffer_((const uint8_t *)DecToAscii, strlen(DecToAscii), _PressAndRelease)) {

 //    ret = 0;

 //  }


 ret &= altcodeOptimize_(DecToAscii, strlen(DecToAscii));


 ret &= releaseEx_(TINY_KEY_ALT_LEFT, _Keycode);


 if (option == _Return)

 {

   ret &= pressEx_(TINY_KEY_KEYPAD_ENTER, _Keycode);

   releaseAll();

 }


 D_PROC_L1("altcodePointWin_()", ret);

 return ret;

}


/*

  altcodeBuffer_(...)

  option = _No_Return (0)

  option = _Return (4) ajout de la touche return

*/

size_t Keyboard_::altcodeBuffer_(const uint8_t *buffer, const size_t &size, const uint8_t option /* option = _No_Return */)

{

 D_PROC_("altcodeBuffer_()");

 size_t NbCharacter = 0;

 uint8_t ret = 1;

 uint32_t unicode;


 if (buffer == NULL || size == 0 || *buffer == 0)

 {

   return 0;

 }


 for (size_t i = 0; i < size; ++i)

 {

   if (!setAlign_(buffer, i))

   {

     ret = 0;

     break;

   }


   if (!(i < size))

   {

     ret = 0;

     break;

   }


   if (this->OS == Windows) {

     if (this->_infoUtf8.asciiEx) {

       ret &= altCP1252Win_(this->_infoUtf8.asciiEx);

     } else {

       unicode = UTF8_to_CodePoint_((const uint8_t *)this->_infoUtf8.utf8, strlen(this->_infoUtf8.utf8));

       D_PROC_L2("altcodeBuffer_()", unicode);

       ret &= altcodePointWin_(unicode);

     }

   } else {

     ret = 0;

     break;

   }


   NbCharacter += 1;

   D_PROC_L2("altcodeBuffer_()", NbCharacter);

 }


 if (option == _Return)

 { // == et non & car fonctionne seulement en association avec print

   ret &= pressEx_(TINY_KEY_KEYPAD_ENTER, _Keycode);

   releaseAll();

 }


 D_PROC_L1("altcodeBuffer_()", NbCharacter);


 if (ret)

 {

   return NbCharacter;

 }

 return 0;

}


/*

  altcodeBufferEx_(...)

  option = _No_Return (0)

  option = _Return (4) ajout de la touche return

*/

size_t Keyboard_::altcodeBufferEx_(const uint8_t *buffer, const size_t &size, const uint8_t option /* option = _No_Return */)

{

 D_PROC_("altcodeBufferEx_()");

 size_t NbCharacter = 0;

 uint8_t ret = 1;


 if (buffer == NULL || size == 0 || *buffer == 0)

 {

   return 0;

 }


 for (size_t i = 0; i < size; ++i)

 {

   if (this->OS == Windows) {

     ret &= altCP1252Win_(*(buffer + i));

     NbCharacter += 1;

     D_PROC_L2("altcodeBufferEx_()", NbCharacter);

   } else {

     ret = 0;

     break;

   }

 }


 if (option == _Return)

 {

   ret &= pressEx_(TINY_KEY_KEYPAD_ENTER, _Keycode);

   releaseAll();

 }


 D_PROC_L1("altcodeBufferEx_()", NbCharacter);


 if (ret)

 {

   return NbCharacter;

 }

 return 0;

}


/*

  altcodeWinNum_(...)

  option = _No_Return (0)

  option = _Return (4) ajout de la touche return

*/

uint8_t Keyboard_::altcodeWinNum_(const uint32_t &unicode, const uint8_t option /* option = _No_Return */)

{

 D_PROC_("altcodeWinNum_()");


 if (unicode > 0x10FFFF) {

   return 0;

 }


 if (unicode < 256)

 {

   return altCP1252Win_((const uint8_t &)unicode, option);

 }

 else

 {

   return altcodePointWin_(unicode, option);

 }

 return 0;

}


/*

  altcodeWinEx(...)

  traitement des caractères ASCII étendu en mémoire Flash du programme

*/

size_t Keyboard_::altcodeWinEx(const __FlashStringHelper *ifsh)

{

 D_PROC_("altcodeWinEx()");

 uint8_t asciiEx, ret = 0;

 // NbCharacter renvoie le nombre de caractère

 // et fait office de variable d'incrémentaton pgm_read_byte(...)

 size_t NbCharacter = 0;


 PGM_P p = reinterpret_cast<PGM_P>(ifsh);

 while (1)

 {

   asciiEx = pgm_read_byte(p + NbCharacter);

   if (asciiEx) {

     ret = altcodeBufferEx_(&asciiEx, 1);

     if (ret) {

       NbCharacter += 1;

     } else {

       NbCharacter = 0;

       break;

     }

   } else {

     NbCharacter = 0;

     break;

   }

 }

 D_PROC_L1("altcodeWinEx()", NbCharacter);

 return NbCharacter;

}


size_t Keyboard_::altcodeWinExln(const __FlashStringHelper *ifsh)

{

 D_PROC_("altcodeWinExln()");

 size_t NbCharacter = 0;

 NbCharacter = altcodeWinEx(ifsh);

 if (pressEx_(TINY_KEY_RETURN))

 {

   releaseAll();

   return NbCharacter;

 }

 return 0;

}


/*

  keypadBuffer(...)

  option = _Print (0) (par défaut) avec releaseAll

  option = _Press (1)

  option = _Release (2)

  option = _PressAndRelease (3) (press et release sans releaseAll)

  option = _Return (4) ajout de la touche return

*/

size_t Keyboard_::keypadBuffer_(const uint8_t *buffer, const size_t &size, const uint8_t option /* option = _Print */)

{

 D_PROC_("keypadBuffer_()");

 Keycode keypad;

 const uint8_t *pointer;

 char caract;

 uint8_t ret = 1;

 size_t NbCharacter = 0, i;


 if (buffer == NULL || size == 0 || *buffer == 0)

 {

   return 0;

 }


 for (i = 0; i < size; i++)

 {

   pointer = (buffer + i);

   if ((*pointer > 0x30) && (*pointer < 0x3A))

   {

     keypad = (Keycode)(*pointer + 0x28);

   }

   else

   {

     switch (*pointer)

     {

       case 0x0D:

         keypad = TINY_KEY_KEYPAD_ENTER;

         break;

       case 0x30:

         keypad = TINY_KEYPAD_0;

         break;

       case 0x2A:

         keypad = TINY_KEY_KEYPAD_MULTIPLY;

         break;

       case 0x2B:

         keypad = TINY_KEY_KEYPAD_ADD;

         break;

       case 0x2C: // correspond à la virgule qui ne fait pas partie du keypad mais accepté

         keypad = TINY_KEY_RESERVED;

         // (press) ou (release) ne doivent pas fonctionner ici

         // seulement (print) doit être pris en compte

         if (!(option & _PressAndRelease))

         {

           ret &= print(',');

         }

         break;

       case 0x2D:

         keypad = TINY_KEY_KEYPAD_SUBTRACT;

         break;

       case 0x2E: // correspond au point

         keypad = TINY_KEY_KEYPAD_DECIMAL;

         if (!(option & _PressAndRelease)) // (press) ou (release) ne doivent pas fonctionner ici

         {

           keypad = TINY_KEY_RESERVED;

           if (this->_Notation_decimale == '.')

           {

             caract = '.';

           }

           else if (this->_Notation_decimale == ',')

           {

             caract = ',';

           }

           else

           {

             keypad = TINY_KEY_KEYPAD_DECIMAL;

           }

         }

         if (!keypad)

         {

           ret &= print(caract);

         }

         break;

       case 0x2F:

         keypad = TINY_KEY_KEYPAD_DIVIDE;

         break;

       default:

         keypad = TINY_KEY_RESERVED;

         ret = 0;

         break;

     }

   }

   if (keypad)

   {

     NbCharacter += 1;

     if (!(option & _PressAndRelease))

     { // print

       ret &= pressEx_(keypad, _Keycode);

       releaseAll();

     }

     else

     {

       if (option & _Press) // press

       {

         ret &= pressEx_(keypad, _Keycode);

       }

       if (option & _Release) // release

       {

         ret &= releaseEx_(keypad, _Keycode);

       }

     }

   }

 }

 if (option == _Return) // seulement pour print

 {

   ret &= pressEx_(TINY_KEY_KEYPAD_ENTER, _Keycode);

   releaseAll();

 }


 D_PROC_L1("keypadBuffer_()", NbCharacter);


 if (ret)

 {

   return NbCharacter;

 }

 return 0;

}


uint8_t Keyboard_::isNotEqual_(const char *character, const char &c, uint8_t &debut, uint8_t &fin)

{

 for (uint8_t indice = debut; indice < fin; ++indice)

 {

   if (character[indice] == c)

   {

     return 0;

   }

 }

 return 1;

}


uint8_t Keyboard_::charNum_to_keycode(const uint8_t &c)

{

 Keycode keypad = TINY_KEY_RESERVED; // TINY_KEY_RESERVED=0


 if ((c > 0x30) && (c < 0x3A))

 {

   keypad = (Keycode)(c + 0x28);

 }

 else if (c == 0x30)

 {

   keypad = TINY_KEYPAD_0;

 }

 return keypad;

}


uint8_t Keyboard_::altcodeOptimize_(const char *character, const uint8_t &size)

{

 uint8_t i = 0, debut = 0, fin = 1;


 _keyReport.modifiers = 0x04;

 _keyReport.keys[i] = charNum_to_keycode(character[0]);

 i += 1;

 while (1)

 {

   if (i > 5)

   {

     goto section1;

   }

   if (isNotEqual_(character, character[fin], debut, fin))

   {

     _keyReport.keys[i] = charNum_to_keycode(character[fin]);

     i += 1;

     fin += 1;

     goto section2;

   }

section1:

   i = 0;


   sendReport(&_keyReport);


   memset(&_keyReport.keys, 0, sizeof(_keyReport.keys));

   sendReport(&_keyReport);


   debut = fin;


section2:

   if (fin > (size - 1))

   {

     sendReport(&_keyReport);

     break;

   }

 }

 memset(&_keyReport.keys, 0, sizeof(_keyReport.keys));

 sendReport(&_keyReport);

 // releaseAll

 releaseAll();


 return 1;

}


size_t Keyboard_::setPrefixHex(const char *prefix /* prefix=NULL */)

{

 uint8_t i = sizeof(prefix);


 if (prefix == NULL)

 {

   this->_prefix[0] = '\0';

   return 1;

 }

 if (strlen(prefix) < 4)

 {

   while (i--)

   {

     this->_prefix[i] = 0;

   }

   i = strlen(prefix);

   while (i--)

   {

     this->_prefix[i] = prefix[i];

   }

   return 1;

 }

 return 0;

}


// size en octet

size_t Keyboard_::printHex_(uint32_t val, uint8_t size)

{

 char hex[8 + 1];

 uint8_t octet, num, j = 0, ret = 1;


 val = val << (32 - (size * 8));

 for (int i = 0; i < size; i++)

 {

   octet = (val >> 24);

   num = (octet & 0xF0) >> 4;

   hex[j] = (num > 9 ? ('A' + (num - 10)) : ('0' + num));

   num = octet & 0x0F;

   hex[j + 1] = (num > 9 ? ('A' + (num - 10)) : ('0' + num));

   val = val << 8;

   j += 2;

 }

 hex[j] = '\0';

 if (this->_prefix[0])

 {

   if (!printBuffer_((const uint8_t *)this->_prefix, strlen(this->_prefix)))

   {

     ret &= 0;

   }

 }

 if (printBuffer_((const uint8_t *)hex, strlen(hex)))

 {

   return ret;

 }

 return 0;

}


size_t Keyboard_::setPrecision(const uint8_t NB_decimale /* NB_decimale = 2 */)

{

 if (NB_decimale > 6)

 {

   this->_NB_decimale = 6;

 }

 else

 {

   this->_NB_decimale = NB_decimale;

 }

 return this->_NB_decimale;

}


size_t Keyboard_::setNotation(const char Notation_decimale /* Notation_decimale = '\0' */)

{

 if (Notation_decimale == ',' || Notation_decimale == '.' || Notation_decimale == '\0')

 {

   this->_Notation_decimale = Notation_decimale;

   return 1;

 }

 return 0;

}


size_t Keyboard_::setSignPositif(const char signPositif /* signPositif = '\0' */)

{

 if (signPositif == '\0' || signPositif == ' ' || signPositif == '+')

 {

   this->_signPositif = signPositif;

   return 1;

 }

 return 0;

}


size_t Keyboard_::print(const __FlashStringHelper *ifsh)

{

 return flashMemoryUTF8_(ifsh, _For_Print);

}


size_t Keyboard_::println(const __FlashStringHelper *ifsh)

{

 return flashMemoryUTF8_(ifsh, _For_Print | _Return);

}


size_t Keyboard_::altcodeWin(const __FlashStringHelper *ifsh)

{

 return flashMemoryUTF8_(ifsh, _For_AltCode);

}


size_t Keyboard_::altcodeWinln(const __FlashStringHelper *ifsh)

{

 return flashMemoryUTF8_(ifsh, _For_AltCode | _Return);

}


size_t Keyboard_::print(const char *str)

{

 return printBuffer_((const uint8_t *)str, strlen(str));

}


size_t Keyboard_::println(const char *str)

{

 return printBuffer_((const uint8_t *)str, strlen(str), _Return);

}


size_t Keyboard_::print(const String &s)

{

 return printBuffer_((const uint8_t *)s.c_str(), s.length());

}


size_t Keyboard_::println(const String &s)

{

 return printBuffer_((const uint8_t *)s.c_str(), s.length(), _Return);

}


size_t Keyboard_::print(const char &v)

{

 return printBuffer_((const uint8_t *)&v, 1);

}


size_t Keyboard_::println(const char &v)

{

 return printBuffer_((const uint8_t *)&v, 1, _Return);

}


size_t Keyboard_::println(void)

{

 return write(TINY_KEY_RETURN);

}


size_t Keyboard_::write(Keycode k)

{

 if (pressEx_(k, _Keycode))

 {

   releaseAll();

   return 1;

 }

 return 0;

}


size_t Keyboard_::press(Keycode k)

{

 return pressEx_(k, _Keycode);

}


size_t Keyboard_::release(Keycode k)

{

 return releaseEx_(k, _Keycode);

}


size_t Keyboard_::pressScancode(const uint16_t &scancode)

{

 return printScancode_(highByte(scancode), lowByte(scancode), _Press);

}


size_t Keyboard_::releaseScancode(const uint16_t &scancode)

{

 return printScancode_(highByte(scancode), lowByte(scancode), _Release);

}


size_t Keyboard_::printScancode(const uint16_t &scancode)

{

 return printScancode_(highByte(scancode), lowByte(scancode));

}


size_t Keyboard_::printScancodeln(const uint16_t &scancode)

{

 if (printScancode_(highByte(scancode), lowByte(scancode)))

 {

   return (write(TINY_KEY_RETURN));

 }

 return 0;

}


size_t Keyboard_::printScancodeln(void)

{

 return write(TINY_KEY_RETURN);

}


size_t Keyboard_::printAsciiEx(const __FlashStringHelper *ifsh)

{

 D_PROC_("printAsciiEx(const __FlashStringHelper)");

 uint8_t asciiEx;

 // NbCharacter renvoie le nombre de caractère

 // et fait office de variable d'incrémentaton pgm_read_byte(...)

 size_t NbCharacter = 0;


 PGM_P p = reinterpret_cast<PGM_P>(ifsh);

 while (1)

 {

   asciiEx = pgm_read_byte(p + NbCharacter);

   if (!asciiEx)

   {

     break;

   }

   if (printAsciiBufferEx_(&asciiEx, 1))

   {

     NbCharacter += 1;

   }

   else

   {

     NbCharacter = 0;

     break;

   }

 }

 D_PROC_L1("printAsciiEx()", NbCharacter);

 return NbCharacter;

}


size_t Keyboard_::printAsciiExln(const __FlashStringHelper *ifsh)

{

 D_PROC_("printAsciiExln(const __FlashStringHelper)");

 size_t NbCharacter = 0;

 NbCharacter = printAsciiEx(ifsh);

 if (pressEx_(TINY_KEY_RETURN))

 {

   releaseAll();

   return NbCharacter;

 }

 return 0;

}


uint8_t Keyboard_::pressReleaseNum_(const uint8_t &n, uint8_t option)

{

 D_PROC_("pressReleaseNum_()");

 uint8_t v = n;


 if (v != 13)

 {

   v = v + 48;

 }


 if (option & _For_keypad)

 {

   option = option - _For_keypad;

   return keypadBuffer_((const uint8_t *)&v, 1, option);

 }

 else if (option & _For_Print)

 {

   option = option - _For_Print;

   return printBuffer_((const uint8_t *)&v, 1, option);

 }

 return 0;

}


size_t Keyboard_::printEntier_(uint32_t &v, uint8_t option)

{

 // signed    -> range -2,147,483,648 to +2,147,483,647

 // unsigned  -> range 0 to +4 294 967 295


 D_PROC_("printEntier_()");


 uint8_t ret = 1, resultat, nb = 0, i;

 uint32_t j = 0;


 if (option & _Negatif)

 {

   option -= _Negatif;

   resultat = 45;

   if (option & _For_keypad)

   {

     ret &= (keypadBuffer_((const uint8_t *)&resultat, 1));

   }

   else if (option & _For_Print)

   {

     ret &= (printBuffer_((const uint8_t *)&resultat, 1));

   }

 }


 if (v == 0)

 { // traitement particulier pour la valeur 0

   nb = 1;

 }


 j = v;

 while (j > 0)

 { // calcul du nombre de digits

   j = j / 10;

   nb = nb + 1;

 }


 //j = (pow(10, nb-1));

 j = 1;

 while (ret < nb)

 { // aligner la puissance de 10 au nombre de digit-1

   j *= 10; // ex: valeur = 118 -> j = 100

   ret += 1;

 }

 ret = 1;


 for (i = 0; i < nb; i++)

 {

   resultat = v / j;

   resultat = resultat + 48; // permet d'éviter l'utilisation d'une autre variable

   if (option & _For_keypad)

   {

     ret &= (keypadBuffer_((const uint8_t *)&resultat, 1));

   }

   else if (option & _For_Print)

   {

     ret &= (printBuffer_((const uint8_t *)&resultat, 1));

   }

   resultat = resultat - 48;

   v = v - (resultat * j);

   j = j / 10;

 }


 D_PROC_R("printEntier_()", ret);

 return ret;

}


size_t Keyboard_::printFloatDouble_(const double &d, uint8_t option)

{

 D_PROC_("printFloatDouble_()");

 char dtostring[17] = {0}; // 14 + . + signe + 1

 uint8_t ret = 1;


 dtostrf(d, 1, this->_NB_decimale, dtostring);


 if (option & _For_keypad)

 {

   option = option - _For_keypad;

   if (this->_signPositif != '\0')

   {

     if (keypadBuffer_((const uint8_t *)&this->_signPositif, 1))

     {

       ret = 1;

     }

   }

   if (keypadBuffer_((const uint8_t *)dtostring, strlen(dtostring), option))

   {

     ret = 1;

   }

 }

 else if (option & _For_Print)

 {

   option = option - _For_Print;

   if (this->_Notation_decimale == ',')

   {

     uint8_t i = 17;

     while (i--)

     {

       if (dtostring[i] == '.')

       {

         dtostring[i] = ',';

         break;

       }

     }

   }

   if (this->_signPositif != '\0')

   {

     if (printBuffer_((const uint8_t *)&this->_signPositif, 1))

     {

       ret = 1;

     }

   }

   if (printBuffer_((const uint8_t *)dtostring, strlen(dtostring), option))

   {

     ret = 1;

   }

 }

 else

 {

   ret = 0;

 }


 D_PROC_R("printFloatDouble_()", ret);

 return ret;

}


size_t Keyboard_::printAsciiEx(const char &c)

{

 return printAsciiBufferEx_((const uint8_t *)&c, 1);

}


size_t Keyboard_::printAsciiExln(const char &c)

{

 return printAsciiBufferEx_((const uint8_t *)&c, 1, _Return);

}


size_t Keyboard_::printAsciiExln(void)

{

 return write(TINY_KEY_RETURN);

}


size_t Keyboard_::printAsciiEx(const char *str)

{

 return printAsciiBufferEx_((const uint8_t *)str, strlen(str));

}


size_t Keyboard_::printAsciiExln(const char *str)

{

 return printAsciiBufferEx_((const uint8_t *)str, strlen(str), _Return);

}


size_t Keyboard_::printAsciiEx(const String &s)

{

 return printAsciiBufferEx_((const uint8_t *)s.c_str(), s.length());

}


size_t Keyboard_::printAsciiExln(const String &s)

{

 return printAsciiBufferEx_((const uint8_t *)s.c_str(), s.length(), _Return);

}


size_t Keyboard_::pressAsciiEx(const char &c)

{

 return printAsciiBufferEx_((const uint8_t *)&c, 1, _Press);

}


size_t Keyboard_::releaseAsciiEx(const char &c)

{

 return printAsciiBufferEx_((const uint8_t *)&c, 1, _Release);

}


size_t Keyboard_::press(const char *str)

{

 D_PROC_("const char* str");

 D_PROC_R("const char* str", strlen(str));

 return printBuffer_((const uint8_t *)str, strlen(str), _Press);

}


size_t Keyboard_::release(const char *str)

{

 return printBuffer_((const uint8_t *)str, strlen(str), _Release);

}


size_t Keyboard_::press(const String &s)

{

 return printBuffer_((const uint8_t *)s.c_str(), s.length(), _Press);

}


size_t Keyboard_::release(const String &s)

{

 return printBuffer_((const uint8_t *)s.c_str(), s.length(), _Release);

}


size_t Keyboard_::press(const char& c)

{

 return printBuffer_((const uint8_t *)&c, 1, _Press);

}


size_t Keyboard_::release(const char& c)

{

 return printBuffer_((const uint8_t *)&c, 1, _Release);

}


// Fonctionnement avec la position physique des touches

size_t Keyboard_::keyCombi(Keycode key1, const char c)

{

 D_PROC_("keyCombi");

 size_t ret = 0;


 if (!setAlign_((const uint8_t *)&c, ret))

 {

   return 0;

 }

 if (!isSimpleKey())

 {

   return 0;

 }


 ret = press(key1);

 ret &= printScancode((this->_infoUtf8.key1 & 0x3F) << 8); // releaseAll inclu dans print


 return ret;

}


size_t Keyboard_::keyCombi(Keycode key1, const char *str)

{

 D_PROC_("keyCombi");

 size_t ret = 0;


 if (!setAlign_((const uint8_t *)str, ret))

 {

   return 0;

 }

 if (!isSimpleKey())

 {

   return 0;

 }

 ret = press(key1);


 ret &= printScancode((this->_infoUtf8.key1 & 0x3F) << 8); // releaseAll inclu dans print

 return ret;

}


size_t Keyboard_::keyCombi(Keycode key1, const String &s)

{

 D_PROC_("keyCombi");

 size_t ret = 0;


 if (!setAlign_((const uint8_t *)s.c_str(), ret))

 {

   return 0;

 }

 if (!isSimpleKey())

 {

   return 0;

 }

 ret = press(key1);


 ret &= printScancode((this->_infoUtf8.key1 & 0x3F) << 8); // releaseAll inclu dans print

 return ret;

}


size_t Keyboard_::keyCombi(Keycode key1)

{

 D_PROC_("keyCombi");

 return write(key1);

}


size_t Keyboard_::keyCombi(Keycode key1, Keycode key2)

{

 D_PROC_("keyCombi");

 uint8_t ret;

 ret = press(key1);

 ret &= write(key2); // releaseAll inclu dans write

 return ret;

}


size_t Keyboard_::keyCombi(Keycode key1, Keycode key2, Keycode key3)

{

 uint8_t ret;

 ret = press(key1);

 ret &= press(key2);

 ret &= write(key3); // releaseAll inclu dans write

 return ret;

}


size_t Keyboard_::keyCombi(Keycode key1, Keycode key2, const char c)

{

 D_PROC_("keyCombi");

 size_t ret = 0;


 if (!setAlign_((const uint8_t *)&c, ret))

 {

   return 0;

 }

 if (!isSimpleKey())

 {

   return 0;

 }

 ret = press(key1);

 ret &= press(key2);

 ret &= printScancode((this->_infoUtf8.key1 & 0x3F) << 8); // releaseAll inclu dans print

 return ret;

}


size_t Keyboard_::keyCombi(Keycode key1, Keycode key2, const char *str)

{

 D_PROC_("keyCombi");

 size_t ret = 0;


 if (!setAlign_((const uint8_t *)str, ret))

 {

   return 0;

 }

 if (!isSimpleKey())

 {

   return 0;

 }

 ret = press(key1);

 ret &= press(key2);

 ret &= printScancode((this->_infoUtf8.key1 & 0x3F) << 8); // releaseAll inclu dans print

 return ret;

}


size_t Keyboard_::keyCombi(Keycode key1, Keycode key2, const String &s)

{

 D_PROC_("keyCombi");

 size_t ret = 0;


 if (!setAlign_((const uint8_t *)s.c_str(), ret))

 {

   return 0;

 }

 if (!isSimpleKey())

 {

   return 0;

 }

 ret = press(key1);

 ret &= press(key2);

 ret &= printScancode((this->_infoUtf8.key1 & 0x3F) << 8); // releaseAll inclu dans print

 return ret;

}


size_t Keyboard_::keyCombi(Keycode key1, Keycode key2, Keycode key3, const char c)

{

 D_PROC_("keyCombi");

 size_t ret = 0;


 if (!setAlign_((const uint8_t *)&c, ret))

 {

   return 0;

 }

 if (!isSimpleKey())

 {

   return 0;

 }

 ret = press(key1);

 ret &= press(key2);

 ret &= press(key3);

 ret &= printScancode((this->_infoUtf8.key1 & 0x3F) << 8); // releaseAll inclu dans print

 return ret;

}


size_t Keyboard_::keyCombi(Keycode key1, Keycode key2, Keycode key3, const char *str)

{

 D_PROC_("keyCombi");

 size_t ret = 0;


 if (!setAlign_((const uint8_t *)str, ret))

 {

   return 0;

 }

 if (!isSimpleKey())

 {

   return 0;

 }

 ret = press(key1);

 ret &= press(key2);

 ret &= press(key3);

 ret &= printScancode((this->_infoUtf8.key1 & 0x3F) << 8); // releaseAll inclu dans print

 return ret;

}


size_t Keyboard_::keyCombi(Keycode key1, Keycode key2, Keycode key3, const String &s)

{

 D_PROC_("keyCombi");

 size_t ret = 0;


 if (!setAlign_((const uint8_t *)s.c_str(), ret))

 {

   return 0;

 }

 if (!isSimpleKey())

 {

   return 0;

 }

 ret = press(key1);

 ret &= press(key2);

 ret &= press(key3);

 ret &= printScancode((this->_infoUtf8.key1 & 0x3F) << 8); // releaseAll inclu dans print

 return ret;

}


size_t Keyboard_::altcodeWin(const String &s)

{

 return altcodeBuffer_((const uint8_t *)s.c_str(), s.length());

}


size_t Keyboard_::altcodeWin(const char *str)

{

 return altcodeBuffer_((const uint8_t *)str, strlen(str));

}


size_t Keyboard_::altcodeWinln(const String &s)

{

 return altcodeBuffer_((const uint8_t *)s.c_str(), s.length(), _Return);

}


size_t Keyboard_::altcodeWinln(const char *str)

{

 return altcodeBuffer_((const uint8_t *)str, strlen(str), _Return);

}


size_t Keyboard_::altcodeWinln(void)

{

 return write(TINY_KEY_RETURN);

}


size_t Keyboard_::altcodeWinEx(const char *str)

{

 return altcodeBufferEx_((const uint8_t *)str, strlen(str));

}


size_t Keyboard_::altcodeWinExln(const char *str)

{

 return altcodeBufferEx_((const uint8_t *)str, strlen(str), _Return);

}


size_t Keyboard_::altcodeWinEx(const String &s)

{

 return altcodeBufferEx_((const uint8_t *)s.c_str(), s.length());

}


size_t Keyboard_::altcodeWinExln(const String &s)

{

 return altcodeBufferEx_((const uint8_t *)s.c_str(), s.length(), _Return);

}


size_t Keyboard_::altcodeWinEx(const uint8_t &asciiEx)

{

 return altCP1252Win_(asciiEx);

}


size_t Keyboard_::altcodeWinExln(const uint8_t &asciiEx)

{

 return altCP1252Win_(asciiEx, _Return);

}


size_t Keyboard_::altcodeWinExln(void)

{

 return write(TINY_KEY_RETURN);

}


size_t Keyboard_::printKeypad(const char *str)

{

 return keypadBuffer_((const uint8_t *)str, strlen(str));

}


size_t Keyboard_::printKeypadln(const char *str)

{

 return keypadBuffer_((const uint8_t *)str, strlen(str), _Return);

}


size_t Keyboard_::printKeypad(const String &s)

{

 return keypadBuffer_((const uint8_t *)s.c_str(), s.length());

}


size_t Keyboard_::printKeypadln(const String &s)

{

 return keypadBuffer_((const uint8_t *)s.c_str(), s.length(), _Return);

}


size_t Keyboard_::printKeypad(const char &c)

{

 return keypadBuffer_((const uint8_t *)&c, 1);

}


size_t Keyboard_::printKeypadln(const char &c)

{

 return keypadBuffer_((const uint8_t *)&c, 1, _Return);

}


size_t Keyboard_::printKeypadln(void)

{

 return write(TINY_KEY_KEYPAD_ENTER);

}


size_t Keyboard_::print(const float &f)

{

 return printFloatDouble_(f, _For_Print);

}


size_t Keyboard_::print(const double &d)

{

 return printFloatDouble_(d, _For_Print);

}


size_t Keyboard_::println(const float &f)

{

 if (printFloatDouble_(f, _For_Print))

 {

   return write(TINY_KEY_RETURN);

 }

 return 0;

}


size_t Keyboard_::println(const double &d)

{

 if (printFloatDouble_(d, _For_Print))

 {

   return write(TINY_KEY_RETURN);

 }

 return 0;

}


size_t Keyboard_::printKeypad(const float &f)

{

 return printFloatDouble_(f, _For_keypad);

}


size_t Keyboard_::printKeypad(const double &d)

{

 return printFloatDouble_(d, _For_keypad);

}


size_t Keyboard_::printKeypadln(const float &f)

{

 if (printFloatDouble_(f, _For_keypad))

 {

   return printKeypadln();

 }

 return 0;

}


size_t Keyboard_::printKeypadln(const double &d)

{

 if (printFloatDouble_(d, _For_keypad))

 {

   return printKeypadln();

 }

 return 0;

}


size_t Keyboard_::pressKeypad(const char& c)

{

 return keypadBuffer_((const uint8_t *)&c, 1, _Press);

}


size_t Keyboard_::releaseKeypad(const char& c)

{

 return keypadBuffer_((const uint8_t *)&c, 1, _Release);

}


Keyboard_ KeyboardEx;