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