Curses.pm
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:17k
源码类别:

外挂编程

开发平台:

Windows_Unix

  1. #!/usr/bin/perl
  2. #########################################################################
  3. #  OpenKore - Interface::Console::Curses
  4. #  You need Curses (the Perl bindings for (n)curses)
  5. #
  6. #  Copyright (c) 2004 OpenKore development team 
  7. #
  8. #  This program is free software; you can redistribute it and/or modify
  9. #  it under the terms of the GNU General Public License as published by
  10. #  the Free Software Foundation; either version 2 of the License, or
  11. #  (at your option) any later version.
  12. #
  13. #  This program is distributed in the hope that it will be useful,
  14. #  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. #  GNU General Public License for more details.
  17. #
  18. #
  19. #  $Revision: 5955 $
  20. #  $Id: Curses.pm 5955 2007-09-14 18:15:20Z vcl_kore $
  21. #
  22. #########################################################################
  23. package Interface::Console::Curses;
  24. use strict;
  25. use Curses;
  26. use Time::HiRes qw(time usleep);
  27. use Globals;
  28. use Utils;
  29. use base qw(Interface::Console);
  30. use Modules;
  31. use constant MAXHISTORY => 50;
  32. sub new {
  33. my %interface = ();
  34. bless %interface, __PACKAGE__;
  35. my $self = %interface;
  36. initscr;
  37. idlok 1;
  38. idcok 1;
  39. nonl;
  40. cbreak;
  41. noecho;
  42. intrflush 1;
  43. keypad 1;
  44. nodelay 1;
  45. start_color;
  46. use_default_colors;
  47. init_pair(1, COLOR_BLACK, -1);
  48. init_pair(2, COLOR_RED, -1);
  49. init_pair(3, COLOR_GREEN, -1);
  50. init_pair(4, COLOR_YELLOW, -1);
  51. init_pair(5, COLOR_BLUE, -1);
  52. init_pair(6, COLOR_MAGENTA, -1);
  53. init_pair(7, COLOR_CYAN, -1);
  54. init_pair(8, COLOR_WHITE, -1);
  55. $self->{winStatus} = newwin(4, 0, 0, 0);
  56. $self->{winObjects} = newwin($LINES-5, 15, 4, $COLS-15);
  57. $self->{winLog} = newwin($LINES-5, $COLS-15, 4, 0);
  58. scrollok $self->{winLog}, 1;
  59. $self->{winInput} = newwin(1, 0, $LINES-1, 0);
  60. $self->updateLayout;
  61. $self->setCursor;
  62. $self->{time_start} = time;
  63. return %interface;
  64. }
  65. sub DESTROY {
  66. my $self = shift;
  67. delwin $self->{winHelp} if ($self->{winHelp});
  68. delwin $self->{winInput};
  69. delwin $self->{winChat} if ($self->{winChat});
  70. delwin $self->{winLog};
  71. delwin $self->{winFight} if ($self->{winFight});
  72. delwin $self->{winObjects} if ($self->{winObjects});
  73. delwin $self->{winStatus};
  74. endwin;
  75. }
  76. sub iterate {
  77. my $self = shift;
  78. return if (!timeOut($self->{time_refresh}, 0.5));
  79. $self->{time_refresh} = time;
  80. if ($self->{lines} != $LINES || $self->{cols} != $COLS) {
  81. $self->updateLayout;
  82. } else {
  83. $self->updatePeriodic;
  84. }
  85. $self->setCursor;
  86. }
  87. sub getInput {
  88. my $self = shift;
  89. my $timeout = shift;
  90. my $msg;
  91. if ($timeout < 0) {
  92. while (!defined($msg)) {
  93. $msg = $self->readEvents;
  94. usleep 10000 unless defined $msg;
  95. }
  96. } elsif ($timeout > 0) {
  97. my $startTime = time;
  98. while (!timeOut($startTime, $timeout)) {
  99. $msg = $self->readEvents;
  100. last if (defined $msg);
  101. usleep 10000;
  102. }
  103. } else {
  104. $msg = $self->readEvents;
  105. }
  106. undef $msg if (defined $msg && $msg eq "");
  107. return $msg;
  108. }
  109. sub writeOutput {
  110. my $self = shift;
  111. my $type = shift;
  112. my $msg = shift;
  113. my $domain = shift;
  114. my @localtime = localtime time;
  115. my $time = sprintf("%02d:%02d:%02d", $localtime[2], $localtime[1], $localtime[0]);
  116. my $color = $consoleColors{$type}{$domain} ne "" ? lc($consoleColors{$type}{$domain}) : lc($consoleColors{$type}{default});
  117. $color = "bold|" . $color unless $color eq "" || $color =~ /^dark/;
  118. $color =~ s/^dark//g;
  119. $color =~ s/gr[ae]y/white/g;
  120. $color = "{" . $color . "}" unless $color eq "";
  121. foreach my $s (split("n", $msg)) {
  122. if ($self->{winFight} && existsInList("attackMon,attackMonMiss,attacked,attackedMiss,skill,parseMsg_damage", $domain)) {
  123. scroll $self->{winFight};
  124. $self->printw($self->{winFight}, $self->{winFightHeight} - 2, 0, "{normal}@<<<<<<< $color@*", $time, $s);
  125. } elsif ($self->{winChat} && existsInList("emotion,gmchat,guildchat,partychat,pm,publicchat,selfchat", $domain)) {
  126. scroll $self->{winChat};
  127. $self->printw($self->{winChat}, $self->{winChatHeight} - 2, 0, "{normal}@<<<<<<< $color@*", $time, $s);
  128. } else {
  129. scroll $self->{winLog};
  130. $self->printw($self->{winLog}, $self->{winLogHeight} - 1, 0, "{normal}@<<<<<<< $color@*", $time, $s);
  131. }
  132. }
  133. noutrefresh $self->{winFight} if $self->{winFight};
  134. noutrefresh $self->{winLog};
  135. noutrefresh $self->{winChat} if $self->{winChat};
  136. $self->updatePopups;
  137. $self->setCursor;
  138. }
  139. sub title {
  140. my $self = shift;
  141. my $title = shift;
  142. }
  143. sub displayUsage {
  144. my $self = shift;
  145. my $text = shift;
  146. print $text;
  147. }
  148. sub errorDialog {
  149. my $self = shift;
  150. my $msg = shift;
  151. my $fatal = shift;
  152. # FIXME: Need better error dialog
  153. print "ERROR: $msg";
  154. }
  155. ################################
  156. sub readEvents {
  157. my $self = shift;
  158. my $ch = getch();
  159. return undef if ($ch eq ERR);
  160. my $ret;
  161. while ($ch ne ERR) {
  162. if ($ch eq "r" || $ch eq KEY_ENTER) {
  163. # Enter
  164. $ret = $self->{inputBuffer};
  165. undef $self->{inputBuffer};
  166. $self->{inputPos} = 0;
  167. if (length($ret) > 0 && $ret ne $self->{inputHistory}[0]) {
  168. unshift @{$self->{inputHistory}}, $ret;
  169. pop @{$self->{inputHistory}} if (@{$self->{inputHistory}} > MAXHISTORY);
  170. }
  171. $self->{inputHistoryPos} = 0;
  172. last;
  173. } elsif ((ord($ch) == 9 || ord($ch) == 127 || $ch eq KEY_BACKSPACE) && $self->{inputBuffer}) {
  174. # Backspace
  175. $self->{inputBuffer} = substr($self->{inputBuffer}, 0, $self->{inputPos} - 1) . substr($self->{inputBuffer}, $self->{inputPos});
  176. $self->{inputPos}--;
  177. } elsif (ord($ch) == 12) {
  178. # Ctrl-L
  179. clear;
  180. $self->updateLayout;
  181. } elsif (ord($ch) == 21) {
  182. # Ctrl-U
  183. undef $self->{inputBuffer};
  184. $self->{inputPos} = 0;
  185. $self->{inputHistoryPos} = 0;
  186. } elsif ($ch == KEY_LEFT) {
  187. # Cursor left
  188. $self->{inputPos}-- if ($self->{inputPos} > 0);
  189. } elsif ($ch == KEY_RIGHT) {
  190. # Cursor right
  191. $self->{inputPos}++ if ($self->{inputPos} < length($self->{inputBuffer}));
  192. } elsif ($ch == KEY_UP) {
  193. # Input history
  194. $self->{inputHistoryPos}++ if (defined $self->{inputHistory}[$self->{inputHistoryPos}]);
  195. $self->{inputBuffer} = $self->{inputHistory}[$self->{inputHistoryPos}-1];
  196. $self->{inputPos} = length($self->{inputBuffer});
  197. } elsif ($ch == KEY_DOWN) {
  198. # Input history
  199. $self->{inputHistoryPos}-- if ($self->{inputHistoryPos} > 0);
  200. $self->{inputBuffer} = $self->{inputHistoryPos} ? $self->{inputHistory}[$self->{inputHistoryPos}-1] : "";
  201. $self->{inputPos} = length($self->{inputBuffer});
  202. } elsif ($ch == KEY_PPAGE) {
  203. # TODO: Scrollback buffer
  204. } elsif ($ch == KEY_NPAGE) {
  205. # TODO: Scrollback buffer
  206. } elsif ($ch == KEY_F(1)) {
  207. # Toggle help window
  208. $self->toggleWindow("Help");
  209. $self->updateLayout;
  210. } elsif ($ch == KEY_F(2)) {
  211. # Toggle objects window
  212. $self->toggleWindow("Objects");
  213. $self->updateLayout;
  214. } elsif ($ch == KEY_F(3)) {
  215. # Toggle fight window
  216. $self->toggleWindow("Fight");
  217. $self->updateLayout;
  218. } elsif ($ch == KEY_F(4)) {
  219. # Toggle chat window
  220. $self->toggleWindow("Chat");
  221. $self->updateLayout;
  222. } elsif (ord($ch) >= 32 && ord($ch) <= 126) {
  223. # Normal character
  224. $self->{inputBuffer} = substr($self->{inputBuffer}, 0, $self->{inputPos}) . $ch . substr($self->{inputBuffer}, $self->{inputPos});
  225. $self->{inputPos} += length($ch);
  226. }
  227. $ch = getch();
  228. }
  229. my $pos = 0;
  230. $pos += 10 while (length($self->{inputBuffer}) - $pos >= $COLS);
  231. erase $self->{winInput};
  232. addstr $self->{winInput}, 0, 0, substr($self->{inputBuffer}, $pos);
  233. noutrefresh $self->{winInput};
  234. $self->setCursor;
  235. return ($ret ne "") ? $ret : undef;
  236. }
  237. sub printw {
  238. my $self = shift;
  239. my $win = shift;
  240. my $line = shift;
  241. my $col = shift;
  242. my $picture = shift;
  243. my @params = @_;
  244. my %attrtable = (
  245. normal => A_NORMAL,
  246. underline => A_UNDERLINE,
  247. reverse => A_REVERSE,
  248. blink => A_BLINK,
  249. dim => A_DIM,
  250. bold => A_BOLD,
  251. black => COLOR_PAIR(1),
  252. red => COLOR_PAIR(2),
  253. green => COLOR_PAIR(3),
  254. yellow => COLOR_PAIR(4),
  255. blue => COLOR_PAIR(5),
  256. magenta => COLOR_PAIR(6),
  257. cyan => COLOR_PAIR(7),
  258. white => COLOR_PAIR(8)
  259. );
  260. $^A = '';
  261. formline $picture, @params;
  262. my @text = split(/{([^}]+)}/, $^A);
  263. move $win, $line, $col;
  264. for (my $i = 0; $i < @text; $i += 2) {
  265. addstr $win, $text[$i];
  266. if ($text[$i+1] ne "") {
  267. attrset $win, A_NORMAL;
  268. foreach my $attr (split(/|/, $text[$i+1])) {
  269. attron $win, $attrtable{$attr} if $attrtable{$attr};
  270. }
  271. }
  272. }
  273. }
  274. sub makeBar {
  275. my $self = shift;
  276. my $len = shift;
  277. my $cur = shift;
  278. my $max = shift;
  279. my $color1 = shift;
  280. my $treshold = shift;
  281. my $color2 = shift;
  282. $len -= 2;
  283. my $pct = $max ? ($cur / $max * 100) : 0;
  284. my $cnt = int($len * $pct / 100);
  285. my $color = ($color1 ne "") ? (($pct >= $treshold && $color2 ne "") ? $color2 : $color1) : undef;
  286. my $bar = "";
  287. $bar .= "{normal}" if $color ne "";
  288. $bar .= "[";
  289. if (!$cur && !$max) {
  290. $bar .= (" " x $len);
  291. } else {
  292. $bar .= "{".$color."}" if $color ne "";
  293. $bar .= ("#" x $cnt);
  294. $bar .= "{normal}" if $color ne "";
  295. $bar .= ("-" x ($len-$cnt));
  296. }
  297. $bar .= "]";
  298. return $bar;
  299. }
  300. sub toggleWindow {
  301. my $self = shift;
  302. my $name = shift;
  303. if (!$self->{"win".$name}) {
  304. $self->{"win".$name} = newwin(5, 0, 0, 0);
  305. scrollok $self->{"win".$name}, 1 if ($name eq "Fight" || $name eq "Chat");
  306. } else {
  307. delwin $self->{"win".$name};
  308. undef $self->{"win".$name};
  309. }
  310. }
  311. sub updateLayout {
  312. my $self = shift;
  313. # Calculate window sizes
  314. $self->{winStatusHeight} = 5;
  315. $self->{winStatusWidth} = $COLS;
  316. $self->{winObjectsHeight} = $LINES - $self->{winStatusHeight} - 2;
  317. $self->{winObjectsWidth} = int($COLS * 0.20);
  318. $self->{winObjectsWidth} = 0 unless ($self->{winObjects});
  319. $self->{winChatHeight} = int(($LINES - $self->{winStatusHeight} - 2) * 0.20);
  320. $self->{winChatHeight} = 0 unless ($self->{winChat});
  321. $self->{winChatWidth} = $COLS - $self->{winObjectsWidth};
  322. $self->{winFightHeight} = int(($LINES - $self->{winStatusHeight} - 2) * 0.20);
  323. $self->{winFightHeight} = 0 unless ($self->{winFight});
  324. $self->{winFightWidth} = $COLS - $self->{winObjectsWidth};
  325. $self->{winLogHeight} = $LINES - $self->{winStatusHeight} - $self->{winFightHeight} - $self->{winChatHeight} - 2;
  326. $self->{winLogWidth} = $COLS - $self->{winObjectsWidth};
  327. # Status window
  328. resize $self->{winStatus}, $self->{winStatusHeight}-1, $self->{winStatusWidth};
  329. mvwin $self->{winStatus}, 0, 0;
  330. hline $self->{winStatusHeight}-1, 0, 0, $self->{winStatusWidth};
  331. # Objects window
  332. if ($self->{winObjects}) {
  333. resize $self->{winObjects}, $self->{winObjectsHeight}, $self->{winObjectsWidth}-1;
  334. mvwin $self->{winObjects}, $self->{winStatusHeight}, $self->{winLogWidth}+1;
  335. vline $self->{winStatusHeight}, $self->{winLogWidth}, 0, $self->{winObjectsHeight};
  336. }
  337. # Fight window
  338. if ($self->{winFight}) {
  339. resize $self->{winFight}, $self->{winFightHeight}-1, $self->{winFightWidth};
  340. mvwin $self->{winFight}, $self->{winStatusHeight}, 0;
  341. hline $self->{winStatusHeight} + $self->{winFightHeight} - 1, 0, 0, $self->{winFightWidth};
  342. }
  343. # Log Window
  344. if ($self->{winLog}) {
  345. resize $self->{winLog}, $self->{winLogHeight}, $self->{winLogWidth};
  346. mvwin $self->{winLog}, $self->{winStatusHeight} + $self->{winFightHeight}, 0;
  347. }
  348. # Chat window
  349. if ($self->{winChat}) {
  350. hline $self->{winStatusHeight} + $self->{winFightHeight} + $self->{winLogHeight}, 0, 0, $self->{winChatWidth};
  351. resize $self->{winChat}, $self->{winChatHeight}-1, $self->{winChatWidth};
  352. mvwin $self->{winChat}, $self->{winStatusHeight} + $self->{winFightHeight} + $self->{winLogHeight} + 1, 0;
  353. }
  354. # Input window
  355. hline $LINES-2, 0, 0, $COLS;
  356. resize $self->{winInput}, 1, $COLS;
  357. mvwin $self->{winInput}, $LINES-1, 0;
  358. noutrefresh;
  359. $self->{lines} = $LINES;
  360. $self->{cols} = $COLS;
  361. $self->updateAll;
  362. }
  363. sub updateAll {
  364. my $self = shift;
  365. $self->updateStatus;
  366. $self->updateObjects;
  367. noutrefresh $self->{winFight} if ($self->{winFight});
  368. noutrefresh $self->{winLog};
  369. noutrefresh $self->{winChat} if ($self->{winChat});
  370. noutrefresh $self->{winInput};
  371. $self->updatePopups;
  372. }
  373. sub updatePeriodic {
  374. my $self = shift;
  375. $self->updateStatus;
  376. $self->updateObjects;
  377. $self->updatePopups;
  378. }
  379. sub updatePopups {
  380. my $self = shift;
  381. $self->updateHelp;
  382. }
  383. sub updateStatus {
  384. my $self = shift;
  385. return if (!$char || !$self->{winStatus});
  386. erase $self->{winStatus};
  387. my $width = int($self->{winStatusWidth} / 2);
  388. $self->printw($self->{winStatus}, 0, 0, "{bold|yellow} Char: {bold|white}@*{normal} (@*@*@*@*",
  389. $char->{name}, $jobs_lut{$char->{jobID}}, " - ", $sex_lut{$char->{sex}}, ")");
  390. my $bexpbar = $self->makeBar($width-24, $char->{exp}, $char->{exp_max});
  391. $self->printw($self->{winStatus}, 1, 0, "{bold|yellow}   Base:{normal} @<< $bexpbar (@#.##%)",
  392. $char->{lv}, $char->{exp_max} ? $char->{exp} / $char->{exp_max} * 100 : 0);
  393. my $jexpbar = $self->makeBar($width-24, $char->{exp_job}, $char->{exp_job_max});
  394. $self->printw($self->{winStatus}, 2, 0, "{bold|yellow}    Job:{normal} @<< $jexpbar (@#.##%)",
  395. $char->{lv_job}, $char->{exp_job_max} ? $char->{exp_job} / $char->{exp_job_max} * 100 : 0);
  396. $self->printw($self->{winStatus}, 3, 0, "{bold|yellow}    Map:{normal} @* (@*,@*)",
  397. $field{name}, $char->{pos}{x}, $char->{pos}{y});
  398. vline $self->{winStatus}, 0, $width-1, 0, $self->{winStatusHeight};
  399. my $hpbar = $self->makeBar($width-29, $char->{hp}, $char->{hp_max}, "bold|red", 15, "bold|green");
  400. $self->printw($self->{winStatus}, 0, $width, "{bold|yellow}     HP:{normal} @####/@#### $hpbar (@##%)",
  401. $char->{hp}, $char->{hp_max}, $char->{hp_max} ? int($char->{hp} / $char->{hp_max} * 100) : 0);
  402. my $spbar = $self->makeBar($width-29, $char->{sp}, $char->{sp_max}, "bold|blue");
  403. $self->printw($self->{winStatus}, 1, $width, "{bold|yellow}     SP:{normal} @####/@#### $spbar (@##%)",
  404. $char->{sp}, $char->{sp_max}, $char->{sp_max} ? int($char->{sp} / $char->{sp_max} * 100) : 0);
  405. my $weightbar = $self->makeBar($width-29, $char->{weight}, $char->{weight_max}, "cyan", 50, "red");
  406. $self->printw($self->{winStatus}, 2, $width, "{bold|yellow} Weight:{normal} @####/@#### $weightbar (@##%)",
  407. $char->{weight}, $char->{weight_max}, $char->{weight_max} ? int($char->{weight} / $char->{weight_max} * 100) : 0);
  408. my $statuses = ($char->{statuses}) ? join(",", keys %{$char->{statuses}}) : "none";
  409. $self->printw($self->{winStatus}, 3, $width, "{bold|yellow} Status:{normal} @*",
  410. $statuses);
  411. $self->{heartBeat} = !$self->{heartBeat};
  412. addstr $self->{winStatus}, 0, 0, $self->{heartBeat} ? ":" : ".";
  413. noutrefresh $self->{winStatus};
  414. }
  415. sub updateObjects {
  416. my $self = shift;
  417. return if (!$self->{winObjects});
  418. my $line = 0;
  419. my $namelen = $self->{winObjectsWidth} - 8;
  420. erase $self->{winObjects};
  421. # Players
  422. for (my $i = 0; $i < @playersID && $line < $self->{winObjectsHeight}; $i++) {
  423. my $id = $playersID[$i];
  424. next if ($id eq "");
  425. my $name = $players{$id}{name};
  426. my $dist = distance($char->{pos}, $players{$id}{pos});
  427. $self->printw($self->{winObjects}, $line++, 0, "{bold|cyan}@# {cyan}@".("<"x$namelen)." {normal}@#", $i, $name, $dist);
  428. }
  429. # Monsters
  430. for (my $i = 0; $i < @monstersID && $line < $self->{winObjectsHeight}; $i++) {
  431. my $id = $monstersID[$i];
  432. next if ($id eq "");
  433. my $name = $monsters{$id}{name};
  434. my $dist = distance($char->{pos}, $monsters{$id}{pos});
  435. $self->printw($self->{winObjects}, $line++, 0, "{bold|red}@# {red}@".("<"x$namelen)." {normal}@#", $i, $name, $dist);
  436. }
  437. # Items
  438. for (my $i = 0; $i < @itemsID && $line < $self->{winObjectsHeight}; $i++) {
  439. my $id = $itemsID[$i];
  440. next if ($id eq "");
  441. my $name = $items{$id}{name};
  442. my $dist = distance($char->{pos}, $items{$id}{pos});
  443. $self->printw($self->{winObjects}, $line++, 0, "{bold|green}@# {green}@".("<"x$namelen)." {normal}@#", $i, $name, $dist);
  444. }
  445. # NPCs
  446. for (my $i = 0; $i < @npcsID && $line < $self->{winObjectsHeight}; $i++) {
  447. my $id = $npcsID[$i];
  448. next if ($id eq "");
  449. my $name = $npcs{$id}{name};
  450. my $dist = distance($char->{pos}, $npcs{$id}{pos});
  451. $self->printw($self->{winObjects}, $line++, 0, "{bold|blue}@# {blue}@".("<"x$namelen)." {normal}@#", $i, $name, $dist);
  452. }
  453. noutrefresh $self->{winObjects};
  454. }
  455. sub updateHelp {
  456. my $self = shift;
  457. return if (!$self->{winHelp});
  458. my $height = 15;
  459. my $width = 70;
  460. resize $self->{winHelp}, $height, $width;
  461. mvwin $self->{winHelp}, int(($LINES-$height)/2), int(($COLS-$width)/2);
  462. erase $self->{winHelp};
  463. box $self->{winHelp}, 0, 0;
  464. my $center = "@" . ("|" x ($width-7));
  465. $self->printw($self->{winHelp}, 1, 1, " {bold|white} $center {normal}",
  466. "OpenKore v$Settings::VERSION");
  467. $self->printw($self->{winHelp}, 3, 1, " {bold|white}<F1>{normal}        Show/hide this help window");
  468. $self->printw($self->{winHelp}, 4, 1, " {bold|white}<F2>{normal}        Show/hide objects (players,monsters,items,NPCs) pane");
  469. $self->printw($self->{winHelp}, 5, 1, " {bold|white}<F3>{normal}        Show/hide fight message pane");
  470. $self->printw($self->{winHelp}, 6, 1, " {bold|white}<F4>{normal}        Show/hide chat message pane");
  471. $self->printw($self->{winHelp}, 8, 1, " {bold|white}<Ctrl-L>{normal}    Redraw screen");
  472. $self->printw($self->{winHelp}, 9, 1, " {bold|white}<Ctrl-U>{normal}    Clear input line");
  473. $self->printw($self->{winHelp}, 11, 1, " {bold|white}<Up>{normal}/{bold|white}<Down>{normal} Input history");
  474. $self->printw($self->{winHelp}, 13, 1, " {bold|blue} $center {normal}",
  475. "Visit http://openkore.sourceforge.net/ for more stuff");
  476. noutrefresh $self->{winHelp};
  477. }
  478. sub setCursor {
  479. my $self = shift;
  480. my $pos = $self->{inputPos};
  481. $pos -= 10 while ($pos >= $COLS);
  482. move $LINES - 1, $pos;
  483. noutrefresh;
  484. doupdate;
  485. }
  486. 1;