At least one button must be specified.
    **/
    template<typename t>
    inline int dialog(const char *const title, const char *const msg,
                      const char *const button1_label, const char *const button2_label,
                      const char *const button3_label, const char *const button4_label,
                      const char *const button5_label, const char *const button6_label,
                      const CImg<t>& logo, const bool is_centered=false) {
#if cimg_display==0
      cimg::unused(title,msg,button1_label,button2_label,button3_label,button4_label,button5_label,button6_label,
                   logo._data,is_centered);
      throw CImgIOException("cimg::dialog(): No display available.");
#else
      static const unsigned char
        black[] = { 0,0,0 }, white[] = { 255,255,255 }, gray[] = { 200,200,200 }, gray2[] = { 150,150,150 };

      // Create buttons and canvas graphics
      CImgList<unsigned char> buttons, cbuttons, sbuttons;
      if (button1_label) {
        CImg<unsigned char>().draw_text(0,0,button1_label,black,gray,1,13).move_to(buttons);
        if (button2_label) {
          CImg<unsigned char>().draw_text(0,0,button2_label,black,gray,1,13).move_to(buttons);
          if (button3_label) {
            CImg<unsigned char>().draw_text(0,0,button3_label,black,gray,1,13).move_to(buttons);
            if (button4_label) {
              CImg<unsigned char>().draw_text(0,0,button4_label,black,gray,1,13).move_to(buttons);
              if (button5_label) {
                CImg<unsigned char>().draw_text(0,0,button5_label,black,gray,1,13).move_to(buttons);
                if (button6_label) {
                  CImg<unsigned char>().draw_text(0,0,button6_label,black,gray,1,13).move_to(buttons);
                }}}}}}
      if (!buttons._width)
        throw CImgArgumentException("cimg::dialog(): No buttons have been defined.");
      cimglist_for(buttons,l) buttons[l].resize(-100,-100,1,3);

      unsigned int bw = 0, bh = 0;
      cimglist_for(buttons,l) { bw = std::max(bw,buttons[l]._width); bh = std::max(bh,buttons[l]._height); }
      bw+=8; bh+=8;
      if (bw<64) bw = 64;
      if (bw>128) bw = 128;
      if (bh<24) bh = 24;
      if (bh>48) bh = 48;

      CImg<unsigned char> button(bw,bh,1,3);
      button.draw_rectangle(0,0,bw - 1,bh - 1,gray);
      button.draw_line(0,0,bw - 1,0,white).draw_line(0,bh - 1,0,0,white);
      button.draw_line(bw - 1,0,bw - 1,bh - 1,black).draw_line(bw - 1,bh - 1,0,bh - 1,black);
      button.draw_line(1,bh - 2,bw - 2,bh - 2,gray2).draw_line(bw - 2,bh - 2,bw - 2,1,gray2);
      CImg<unsigned char> sbutton(bw,bh,1,3);
      sbutton.draw_rectangle(0,0,bw - 1,bh - 1,gray);
      sbutton.draw_line(0,0,bw - 1,0,black).draw_line(bw - 1,0,bw - 1,bh - 1,black);
      sbutton.draw_line(bw - 1,bh - 1,0,bh - 1,black).draw_line(0,bh - 1,0,0,black);
      sbutton.draw_line(1,1,bw - 2,1,white).draw_line(1,bh - 2,1,1,white);
      sbutton.draw_line(bw - 2,1,bw - 2,bh - 2,black).draw_line(bw - 2,bh - 2,1,bh - 2,black);
      sbutton.draw_line(2,bh - 3,bw - 3,bh - 3,gray2).draw_line(bw - 3,bh - 3,bw - 3,2,gray2);
      sbutton.draw_line(4,4,bw - 5,4,black,1,0xAAAAAAAA,true).
        draw_line(bw - 5,4,bw - 5,bh - 5,black,1,0xAAAAAAAA,false);
      sbutton.draw_line(bw - 5,bh - 5,4,bh - 5,black,1,0xAAAAAAAA,false).
        draw_line(4,bh - 5,4,4,black,1,0xAAAAAAAA,false);
      CImg<unsigned char> cbutton(bw,bh,1,3);
      cbutton.draw_rectangle(0,0,bw - 1,bh - 1,black).draw_rectangle(1,1,bw - 2,bh - 2,gray2).
        draw_rectangle(2,2,bw - 3,bh - 3,gray);
      cbutton.draw_line(4,4,bw - 5,4,black,1,0xAAAAAAAA,true).
        draw_line(bw - 5,4,bw - 5,bh - 5,black,1,0xAAAAAAAA,false);
      cbutton.draw_line(bw - 5,bh - 5,4,bh - 5,black,1,0xAAAAAAAA,false).
        draw_line(4,bh - 5,4,4,black,1,0xAAAAAAAA,false);

      cimglist_for(buttons,ll) {
        CImg<unsigned char>(cbutton).
          draw_image(1 + (bw  -buttons[ll].width())/2,1 + (bh - buttons[ll].height())/2,buttons[ll]).
          move_to(cbuttons);
        CImg<unsigned char>(sbutton).
          draw_image((bw - buttons[ll].width())/2,(bh - buttons[ll].height())/2,buttons[ll]).
          move_to(sbuttons);
        CImg<unsigned char>(button).
          draw_image((bw - buttons[ll].width())/2,(bh - buttons[ll].height())/2,buttons[ll]).
          move_to(buttons[ll]);
      }

      CImg<unsigned char> canvas;
      if (msg)
        ((CImg<unsigned char>().draw_text(0,0,"%s",gray,0,1,13,msg)*=-1)+=200).resize(-100,-100,1,3).move_to(canvas);

      const unsigned int
        bwall = (buttons._width - 1)*(12 + bw) + bw,
        w = cimg::max(196U,36 + logo._width + canvas._width,24 + bwall),
        h = cimg::max(96U,36 + canvas._height + bh,36 + logo._height + bh),
        lx = 12 + (canvas._data?0:((w - 24 - logo._width)/2)),
        ly = (h - 12 - bh - logo._height)/2,
        tx = lx + logo._width + 12,
        ty = (h - 12 - bh - canvas._height)/2,
        bx = (w - bwall)/2,
        by = h - 12 - bh;

      if (canvas._data)
        canvas = CImg<unsigned char>(w,h,1,3).
          draw_rectangle(0,0,w - 1,h - 1,gray).
          draw_line(0,0,w - 1,0,white).draw_line(0,h - 1,0,0,white).
          draw_line(w - 1,0,w - 1,h - 1,black).draw_line(w - 1,h - 1,0,h - 1,black).
          draw_image(tx,ty,canvas);
      else
        canvas = CImg<unsigned char>(w,h,1,3).
          draw_rectangle(0,0,w - 1,h - 1,gray).
          draw_line(0,0,w - 1,0,white).draw_line(0,h - 1,0,0,white).
          draw_line(w - 1,0,w - 1,h - 1,black).draw_line(w - 1,h - 1,0,h - 1,black);
      if (logo._data) canvas.draw_image(lx,ly,logo);

      unsigned int xbuttons[6] = { 0 };
      cimglist_for(buttons,lll) {
        xbuttons[lll] = bx + (bw + 12)*lll;
        canvas.draw_image(xbuttons[lll],by,buttons[lll]);
      }

      // Open window and enter events loop
      CImgDisplay disp(canvas,title?title:" ",0,false,is_centered?true:false);
      if (is_centered) disp.move((CImgDisplay::screen_width() - disp.width())/2,
                                 (CImgDisplay::screen_height() - disp.height())/2);
      bool stop_flag = false, refresh = false;
      int oselected = -1, oclicked = -1, selected = -1, clicked = -1;
      while (!disp.is_closed() && !stop_flag) {
        if (refresh) {
          if (clicked>=0)
            CImg<unsigned char>(canvas).draw_image(xbuttons[clicked],by,cbuttons[clicked]).display(disp);
          else {
            if (selected>=0)
              CImg<unsigned char>(canvas).draw_image(xbuttons[selected],by,sbuttons[selected]).display(disp);
            else canvas.display(disp);
          }
          refresh = false;
        }
        disp.wait(15);
        if (disp.is_resized()) disp.resize(disp,false);

        if (disp.button()&1)  {
          oclicked = clicked;
          clicked = -1;
          cimglist_for(buttons,l)
            if (disp.mouse_y()>=(int)by && disp.mouse_y()<(int)(by + bh) &&
                disp.mouse_x()>=(int)xbuttons[l] && disp.mouse_x()<(int)(xbuttons[l] + bw)) {
              clicked = selected = l;
              refresh = true;
            }
          if (clicked!=oclicked) refresh = true;
        } else if (clicked>=0) stop_flag = true;

        if (disp.key()) {
          oselected = selected;
          switch (disp.key()) {
          case cimg::keyESC : selected = -1; stop_flag = true; break;
          case cimg::keyENTER : if (selected<0) selected = 0; stop_flag = true; break;
          case cimg::keyTAB :
          case cimg::keyARROWRIGHT :
          case cimg::keyARROWDOWN : selected = (selected + 1)%buttons.width(); break;
          case cimg::keyARROWLEFT :
          case cimg::keyARROWUP : selected = (selected + buttons.width() - 1)%buttons.width(); break;
          }
          disp.set_key();
          if (selected!=oselected) refresh = true;
        }
      }
      if (!disp) selected = -1;