Adonthell
0.4
|
00001 /* 00002 $Id: win_select.cc,v 1.7 2002/01/05 21:22:56 ksterker Exp $ 00003 00004 (C) Copyright 2000 Joel Vennin 00005 Part of the Adonthell Project http://adonthell.linuxgames.com 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License. 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT AN Y WARRANTY. 00011 00012 See the COPYING file for more details 00013 */ 00014 00015 #include "win_select.h" 00016 00017 #include "audio.h" 00018 00019 win_select::win_select() 00020 { 00021 cur_select_ = list_wb_.begin(); 00022 00023 set_mode(MODE_BRIGHTNESS); 00024 00025 border_select_ = NULL; 00026 00027 set_circle(false); 00028 00029 finish_scroll_ = true; 00030 //set_visible_scrollbar(false); 00031 } 00032 00033 00034 void win_select::add(win_base * w) 00035 { 00036 win_scroll::add(w); 00037 cur_select_ = list_wb_.begin (); 00038 //if select has a border for the selection, just set border to the win_base added 00039 if(border_select_ != NULL) w->set_border(*border_select_); 00040 00041 //set the object to unselect 00042 rules(false, w); 00043 00044 set_default(); 00045 00046 //update_cur_select_position(); 00047 } 00048 00049 00050 void win_select::remove(win_base * w) 00051 { 00052 rules(false, w); 00053 00054 win_scroll::remove(w); 00055 00056 set_default(); 00057 } 00058 00059 00060 void win_select::remove_all() 00061 { 00062 win_scroll::remove_all(); 00063 cur_select_ = list_wb_.begin(); 00064 } 00065 00066 00067 void win_select::next() 00068 { 00069 //test if next possible 00070 if(cur_select_ == list_wb_.end() || list_wb_.size() == 0) return; 00071 00072 audio::play_wave (-1, 1); 00073 (*cur_select_)->on_unselect(); 00074 00075 //unselect cur element 00076 rules(false,*cur_select_); 00077 (*cur_select_)->set_activate (false); 00078 00079 //create a temporary index 00080 lwb :: iterator i = cur_select_; 00081 00082 //go next 00083 i++; 00084 00085 //while not a the end, not be selected and different at old object go to the next 00086 while( i != list_wb_.end() && !(*i)->is_can_be_selected() && i != cur_select_) i++; 00087 00088 //if at end of list and select circle is activate 00089 if(i == list_wb_.end()) 00090 { 00091 //cur is the begin of list 00092 if( circle_ ) 00093 { 00094 i = list_wb_.begin(); 00095 while(i != list_wb_.end() && !(*i)->is_can_be_selected() && i != cur_select_) i++; 00096 if(i != list_wb_.end()) cur_select_ = i; 00097 } 00098 }else cur_select_ = i; 00099 00100 rules(true,*cur_select_); 00101 00102 (*cur_select_)->on_select(); 00103 00104 on_next(); 00105 00106 finish_scroll_ =false; 00107 00108 //update_cur_select_position(); 00109 } 00110 00111 00112 void win_select::previous() 00113 { 00114 if(cur_select_==list_wb_.end() || list_wb_.size() == 0) return; 00115 00116 audio::play_wave (-1, 1); 00117 (*cur_select_)->on_unselect(); 00118 00119 //set to unselect object 00120 rules(false,*cur_select_); 00121 00122 (*cur_select_)->set_activate (false); 00123 00124 lwb::iterator i=cur_select_; 00125 00126 if(circle_) 00127 { 00128 if(i==list_wb_.begin()) i=list_wb_.end(); 00129 i--; 00130 } 00131 else if(i!=list_wb_.begin()) i--; 00132 00133 while(i != list_wb_.begin() && !(*i)->is_can_be_selected() && i != cur_select_) i--; 00134 00135 if( i== list_wb_.begin() && !(*i)->is_can_be_selected()) 00136 { 00137 if(circle_) 00138 { 00139 i = list_wb_.end(); 00140 i--; 00141 while(i!=list_wb_.begin() && !(*i)->is_can_be_selected() && i!=cur_select_) i--; 00142 if((*i)->is_can_be_selected()) cur_select_=i; 00143 } 00144 } else cur_select_=i; 00145 00146 (*cur_select_)->on_select(); 00147 00148 //set to select object 00149 rules(true,*cur_select_); 00150 00151 //update_position(); 00152 on_previous(); 00153 00154 finish_scroll_ =false; 00155 //update_cur_select_position(); 00156 } 00157 00158 00159 void win_select::activate() 00160 { 00161 if(cur_select_ == list_wb_.end()) return; 00162 00163 audio::play_wave (-1, 0); 00164 00165 //set_activate(false); 00166 00167 (*cur_select_)->set_activate(true); 00168 00169 on_activate_key(); 00170 } 00171 00172 00173 bool win_select::input_update() 00174 { 00175 00176 if(win_scroll::input_update()) 00177 { 00178 if(focus_object_) return true; 00179 00180 if(input::has_been_pushed(win_keys::KEY_NEXT)) next(); 00181 if(input::has_been_pushed(win_keys::KEY_PREVIOUS)) previous(); 00182 if(input::has_been_pushed(win_keys::KEY_ACTIVATE) || 00183 input::has_been_pushed(win_keys::KEY_ACTIVATE_ENTRY)) activate(); 00184 00185 return true; 00186 } 00187 return false; 00188 } 00189 00190 void win_select::rules(const bool b, win_base * wb) 00191 { 00192 if(!wb->is_can_be_selected()) return; 00193 00194 switch(mode_) 00195 { 00196 case MODE_BORDER: 00197 wb->set_visible_border(b); 00198 break; 00199 00200 case MODE_BRIGHTNESS: 00201 wb->set_brightness(!b); 00202 break; 00203 } 00204 } 00205 00206 00207 void win_select::set_default() 00208 { 00209 if(list_wb_.size() == 0) return; 00210 00211 if(cur_select_ != list_wb_.end()) 00212 { 00213 rules(false,*cur_select_); 00214 } 00215 00216 cur_select_ = list_wb_.begin(); 00217 00218 while(cur_select_ != list_wb_.end() && !(*cur_select_)->is_can_be_selected()) cur_select_++; 00219 00220 if(cur_select_ != list_wb_.end()) rules(true,*cur_select_); 00221 00222 finish_scroll_ =false; 00223 } 00224 00225 void win_select::set_default_object(const win_base * wb) 00226 { 00227 if(list_wb_.size() == 0) return; 00228 00229 if(cur_select_ != list_wb_.end()) rules(false,*cur_select_); 00230 00231 cur_select_ = list_wb_.begin(); 00232 00233 while(cur_select_ != list_wb_.end() && *cur_select_ != wb) cur_select_++; 00234 00235 if(cur_select_ != list_wb_.end()) rules(true,*cur_select_); 00236 00237 finish_scroll_ =false; 00238 //update_cur_select_position(); 00239 } 00240 00241 00242 void win_select::set_default_position(const u_int16 pos) 00243 { 00244 if(list_wb_.size() == 0 || pos > list_wb_.size()) return; 00245 00246 if(cur_select_ != list_wb_.end()) rules(false,*cur_select_); 00247 00248 cur_select_ = list_wb_.begin(); 00249 00250 u_int16 i = 0; 00251 00252 while(cur_select_ != list_wb_.end() && i++ < pos) cur_select_++; 00253 00254 if(cur_select_ != list_wb_.end()) rules(true,*cur_select_); 00255 00256 finish_scroll_ =false; 00257 //update_cur_select_position(); 00258 } 00259 00260 00261 win_base * win_select::get_selected_object() 00262 { 00263 if(cur_select_ != list_wb_.end() || list_wb_.size() == 0) return *cur_select_; 00264 else return NULL; 00265 } 00266 00267 u_int16 win_select::get_selected_position() 00268 { 00269 u_int16 pos_=0; 00270 00271 lwb::iterator i = list_wb_.begin(); 00272 00273 if(i==list_wb_.end()) return 0; 00274 00275 while( (*i++) != (*cur_select_)) pos_++; 00276 00277 return pos_+1; 00278 } 00279 00280 00281 00282 void win_select::update_cur_select_position() 00283 { 00284 if(!max_amplitude_) return; 00285 00286 while( 1 ) 00287 { 00288 // if((*cur_select_)->height() > height() + (space_with_border_ << 1) ) break; 00289 // Workaround if the object is bigger than the select (Alex). 00290 if((*cur_select_)->height() + (space_with_border_ << 1) > height()) break; 00291 else if((*cur_select_)->y() + (*cur_select_)->pad_y() < space_with_border_ ) up(); 00292 else if((*cur_select_)->y() + (*cur_select_)->pad_y() + (*cur_select_)->height() > height() - space_with_border_) down(); 00293 else break; 00294 } 00295 } 00296 00297 00298 bool win_select::update() 00299 { 00300 if(win_scroll::update()) 00301 { 00302 if(!finish_scroll_) 00303 { 00304 if(!max_amplitude_) {finish_scroll_=true;return true;} 00305 if((*cur_select_)->height() + (space_with_border_ << 1) > height()) {finish_scroll_ = true; return true;} 00306 else if((*cur_select_)->y() + (*cur_select_)->pad_y() < space_with_border_ ) up(); 00307 else if((*cur_select_)->y() + (*cur_select_)->pad_y() + (*cur_select_)->height() > height() - space_with_border_) down(); 00308 else finish_scroll_ = true; 00309 } 00310 return true; 00311 } 00312 return false; 00313 } 00314 00315 00316 00317 /* 00318 #include <list> 00319 #include "types.h" 00320 #include "input.h" 00321 #include "image.h" 00322 #include "win_types.h" 00323 #include "win_base.h" 00324 #include "win_border.h" 00325 #include "win_scrollbar.h" 00326 #include "win_theme.h" 00327 #include "win_container.h" 00328 #include "win_scrolled.h" 00329 #include "win_select.h" 00330 00331 //STATIC INIT 00332 win_select * win_select::curselect_=NULL; 00333 bool win_select::activate_keyboard_=true; 00334 00335 s_int32 win_select::next_key=WIN_SELECT_DEFAULT_KEY_NEXT; 00336 s_int32 win_select::previous_key=WIN_SELECT_DEFAULT_KEY_PREVIOUS; 00337 s_int32 win_select::activate_key=WIN_SELECT_DEFAULT_KEY_ACTIVATE; 00338 s_int32 win_select::back_key=WIN_SELECT_DEFAULT_KEY_BACK; 00339 00340 00341 win_select::win_select(s_int16 tx,s_int16 ty,u_int16 tl,u_int16 th,win_theme * wth):win_scrolled(tx,ty,tl,th,wth) 00342 { 00343 //father select is the father of this object 00344 fatherselect_=NULL; 00345 //if there are no select object attached to the static curselet, this object become the curselect 00346 if(!curselect_) curselect_=this; 00347 00348 index_list=list_obj.begin(); 00349 //the default mode select for this object is the border 00350 mode_selected_=WIN_SELECT_MODE_BORDER; 00351 //by default, the scroll bar is not visible 00352 visible_scrollbar_=false; 00353 //if when you select you change the first to the last 00354 select_circle_=false; 00355 00356 //type of the select 00357 type_selected_=WIN_SELECT_TYPE_NORMAL; 00358 00359 } 00360 00361 00362 win_select::~win_select() 00363 { 00364 //WARNING CHECK BACK 00365 if(curselect_==this) 00366 { 00367 back(); 00368 curselect_=NULL; 00369 } 00370 //WARNING DESTROY() 00371 } 00372 00373 00374 void win_select::add(win_base * wb) 00375 { 00376 //call the add of win_scrolled 00377 win_scrolled::add(wb); 00378 00379 //prevent the new object is in select 00380 wb->set_in_select(true); 00381 00382 //set the parameters for this object 00383 set_select_object(wb,false); 00384 00385 //when you add an object, automatically the index become the first element of the list 00386 set_default(); 00387 00388 //a select can have just one mode to select each object in the list 00389 wb->set_select_mode_(mode_selected_); 00390 } 00391 00392 void win_select::add(win_select * ws) 00393 { 00394 //add a select object 00395 win_select::add((win_base*)ws); 00396 //add the object but prevent the new object that this objetc is the father 00397 ws->fatherselect_=this; 00398 } 00399 00400 void win_select::remove(win_base * wb) 00401 { 00402 //remove an objetc prevent that the object is not in_select 00403 win_scrolled::remove(wb); 00404 wb->set_in_select(false); 00405 wb->set_draw_brightness(false); 00406 index_list=list_obj.begin(); 00407 } 00408 00409 void win_select::remove_all() 00410 { 00411 for(list<win_base *>::iterator i=list_obj.begin();i!=list_obj.end();i++) 00412 { 00413 (*i)->set_in_select(false); 00414 (*i)->wb_father_=NULL;//part of win_container 00415 } 00416 list_obj.clear(); 00417 index_list=list_obj.begin(); 00418 00419 //win scrolled part 00420 max_amplitude_=0; 00421 cur_amplitude_=0; 00422 theme_->scrollbar->update_scroll_bar(this); 00423 } 00424 00425 void win_select::destroy() 00426 { 00427 win_scrolled::destroy(); 00428 index_list=list_obj.begin(); 00429 } 00430 00431 00432 void win_select::on_next() 00433 { 00434 if(callback_[WIN_SIG_NEXT_KEY]) (callback_[WIN_SIG_NEXT_KEY])(); 00435 } 00436 00437 void win_select::on_previous() 00438 { 00439 if(callback_[WIN_SIG_PREVIOUS_KEY]) (callback_[WIN_SIG_PREVIOUS_KEY])(); 00440 } 00441 00442 bool win_select::update() 00443 { 00444 if(win_scrolled::update()) 00445 { 00446 if(focus_ && activate_keyboard_ && activated_) 00447 { 00448 if(input::has_been_pushed (SDLKey (next_key))) next_(); 00449 if(input::has_been_pushed (SDLKey (previous_key))) previous_(); 00450 if(input::has_been_pushed (SDLKey (back_key))) back(); 00451 if(input::has_been_pushed (SDLKey (activate_key))) activate___(); 00452 } 00453 return true; 00454 } 00455 return false; 00456 } 00457 00458 //if b is true, cur object take parameters to an selected object 00459 void win_select::set_select_object(win_base * wb,bool b) 00460 { 00461 switch(mode_selected_) 00462 { 00463 case WIN_SELECT_MODE_BRIGHTNESS: 00464 wb->set_draw_brightness(!b); 00465 break; 00466 case WIN_SELECT_MODE_BORDER: 00467 wb->set_border_visible(b); 00468 } 00469 00470 switch(type_selected_) 00471 { 00472 case WIN_SELECT_TYPE_NORMAL: 00473 wb->set_visible(true); 00474 break; 00475 case WIN_SELECT_TYPE_SCROLL: 00476 wb->set_visible(b); 00477 break; 00478 } 00479 } 00480 00481 00482 //WARNING: lots of confuse in next_ and previous maybe rewrite them 00483 void win_select::next_() 00484 { 00485 //test if next is possible 00486 if(index_list==list_obj.end() || !activated_) return; 00487 00488 //unselect cur element 00489 (*index_list)->on_unselect(); 00490 00491 set_select_object(*index_list,false); 00492 00493 //create a temporary index 00494 list<win_base*>::iterator cur_i=index_list; 00495 00496 //to next elements 00497 cur_i++; 00498 00499 //while not a the end, not be selected and different at old object go to the next 00500 while(cur_i!=list_obj.end() && !(*cur_i)->is_can_be_selected() && cur_i!=index_list) cur_i++; 00501 00502 //if at end of list and select circle is activate 00503 if(cur_i==list_obj.end()) 00504 { 00505 //cur is the begin of list 00506 if(select_circle_) 00507 { 00508 cur_i=list_obj.begin(); 00509 while(cur_i!=list_obj.end() && !(*cur_i)->is_can_be_selected() && cur_i!=index_list) cur_i++; 00510 if(cur_i!=list_obj.end()) index_list=cur_i; 00511 } 00512 }else index_list=cur_i; 00513 00514 set_select_object(*index_list,true); 00515 00516 (*index_list)->on_select(); 00517 00518 update_position(); 00519 00520 on_next(); 00521 } 00522 00523 void win_select::previous_() 00524 { 00525 if(index_list==list_obj.end() || !activated_) return; 00526 00527 (*index_list)->on_unselect(); 00528 00529 //set to unselect object 00530 set_select_object(*index_list,false); 00531 00532 list<win_base*>::iterator cur_i=index_list; 00533 00534 00535 00536 if(select_circle_) 00537 { 00538 00539 if(cur_i==list_obj.begin()) cur_i=list_obj.end(); 00540 cur_i--; 00541 } 00542 else if(cur_i!=list_obj.begin()) cur_i--; 00543 00544 00545 00546 00547 00548 00549 00550 while(cur_i!=list_obj.begin() && !(*cur_i)->is_can_be_selected() && cur_i!=index_list) cur_i--; 00551 00552 if(cur_i==list_obj.begin() && !(*cur_i)->is_can_be_selected()) 00553 { 00554 if(select_circle_) 00555 { 00556 00557 cur_i=list_obj.end(); 00558 cur_i--; 00559 00560 while(cur_i!=list_obj.begin() && !(*cur_i)->is_can_be_selected() && cur_i!=index_list) cur_i--; 00561 if((*cur_i)->is_can_be_selected()) index_list=cur_i; 00562 } 00563 } else index_list=cur_i; 00564 00565 (*index_list)->on_select(); 00566 00567 00568 //set to select object 00569 set_select_object(*index_list,true); 00570 00571 update_position(); 00572 on_previous(); 00573 00574 } 00575 00576 00577 void win_select::set_can_be_selected_all(bool b) 00578 { 00579 for(list<win_base*>::iterator i=list_obj.begin();i!=list_obj.end();i++) 00580 (*i)->set_can_be_selected(b); 00581 } 00582 00583 void win_select::set_default() 00584 { 00585 if(list_obj.size()==0) return; 00586 00587 if(index_list!=list_obj.end()) set_select_object(*index_list,false); 00588 00589 index_list=list_obj.begin(); 00590 00591 while(index_list!=list_obj.end() && !(*index_list)->is_can_be_selected()) index_list++; 00592 00593 if(index_list!=list_obj.end()) set_select_object(*index_list,true); 00594 } 00595 00596 00597 void win_select::update_position() 00598 { 00599 00600 //this function is used to see the cur object which is selected 00601 static bool tmp_is_visible_; 00602 00603 //if(index_list==list_obj.end()){cout << "tets\n"; return;} 00604 00605 switch(type_selected_) 00606 { 00607 case WIN_SELECT_TYPE_NORMAL: 00608 tmp_is_visible_=false; 00609 //if not amplitude --> all object in the list is visible 00610 if(!max_amplitude_) {tmp_is_visible_=true;return;} 00611 while(!tmp_is_visible_) 00612 { 00613 00614 // if(((*index_list)->y()+(*index_list)->pady()>space_between_border_) && 00615 // ((*index_list)->y()+(*index_list)->height()>height_-space_between_border_)) {tmp_is_visible_=true;cout << "16\n";} 00616 if((*index_list)->height()>height_+(space_between_border_<<1)) tmp_is_visible_=true; 00617 00618 else if((*index_list)->y()+(*index_list)->pady()<space_between_border_) up(); 00619 else if((*index_list)->y()+(*index_list)->pady()+(*index_list)->height()>height_-space_between_border_) down(); 00620 else tmp_is_visible_=true; 00621 } 00622 break; 00623 00624 case WIN_SELECT_TYPE_SCROLL: 00625 //set position of the cur select object 00626 00627 (*index_list)->move(space_between_border_,space_between_border_); 00628 00629 break; 00630 default: 00631 break; 00632 } 00633 } 00634 00635 00636 void win_select::set_type(u_int8 t) 00637 { 00638 type_selected_=t; 00639 //set all object to the new type set 00640 for(list<win_base*>::iterator i=list_obj.begin();i!=list_obj.end();i++) 00641 set_select_object(*i,false); 00642 00643 //select the first object 00644 set_default(); 00645 } 00646 00647 00648 00649 //return the cur object which is selected 00650 win_base * win_select::get() 00651 { 00652 if(index_list==list_obj.end()) return NULL; 00653 else return (*index_list); 00654 } 00655 00656 //if error return 0 00657 u_int16 win_select::get_pos() 00658 { 00659 u_int16 pos_=0; 00660 list<win_base *>::iterator i=list_obj.begin(); 00661 if(i==list_obj.end()) return 0; 00662 while((*i++)!=(*index_list)) pos_++; 00663 return pos_+1; 00664 } 00665 00666 void win_select::set_default(u_int16 nb) 00667 { 00668 if(index_list==list_obj.end()) return; 00669 u_int16 j=1; 00670 (*index_list)->set_select(false); 00671 if(mode_selected_==WIN_SELECT_MODE_BRIGHTNESS) 00672 (*index_list)->set_draw_brightness(true); 00673 else if(mode_selected_==WIN_SELECT_MODE_BORDER) 00674 (*index_list)->set_border_visible(false); 00675 00676 index_list=list_obj.begin(); 00677 while(index_list!=list_obj.end() && j++<nb) index_list++; 00678 if(index_list!=list_obj.end()) 00679 { 00680 (*index_list)->set_select(true); 00681 if(mode_selected_==WIN_SELECT_MODE_BRIGHTNESS) 00682 (*index_list)->set_draw_brightness(false); 00683 else if(mode_selected_==WIN_SELECT_MODE_BORDER) 00684 (*index_list)->set_border_visible(true); 00685 } 00686 } 00687 00688 void win_select::set_default(win_base * wb) 00689 { 00690 if(index_list==list_obj.end()) return; 00691 (*index_list)->set_select(false); 00692 00693 if(mode_selected_==WIN_SELECT_MODE_BRIGHTNESS) 00694 (*index_list)->set_draw_brightness(true); 00695 else if(mode_selected_==WIN_SELECT_MODE_BORDER) 00696 (*index_list)->set_border_visible(false); 00697 00698 index_list=list_obj.begin(); 00699 while(index_list != list_obj.end() && (*index_list)!=wb) index_list++; 00700 if(index_list!=list_obj.end()) 00701 { 00702 (*index_list)->set_select(true); 00703 if(mode_selected_==WIN_SELECT_MODE_BRIGHTNESS) 00704 (*index_list)->set_draw_brightness(false); 00705 else if(mode_selected_==WIN_SELECT_MODE_BORDER) 00706 (*index_list)->set_border_visible(true); 00707 } 00708 } 00709 00710 void win_select::set_select_mode(u_int8 mode) 00711 { 00712 mode_selected_=mode; 00713 if(mode_selected_==WIN_SELECT_MODE_BRIGHTNESS) 00714 for(list<win_base*>::iterator i=list_obj.begin();i!=list_obj.end();i++) 00715 (*i)->set_draw_brightness(true); 00716 if(index_list!=list_obj.end()) (*index_list)->set_draw_brightness(false); 00717 for(list<win_base*>::iterator i=list_obj.begin();i!=list_obj.end();i++) 00718 (*i)->set_select_mode_(mode); 00719 } 00720 00721 void win_select::activate() 00722 { 00723 if(curselect_) curselect_->activate___(); 00724 } 00725 00726 void win_select::next() 00727 { 00728 if(curselect_) curselect_->next_(); 00729 } 00730 00731 void win_select::previous() 00732 { 00733 if(curselect_) curselect_->previous_(); 00734 } 00735 00736 bool win_select::activate___() 00737 { 00738 if(index_list!=list_obj.end()) 00739 { 00740 (*index_list)->set_activated(true); 00741 on_activate_key(); 00742 return true; 00743 } 00744 return false; 00745 } 00746 00747 void win_select::on_activate() 00748 { 00749 win_scrolled::on_activate(); 00750 if(!curselect_) {curselect_=this;return;} 00751 if(curselect_==this) return; 00752 //if curselect 00753 curselect_->on_unactivate(); 00754 curselect_=this; 00755 } 00756 00757 bool win_select::back() 00758 { 00759 //if true we can go to the father 00760 if(curselect_) 00761 { 00762 if(curselect_->fatherselect_) 00763 { 00764 if(curselect_->index_list!=curselect_->list_obj.end()) 00765 { 00766 curselect_->on_unactivate(); 00767 curselect_=curselect_->fatherselect_; 00768 curselect_->on_activate(); 00769 return true; 00770 } 00771 } 00772 } 00773 return false; 00774 } 00775 00776 void win_select::set_cur_select(win_select * ws) 00777 { 00778 if(curselect_ && curselect_!=ws) curselect_->set_activated(false); 00779 curselect_=ws; 00780 } 00781 00782 void win_select::init() 00783 { 00784 if(curselect_) curselect_->set_activated(false); 00785 curselect_=NULL; 00786 } 00787 00788 00789 00790 00791 00792 00793 00794 00795 00796 00797 00798 */ 00799 00800 00801 00802 00803 00804 00805