2007-08-14 Michael Snyder <msnyder@access-company.com>
[external/binutils.git] / gdb / tui / tui-regs.c
1 /* TUI display registers in window.
2
3    Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007
4    Free Software Foundation, Inc.
5
6    Contributed by Hewlett-Packard Company.
7
8    This file is part of GDB.
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor,
23    Boston, MA 02110-1301, USA.  */
24
25 #include "defs.h"
26 #include "tui/tui.h"
27 #include "tui/tui-data.h"
28 #include "symtab.h"
29 #include "gdbtypes.h"
30 #include "gdbcmd.h"
31 #include "frame.h"
32 #include "regcache.h"
33 #include "inferior.h"
34 #include "target.h"
35 #include "gdb_string.h"
36 #include "tui/tui-layout.h"
37 #include "tui/tui-win.h"
38 #include "tui/tui-windata.h"
39 #include "tui/tui-wingeneral.h"
40 #include "tui/tui-file.h"
41 #include "reggroups.h"
42
43 #include "gdb_curses.h"
44
45
46 /*****************************************
47 ** STATIC LOCAL FUNCTIONS FORWARD DECLS    **
48 ******************************************/
49 static void
50 tui_display_register (struct tui_data_element *data,
51                       struct tui_gen_win_info *win_info);
52
53 static enum tui_status
54 tui_show_register_group (struct gdbarch *gdbarch, 
55                          struct reggroup *group,
56                          struct frame_info *frame, 
57                          int refresh_values_only);
58
59 static enum tui_status
60 tui_get_register (struct gdbarch *gdbarch, 
61                   struct frame_info *frame,
62                   struct tui_data_element *data, 
63                   int regnum, int *changedp);
64 static void tui_register_format (struct gdbarch *, 
65                                  struct frame_info *, 
66                                  struct tui_data_element*, 
67                                  int);
68 static void tui_scroll_regs_forward_command (char *, int);
69 static void tui_scroll_regs_backward_command (char *, int);
70
71
72
73 /*****************************************
74 ** PUBLIC FUNCTIONS                     **
75 ******************************************/
76
77 /* Answer the number of the last line in the regs display.  If there
78    are no registers (-1) is returned.  */
79 int
80 tui_last_regs_line_no (void)
81 {
82   int num_lines = (-1);
83
84   if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
85     {
86       num_lines = (TUI_DATA_WIN->detail.data_display_info.regs_content_count /
87                   TUI_DATA_WIN->detail.data_display_info.regs_column_count);
88       if (TUI_DATA_WIN->detail.data_display_info.regs_content_count %
89           TUI_DATA_WIN->detail.data_display_info.regs_column_count)
90         num_lines++;
91     }
92   return num_lines;
93 }
94
95
96 /* Answer the line number that the register element at element_no is
97    on.  If element_no is greater than the number of register elements
98    there are, -1 is returned.  */
99 int
100 tui_line_from_reg_element_no (int element_no)
101 {
102   if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
103     {
104       int i, line = (-1);
105
106       i = 1;
107       while (line == (-1))
108         {
109           if (element_no <
110               (TUI_DATA_WIN->detail.data_display_info.regs_column_count * i))
111             line = i - 1;
112           else
113             i++;
114         }
115
116       return line;
117     }
118   else
119     return (-1);
120 }
121
122
123 /* Answer the index of the first element in line_no.  If line_no is
124    past the register area (-1) is returned.  */
125 int
126 tui_first_reg_element_no_inline (int line_no)
127 {
128   if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count)
129       <= TUI_DATA_WIN->detail.data_display_info.regs_content_count)
130     return ((line_no + 1) *
131             TUI_DATA_WIN->detail.data_display_info.regs_column_count) -
132       TUI_DATA_WIN->detail.data_display_info.regs_column_count;
133   else
134     return (-1);
135 }
136
137
138 /* Answer the index of the last element in line_no.  If line_no is
139    past the register area (-1) is returned.  */
140 int
141 tui_last_reg_element_no_in_line (int line_no)
142 {
143   if ((line_no * TUI_DATA_WIN->detail.data_display_info.regs_column_count) <=
144       TUI_DATA_WIN->detail.data_display_info.regs_content_count)
145     return ((line_no + 1) *
146             TUI_DATA_WIN->detail.data_display_info.regs_column_count) - 1;
147   else
148     return (-1);
149 }
150
151 /* Show the registers of the given group in the data window
152    and refresh the window.  */
153 void
154 tui_show_registers (struct reggroup *group)
155 {
156   enum tui_status ret = TUI_FAILURE;
157   struct tui_data_info *display_info;
158
159   /* Make sure the curses mode is enabled.  */
160   tui_enable ();
161
162   /* Make sure the register window is visible.  If not, select an
163      appropriate layout.  */
164   if (TUI_DATA_WIN == NULL || !TUI_DATA_WIN->generic.is_visible)
165     tui_set_layout_for_display_command (DATA_NAME);
166
167   display_info = &TUI_DATA_WIN->detail.data_display_info;
168   if (group == 0)
169     group = general_reggroup;
170
171   /* Say that registers should be displayed, even if there is a
172      problem.  */
173   display_info->display_regs = TRUE;
174
175   if (target_has_registers && target_has_stack && target_has_memory)
176     {
177       ret = tui_show_register_group (current_gdbarch, group,
178                                      get_current_frame (),
179                                      group == display_info->current_group);
180     }
181   if (ret == TUI_FAILURE)
182     {
183       display_info->current_group = 0;
184       tui_erase_data_content (NO_REGS_STRING);
185     }
186   else
187     {
188       int i;
189
190       /* Clear all notation of changed values.  */
191       for (i = 0; i < display_info->regs_content_count; i++)
192         {
193           struct tui_gen_win_info *data_item_win;
194           struct tui_win_element *win;
195
196           data_item_win = &display_info->regs_content[i]
197             ->which_element.data_window;
198           win = (struct tui_win_element *) data_item_win->content[0];
199           win->which_element.data.highlight = FALSE;
200         }
201       display_info->current_group = group;
202       tui_display_all_data ();
203     }
204 }
205
206
207 /* Set the data window to display the registers of the register group
208    using the given frame.  Values are refreshed only when
209    refresh_values_only is TRUE.  */
210
211 static enum tui_status
212 tui_show_register_group (struct gdbarch *gdbarch, 
213                          struct reggroup *group,
214                          struct frame_info *frame, 
215                          int refresh_values_only)
216 {
217   enum tui_status ret = TUI_FAILURE;
218   int nr_regs;
219   int allocated_here = FALSE;
220   int regnum, pos;
221   char title[80];
222   struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
223
224   /* Make a new title showing which group we display.  */
225   snprintf (title, sizeof (title) - 1, "Register group: %s",
226             reggroup_name (group));
227   xfree (TUI_DATA_WIN->generic.title);
228   TUI_DATA_WIN->generic.title = xstrdup (title);
229
230   /* See how many registers must be displayed.  */
231   nr_regs = 0;
232   for (regnum = 0;
233        regnum < gdbarch_num_regs (current_gdbarch)
234                 + gdbarch_num_pseudo_regs (current_gdbarch);
235        regnum++)
236     {
237       /* Must be in the group and have a name.  */
238       if (gdbarch_register_reggroup_p (gdbarch, regnum, group)
239           && gdbarch_register_name (gdbarch, regnum) != 0)
240         nr_regs++;
241     }
242
243   if (display_info->regs_content_count > 0 && !refresh_values_only)
244     {
245       tui_free_data_content (display_info->regs_content,
246                              display_info->regs_content_count);
247       display_info->regs_content_count = 0;
248     }
249
250   if (display_info->regs_content_count <= 0)
251     {
252       display_info->regs_content = tui_alloc_content (nr_regs, DATA_WIN);
253       allocated_here = TRUE;
254       refresh_values_only = FALSE;
255     }
256
257   if (display_info->regs_content != (tui_win_content) NULL)
258     {
259       if (!refresh_values_only || allocated_here)
260         {
261           TUI_DATA_WIN->generic.content = (void*) NULL;
262           TUI_DATA_WIN->generic.content_size = 0;
263           tui_add_content_elements (&TUI_DATA_WIN->generic, nr_regs);
264           display_info->regs_content
265             = (tui_win_content) TUI_DATA_WIN->generic.content;
266           display_info->regs_content_count = nr_regs;
267         }
268
269       /* Now set the register names and values.  */
270       pos = 0;
271       for (regnum = 0;
272            regnum < gdbarch_num_regs (current_gdbarch)
273                     + gdbarch_num_pseudo_regs (current_gdbarch);
274            regnum++)
275         {
276           struct tui_gen_win_info *data_item_win;
277           struct tui_data_element *data;
278           const char *name;
279
280           if (!gdbarch_register_reggroup_p (gdbarch, regnum, group))
281             continue;
282
283           name = gdbarch_register_name (gdbarch, regnum);
284           if (name == 0)
285             continue;
286
287           data_item_win =
288             &display_info->regs_content[pos]->which_element.data_window;
289           data =
290             &((struct tui_win_element *) data_item_win->content[0])->which_element.data;
291           if (data)
292             {
293               if (!refresh_values_only)
294                 {
295                   data->item_no = regnum;
296                   data->name = name;
297                   data->highlight = FALSE;
298                 }
299               if (data->value == (void*) NULL)
300                 data->value = (void*) xmalloc (MAX_REGISTER_SIZE);
301
302               tui_get_register (gdbarch, frame, data, regnum, 0);
303             }
304           pos++;
305         }
306
307       TUI_DATA_WIN->generic.content_size =
308         display_info->regs_content_count + display_info->data_content_count;
309       ret = TUI_SUCCESS;
310     }
311
312   return ret;
313 }
314
315 /* Function to display the registers in the content from
316    'start_element_no' until the end of the register content or the end
317    of the display height.  No checking for displaying past the end of
318    the registers is done here.  */
319 void
320 tui_display_registers_from (int start_element_no)
321 {
322   struct tui_data_info *display_info = &TUI_DATA_WIN->detail.data_display_info;
323
324   if (display_info->regs_content != (tui_win_content) NULL 
325       && display_info->regs_content_count > 0)
326     {
327       int i = start_element_no;
328       int j, value_chars_wide, item_win_width, cur_y;
329
330       int max_len = 0;
331       for (i = 0; i < display_info->regs_content_count; i++)
332         {
333           struct tui_data_element *data;
334           struct tui_gen_win_info *data_item_win;
335           char *p;
336           int len;
337
338           data_item_win = &display_info->regs_content[i]->which_element.data_window;
339           data = &((struct tui_win_element *)
340                    data_item_win->content[0])->which_element.data;
341           len = 0;
342           p = data->content;
343           if (p != 0)
344             while (*p)
345               {
346                 if (*p++ == '\t')
347                   len = 8 * ((len / 8) + 1);
348                 else
349                   len++;
350               }
351
352           if (len > max_len)
353             max_len = len;
354         }
355       item_win_width = max_len + 1;
356       i = start_element_no;
357
358       display_info->regs_column_count =
359         (TUI_DATA_WIN->generic.width - 2) / item_win_width;
360       if (display_info->regs_column_count == 0)
361         display_info->regs_column_count = 1;
362       item_win_width =
363         (TUI_DATA_WIN->generic.width - 2) / display_info->regs_column_count;
364
365       /* Now create each data "sub" window, and write the display into
366          it.  */
367       cur_y = 1;
368       while (i < display_info->regs_content_count 
369              && cur_y <= TUI_DATA_WIN->generic.viewport_height)
370         {
371           for (j = 0;
372                j < display_info->regs_column_count
373                  && i < display_info->regs_content_count;
374                j++)
375             {
376               struct tui_gen_win_info *data_item_win;
377               struct tui_data_element *data_element_ptr;
378
379               /* Create the window if necessary.  */
380               data_item_win = &display_info->regs_content[i]
381                 ->which_element.data_window;
382               data_element_ptr = &((struct tui_win_element *)
383                                  data_item_win->content[0])->which_element.data;
384               if (data_item_win->handle != (WINDOW*) NULL
385                   && (data_item_win->height != 1
386                       || data_item_win->width != item_win_width
387                       || data_item_win->origin.x != (item_win_width * j) + 1
388                       || data_item_win->origin.y != cur_y))
389                 {
390                   tui_delete_win (data_item_win->handle);
391                   data_item_win->handle = 0;
392                 }
393                   
394               if (data_item_win->handle == (WINDOW *) NULL)
395                 {
396                   data_item_win->height = 1;
397                   data_item_win->width = item_win_width;
398                   data_item_win->origin.x = (item_win_width * j) + 1;
399                   data_item_win->origin.y = cur_y;
400                   tui_make_window (data_item_win, DONT_BOX_WINDOW);
401                   scrollok (data_item_win->handle, FALSE);
402                 }
403               touchwin (data_item_win->handle);
404
405               /* Get the printable representation of the register
406                  and display it.  */
407               tui_display_register (data_element_ptr, data_item_win);
408               i++;              /* Next register.  */
409             }
410           cur_y++;              /* Next row.  */
411         }
412     }
413 }
414
415
416 /* Function to display the registers in the content from
417    'start_element_no' on 'start_line_no' until the end of the register
418    content or the end of the display height.  This function checks
419    that we won't display off the end of the register display.  */
420 void
421 tui_display_reg_element_at_line (int start_element_no,
422                                  int start_line_no)
423 {
424   if (TUI_DATA_WIN->detail.data_display_info.regs_content != (tui_win_content) NULL
425       && TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
426     {
427       int element_no = start_element_no;
428
429       if (start_element_no != 0 && start_line_no != 0)
430         {
431           int last_line_no, first_line_on_last_page;
432
433           last_line_no = tui_last_regs_line_no ();
434           first_line_on_last_page = last_line_no - (TUI_DATA_WIN->generic.height - 2);
435           if (first_line_on_last_page < 0)
436             first_line_on_last_page = 0;
437
438           /* If there is no other data displayed except registers, and
439              the element_no causes us to scroll past the end of the
440              registers, adjust what element to really start the
441              display at.  */
442           if (TUI_DATA_WIN->detail.data_display_info.data_content_count <= 0
443               && start_line_no > first_line_on_last_page)
444             element_no = tui_first_reg_element_no_inline (first_line_on_last_page);
445         }
446       tui_display_registers_from (element_no);
447     }
448 }
449
450
451
452 /* Function to display the registers starting at line line_no in the
453    data window.  Answers the line number that the display actually
454    started from.  If nothing is displayed (-1) is returned.  */
455 int
456 tui_display_registers_from_line (int line_no, 
457                                  int force_display)
458 {
459   if (TUI_DATA_WIN->detail.data_display_info.regs_content_count > 0)
460     {
461       int line, element_no;
462
463       if (line_no < 0)
464         line = 0;
465       else if (force_display)
466         { /* If we must display regs (force_display is true), then
467              make sure that we don't display off the end of the
468              registers.  */
469           if (line_no >= tui_last_regs_line_no ())
470             {
471               if ((line = tui_line_from_reg_element_no (
472                  TUI_DATA_WIN->detail.data_display_info.regs_content_count - 1)) < 0)
473                 line = 0;
474             }
475           else
476             line = line_no;
477         }
478       else
479         line = line_no;
480
481       element_no = tui_first_reg_element_no_inline (line);
482       if (element_no < TUI_DATA_WIN->detail.data_display_info.regs_content_count)
483         tui_display_reg_element_at_line (element_no, line);
484       else
485         line = (-1);
486
487       return line;
488     }
489
490   return (-1);                  /* Nothing was displayed.  */
491 }
492
493
494 /* This function check all displayed registers for changes in values,
495    given a particular frame.  If the values have changed, they are
496    updated with the new value and highlighted.  */
497 void
498 tui_check_register_values (struct frame_info *frame)
499 {
500   if (TUI_DATA_WIN != NULL
501       && TUI_DATA_WIN->generic.is_visible)
502     {
503       struct tui_data_info *display_info
504         = &TUI_DATA_WIN->detail.data_display_info;
505
506       if (display_info->regs_content_count <= 0 
507           && display_info->display_regs)
508         tui_show_registers (display_info->current_group);
509       else
510         {
511           int i, j;
512
513           for (i = 0; (i < display_info->regs_content_count); i++)
514             {
515               struct tui_data_element *data;
516               struct tui_gen_win_info *data_item_win_ptr;
517               int was_hilighted;
518
519               data_item_win_ptr = &display_info->regs_content[i]->
520                 which_element.data_window;
521               data = &((struct tui_win_element *)
522                        data_item_win_ptr->content[0])->which_element.data;
523               was_hilighted = data->highlight;
524
525               tui_get_register (current_gdbarch, frame, data,
526                                 data->item_no, &data->highlight);
527
528               if (data->highlight || was_hilighted)
529                 {
530                   tui_display_register (data, data_item_win_ptr);
531                 }
532             }
533         }
534     }
535 }
536
537 /* Display a register in a window.  If hilite is TRUE, then the value
538    will be displayed in reverse video.  */
539 static void
540 tui_display_register (struct tui_data_element *data,
541                       struct tui_gen_win_info *win_info)
542 {
543   if (win_info->handle != (WINDOW *) NULL)
544     {
545       int i;
546
547       if (data->highlight)
548         wstandout (win_info->handle);
549       
550       wmove (win_info->handle, 0, 0);
551       for (i = 1; i < win_info->width; i++)
552         waddch (win_info->handle, ' ');
553       wmove (win_info->handle, 0, 0);
554       if (data->content)
555         waddstr (win_info->handle, data->content);
556
557       if (data->highlight)
558         wstandend (win_info->handle);
559       tui_refresh_win (win_info);
560     }
561 }
562
563 static void
564 tui_reg_next_command (char *arg, int from_tty)
565 {
566   if (TUI_DATA_WIN != 0)
567     {
568       struct reggroup *group
569         = TUI_DATA_WIN->detail.data_display_info.current_group;
570
571       group = reggroup_next (current_gdbarch, group);
572       if (group == 0)
573         group = reggroup_next (current_gdbarch, 0);
574
575       if (group)
576         tui_show_registers (group);
577     }
578 }
579
580 static void
581 tui_reg_float_command (char *arg, int from_tty)
582 {
583   tui_show_registers (float_reggroup);
584 }
585
586 static void
587 tui_reg_general_command (char *arg, int from_tty)
588 {
589   tui_show_registers (general_reggroup);
590 }
591
592 static void
593 tui_reg_system_command (char *arg, int from_tty)
594 {
595   tui_show_registers (system_reggroup);
596 }
597
598 static struct cmd_list_element *tuireglist;
599
600 static void
601 tui_reg_command (char *args, int from_tty)
602 {
603   printf_unfiltered (_("\"tui reg\" must be followed by the name of a "
604                      "tui reg command.\n"));
605   help_list (tuireglist, "tui reg ", -1, gdb_stdout);
606 }
607
608 void
609 _initialize_tui_regs (void)
610 {
611   struct cmd_list_element **tuicmd;
612
613   tuicmd = tui_get_cmd_list ();
614
615   add_prefix_cmd ("reg", class_tui, tui_reg_command,
616                   _("TUI commands to control the register window."),
617                   &tuireglist, "tui reg ", 0,
618                   tuicmd);
619
620   add_cmd ("float", class_tui, tui_reg_float_command,
621            _("Display only floating point registers."),
622            &tuireglist);
623   add_cmd ("general", class_tui, tui_reg_general_command,
624            _("Display only general registers."),
625            &tuireglist);
626   add_cmd ("system", class_tui, tui_reg_system_command,
627            _("Display only system registers."),
628            &tuireglist);
629   add_cmd ("next", class_tui, tui_reg_next_command,
630            _("Display next register group."),
631            &tuireglist);
632
633   if (xdb_commands)
634     {
635       add_com ("fr", class_tui, tui_reg_float_command,
636                _("Display only floating point registers\n"));
637       add_com ("gr", class_tui, tui_reg_general_command,
638                _("Display only general registers\n"));
639       add_com ("sr", class_tui, tui_reg_system_command,
640                _("Display only special registers\n"));
641       add_com ("+r", class_tui, tui_scroll_regs_forward_command,
642                _("Scroll the registers window forward\n"));
643       add_com ("-r", class_tui, tui_scroll_regs_backward_command,
644                _("Scroll the register window backward\n"));
645     }
646 }
647
648
649 /*****************************************
650 ** STATIC LOCAL FUNCTIONS                 **
651 ******************************************/
652
653 extern int pagination_enabled;
654
655 static void
656 tui_restore_gdbout (void *ui)
657 {
658   ui_file_delete (gdb_stdout);
659   gdb_stdout = (struct ui_file*) ui;
660   pagination_enabled = 1;
661 }
662
663 /* Get the register from the frame and make a printable representation
664    of it in the data element.  */
665 static void
666 tui_register_format (struct gdbarch *gdbarch, 
667                      struct frame_info *frame,
668                      struct tui_data_element *data_element, 
669                      int regnum)
670 {
671   struct ui_file *stream;
672   struct ui_file *old_stdout;
673   const char *name;
674   struct cleanup *cleanups;
675   char *p, *s;
676   int pos;
677   struct type *type = register_type (gdbarch, regnum);
678
679   name = gdbarch_register_name (gdbarch, regnum);
680   if (name == 0)
681     {
682       return;
683     }
684   
685   pagination_enabled = 0;
686   old_stdout = gdb_stdout;
687   stream = tui_sfileopen (256);
688   gdb_stdout = stream;
689   cleanups = make_cleanup (tui_restore_gdbout, (void*) old_stdout);
690   if (TYPE_VECTOR (type) != 0 && 0)
691     {
692       gdb_byte buf[MAX_REGISTER_SIZE];
693       int len;
694
695       len = register_size (current_gdbarch, regnum);
696       fprintf_filtered (stream, "%-14s ", name);
697       get_frame_register (frame, regnum, buf);
698       print_scalar_formatted (buf, type, 'f', len, stream);
699     }
700   else
701     {
702       gdbarch_print_registers_info (current_gdbarch, stream,
703                                     frame, regnum, 1);
704     }
705
706   /* Save formatted output in the buffer.  */
707   p = tui_file_get_strbuf (stream);
708
709   /* Remove the possible \n.  */
710   s = strrchr (p, '\n');
711   if (s && s[1] == 0)
712     *s = 0;
713
714   xfree (data_element->content);
715   data_element->content = xstrdup (p);
716   do_cleanups (cleanups);
717 }
718
719 /* Get the register value from the given frame and format it for the
720    display.  When changep is set, check if the new register value has
721    changed with respect to the previous call.  */
722 static enum tui_status
723 tui_get_register (struct gdbarch *gdbarch, 
724                   struct frame_info *frame,
725                   struct tui_data_element *data, 
726                   int regnum, int *changedp)
727 {
728   enum tui_status ret = TUI_FAILURE;
729
730   if (changedp)
731     *changedp = FALSE;
732   if (target_has_registers)
733     {
734       gdb_byte buf[MAX_REGISTER_SIZE];
735       get_frame_register (frame, regnum, buf);
736
737       if (changedp)
738         {
739           int size = register_size (gdbarch, regnum);
740           char *old = (char*) data->value;
741           int i;
742
743           for (i = 0; i < size; i++)
744             if (buf[i] != old[i])
745               {
746                 *changedp = TRUE;
747                 old[i] = buf[i];
748               }
749         }
750
751       /* Reformat the data content if the value changed.  */
752       if (changedp == 0 || *changedp == TRUE)
753         tui_register_format (gdbarch, frame, data, regnum);
754
755       ret = TUI_SUCCESS;
756     }
757   return ret;
758 }
759
760 static void
761 tui_scroll_regs_forward_command (char *arg, int from_tty)
762 {
763   tui_scroll (FORWARD_SCROLL, TUI_DATA_WIN, 1);
764 }
765
766
767 static void
768 tui_scroll_regs_backward_command (char *arg, int from_tty)
769 {
770   tui_scroll (BACKWARD_SCROLL, TUI_DATA_WIN, 1);
771 }