1311 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1311 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #define XVT_INCL_NATIVE
 | |
| #define STRICT
 | |
| 
 | |
| #define XI_INTERNAL
 | |
| #include <xi.h>
 | |
| 
 | |
| #include <applicat.h>
 | |
| #include <checks.h>
 | |
| #include <urldefid.h>
 | |
| #include <utility.h> 
 | |
| 
 | |
| #define __WINDOW_CPP
 | |
| #include <window.h>
 | |
| #include <colors.h>
 | |
| 
 | |
| HIDDEN MENU_ITEM* find_menu_item(MENU_ITEM* menu, MENU_TAG id, bool ismbar)
 | |
| {                                               
 | |
|   MENU_ITEM* fnd = NULL;  
 | |
|   MENU_ITEM* mn  = ismbar ? &menu[0] : &menu->child[0];
 | |
| 
 | |
|   for (int m = 0; mn != NULL && mn->tag != 0; m++, mn=ismbar?&menu[m]:&menu->child[m])
 | |
|   {
 | |
|     fnd = mn->tag == id ? mn : find_menu_item(mn, id, FALSE);
 | |
|     if (fnd != NULL) break;
 | |
|   } 
 | |
|   
 | |
|   return fnd;
 | |
| }
 | |
| 
 | |
| HIDDEN bool remove_menu_item(MENU_ITEM* menu, MENU_TAG id, bool ismbar)
 | |
