comparison src/redisplay-tty.c @ 412:697ef44129c6 r21-2-14

Import from CVS: tag r21-2-14
author cvs
date Mon, 13 Aug 2007 11:20:41 +0200
parents de805c49cfc1
children 11054d720c21
comparison
equal deleted inserted replaced
411:12e008d41344 412:697ef44129c6
51 other conflicts as well on some systems, so screw it: we'll just 51 other conflicts as well on some systems, so screw it: we'll just
52 re-declare the routines we use and assume the code in this file is 52 re-declare the routines we use and assume the code in this file is
53 invoking them correctly. */ 53 invoking them correctly. */
54 /* # include <curses.h> */ 54 /* # include <curses.h> */
55 /* # include <term.h> */ 55 /* # include <term.h> */
56 EXTERN_C int tgetent (const char *, const char *); 56 #ifdef __cplusplus
57 EXTERN_C int tgetflag (const char *); 57 extern "C" {
58 EXTERN_C int tgetnum (const char *); 58 #endif
59 EXTERN_C char *tgetstr (const char *, char **); 59 extern int tgetent (CONST char *, CONST char *);
60 EXTERN_C void tputs (const char *, int, void (*)(int)); 60 extern int tgetflag (CONST char *);
61 61 extern int tgetnum (CONST char *);
62 extern char *tgetstr (CONST char *, char **);
63 extern void tputs (CONST char *, int, void (*)(int));
64 #ifdef __cplusplus
65 }
66 #endif
62 #define FORCE_CURSOR_UPDATE(c) send_string_to_tty_console (c, 0, 0) 67 #define FORCE_CURSOR_UPDATE(c) send_string_to_tty_console (c, 0, 0)
63 #define OUTPUTN(c, a, n) \ 68 #define OUTPUTN(c, a, n) \
64 do { \ 69 do { \
65 cmputc_console = c; \ 70 cmputc_console = c; \
66 FORCE_CURSOR_UPDATE (c); \ 71 FORCE_CURSOR_UPDATE (c); \
100 is considered to be fixed width -- in other words, we return LEN. 105 is considered to be fixed width -- in other words, we return LEN.
101 Under Mule, however, a character can still cover more than one 106 Under Mule, however, a character can still cover more than one
102 column, so we use emchar_string_displayed_columns(). 107 column, so we use emchar_string_displayed_columns().
103 ****************************************************************************/ 108 ****************************************************************************/
104 static int 109 static int
105 tty_text_width (struct frame *f, struct face_cachel *cachel, const Emchar *str, 110 tty_text_width (struct frame *f, struct face_cachel *cachel, CONST Emchar *str,
106 Charcount len) 111 Charcount len)
107 { 112 {
108 return emchar_string_displayed_columns (str, len); 113 return emchar_string_displayed_columns (str, len);
109 } 114 }
110 115
131 { 136 {
132 return 1; 137 return 1;
133 } 138 }
134 139
135 /***************************************************************************** 140 /*****************************************************************************
136 tty_frame_output_begin 141 tty_output_begin
137 142
138 Perform any necessary initialization prior to an update. 143 Perform any necessary initialization prior to an update.
139 ****************************************************************************/ 144 ****************************************************************************/
140 #ifdef DEBUG_XEMACS 145 #ifdef DEBUG_XEMACS
141 void tty_frame_output_begin (struct frame *f); 146 void tty_output_begin (struct device *d);
142 void 147 void
143 #else 148 #else
144 static void 149 static void
145 #endif 150 #endif
146 tty_frame_output_begin (struct frame *f) 151 tty_output_begin (struct device *d)
147 { 152 {
148 #ifndef HAVE_TERMIOS 153 #ifndef HAVE_TERMIOS
149 /* Termcap requires `ospeed' to be a global variable so we have to 154 /* Termcap requires `ospeed' to be a global variable so we have to
150 always set it for whatever tty console we are actually currently 155 always set it for whatever tty console we are actually currently
151 working with. */ 156 working with. */
152 ospeed = DEVICE_TTY_DATA (XDEVICE (FRAME_DEVICE (f)))->ospeed; 157 ospeed = DEVICE_TTY_DATA (d)->ospeed;
153 #endif 158 #endif
154 } 159 }
155 160
156 /***************************************************************************** 161 /*****************************************************************************
157 tty_frame_output_end 162 tty_output_end
158 163
159 Perform any necessary flushing of queues when an update has completed. 164 Perform any necessary flushing of queues when an update has completed.
160 ****************************************************************************/ 165 ****************************************************************************/
161 #ifdef DEBUG_XEMACS 166 #ifdef DEBUG_XEMACS
162 void tty_frame_output_end (struct frame *f); 167 void tty_output_end (struct device *d);
163 void 168 void
164 #else 169 #else
165 static void 170 static void
166 #endif 171 #endif
167 tty_frame_output_end (struct frame *f) 172 tty_output_end (struct device *d)
168 { 173 {
169 struct device *d = XDEVICE (FRAME_DEVICE (f));
170 struct console *c = XCONSOLE (DEVICE_CONSOLE (d)); 174 struct console *c = XCONSOLE (DEVICE_CONSOLE (d));
171 175
172 CONSOLE_TTY_CURSOR_X (c) = CONSOLE_TTY_FINAL_CURSOR_X (c); 176 CONSOLE_TTY_CURSOR_X (c) = CONSOLE_TTY_FINAL_CURSOR_X (c);
173 CONSOLE_TTY_CURSOR_Y (c) = CONSOLE_TTY_FINAL_CURSOR_Y (c); 177 CONSOLE_TTY_CURSOR_Y (c) = CONSOLE_TTY_FINAL_CURSOR_Y (c);
174 FORCE_CURSOR_UPDATE (c); 178 FORCE_CURSOR_UPDATE (c);
327 XSETWINDOW (window, w); 331 XSETWINDOW (window, w);
328 instance = glyph_image_instance (rb->object.dglyph.glyph, 332 instance = glyph_image_instance (rb->object.dglyph.glyph,
329 window, ERROR_ME_NOT, 1); 333 window, ERROR_ME_NOT, 1);
330 334
331 if (IMAGE_INSTANCEP (instance)) 335 if (IMAGE_INSTANCEP (instance))
332 { 336 switch (XIMAGE_INSTANCE_TYPE (instance))
333 switch (XIMAGE_INSTANCE_TYPE (instance)) 337 {
338 case IMAGE_TEXT:
334 { 339 {
335 case IMAGE_MONO_PIXMAP: 340 Bufbyte *temptemp;
336 case IMAGE_COLOR_PIXMAP: 341 Lisp_Object string =
337 case IMAGE_SUBWINDOW: 342 XIMAGE_INSTANCE_TEXT_STRING (instance);
338 case IMAGE_WIDGET: 343 Bytecount len = XSTRING_LENGTH (string);
339 /* just do nothing here */ 344
340 break; 345 /* In the unlikely instance that a garbage-collect
341 346 occurs during encoding, we at least need to
342 case IMAGE_NOTHING: 347 copy the string.
343 /* nothing is as nothing does */ 348 */
344 break; 349 temptemp = (Bufbyte *) alloca (len);
345 350 memcpy (temptemp, XSTRING_DATA (string), len);
346 case IMAGE_TEXT: 351 {
347 case IMAGE_POINTER: 352 int i;
348 default: 353
349 abort (); 354 /* Now truncate the first rb->object.dglyph.xoffset
355 columns. */
356 for (i = 0; i < rb->object.dglyph.xoffset;)
357 {
358 #ifdef MULE
359 Emchar ch = charptr_emchar (temptemp);
360 i += XCHARSET_COLUMNS (CHAR_CHARSET (ch));
361 #else
362 i++; /* telescope this */
363 #endif
364 INC_CHARPTR (temptemp);
365 }
366
367 /* If we truncated one column too many, then
368 add a space at the beginning. */
369 if (i > rb->object.dglyph.xoffset)
370 {
371 assert (i > 0);
372 *--temptemp = ' ';
373 i--;
374 }
375 len -= i;
376 }
377
378 tty_output_bufbyte_string (w, dl, temptemp, len,
379 xpos, findex, 0);
380
381 if (xpos >= cursor_start
382 && (cursor_start <
383 xpos + (bufbyte_string_displayed_columns
384 (temptemp, len))))
385 {
386 cmgoto (f, dl->ypos - 1, cursor_start);
387 }
350 } 388 }
351 IMAGE_INSTANCE_OPTIMIZE_OUTPUT 389 break;
352 (XIMAGE_INSTANCE (instance)) = 0; 390
353 } 391 case IMAGE_MONO_PIXMAP:
392 case IMAGE_COLOR_PIXMAP:
393 case IMAGE_SUBWINDOW:
394 case IMAGE_WIDGET:
395 /* just do nothing here */
396 break;
397
398 case IMAGE_POINTER:
399 abort ();
400
401 case IMAGE_NOTHING:
402 /* nothing is as nothing does */
403 break;
404
405 default:
406 abort ();
407 }
354 408
355 xpos += rb->width; 409 xpos += rb->width;
356 elt++; 410 elt++;
357 } 411 }
358 else 412 else
408 Clear the area in the box defined by the given parameters. 462 Clear the area in the box defined by the given parameters.
409 ****************************************************************************/ 463 ****************************************************************************/
410 static void 464 static void
411 tty_clear_region (Lisp_Object window, struct device* d, struct frame * f, 465 tty_clear_region (Lisp_Object window, struct device* d, struct frame * f,
412 face_index findex, int x, int y, 466 face_index findex, int x, int y,
413 int width, int height, Lisp_Object fcolor, Lisp_Object bcolor, 467 int width, int height, Lisp_Object fcolor, Lisp_Object bcolor,
414 Lisp_Object background_pixmap) 468 Lisp_Object background_pixmap)
415 { 469 {
416 struct console *c = XCONSOLE (FRAME_CONSOLE (f)); 470 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
417 int line; 471 int line;
418 struct window* w = XWINDOW (window); 472 struct window* w = XWINDOW (window);
509 #ifdef NOT_SURE 563 #ifdef NOT_SURE
510 internal_cursor_to (f, 0, 0); 564 internal_cursor_to (f, 0, 0);
511 clear_to_end (f); 565 clear_to_end (f);
512 #else 566 #else
513 /* #### Not implemented. */ 567 /* #### Not implemented. */
514 stderr_out ("Not yet.\n"); 568 fprintf (stderr, "Not yet.\n");
515 #endif 569 #endif
516 } 570 }
517 tty_turn_off_frame_face (f, Vdefault_face); 571 tty_turn_off_frame_face (f, Vdefault_face);
518 } 572 }
519 573
880 934
881 OUTPUT1_IF (c, TTY_SD (c).orig_pair); 935 OUTPUT1_IF (c, TTY_SD (c).orig_pair);
882 OUTPUT1_IF (c, TTY_SD (c).keypad_off); 936 OUTPUT1_IF (c, TTY_SD (c).keypad_off);
883 OUTPUT1_IF (c, TTY_SD (c).cursor_normal); 937 OUTPUT1_IF (c, TTY_SD (c).cursor_normal);
884 OUTPUT1_IF (c, TTY_SD (c).end_motion); 938 OUTPUT1_IF (c, TTY_SD (c).end_motion);
885 tty_frame_output_end (XFRAME (CONSOLE_SELECTED_FRAME (c))); 939 tty_output_end (XDEVICE (CONSOLE_SELECTED_DEVICE (c)));
886 } 940 }
887 941
888 /***************************************************************************** 942 /*****************************************************************************
889 tty_redisplay_shutdown 943 tty_redisplay_shutdown
890 944
893 void 947 void
894 tty_redisplay_shutdown (struct console *c) 948 tty_redisplay_shutdown (struct console *c)
895 { 949 {
896 Lisp_Object dev = CONSOLE_SELECTED_DEVICE (c); 950 Lisp_Object dev = CONSOLE_SELECTED_DEVICE (c);
897 951
898 if (!NILP (dev)) 952 if (!GC_NILP (dev))
899 { 953 {
900 Lisp_Object frm = DEVICE_SELECTED_FRAME (XDEVICE (dev)); 954 Lisp_Object frm = DEVICE_SELECTED_FRAME (XDEVICE (dev));
901 955
902 if (!NILP (frm)) 956 if (!GC_NILP (frm))
903 { 957 {
904 struct frame *f = XFRAME (frm); 958 struct frame *f = XFRAME (frm);
905 959
906 /* Clear the bottom line of the frame. */ 960 /* Clear the bottom line of the frame. */
907 redisplay_clear_region (FRAME_SELECTED_WINDOW (f), DEFAULT_INDEX, 0, 961 redisplay_clear_region (FRAME_SELECTED_WINDOW (f), DEFAULT_INDEX, 0,
908 f->height, f->width, 1); 962 f->height, f->width, 1);
909 963
910 /* And then stick the cursor there. */ 964 /* And then stick the cursor there. */
911 tty_set_final_cursor_coords (f, f->height, 0); 965 tty_set_final_cursor_coords (f, f->height, 0);
912 tty_frame_output_end (f); 966 tty_output_end (XDEVICE (dev));
913 } 967 }
914 } 968 }
915 } 969 }
916 970
917 971
918 /* #### Everything below here is old shit. It should either be moved 972 /* #### Everything below here is old shit. It should either be moved
919 up or removed. */ 973 up or removed. */
920 974
921 975
922 /* FLAGS - these don't need to be console local since only one console 976 /* FLAGS - these don't need to be console local since only one console
923 can be being updated at a time. */ 977 can be being updated at a time. */
924 static int insert_mode_on; /* nonzero if in insert mode */ 978 static int insert_mode_on; /* nonzero if in insert mode */
925 static int standout_mode_on; /* nonzero if in standout mode */ 979 static int standout_mode_on; /* nonzero if in standout mode */
926 static int underline_mode_on; /* nonzero if in underline mode */ 980 static int underline_mode_on; /* nonzero if in underline mode */
927 static int alternate_mode_on; /* nonzero if in alternate char set */ 981 static int alternate_mode_on; /* nonzero if in alternate char set */
928 static int attributes_on; /* nonzero if any attributes on */ 982 static int attributes_on; /* nonzero if any attributes on */
1052 doing this after all the tgetstr()s and adjusting all the 1106 doing this after all the tgetstr()s and adjusting all the
1053 pointers. */ 1107 pointers. */
1054 CONSOLE_TTY_DATA (c)->term_entry_buffer = (char *) xmalloc (2044); 1108 CONSOLE_TTY_DATA (c)->term_entry_buffer = (char *) xmalloc (2044);
1055 bufptr = CONSOLE_TTY_DATA (c)->term_entry_buffer; 1109 bufptr = CONSOLE_TTY_DATA (c)->term_entry_buffer;
1056 1110
1057 #ifdef SIGTTOU 1111 #if !defined(WIN32)
1058 /* SIGTT* don't exist under win32 */ 1112 /* SIGTT* don't exist under win32 */
1059 EMACS_BLOCK_SIGNAL (SIGTTOU); 1113 EMACS_BLOCK_SIGNAL (SIGTTOU);
1060 #endif 1114 #endif
1061 status = tgetent (entry_buffer, terminal_type); 1115 status = tgetent (entry_buffer, terminal_type);
1062 #ifdef SIGTTOU 1116 #if !defined(WIN32)
1063 EMACS_UNBLOCK_SIGNAL (SIGTTOU); 1117 EMACS_UNBLOCK_SIGNAL (SIGTTOU);
1064 #endif 1118 #endif
1065 #if 0 1119 #if 0
1066 if (status < 0) 1120 if (status < 0)
1067 return TTY_UNABLE_OPEN_DATABASE; 1121 return TTY_UNABLE_OPEN_DATABASE;
1248 return TTY_INIT_SUCCESS; 1302 return TTY_INIT_SUCCESS;
1249 } 1303 }
1250 1304
1251 struct fkey_table 1305 struct fkey_table
1252 { 1306 {
1253 const char *cap; 1307 CONST char *cap, *name;
1254 const char *name;
1255 }; 1308 };
1256 1309
1257 /* Termcap capability names that correspond directly to X keysyms. 1310 /* Termcap capability names that correspond directly to X keysyms.
1258 Some of these (marked "terminfo") aren't supplied by old-style 1311 Some of these (marked "terminfo") aren't supplied by old-style
1259 (Berkeley) termcap entries. They're listed in X keysym order; 1312 (Berkeley) termcap entries. They're listed in X keysym order;
1381 for (i = 0; i < countof (keys); i++) 1434 for (i = 0; i < countof (keys); i++)
1382 { 1435 {
1383 char *sequence = tgetstr (keys[i].cap, address); 1436 char *sequence = tgetstr (keys[i].cap, address);
1384 if (sequence) 1437 if (sequence)
1385 Fdefine_key (function_key_map, 1438 Fdefine_key (function_key_map,
1386 build_ext_string (sequence, Qbinary), 1439 build_ext_string (sequence, FORMAT_BINARY),
1387 vector1 (intern (keys[i].name))); 1440 vector1 (intern (keys[i].name)));
1388 } 1441 }
1389 1442
1390 /* The uses of the "k0" capability are inconsistent; sometimes it 1443 /* The uses of the "k0" capability are inconsistent; sometimes it
1391 describes F10, whereas othertimes it describes F0 and "k;" describes F10. 1444 describes F10, whereas othertimes it describes F0 and "k;" describes F10.
1392 We will attempt to politely accommodate both systems by testing for 1445 We will attempt to politely accommodate both systems by testing for
1393 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10. 1446 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10.
1394 */ 1447 */
1395 { 1448 {
1396 const char *k_semi = tgetstr ("k;", address); 1449 char *k_semi = tgetstr ("k;", address);
1397 const char *k0 = tgetstr ("k0", address); 1450 char *k0 = tgetstr ("k0", address);
1451 CONST char *k0_name = "f10";
1398 1452
1399 if (k_semi) 1453 if (k_semi)
1400 Fdefine_key (function_key_map, build_ext_string (k_semi, Qbinary), 1454 {
1401 vector1 (intern ("f10"))); 1455 Fdefine_key (function_key_map, build_ext_string (k_semi, FORMAT_BINARY),
1456 vector1 (intern ("f10")));
1457 k0_name = "f0";
1458 }
1402 1459
1403 if (k0) 1460 if (k0)
1404 Fdefine_key (function_key_map, build_ext_string (k0, Qbinary), 1461 Fdefine_key (function_key_map, build_ext_string (k0, FORMAT_BINARY),
1405 vector1 (intern (k_semi ? "f0" : "f10"))); 1462 vector1 (intern (k0_name)));
1406 } 1463 }
1407 1464
1408 /* Set up cookies for numbered function keys above f10. */ 1465 /* Set up cookies for numbered function keys above f10. */
1409 { 1466 {
1410 char fcap[3], fkey[4]; 1467 char fcap[3], fkey[4];
1423 char *sequence = tgetstr (fcap, address); 1480 char *sequence = tgetstr (fcap, address);
1424 if (sequence) 1481 if (sequence)
1425 { 1482 {
1426 sprintf (fkey, "f%d", i); 1483 sprintf (fkey, "f%d", i);
1427 Fdefine_key (function_key_map, 1484 Fdefine_key (function_key_map,
1428 build_ext_string (sequence, Qbinary), 1485 build_ext_string (sequence, FORMAT_BINARY),
1429 vector1 (intern (fkey))); 1486 vector1 (intern (fkey)));
1430 } 1487 }
1431 } 1488 }
1432 } 1489 }
1490 }
1491
1492 /*
1493 * Various mappings to try and get a better fit.
1494 */
1495 {
1496 #define CONDITIONAL_REASSIGN(cap1, cap2, sym) \
1497 if (!tgetstr (cap1, address)) \
1498 { \
1499 char *sequence = tgetstr (cap2, address); \
1500 if (sequence) \
1501 Fdefine_key (function_key_map, \
1502 build_ext_string (sequence, FORMAT_BINARY), \
1503 vector1 (intern (sym))); \
1504 }
1505
1506 /* if there's no key_next keycap, map key_npage to `next' keysym */
1507 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1508 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1509 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1510 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1511 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1512
1513 /* IBM has their own non-standard dialect of terminfo.
1514 If the standard name isn't found, try the IBM name. */
1515 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1516 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1517 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1518 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1519 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1520 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1521 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1522 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1523 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1524 #undef CONDITIONAL_REASSIGN
1433 } 1525 }
1434
1435 /*
1436 * Various mappings to try and get a better fit.
1437 */
1438 #define CONDITIONAL_REASSIGN(cap1, cap2, keyname) do { \
1439 if (!tgetstr (cap1, address)) \
1440 { \
1441 char *sequence = tgetstr (cap2, address); \
1442 if (sequence) \
1443 Fdefine_key (function_key_map, \
1444 build_ext_string (sequence, Qbinary), \
1445 vector1 (intern (keyname))); \
1446 } \
1447 } while (0)
1448
1449 /* if there's no key_next keycap, map key_npage to `next' keysym */
1450 CONDITIONAL_REASSIGN ("%5", "kN", "next");
1451 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */
1452 CONDITIONAL_REASSIGN ("%8", "kP", "prior");
1453 /* if there's no key_dc keycap, map key_ic to `insert' keysym */
1454 CONDITIONAL_REASSIGN ("kD", "kI", "insert");
1455
1456 /* IBM has their own non-standard dialect of terminfo.
1457 If the standard name isn't found, try the IBM name. */
1458 CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
1459 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
1460 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
1461 CONDITIONAL_REASSIGN ("%7", "ki", "menu");
1462 CONDITIONAL_REASSIGN ("@7", "kw", "end");
1463 CONDITIONAL_REASSIGN ("F1", "k<", "f11");
1464 CONDITIONAL_REASSIGN ("F2", "k>", "f12");
1465 CONDITIONAL_REASSIGN ("%1", "kq", "help");
1466 CONDITIONAL_REASSIGN ("*6", "kU", "select");
1467 #undef CONDITIONAL_REASSIGN
1468 1526
1469 return Qnil; 1527 return Qnil;
1470 } 1528 }
1471 1529
1472 1530
1484 CONSOLE_HAS_METHOD (tty, divider_height); 1542 CONSOLE_HAS_METHOD (tty, divider_height);
1485 CONSOLE_HAS_METHOD (tty, eol_cursor_width); 1543 CONSOLE_HAS_METHOD (tty, eol_cursor_width);
1486 CONSOLE_HAS_METHOD (tty, clear_to_window_end); 1544 CONSOLE_HAS_METHOD (tty, clear_to_window_end);
1487 CONSOLE_HAS_METHOD (tty, clear_region); 1545 CONSOLE_HAS_METHOD (tty, clear_region);
1488 CONSOLE_HAS_METHOD (tty, clear_frame); 1546 CONSOLE_HAS_METHOD (tty, clear_frame);
1489 CONSOLE_HAS_METHOD (tty, frame_output_begin); 1547 CONSOLE_HAS_METHOD (tty, output_begin);
1490 CONSOLE_HAS_METHOD (tty, frame_output_end); 1548 CONSOLE_HAS_METHOD (tty, output_end);
1491 CONSOLE_HAS_METHOD (tty, flash); 1549 CONSOLE_HAS_METHOD (tty, flash);
1492 CONSOLE_HAS_METHOD (tty, ring_bell); 1550 CONSOLE_HAS_METHOD (tty, ring_bell);
1493 CONSOLE_HAS_METHOD (tty, set_final_cursor_coords); 1551 CONSOLE_HAS_METHOD (tty, set_final_cursor_coords);
1494 } 1552 }