///////////////////////////////////////////////////////////////////////////////
//                             Lisaac Library                                //
//                                                                           //
//                   LSIIT - ULP - CNRS - INRIA - FRANCE                     //
//                                                                           //
//   This program is free software: you can redistribute it and/or modify    //
//   it under the terms of the GNU General Public License as published by    //
//   the Free Software Foundation, either version 3 of the License, or       //
//   (at your option) any later version.                                     //
//                                                                           //
//   This program 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 General Public License for more details.                            //
//                                                                           //
//   You should have received a copy of the GNU General Public License       //
//   along with this program.  If not, see <http://www.gnu.org/licenses/>.   //
//                                                                           //
//                     http://isaacproject.u-strasbg.fr/                     //
///////////////////////////////////////////////////////////////////////////////
Section Header

  + name    := G_IN;


  - copyright   := "2003-2005 Jérome Boutet, 2003-2007 Benoit Sonntag";
      
  - author  := "Sonntag Benoit (bsonntag@loria.fr)";
  - comment := "Output text for GUI.";

Section Inherit  

  + parent_area:Expanded AREA;
  
  + parent_g_expr:Expanded G_EXPR;
          
Section Public
  
  + action:BLOCK := 
  { in:G_IN; 
    // Nothing.
  };
  
  + stat:INTEGER_8;
  
  + text:STRING;
  
  + justify:UINTEGER_8;
  
  + cursor:INTEGER;
  
  - left  :UINTEGER_8 := 0;
  - right :UINTEGER_8 := 1;
  - center:UINTEGER_8 := 2;
  
  //
  // Width / Height
  //
  
  + width_min:INTEGER;
  
  + height_min:INTEGER;  
  
  - height_max:INTEGER <- height_min;
  
  //
  // Creation.
  //
  
  - create (car,line:INTEGER) :SELF <-
  ( + result:SELF;
    
    result := clone;
    result.make (car,line) justify 0 action NULL;
    result
  );

  - create (car,line:INTEGER) action a:BLOCK :SELF <-
  ( + result:SELF;
    
    result := clone;
    result.make (car,line) justify 0 action a;
    result
  );
  
  - create (car,line:INTEGER) justify j:UINTEGER_8 :SELF <-
  [
    -? {j.in_range 0 to 2};
  ]
  ( + result:SELF;
        
    result := clone;
    result.make (car,line) justify j action NULL;
    result
  );

  - create (car,line:INTEGER) justify j:UINTEGER_8 action a:BLOCK :SELF <-
  [
    -? {j.in_range 0 to 2};
  ]
  ( + result:SELF;
        
    result := clone;
    result.make (car,line) justify j action a;
    result
  );
  
  - make (car,line:INTEGER) justify j:UINTEGER_8 action a:BLOCK <-
  [
    -? {car > 1}; 
    -? {line > 0};
  ]
  (
    text    := STRING.create (car*line);
    width_min  := car  * 8;
    height_min := line * 16;
    justify := j;
    action  := a;
  ); 

  //
  // Update position.
  //
  
  - set_position rac:AREA at (x,y:INTEGER) size (w,h:INTEGER) <-
  ( 
    update rac from (x,y) size (w,h);
  );
  
  //
  // Display.
  //
    
  - draw (x0,y0:INTEGER) to (x1,y1:INTEGER) <-
  ( + beg,idx,siz,px,py,idx2:INTEGER;
        
    clipping (x0,y0) to (x1,y1);    
    //    
    rectangle_fill (x_min,y_min) to (x_max,y_max) color white;
    //    
    ((stat & 11b) = 2).if {
      text.insert '|' to cursor;
    };
    ((stat & 11b) = 0).if {
      color black;
    } else {    
      color red;
    };
    beg := text.lower;
    py := (height - height_min) / 2;
    {
      idx := text.index_of '\n' since beg;
      {
	siz := font_width text at beg to (idx-1);
	(siz > width).if {	
	  idx2 := text.last_index_of ' ' since (idx-1);
	  (idx2 > beg).if {
	    idx := idx2;
	  } else {
	    idx := idx - 1;
	  };
	};
      }.do_while {siz > width};      
      (justify != left).if {	
	(justify = right).if {
	  // Right
	  px := width - siz;
	} else {
	  // Center
	  px := (width - siz) >> 1;
	};
      };
      print text at beg to (idx-1) to (px,py); 
      py  := py + 16;
      beg := idx + 1;      
    }.do_until {(idx > text.count) || {py > height}};    
    ((stat & 11b) = 2).if {
      text.remove (cursor+1);
    };
    (py > height).if {
      text.remove_last (text.upper - idx + 2);
      stat := stat | 4;
    };
    //
  );
  
  //
  // Event manager.
  //
  
  - receive msg:EVENT <-
  // 0 : Out
  // 1 : in
  // 2 : input
  // 4 : End of buffer.
  ( + mouse:EVENT_MOUSE;
    + keyb:EVENT_KEYBOARD;
    + win:AREA;    
    + cmd:UINTEGER_8;
    + key:CHARACTER;
        
    mouse ?= msg;
    (mouse != NULL).if {
      win := INTERFACE.get_object (mouse.x_current,mouse.y_current);
      (stat = -1).if {
	(win != Self).if {
	  INTERFACE.receive msg;
	};
      } else {
	(stat & 11b)
	.when 0 then {
	  (win = Self).if {
	    stat := 1;
	    refresh;
	  } else {
	    INTERFACE.receive msg;
	  };
	}
	.when 1 then {
	  (win = Self).if {
	    (MOUSE.left).if {
	      stat := 2;
	      cursor := text.count;
	      refresh;
	    };
	  } else {
	    stat := 0;
	    refresh;
	  };
	}
	.when 2 then {
	  ((win != Self) && {MOUSE.left}).if {
	    stat := 0;	  
	    refresh;
	    // Action.
	    (action != NULL).if {
	      action.value Self;
	      (cursor > text.count).if {
		cursor := text.count;
	      };
	    };
	    INTERFACE.receive msg;
	  };
	};
      };
    };
    
    keyb ?= msg;
    ((keyb != NULL) && {(stat & 11b) = 2}).if {
      cmd := (keyb.key >> 8).to_uinteger_8;
      key := (keyb.key & 0FFh).to_character;
      ((cmd & 8) != 0).if {
	key
	// Enter
	.when '\13\' then {	  
	  text.add_last '\n';
	  cursor := cursor + 1;
	  refresh;
	  // Action.
	  (action != NULL).if {
	    action.value Self;
	    (cursor > text.count).if {
	      cursor := text.count;
	    };
	  };	  
	  ((stat & 100b) != 0).if {	    
	    stat := 0;
	    INTERFACE.receive msg;
	  };
	}
	// Move cursor.	
	.when 'L' then { 
	  (cursor != 0).if {
	    cursor := cursor - 1;
	  };
	}
	.when 'R' then {
	  (cursor != text.count).if {
	    cursor := cursor + 1;
	  };
	}
	.when 'B' then {
	  cursor := 0;
	}
	.when 'E' then {
	  cursor := text.count;
	}
	// Suppr.
	.when '\8\' then {
	  (cursor != 0).if {
	    text.remove cursor;
	    cursor := cursor - 1;
	  };
	}
	.when 'S' then {
	  (cursor != text.count).if {
	    text.remove (cursor+1);
	  };
	};
      } else {
	text.insert key to cursor;
	cursor := cursor + 1;
      };
      stat := stat & 11b;
      refresh;      
    };
  );

Section Private
  
  //
  // Obsolete (A revoir)
  //
  
  - what_letter pos_x:INTEGER :INTEGER <-
  // Return cursor position under `pos_x' coord.
  ( + result:INTEGER; 
    + x,x_cur:INTEGER; // la position x de la souris moins la taille du label
    
    x := pos_x - (font_width name + 4); // 4 for border
        
    result := text.lower;    
    {(result <= text.upper) && {x_cur < x}}.while_do {
      x_cur := x_cur + font_width_letter (text.item result);
      result := result + 1;
    };
        
    result-1
  );