| {                                               
 | |
|   MENU_ITEM* mn  = ismbar ? &menu[0] : &menu->child[0];
 | |
| 
 | |
|   for (int m = 0; mn != NULL && mn->tag != 0; m++, mn=ismbar?&menu[m]:&menu->child[m])
 | |
|   {
 | |
|     if (mn->tag == id) 
 | |
|     { 
 | |
|       do    
 | |
|       {
 | |
|         xvt_mem_rep((DATA_PTR)mn, (DATA_PTR)(mn+1), sizeof(MENU_ITEM), 1);
 | |
|         mn++;
 | |
|       } 
 | |
|       while (mn->tag != 0); 
 | |
|       return TRUE;
 | |
|     }
 | |
|     else if (remove_menu_item(mn, id, FALSE)) 
 | |
|       return TRUE;
 | |
|   }
 | |
|   
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| HIDDEN void set_menu_item(MENU_ITEM& m, TToken_string& tt)
 | |
| {                        
 | |
|   MENU_TAG tag  = tt.get_int(0);
 | |
|   TString  flag = tt.items() <=  2 ? "": tt.get(2);
 | |
|   char* text = NULL; 
 | |
|   if (strlen(tt.get(1)) > 0)
 | |
|   {
 | |
|     text = (char*)xvt_mem_alloc(strlen(tt.get(1)) + 1);
 | |
|     strcpy(text, tt.get(1));  
 | |
|   }
 | |
| 
 | |
|   m.tag       = tag;
 | |
|   m.text      = text;
 | |
|   m.enabled   = !(flag.find('D') != -1);
 | |
|   m.checkable = flag.find('C') != -1 || flag.find('c') != -1;
 | |
|   m.checked   = flag.find('c') != -1;      
 | |
|   m.separator = text == NULL;
 | |
| } 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TWindow_manager
 | |
| ///////////////////////////////////////////////////////////
 | |
|           
 | |
| // @doc INTERNAL          
 | |
|           
 | |
| // @class TWindow_manager | Classe per la gestione di un array di finestre modali
 | |
| class TWindow_manager
 | |
| {
 | |
|   // @author:(INTERNAL) Guido
 | |
| 
 | |
|   // @access:(INTERNAL) Private Member
 | |
|   
 | |
|   // @ccost:(INTERNAL) MAX_WIN | 8 | Numero massimo di finestre modali
 | |
|   enum { MAX_WIN = 8 };         
 | |
| 
 | |
|   // @cmember:(INTERNAL) Stack contenente la finestra attiva
 | |
|   TWindow* _window[MAX_WIN];    
 | |
|   // @cmember:(INTERNAL) Stack pointer
 | |
|   char _current;                
 | |
|   // @cmember:(INTERNAL) Permette di abilitare/disabilitare il menu' della task window (stesso 
 | |
|   //                                    funzionamento della <mf TMask::enable>)
 | |
|   void menu_enable(bool) const; 
 | |
|   
 | |
|   // @cmember:(INTERNAL) Tiene sempre disponibile un file con un numero di handle inferiore a 20
 | |
|   //                                    (per sopperire ad una mancanza di XVT)
 | |
|   FILE* _lowhandle;
 | |
| 
 | |
| // @access Public Member  
 | |
| public:
 | |
|   // @cmember Costruttore
 | |
|   TWindow_manager(); 
 | |
|   // @cmember Distruttore
 | |
|   ~TWindow_manager();
 | |
|   
 | |
|   // @cmember Libera lo spazio per aprire il file (vedi <p _lowhandle>)
 | |
|   void free_handle();
 | |
|   // @cmember Occupa lo spazio per aprire il file (vedi <p _lowhandle>)
 | |
|   void lock_handle();
 | |
| 
 | |
|   // @cmember Registra la finestra <p m> corrente 
 | |
|   void reg(TWindow* m);
 | |
|   // @cmember De-registra la finestra corrente
 | |
|   void unreg(const TWindow* m);
 | |
|   
 | |
|   // @cmember Ritorna il puntatore alla finestra corrente
 | |
|   TWindow* cur_win() const 
 | |
|   { return (_current < 0) ? NULL : _window[_current]; } 
 | |
| 
 | |
|   // @cmember Chiude tutte le finestre modali aperte
 | |
|   void destroy();
 | |
|   // @cmember Ritorna TRUE se la finestra corrente puo' essere chiusa
 | |
|   bool can_close() const; 
 | |
| } WinManager;
 | |
| 
 | |
| 
 | |
| 
 | |
| TWindow_manager::TWindow_manager() : _current(-1), _lowhandle(NULL)
 | |
| {
 | |
|   lock_handle();
 | |
| }
 | |
| 
 | |
| TWindow_manager::~TWindow_manager()
 | |
| { 
 | |
|   destroy(); 
 | |
|   free_handle();
 | |
| }  
 | |
| 
 | |
| void TWindow_manager::destroy()
 | |
| {
 | |
|   while (_current >= 0)
 | |
|   {
 | |
|     TWindow* w = cur_win();
 | |
|     w->stop_run(K_FORCE_CLOSE);
 | |
|     w->close_modal();
 | |
|   }
 | |
| }
 | |
| 
 | |
| void TWindow_manager::lock_handle()
 | |
| {
 | |
|   CHECK(_lowhandle == NULL, "Can't relock low handle");
 | |
|   _lowhandle = fopen("con", "r");
 | |
|   CHECK(_lowhandle != NULL, "Can't lock low handle");
 | |
| }
 | |
| 
 | |
| void TWindow_manager::free_handle()
 | |
| {
 | |
|   CHECK(_lowhandle, "Can't unlock low handle");
 | |
|   fclose(_lowhandle);
 | |
|   _lowhandle = NULL;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TWindow_manager::can_close() const 
 | |
| { 
 | |
|   bool ok = TRUE;
 | |
|   if (_current >= 0)
 | |
|     ok = cur_win()->can_be_closed();
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Dis/abilitazione del menu principale
 | |
| HIDDEN void xvt_menu_enable(MENU_ITEM* m, bool on)
 | |
| {
 | |
|   while (m->tag)
 | |
|   {
 | |
|     switch(m->tag)
 | |
|     {
 | |
|     case MENU_FILE:      // Leave it as is
 | |
|     case M_FONT:
 | |
|     case -1:             // Separator
 | |
|       break;             
 | |
|     default:
 | |
|       xvt_menu_set_item_enabled(TASK_WIN, m->tag, on);
 | |
|       break;
 | |
|     }
 | |
|     m++;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void TWindow_manager::menu_enable(bool on) const
 | |
| {
 | |
|   MENU_ITEM *mi = xvt_menu_get_tree(TASK_WIN);
 | |
|   xvt_menu_enable(mi, on);
 | |
|   xvt_menu_update(TASK_WIN);
 | |
|   xvt_res_free_menu_tree(mi);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TWindow_manager::reg(TWindow* m)
 | |
| {
 | |
|   _current++;
 | |
|   CHECK(_current < MAX_WIN, "Too many windows");
 | |
| 
 | |
|   switch (_current)
 | |
|   {
 | |
|   case 0 : 
 | |
|     menu_enable(FALSE);                      
 | |
|   {                                                                                   
 | |
|     const bool on = main_app().firm_change_enabled();
 | |
|     xvt_menu_set_item_enabled(TASK_WIN, M_FILE_NEW, on);
 | |
|     xvt_menu_set_item_enabled(TASK_WIN, M_FILE_REVERT, on);
 | |
|   }
 | |
|     break;
 | |
|   case 1 : 
 | |
|     xvt_menu_set_item_enabled(TASK_WIN, M_FILE_QUIT, FALSE); 
 | |
|     xvt_menu_set_item_enabled(TASK_WIN, M_FILE_NEW, FALSE);  
 | |
|     xvt_menu_set_item_enabled(TASK_WIN, M_FILE_REVERT, FALSE);
 | |
|   default: 
 | |
|     _window[_current-1]->deactivate(); break;
 | |
|   }
 | |
| 
 | |
|   _window[_current] = m;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TWindow_manager::unreg(const TWindow* m)
 | |
| {
 | |
| #ifdef DBG
 | |
|   if (m != cur_win())
 | |
|   {
 | |
|     yesnofatal_box("E' successo un casino nel Window Manager");
 | |
|     return;
 | |
|   }
 | |
| #endif
 | |
| 
 | |
|   _current--;
 | |
|   
 | |
|   if (_current < 0)
 | |
|   {
 | |
|     menu_enable(TRUE);
 | |
|   }  
 | |
|   else
 | |
|   {
 | |
|     cur_win()->activate();
 | |
|     
 | |
|     xvt_menu_set_item_enabled(TASK_WIN, M_FILE_QUIT, _current == 0);
 | |
|     
 | |
|     const bool cf = _current == 0 && main_app().firm_change_enabled();
 | |
|     xvt_menu_set_item_enabled(TASK_WIN, M_FILE_NEW, cf);
 | |
|     xvt_menu_set_item_enabled(TASK_WIN, M_FILE_REVERT, cf);
 | |
|     
 | |
|     xvt_menu_update(TASK_WIN);
 | |
|     cur_win()->set_focus();
 | |
|   }     
 | |
| }
 | |
| 
 | |
| 
 | |
| // @func Chiude tutte le finestre aperte
 | |
| void close_all_dialogs()
 | |
| {
 | |
|   WinManager.destroy();
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @func Indica se l'applicazione puo' essere terminata
 | |
| //
 | |
| // @rdesc Ritorna il risultato della ricerca:
 | |
| //
 | |
| // @flag TRUE | Se l'aplicazione puo' essere chiusa
 | |
| // @flag FALSE | Se l'applicazione non puo' essere chiusa
 | |
| bool can_close()
 | |
| {
 | |
|   return WinManager.can_close();
 | |
| }
 | |
| 
 | |
| bool is_valid_window(WINDOW w)
 | |
| {
 | |
|   bool ok = FALSE;
 | |
|   if (w != NULL_WIN)
 | |
|     ok = xvt_vobj_get_attr(w, ATTR_NATIVE_WINDOW) != NULL;
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| // @func Ritorna l'handle della finestra corrente
 | |
| //
 | |
| // @rdesc Restituisce l'handle della finestra corrente.
 | |
| WINDOW cur_win()
 | |
| 
 | |
|   // @comm Se non esiste una finestra corrente allora ritorna NULL_WIN
 | |
| {
 | |
|   WINDOW win = NULL_WIN;
 | |
|   TWindow* w = WinManager.cur_win();
 | |
|   if (w)
 | |
|   { 
 | |
|     win = w->win();
 | |
|     if (!is_valid_window(w->win()))
 | |
|     {
 | |
|       w->stop_run(K_FORCE_CLOSE);
 | |
|       win = NULL_WIN;
 | |
|     }  
 | |
|   }  
 | |
|   return win;  
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TImage
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| 
 | |
| // Certified 99%
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Setta l'immagine e le sue dimensioni
 | |
| //
 | |
| // @rdesc Ritorna l'immagine stessa
 | |
| XVT_IMAGE TImage::set(
 | |
|   XVT_IMAGE i) // @parm Immagine da settare
 | |
| 
 | |
|   // @comm L'immagine precedente viene cancellata quando viene settata una nuova
 | |
| {
 | |
|   if (_image) 
 | |
|     xvt_image_destroy(_image);
 | |
|   _image = i;
 | |
|   if (i)
 | |
|   {
 | |
|     _src.left = _src.top = 0;
 | |
|     xvt_image_get_dimensions(i, &_src.right, &_src.bottom);
 | |
|     _dst = _src;
 | |
|   } 
 | |
|   return _image;
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Legge l'immagine dal file
 | |
| XVT_IMAGE TImage::load(
 | |
|   const char* n) // @parm Nome del file contenente l'immagine
 | |
| {               
 | |
|   WinManager.free_handle();    
 | |
|   XVT_IMAGE i = xvt_image_read_bmp((char*)n);
 | |
|   WinManager.lock_handle();    
 | |
|   
 | |
|   if (i != NULL) set(i);
 | |
|   return i;  
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| XVT_IMAGE TImage::load(short id)
 | |
| {                         
 | |
|   return set(xvt_res_get_image(id));
 | |
| }
 | |
| 
 | |
| 
 | |
| // Certified 100%
 | |
| TImage::TImage(const char* n) : _image(NULL)
 | |
| {
 | |
|   if (n && *n) load(n);
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| TImage::TImage(short id) : _image(NULL)
 | |
| {
 | |
|   if (id > 0) load(id);
 | |
| }
 | |
| 
 | |
| // Certified 90%
 | |
| TImage::TImage(const TImage& im, short w, short h) : _image(NULL)
 | |
| { 
 | |
|   const XVT_IMAGE_FORMAT fmt = xvt_image_get_format(im._image);
 | |
|   set(xvt_image_create(fmt, w, h, NULL));
 | |
|   
 | |
|   if (ok())
 | |
|   { 
 | |
|     if (fmt == XVT_IMAGE_CL8)
 | |
|     {
 | |
|       const short colors = xvt_image_get_ncolors(im._image);
 | |
|       xvt_image_set_ncolors(_image, colors);
 | |
|       for (short c = 0; c < colors; c++) 
 | |
|         xvt_image_set_clut(_image, c, xvt_image_get_clut((XVT_IMAGE)im._image, c));
 | |
|     }    
 | |
|     xvt_image_transfer(_image, (XVT_IMAGE)im._image, &_src, (RCT*)&im._src);
 | |
|   }  
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| TImage::~TImage()
 | |
| {     
 | |
|   if (_image != NULL)                    
 | |
|     xvt_image_destroy(_image);
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Permette di settare la posizione della figura
 | |
| void TImage::set_pos(
 | |
|   int x, // @parm Coordinata x dell'immagine da settare
 | |
|   int y) // @parm Coordinata y dell'immagine da settare
 | |
|   
 | |
|   // @comm Permette di aggiornare il mebro <p _dst> sommandogli i valori                 
 | |
|   //                     passati con <p x> e <p y>
 | |
| {
 | |
|   _dst = _src;
 | |
|   xvt_rect_offset(&_dst, x, y);
 | |
| }               
 | |
| 
 | |
| // Certified 100%
 | |
| void TImage::draw(WINDOW w) const
 | |
| {   
 | |
|   xvt_dwin_draw_image(w, _image, (RCT*)&_dst, (RCT*)&_src);
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Permette di gestire il disegno dell'immagine sullo schermo
 | |
| void TImage::draw(
 | |
|   WINDOW w,    // @parm Immagine da disegnare
 | |
|   int x,       // @parm Coordinata x in cui disegnare l'immagine
 | |
|   int y) const // @parm Coordinata y in cui disegnare l'immagine
 | |
|   // @parm RCT& | _src | Rettangolo contenente l'immagine da disegnare
 | |
|   // @parm RCT& | _dst | Rettangolo in cui disegnare l'immagine
 | |
| 
 | |
|   // @syntax void draw(WINDOW w);
 | |
|   // @syntax void draw(WINDOW w, int x, int y);
 | |
|   // @syntax void draw(WINDOW w, const RCT& dst);
 | |
|   // @syntax void draw(WINDOW w, const RCT& dst, const RCT& src);
 | |
| 
 | |
|   // @comm Nel caso utilizzo l'ultima sintassi e' possibile disegnare solo una parte
 | |
|   //                     dell'immagine, precisamente delle dimensioni <p _dst> se tale parametro e'
 | |
|   //                     minore di <p _pst>
 | |
| {                                       
 | |
|   RCT dst = _src;
 | |
|   xvt_rect_offset(&dst, x, y);
 | |
|   xvt_dwin_draw_image(w, _image, &dst, (RCT*)&_src);
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| void TImage::draw(WINDOW w, const RCT& dst) const
 | |
| {
 | |
|   xvt_dwin_draw_image(w, _image, (RCT*)&dst, (RCT*)&_src);
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| void TImage::draw(WINDOW w, const RCT& dst, const RCT& src) const
 | |
| {
 | |
|   xvt_dwin_draw_image(w, _image, (RCT*)&dst, (RCT*)&src);
 | |
| }
 | |
| 
 | |
| // Certified 99%
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Fa corrispondere la palette della finestra a quella dell'immagine 
 | |
| void TImage::set_palette(
 | |
|   WINDOW w) const // @parm Finestra a cui settare la palette
 | |
| {
 | |
|   XVT_PALETTE wp = xvt_vobj_get_palet(w);
 | |
|   if (wp != NULL)
 | |
|   {
 | |
|     XVT_PALETTE p = xvt_palet_create(XVT_PALETTE_USER, NULL);
 | |
|     const int ncolors = xvt_palet_get_ncolors(wp);
 | |
|     COLOR* color = new COLOR[ncolors];
 | |
|     xvt_palet_get_colors(wp, color, ncolors);
 | |
|     xvt_palet_add_colors(p, color, ncolors);
 | |
|     delete color;
 | |
|     xvt_palet_add_colors_from_image(p, _image);
 | |
|     xvt_vobj_set_palet(w, p);
 | |
|     xvt_palet_destroy(wp);
 | |
|   }  
 | |
| }
 | |
| 
 | |
| // Certified 100%
 | |
| void TImage::set_clut(byte n, COLOR c)
 | |
| {
 | |
|   if (xvt_image_get_format(_image) == XVT_IMAGE_CL8)                  
 | |
|     xvt_image_set_clut(_image, n, c);
 | |
| }
 | |
| 
 | |
| // Certified 99%
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Setta i colori dell'immagine in modo da renderla trasparente
 | |
| void TImage::convert_to_default_colors()
 | |
| 
 | |
|   // @comm Legge nell'immagine i colori CYAN e DARK_CYAN e li setta a seconda del colore
 | |
|   //                     della finestra per fare in modo di rendere trasparenti tali colori.
 | |
| {
 | |
|   if (MASK_BACK_COLOR != COLOR_DKCYAN && xvt_image_get_format(_image) == XVT_IMAGE_CL8)                  
 | |
|   { 
 | |
|     short dx, dy; xvt_image_get_dimensions(_image, &dx, &dy);
 | |
|     for (short y = 0; y < dy; y++) for (short x = 0; x < dx; x++)
 | |
|     {     
 | |
|       const COLOR c = xvt_image_get_pixel(_image, x, y);
 | |
|       switch (c)
 | |
|       {
 | |
|       case COLOR_DKCYAN & 0x00FFFFFF:
 | |
|         xvt_image_set_pixel(_image, x, y, MASK_BACK_COLOR); break;
 | |
|       case COLOR_CYAN & 0x00FFFFFF:
 | |
|         xvt_image_set_pixel(_image, x, y, MASK_LIGHT_COLOR); break;
 | |
|       case COLOR_GRAY & 0x00FFFFFF:
 | |
|         xvt_image_set_pixel(_image, x, y, MASK_DARK_COLOR); break;
 | |
|       default:
 | |
|         break;  
 | |
|       }
 | |
|     }
 | |
|   } 
 | |
| }
 | |
| 
 | |
| // @mfunc Setta i colori dell'immagine  in modo da renderla trasparente
 | |
| void TImage::convert_transparent_color(COLOR transparent)
 | |
| 
 | |
|   // @comm Legge nell'immagine i pixel uguali a quello in alto a sinistra e li setta 
 | |
|   // uguali allo sfondo delle maschere
 | |
| { 
 | |
|   const COLOR trans = xvt_image_get_pixel(_image, 0, 0) & 0x00FFFFFF;
 | |
|   if (trans != (transparent & 0x00FFFFFF) && 
 | |
|       xvt_image_get_format(_image) == XVT_IMAGE_CL8)                  
 | |
|   {                  
 | |
|     for (int index = 0; index < 256; index++)
 | |
|       if (trans == (xvt_image_get_clut(_image, index) & 0x00FFFFFF))
 | |
|       {
 | |
|         xvt_image_set_clut(_image, index, transparent);
 | |
|         break;
 | |
|       }
 | |
|   } 
 | |
| }
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TWindow
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| DRAW_CTOOLS TWindow::_ct;
 | |
| bool TWindow::_ctools_saved;
 | |
| 
 | |
| 
 | |
| TWindow::TWindow()
 | |
| : _win(NULL_WIN), _open(FALSE), _modal(FALSE), _active(TRUE),
 | |
|   _running(FALSE), _pixmap(FALSE), _lastkey(0)
 | |
| {}
 | |
| 
 | |
| word TWindow::class_id() const
 | |
| { return CLASS_WINDOW; }
 | |
| 
 | |
| long XVT_CALLCONV1 TWindow::window_handler(WINDOW win, EVENT* ep)
 | |
| {
 | |
|   TWindow* w = (TWindow*)xvt_vobj_get_data(win);
 | |
|   CHECK(w != NULL, "Invalid window");
 | |
|   w->handler(win, ep);
 | |
| 
 | |
|   return 0L;
 | |
| }
 | |
| 
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Crea la finestra
 | |
| //
 | |
| // @rdesc Ritorna l'handle della finestra creata
 | |
| WINDOW TWindow::create(
 | |
|   short x,           // @parm Coordinata x della finestra
 | |
|   short y,           // @parm Coordinata y della finestra
 | |
|   short dx,          // @parm Larghezza della finestra
 | |
|   short dy,          // @parm Altezza della finestra
 | |
|   const char* title, // @parm Titolo da assegnare alla finestra (default "")
 | |
|   long flags,        // @parm Flag della finestra (default WSF_NONE)
 | |
|   WIN_TYPE wt,       // @parm Tipo di finestra da creare (default W_DOC)
 | |
|   WINDOW parent,     // @parm Handler della finestra padre (default NULL_WIN)
 | |
|   int menu)          // @parm Menu' da assegnare alla finestra (default 0)
 | |
| {
 | |
|   if (menu == 0) flags |= WSF_NO_MENUBAR;
 | |
| 
 | |
|   if (parent == NULL_WIN) parent = TASK_WIN;
 | |
|   if (parent == TASK_WIN) flags |= WSF_INVISIBLE;
 | |
| 
 | |
|   _win = xvt_create_window(
 | |
|     wt,
 | |
|     x, y, dx, dy,
 | |
|     title, 
 | |
|     menu, parent,
 | |
|     flags, 
 | |
|     window_handler,
 | |
|     PTR_LONG(this)
 | |
|     );
 | |
| 
 | |
|   CHECK(_win, "Can't create a window");
 | |
| 
 | |
|   return _win;
 | |
| }
 | |
| 
 | |
| 
 | |
| TWindow::~TWindow()
 | |
| {
 | |
|   if (_win != NULL_WIN)
 | |
|   {   
 | |
|     if (is_valid_window(_win));
 | |
|       xvt_vobj_destroy(_win);
 | |
|     _win = NULL_WIN;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void TWindow::open()
 | |
| {
 | |
|   WINDOW w = win();
 | |
|   CHECK(is_valid_window(w), "Can't open a NULL window");
 | |
|   xvt_vobj_set_visible(w, _open = TRUE);
 | |
|   xvt_scr_set_focus_vobj(w);  
 | |
|   xvt_vobj_raise(w);          
 | |
| }
 | |
| 
 | |
| 
 | |
| void TWindow::open_modal()
 | |
| {
 | |
|   set_modal(TRUE);
 | |
|   _open = TRUE;
 | |
|   open();
 | |
| 
 | |
|   WinManager.reg(this);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TWindow::close()
 | |
| {
 | |
|   CHECK(_win != NULL_WIN, "Can't close a NULL window");
 | |
|   if (is_valid_window(_win))
 | |
|     xvt_vobj_set_visible(_win, _open = FALSE);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TWindow::close_modal()
 | |
| {
 | |
|   WinManager.unreg(this);
 | |
|   close();
 | |
|   _open = FALSE;
 | |
| }
 | |
| 
 | |
| bool TWindow::stop_run(KEY key)
 | |
| {
 | |
|   _running = FALSE;
 | |
|   _lastkey = key;     
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| bool TWindow::can_be_closed() const
 | |
| {
 | |
|   const bool ok = !is_modal();
 | |
|   if (!ok) 
 | |
|     error_box("Chiudere la finestra attiva prima di uscire dal programma");
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Esegue la finestra
 | |
| //
 | |
| // @rdesc Ritorna l'ultimo tasto premuto nella finestra
 | |
| KEY TWindow::run()
 | |
| 
 | |
|   // @comm Se la finestra non era aperta la apre in modo modale
 | |
| {
 | |
|   const bool was_open = is_open();
 | |
| 
 | |
|   start_run();
 | |
|   _running = TRUE;
 | |
| 
 | |
|   if (!was_open) open_modal();
 | |
|   else open();
 | |
| 
 | |
|   while (_running)
 | |
|     do_events();
 | |
| 
 | |
|   if (!was_open) close_modal();
 | |
|   do_events();
 | |
| 
 | |
|   return last_key();
 | |
| }
 | |
| 
 | |
| void TWindow::on_button(short dlg)
 | |
| {   
 | |
|   switch(dlg)
 | |
|   {
 | |
|   case DLG_OK: 
 | |
|     stop_run(K_ENTER); 
 | |
|     break;
 | |
|   case DLG_CANCEL: 
 | |
|     stop_run(K_ESC); 
 | |
|     break;
 | |
|   case DLG_QUIT: 
 | |
|     stop_run(K_QUIT); 
 | |
|     break;
 | |
|   default:
 | |
|     break;
 | |
|   }
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Gestisce l'handler della finestra
 | |
| void TWindow::handler(
 | |
|   WINDOW win, // @parm Finestra da gestire
 | |
|   EVENT* ep)  // @parm Evento da gestire nella finestra
 | |
| {
 | |
|   switch(ep->type)
 | |
|   {
 | |
|   case E_CLOSE:
 | |
|     stop_run(K_ESC);
 | |
|     break;
 | |
|   case E_CONTROL:
 | |
|     if (ep->v.ctl.ci.type == WC_PUSHBUTTON)
 | |
|       on_button(ep->v.ctl.id);
 | |
|     break;  
 | |
|   case E_UPDATE:
 | |
|     update();
 | |
|     break;
 | |
|   case E_CHAR:
 | |
|     on_key(e_char_to_key(ep));
 | |
|     break;
 | |
|   case E_DESTROY:
 | |
|     _win = NULL_WIN;
 | |
|     break;
 | |
|   default:
 | |
|     break;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void TWindow::on_idle()
 | |
| {
 | |
|   // Non c'e' niente da fare qui, ma non si puo' mai sapere
 | |
| }
 | |
| 
 | |
| 
 | |
| TPoint TWindow::size() const
 | |
| {
 | |
|   RCT r;
 | |
|   xvt_vobj_get_client_rect(win() ? win() : TASK_WIN, &r);
 | |
|   return TPoint(r.right / CHARX, r.bottom / CHARY);
 | |
| }
 | |
| 
 | |
| WINDOW TWindow::parent() const
 | |
| {
 | |
|   return xvt_vobj_get_parent(win());
 | |
| }
 | |
| 
 | |
| 
 | |
| void TWindow::set_focus()
 | |
| { 
 | |
|   WINDOW w = win();
 | |
|   if (w)
 | |
|   {
 | |
|     xvt_scr_set_focus_vobj(w);
 | |
|     xvt_vobj_raise(w);        
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void TWindow::iconize() const
 | |
| {
 | |
| #if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_WIN32
 | |
|   HWND hwnd = (HWND)xvt_vobj_get_attr(win(), ATTR_NATIVE_WINDOW);
 | |
|   ShowWindow(hwnd, SW_MINIMIZE);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void TWindow::maximize() const
 | |
| {
 | |
| #if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_WIN32
 | |
|   HWND hwnd = (HWND)xvt_vobj_get_attr(win(), ATTR_NATIVE_WINDOW);
 | |
|   ShowWindow(hwnd, SW_SHOWMAXIMIZED);
 | |
| #else            
 | |
|   RCT r; xvt_rect_set(&r, 1,1,79,23);
 | |
|   xvt_vobj_move(win(),&r);
 | |
| #endif
 | |
| } 
 | |
| 
 | |
| 
 | |
| void TWindow::set_background_color(COLOR col)
 | |
| {
 | |
|   XI_OBJ* itf = xi_get_itf(win());
 | |
|   itf->v.itf->back_color = col;
 | |
|   force_update();
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Attiva/disattiva la finestra
 | |
| void TWindow::activate(
 | |
|   bool on) // @parm Indica l'operazione da svolgere sulla finestra:
 | |
|   //
 | |
|   // @flag TRUE | Abilita la finestra (default)
 | |
|   // @flag FALSE | Disabilita la finestra
 | |
| {
 | |
|   xvt_vobj_set_enabled(win(), _active = on);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TWindow::set_caption(const char* title)
 | |
| {
 | |
|   xvt_vobj_set_title(win(), (char*)title);
 | |
| }
 | |
| 
 | |
| 
 | |
| const char* TWindow::get_caption() const
 | |
| {
 | |
|   char* title = &__tmp_string[512];
 | |
|   xvt_vobj_get_title(win(), title, 80);
 | |
|   return title;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TWindow::force_update()
 | |
| {
 | |
|   if (win() != NULL_WIN)
 | |
|     xvt_dwin_invalidate_rect(win(), NULL);
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TWindow::save_ctools()
 | |
| {
 | |
|   if (_ctools_saved == FALSE)
 | |
|   {
 | |
|     xvt_dwin_get_draw_ctools(win(), &_ct);
 | |
|     return _ctools_saved = TRUE;
 | |
|   }
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TWindow::restore_ctools()
 | |
| {
 | |
|   if (_ctools_saved)
 | |
|   {
 | |
|     xvt_dwin_set_draw_ctools(win(), &_ct);
 | |
|     _ctools_saved = FALSE;
 | |
|     return TRUE;
 | |
|   }
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TWindow::set_color(COLOR fore, COLOR back)
 | |
| {
 | |
|   WINDOW w = win();
 | |
|   xvt_dwin_set_fore_color(w, fore);
 | |
|   xvt_dwin_set_back_color(w, back);
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Sceglie la penna da utilizzare nella finestra
 | |
| void TWindow::set_pen(
 | |
|   COLOR color,     // @parm Colore della penna
 | |
|   int width,       // @parm Larghezza del tratto (default 1)
 | |
|   PAT_STYLE pat,   // @parm Stile del pattern (default PAT_SOLID)
 | |
|   PEN_STYLE style) // @parm Stile della penna (default P_SOLID)
 | |
| {
 | |
|   CPEN pen;
 | |
| 
 | |
|   pen.width = width;
 | |
|   pen.pat   = pat;
 | |
|   pen.style = style;
 | |
|   pen.color = color;
 | |
| 
 | |
|   xvt_dwin_set_cpen(win(), &pen);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TWindow::hide_pen()
 | |
| {
 | |
|   xvt_dwin_set_std_cpen(win(), TL_PEN_HOLLOW);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TWindow::set_brush(COLOR color, PAT_STYLE pat)
 | |
| {
 | |
|   CBRUSH brush = { pat, color };
 | |
|   xvt_dwin_set_cbrush(win(), &brush);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TWindow::hide_brush()
 | |
| {
 | |
|   CBRUSH brush = { PAT_HOLLOW, COLOR_WHITE };
 | |
|   xvt_dwin_set_cbrush(win(), &brush);
 | |
| }
 | |
| 
 | |
| 
 | |
| HIDDEN void swap(short& a, short& b)
 | |
| {
 | |
|   short tmp = a;
 | |
|   a = b;
 | |
|   b = tmp;
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Disegna un rettangolo con la possibilita' di settare la penna e il draw_mode
 | |
| void TWindow::frame(
 | |
|   short left,   // @parm Lato sinistro del rettangolo
 | |
|   short top,    // @parm Lato superiore del rettangolo
 | |
|   short right,  // @parm Lato destro del rettangolo
 | |
|   short bottom, // @parm Lato inferiore del rettangolo
 | |
|   int flag)     // @parm Flag da assegnare per il disegno del rettangolo
 | |
| 
 | |
|   // @comm Se <p left> <gt> <p right> oppure <p top> <gt> <p bottom> i valori
 | |
|   //       vengono scambiati per permettere il disegno corretto del rettangolo
 | |
| {
 | |
|   if (left > right) swap(left, right);
 | |
|   if (top > bottom) swap(top, bottom);
 | |
| 
 | |
|   const bool saved = flag && save_ctools();
 | |
| 
 | |
|   if (flag & 1) hide_pen();
 | |
|   if (flag & 2) hide_brush();
 | |
|   if (flag & 4)
 | |
|   {
 | |
|     set_mode(M_XOR);
 | |
|     set_brush(COLOR_BLACK);     // Needed for Windows
 | |
|   }
 | |
| 
 | |
|   const PNT f = log2dev(left,top);
 | |
|   const PNT t = log2dev(right,bottom);
 | |
|   RCT r;
 | |
|   r.top = f.v; r.left = f.h;
 | |
|   r.bottom = t.v; r.right = t.h;
 | |
| 
 | |
| #if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_WIN32
 | |
|   if (flag & 2)
 | |
|   {
 | |
|     r.left += CHARX>>1; r.top += CHARY>>1;
 | |
|     r.right-= CHARX>>1; r.bottom -= CHARY>>1;
 | |
|   }
 | |
| #endif
 | |
| 
 | |
|   xvt_dwin_draw_rect(win(), &r);
 | |
| 
 | |
|   if (saved) restore_ctools();
 | |
| }
 | |
| 
 | |
| 
 | |
| void TWindow::rect(short left, short top, short right, short bottom)
 | |
| {
 | |
|   frame(left, top, right, bottom, 2);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TWindow::bar(short left, short top, short right, short bottom)
 | |
| {
 | |
|   frame(left, top, right, bottom, 1);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TWindow::invert_bar(short left, short top, short right, short bottom)
 | |
| {
 | |
|   frame(left, top, right, bottom, 5);
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Setta opaque_text
 | |
| void TWindow::set_opaque_text(
 | |
|   bool o) // @parm Indica la modalita' di scrittura dell'opaque_text
 | |
| {
 | |
|   // @comm Quando <p o> e' FALSE il testo viene scritto in modo trasparente
 | |
|   DRAW_CTOOLS ct;
 | |
|   xvt_dwin_get_draw_ctools(win(), &ct);
 | |
|   ct.opaque_text = o;
 | |
|   xvt_dwin_set_draw_ctools(win(), &ct);
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Sceglie il font da utilizzare nella finestra
 | |
| void TWindow::set_font(
 | |
|   const char* family, // @parm Famiglia di appartenenza del font (default XVT_FFN_FIXED)
 | |
|   int style,          // @parm Stile del font (default 0)
 | |
|   int dim)            // @parm Dimensione del font (default 0)
 | |
| {
 | |
|   xvt_set_font(win(), family, style, dim);
 | |
| }
 | |
| 
 | |
| PNT TWindow::log2dev(long x, long y) const
 | |
| {
 | |
|   PNT pnt;
 | |
| 
 | |
|   pnt.h = (int)x;
 | |
|   pnt.v = (int)y;
 | |
| 
 | |
|   if (!_pixmap)
 | |
|   {
 | |
|     pnt.h *= CHARX;
 | |
|     pnt.v *= CHARY;
 | |
|   }
 | |
|   
 | |
|   return pnt;
 | |
| }
 | |
| 
 | |
| TPoint TWindow::dev2log(const PNT& p) const
 | |
| {
 | |
|   TPoint pnt(_pixmap ? p.h : p.h/CHARX, _pixmap ? p.v : p.v/CHARY);
 | |
|   return pnt;
 | |
| }
 | |
| 
 | |
| 
 | |
| void TWindow::stringat(short x, short y, const char* str)
 | |
| {
 | |
|   PNT pnt = log2dev(x,y);
 | |
| #if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_WIN32
 | |
|   pnt.v += BASEY;
 | |
| #endif
 | |
| 
 | |
|   xvt_dwin_draw_text(win(), pnt.h, pnt.v, (char *)str, -1);
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Scrive il testo formattato nella finestra all posizione indicata
 | |
| void TWindow::printat(
 | |
|   short x,         // @parm Coordinata x della finestra in cui scrivere il testo
 | |
|   short y,         // @parm Coordinata y della finestra in cui scrivere il testo
 | |
|   const char* fmt, // @parm Formato che deve essere dato al testo
 | |
|   ...)             // @parmvar Uno o piu' parametri corrispondenti ai codici in <p fmt>
 | |
| {
 | |
|   va_list argptr;
 | |
|   va_start(argptr, fmt);
 | |
|   vsprintf(__tmp_string, fmt, argptr);
 | |
|   va_end(argptr);
 | |
|   stringat(x, y, __tmp_string);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TWindow::line(short x0, short y0, short x1, short y1)
 | |
| {
 | |
|   PNT f = log2dev(x0,y0);
 | |
|   PNT t = log2dev(x1,y1);
 | |
| 
 | |
| #if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_WIN32
 | |
|   if (f.h == 0) f.h = -CHARX; else f.h += CHARX>>1;
 | |
|   if (f.v == 0) f.v = -CHARY; else f.v += CHARY>>1;
 | |
|   if (t.h == 0) t.h = -CHARX; else t.h += CHARX>>1;
 | |
|   if (t.v == 0) t.v = -CHARY; else t.v += CHARY>>1;
 | |
| #endif
 | |
| 
 | |
|   xvt_dwin_draw_set_pos(win(), f);
 | |
|   xvt_dwin_draw_line(win(), t);
 | |
| }
 | |
| 
 | |
| void TWindow::icon(short x0, short y0, int iconid)
 | |
| {
 | |
| #if XVT_OS == XVT_OS_SCOUNIX
 | |
|   bar(x0, y0, x0+1, y0+1);
 | |
| #else
 | |
|   PNT f = log2dev(x0,y0);
 | |
|   if (iconid < 0) iconid = ICON_RSRC;
 | |
|   xvt_dwin_draw_icon(win(), f.h, f.v, iconid);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void TWindow::clear(COLOR color)
 | |
| { xvt_dwin_clear(win(), color); }
 | |
| 
 | |
| void TWindow::set_mode(DRAW_MODE mode)
 | |
| { xvt_dwin_set_draw_mode(win(), mode); }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Aggiunge voci di menu' durante l'esecuzione di una finestra
 | |
| //
 | |
| // @rdesc Ritorna se e' riuscito ad aggiungere la voce al menu':
 | |
| //
 | |
| // @flag TRUE | Se ha ggiunto la voce
 | |
| // @flag FALSE | Se non ha ggiunto la voce
 | |
| bool TWindow::add_menu(
 | |
|   TString_array& menu, // @parm Array da aggiungere al menu'
 | |
|   MENU_TAG id,         // @parm Identificatore del menu' a cui aggiungere le voci
 | |
|   bool force)          // @parm Mai usato
 | |
|   
 | |
|   // @comm Nel caso <p id> sia uguale a 0 la voce veine aggiunte nella barra dei menu'
 | |
| { 
 | |
|   CHECK(menu.items() > 0, "TWindow::add_menu: no menus to add");
 | |
| 
 | |
|   // get menu tree
 | |
|   MENU_ITEM* menubar = xvt_menu_get_tree(win());
 | |
|   
 | |
|   if (id == 0)  // add to menubar
 | |
|   {
 | |
|     // count menus
 | |
|     for (int nmen = 0; menubar[nmen].tag != 0; nmen++);           
 | |
|     menubar = (MENU_ITEM*)xvt_mem_realloc((DATA_PTR)menubar, 
 | |
|                                           sizeof(MENU_ITEM)*(nmen+menu.items()+1));
 | |
|     // zero new
 | |
|     xvt_mem_rep((DATA_PTR)&menubar[nmen], "\0", 1, sizeof(MENU_ITEM)*(menu.items()+1));
 | |
| 
 | |
|     // add new menus
 | |
|     for (int i = 0; i < menu.items(); i++)
 | |
|       set_menu_item(menubar[nmen+i], menu.row(i));
 | |
|   }   
 | |
|   else  // add to menu
 | |
|   {
 | |
|     MENU_ITEM* father = find_menu_item(menubar, id, TRUE);
 | |
|     CHECK(father != NULL, "TWindow::add_menu: you're adding to a NULL menu item");
 | |
|     
 | |
|     // count children
 | |
|     for (int nmen = 0; father->child != NULL && father->child[nmen].tag != 0; nmen++);           
 | |
|     father->child = (MENU_ITEM*)xvt_mem_realloc((DATA_PTR)father->child, 
 | |
|                                                 sizeof(MENU_ITEM)*(nmen+menu.items()+1));
 | |
|     // zero new
 | |
|     xvt_mem_rep((DATA_PTR)&(father->child[nmen]), "\0", 1, sizeof(MENU_ITEM)*(menu.items()+1));
 | |
| 
 | |
|     // add new menus
 | |
|     for (int i = 0; i < menu.items(); i++)
 | |
|       set_menu_item(father->child[nmen+i], menu.row(i));    
 | |
|   }
 | |
|   
 | |
|   xvt_menu_set_tree(win(), menubar);              
 | |
|   xvt_res_free_menu_tree(menubar);
 | |
|   
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| bool TWindow::remove_menu(MENU_TAG id)
 | |
| {
 | |
|   MENU_ITEM* menubar = xvt_menu_get_tree(win());
 | |
|   if (remove_menu_item(menubar, id, TRUE))
 | |
|   {
 | |
|     xvt_menu_set_tree(win(),menubar);
 | |
|     xvt_res_free_menu_tree(menubar);
 | |
|   }                                 
 | |
|   return TRUE;
 | |
| }                                                          
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TTemp_window
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TTemp_window::TTemp_window(WINDOW w)
 | |
| {
 | |
|   set_win(w);
 | |
| }
 | |
| 
 | |
| TTemp_window::~TTemp_window()
 | |
| {
 | |
|   set_win(NULL_WIN);    // I don't want to be closed!
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TScroll_window
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| TScroll_window::TScroll_window()
 | |
| : _origin(0, 0), _max(0, 0), _shift(0), _autoscroll(TRUE),
 | |
|   _has_hscroll(TRUE), _has_vscroll(TRUE)
 | |
| {
 | |
| }
 | |
| 
 | |
| WINDOW TScroll_window::create(short x, short y, short dx, short dy,
 | |
|                               const char* title, long flags, WIN_TYPE wt, WINDOW parent, int menu)
 | |
| {
 | |
|   _has_hscroll = (flags & WSF_HSCROLL) != 0;
 | |
|   _has_vscroll = (flags & WSF_VSCROLL) != 0 ;
 | |
|   return TWindow::create(x, y, dx, dy, title, flags, wt, parent, menu);
 | |
| }
 | |
| 
 | |
| PNT TScroll_window::log2dev(long x, long y) const
 | |
| {
 | |
|   if (_autoscroll)
 | |
|   {
 | |
|     x -= _origin.x;
 | |
|     y -= _origin.y >> _shift;
 | |
|   }
 | |
|   return TWindow::log2dev(x,y);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TScroll_window::set_scroll_max(long maxx, long maxy)
 | |
| {
 | |
|   if (_has_hscroll && maxx >= 0)
 | |
|   {
 | |
|     _max.x = maxx;
 | |
|     xvt_sbar_set_range(win(), HSCROLL, 0, int(maxx));
 | |
|   }
 | |
|   if (_has_vscroll && maxy >= 0)
 | |
|   {
 | |
|     _shift = 0;
 | |
|     while ((maxy >> _shift) > 0x7FFF) _shift++;
 | |
|     _max.y = maxy;
 | |
|     xvt_sbar_set_range(win(), VSCROLL, 0, int(maxy >> _shift));
 | |
|   }
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Aggiorna la scrollbar
 | |
| void TScroll_window::update_thumb(
 | |
|   long x, // @parm Indica la posizione in x in cui spostare la finestra (default -1)
 | |
|   long y) // @parm Indica la posizione in x in cui spostare la finestra (default -1)
 | |
|   
 | |
|   // @comm Nel caso si voglia aggiornare solamente una coordinata l'altra dovra' essere
 | |
|   //                     settata a -1     
 | |
| {
 | |
|   if (x >= 0 && x <= _max.x) _origin.x = x;
 | |
|   if (y >= 0 && y <= _max.y) _origin.y = y;
 | |
| 
 | |
|   if (_has_hscroll)
 | |
|     xvt_sbar_set_pos(win(), HSCROLL, int(_origin.x));
 | |
|   if (_has_vscroll)
 | |
|     xvt_sbar_set_pos(win(), VSCROLL, int(_origin.y >> _shift));
 | |
| }
 | |
| 
 | |
| void TScroll_window::handler(WINDOW win, EVENT* ep)
 | |
| {
 | |
|   bool up = FALSE;
 | |
| 
 | |
|   switch (ep->type)
 | |
|   {
 | |
|   case E_HSCROLL:
 | |
|   case E_VSCROLL:
 | |
|   {
 | |
|     long& pos = (ep->type == E_HSCROLL) ? _origin.x : _origin.y;
 | |
|     const long max = (ep->type == E_HSCROLL) ? _max.x : _max.y;
 | |
|     const short pag = (ep->type == E_HSCROLL) ? columns()/2+1 : rows()/2+1;
 | |
|     switch(ep->v.scroll.what)
 | |
|     {
 | |
|     case SC_PAGE_UP:
 | |
|       pos -= pag;
 | |
|       up = TRUE;
 | |
|       break;
 | |
|     case SC_LINE_UP:
 | |
|       pos--;
 | |
|       up = TRUE;
 | |
|       break;
 | |
|     case SC_PAGE_DOWN:
 | |
|       pos += pag;
 | |
|       up = TRUE;
 | |
|       break;
 | |
|     case SC_LINE_DOWN:
 | |
|       pos++;
 | |
|       up = TRUE;
 | |
|       break;
 | |
|     case SC_THUMB:
 | |
|       pos = ep->v.scroll.pos;
 | |
|       up = TRUE;
 | |
|       break;
 | |
|     default:
 | |
|       break;
 | |
|     }
 | |
|     if (pos < 0) pos = 0;
 | |
|     if (pos > max) pos = max;
 | |
|   }
 | |
|   break;
 | |
| default:
 | |
|   break;
 | |
| }
 | |
| 
 | |
|   if (up)
 | |
|   {
 | |
|     update_thumb();
 | |
|     force_update();
 | |
|   }
 | |
| 
 | |
|   TWindow::handler(win, ep);
 | |
| }
 | |
| 
 | |
| bool TScroll_window::on_key(KEY key)
 | |
| {
 | |
|   switch(key)
 | |
|   {
 | |
|   case K_LHOME:
 | |
|     update_thumb(0,0);
 | |
|     force_update();
 | |
|     break;
 | |
|   case K_LEND:
 | |
|     update_thumb(0,range().y);
 | |
|     force_update();
 | |
|     break;
 | |
|   case K_TAB:
 | |
|     update_thumb(origin().x+8);
 | |
|     force_update();
 | |
|     break;
 | |
|   case K_BTAB:
 | |
|   {
 | |
|     long x = origin().x-8;
 | |
|     if (x < 0) x = 0;
 | |
|     update_thumb(x);
 | |
|     force_update();
 | |
|   }
 | |
|     break;
 | |
|   case K_UP:
 | |
|   case K_DOWN:
 | |
|   case K_PREV:
 | |
|   case K_NEXT:
 | |
|   case K_LEFT:
 | |
|   case K_RIGHT:
 | |
|     dispatch_e_scroll(win(), key);
 | |
|     break;
 | |
|   default:
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   return TWindow::on_key(key);
 | |
| }
 | |
| 
 |