1 /* NetHack 3.6 mactty.c $NHDT-Date: 1432512797 2015/05/25 00:13:17 $ $NHDT-Branch: master $:$NHDT-Revision: 1.9 $ */
2 /* Copyright (c) Jon W{tte 1993. */
3 /* NetHack may be freely redistributed. See license for details. */
8 * This file contains the actual code for the tty library. For a
9 * description, see the file mactty.h, which contains all you
10 * need to know to use the library.
13 #include "hack.h" /* to get flags */
15 #if !TARGET_API_MAC_CARBON
16 #include <Resources.h>
19 char game_active
= 0; /* flag to window rendering routines not to use ppat */
21 /* these declarations are here because I can't include macwin.h without
22 * including the world */
23 extern void dprintf(char *, ...); /* dprintf.c */
26 * Borrowed from the Mac tty port
28 extern WindowPtr _mt_window
;
30 static void select_onscreen_window(tty_record
*record
);
31 static void select_offscreen_port(tty_record
*record
);
33 #define MEMORY_MARGIN 30000
36 * Convenience macro for most functions - put last in declaration
38 #define RECORD_EXISTS(record) \
40 if (!window || !(record = (tty_record *) GetWRefCon(window))) \
41 return general_failure;
44 * Simple macro for deciding whether we draw at once or delay
46 #define DRAW_DIRECT (TA_ALWAYS_REFRESH & record->attribute[TTY_ATTRIB_FLAGS])
49 * Table of special characters. Zero is ALWAYS special; it means
50 * end of string and would be MISSED if it was not included here.
52 #define COOKED_CONTROLS 0X00002581
53 #define RAW_CONTROLS 1
54 static unsigned long s_control
= COOKED_CONTROLS
;
57 * Memory-related error
62 short ret_val
= MemError();
64 ret_val
= general_failure
;
70 * Make a rectangle empty
82 * Union twp rect together
85 union_rect(Rect
*r1
, Rect
*r2
, Rect
*dest
)
87 dest
->left
= min(r1
->left
, r2
->left
);
88 dest
->top
= min(r1
->top
, r2
->top
);
89 dest
->bottom
= max(r1
->bottom
, r2
->bottom
);
90 dest
->right
= max(r1
->right
, r2
->right
);
94 * Dispose a pointer using the set memory-allocator
97 dispose_ptr(void *ptr
)
100 return noErr
; /* Silently accept disposing nulls */
106 #if 0 /* Use alloc.c instead */
108 * Allocate a pointer using the set memory-allocator
111 alloc_ptr (void **ptr
, long size
) {
112 *ptr
= NewPtr (size
);
118 * Set up a GWorld in the record
121 allocate_offscreen_world(tty_record
*record
)
123 GWorldPtr gw
= (GWorldPtr
) 0;
124 GWorldFlags world_flags
= 0;
125 long mem_here
, mem_there
, other
, required_mem
;
131 select_onscreen_window(record
);
133 r_screen
= record
->its_bits
.bounds
;
134 OffsetRect(&r_screen
, p
.h
, p
.v
);
136 gdh
= GetMaxDevice(&r_screen
);
137 required_mem
= (long) (*((*gdh
)->gdPMap
))->pixelSize
138 * ((long) record
->its_bits
.bounds
.right
139 * record
->its_bits
.bounds
.bottom
)
142 PurgeSpace(&other
, &mem_here
);
143 if (other
< mem_here
+ MEMORY_MARGIN
) {
144 mem_here
= other
- MEMORY_MARGIN
;
146 dprintf("Heap %ld Required %ld", mem_here
, required_mem
);
147 if (required_mem
> mem_here
) {
148 mem_there
= required_mem
;
149 if (required_mem
> TempMaxMem(&mem_there
)) {
150 dprintf("No memory");
153 world_flags
|= useTempMem
;
155 s_err
= NewGWorld(&gw
, 0, &r_screen
, (CTabHandle
) 0, (GDHandle
) 0,
158 record
->offscreen_world
= gw
;
159 select_offscreen_port(record
);
161 select_onscreen_window(record
);
162 dprintf("New GWorld @ %lx;dm", gw
);
168 * Done with GWorld, release data
171 deallocate_gworld(tty_record
*record
)
173 if (record
->offscreen_world
) {
174 DisposeGWorld(record
->offscreen_world
);
175 record
->offscreen_world
= (GWorldPtr
) 0;
181 * Get rid of offscreen bitmap
184 free_bits(tty_record
*record
)
188 if (record
->uses_gworld
) {
189 s_err
= deallocate_gworld(record
);
190 #if !TARGET_API_MAC_CARBON
192 s_err
= dispose_ptr(record
->its_bits
.baseAddr
);
194 record
->its_bits
.baseAddr
= (char *) 0;
195 if (record
->offscreen_port
) {
196 ClosePort(record
->offscreen_port
);
197 s_err
= dispose_ptr(record
->offscreen_port
);
199 record
->offscreen_port
= (GrafPtr
) 0;
209 * Snatch a window from the resource fork. Create the record.
210 * Otherwise, do nothing.
214 create_tty(WindowRef
*window
, short resource_id
, Boolean in_color
)
217 Boolean was_allocated
= !!*window
;
220 *window
= GetNewCWindow(resource_id
, (Ptr
) *window
, (WindowRef
) -1L);
222 *window
= GetNewWindow(resource_id
, (Ptr
) *window
, (WindowRef
) -1L);
228 record
= (tty_record
*) NewPtrClear(sizeof(tty_record
));
230 #if !TARGET_API_MAC_CARBON
232 CloseWindow(*window
);
235 DisposeWindow(*window
);
236 #if !TARGET_API_MAC_CARBON
241 record
->its_window
= *window
;
242 SetWRefCon(*window
, (long) record
);
243 record
->was_allocated
= was_allocated
;
244 record
->its_bits
.baseAddr
= (char *) 0;
245 record
->curs_state
= TRUE
;
248 * We need to keep the window world around if we switch worlds
250 record
->offscreen_world
= (GWorldPtr
) 0;
251 record
->uses_gworld
= in_color
;
255 SetPortWindowPort(*window
);
256 GetGWorld(&(record
->its_window_world
), &gh
);
258 record
->its_window_world
= (GWorldPtr
) 0;
262 empty_rect(&(record
->invalid_rect
));
264 record
->invalid_part
= NewRgn();
265 if (!record
->invalid_part
) {
266 return destroy_tty(*window
);
274 init_tty_number(WindowPtr window
, short font_number
, short font_size
,
275 short x_size
, short y_size
)
277 RECORD_EXISTS(record
);
279 record
->font_number
= font_number
;
280 record
->font_size
= font_size
;
281 record
->x_size
= x_size
;
282 record
->y_size
= y_size
;
284 return force_tty_coordinate_system_recalc(window
);
288 * Done with a window - destroy it. Release the memory only if
289 * it wasn't allocated when we got it!
292 destroy_tty(WindowPtr window
)
295 RECORD_EXISTS(record
);
297 s_err
= free_bits(record
);
299 #if !TARGET_API_MAC_CARBON
300 if (record
->was_allocated
) {
304 DisposeWindow(window
);
305 #if !TARGET_API_MAC_CARBON
308 s_err
= dispose_ptr(record
);
315 do_set_port_font(tty_record
*record
)
318 TextFont(record
->font_number
);
319 TextSize(record
->font_size
);
320 if (0L != (record
->attribute
[TTY_ATTRIB_FLAGS
] & TA_OVERSTRIKE
)) {
328 * Fill in some fields from some other fields that may have changed
331 calc_font_sizes(tty_record
*record
)
335 do_set_port_font(record
);
337 GetFontInfo(&font_info
);
338 record
->char_width
= font_info
.widMax
;
339 record
->ascent_height
= font_info
.ascent
+ font_info
.leading
;
340 record
->row_height
= record
->ascent_height
+ font_info
.descent
;
344 * Allocate memory for the bitmap holding the tty window
347 alloc_bits(tty_record
*record
)
351 SetRect(&record
->its_bits
.bounds
, 0, 0,
352 record
->char_width
* record
->x_size
,
353 record
->row_height
* record
->y_size
);
356 * Clear two highest and lowest bit - not a color pixMap, and even in size
358 record
->its_bits
.rowBytes
=
359 ((record
->its_bits
.bounds
.right
+ 15) >> 3) & 0x1ffe;
361 if (record
->uses_gworld
) {
362 s_err
= allocate_offscreen_world(record
);
363 #if !TARGET_API_MAC_CARBON
365 s_err
= alloc_ptr((void **) &(record
->its_bits
.baseAddr
),
366 record
->its_bits
.rowBytes
367 * record
->its_bits
.bounds
.bottom
);
369 s_err
= alloc_ptr((void **) &(record
->offscreen_port
),
373 OpenPort(record
->offscreen_port
);
374 SetPort(record
->offscreen_port
);
375 ClipRect(&(record
->its_bits
.bounds
));
376 SetPortBits(&(record
->its_bits
));
384 * Save the current port/world in a safe place for later retrieval
387 save_port(tty_record
*record
, void *save
)
393 if (record
->uses_gworld
) {
395 *(GWorldPtr
*) save
= gw
;
398 *(GrafPtr
*) save
= gp
;
403 * Restore current port/world after a save
406 use_port(tty_record
*record
, void *port
)
408 if (record
->uses_gworld
) {
409 PixMapHandle pix_map
;
411 SetGWorld((GWorldPtr
) port
, (GDHandle
) 0);
412 pix_map
= GetGWorldPixMap(record
->offscreen_world
);
414 if (port
== record
->offscreen_world
)
417 UnlockPixels(pix_map
);
420 SetPort((GrafPtr
) port
);
425 * Use offscreen drawing - lock the pixels through use_port
428 select_offscreen_port(tty_record
*record
)
430 if (record
->uses_gworld
) {
431 use_port(record
, record
->offscreen_world
);
433 use_port(record
, record
->offscreen_port
);
438 * Use the window - unlock pixels
441 select_onscreen_window(tty_record
*record
)
443 if (record
->uses_gworld
) {
444 use_port(record
, record
->its_window_world
);
445 SetPortWindowPort(record
->its_window
);
447 use_port(record
, record
->its_window
);
452 * Do bits copy depending on if we're using color or not
455 copy_bits(tty_record
*record
, Rect
*bounds
, short xfer_mode
,
458 GWorldFlags pix_state
;
461 if (record
->uses_gworld
) {
462 pix_state
= GetPixelsState(GetGWorldPixMap(record
->offscreen_world
));
463 LockPixels(GetGWorldPixMap(record
->offscreen_world
));
464 source
= (BitMapPtr
) *GetGWorldPixMap(record
->offscreen_world
);
466 source
= &record
->its_bits
;
468 SetPortWindowPort(record
->its_window
);
470 GetPortBitMapForCopyBits(GetWindowPort(record
->its_window
)),
471 bounds
, bounds
, xfer_mode
, mask_rgn
);
473 if (record
->uses_gworld
) {
474 SetPixelsState(GetGWorldPixMap(record
->offscreen_world
), pix_state
);
479 * Fill an area with the background color
482 erase_rect(tty_record
*record
, Rect
*area
)
484 if (game_active
&& u
.uhp
> 0 && iflags
.use_stone
485 && record
->its_window
== _mt_window
) {
488 ppat
= GetPixPat(iflags
.use_stone
+ 127); /* find which pat to get */
489 if (ppat
) { /* in game window, using backgroung pattern, and have
491 FillCRect(area
, ppat
);
500 * Recalculate the window based on new size, font, extent values,
501 * and re-allocate the bitmap.
504 force_tty_coordinate_system_recalc(WindowPtr window
)
507 RECORD_EXISTS(record
);
509 s_err
= free_bits(record
);
513 calc_font_sizes(record
);
515 s_err
= alloc_bits(record
);
518 * Catastrophe! We could not allocate memory for the bitmap! Things
520 * much downhill from here!
522 dprintf("alloc_bits returned null in "
523 "force_tty_coordinate_system_recalc!");
526 select_offscreen_port(record
);
527 do_set_port_font(record
);
528 return clear_tty(window
);
533 * Update TTY according to new color environment for the window
536 tty_environment_changed (tty_record
*record
) {
540 if (record
->uses_gworld
) {
541 r_screen
= record
->its_bits
.bounds
;
543 OffsetRect (&r_screen
, p
.h
, p
.v
);
544 UpdateGWorld (&(record
->offscreen_world
), 0, &r_screen
,
545 (CTabHandle
) 0, (GDHandle
) 0, stretchPix
);
546 select_offscreen_port (record
);
548 select_onscreen_window (record
);
555 * Read a lot of interesting and useful information from the current tty
558 get_tty_metrics(WindowPtr window
, short *x_size
, short *y_size
,
559 short *x_size_pixels
, short *y_size_pixels
,
560 short *font_number
, short *font_size
, short *char_width
,
563 RECORD_EXISTS(record
);
566 * First, test that we actually have something to draw to...
568 if ((((char *) 0 == record
->its_bits
.baseAddr
) && !record
->uses_gworld
)
569 || (((GWorldPtr
) 0 == record
->offscreen_world
)
570 && record
->uses_gworld
)) {
571 return general_failure
;
574 *x_size
= record
->x_size
;
575 *y_size
= record
->y_size
;
576 *x_size_pixels
= record
->its_bits
.bounds
.right
;
577 *y_size_pixels
= record
->its_bits
.bounds
.bottom
;
578 *font_number
= record
->font_number
;
579 *font_size
= record
->font_size
;
580 *char_width
= record
->char_width
;
581 *row_height
= record
->row_height
;
587 * Map a position on the map to screen coordinates
590 pos_rect(tty_record
*record
, Rect
*r
, short x_pos
, short y_pos
, short x_end
,
593 SetRect(r
, x_pos
* (record
->char_width
), y_pos
* (record
->row_height
),
594 (1 + x_end
) * (record
->char_width
),
595 (1 + y_end
) * (record
->row_height
));
599 accumulate_rect(tty_record
*record
, Rect
*rect
)
602 union_rect(rect
, &(record
->invalid_rect
), &(record
->invalid_rect
));
604 RgnHandle rh
= NewRgn();
607 UnionRgn(record
->invalid_part
, rh
, record
->invalid_part
);
613 * get and set window invalid region. exposed for HandleUpdateEvent in
615 * to correct display problem
619 get_invalid_region(WindowPtr window
, Rect
*inval_rect
)
621 RECORD_EXISTS(record
);
623 if (record
->invalid_rect
.right
<= record
->invalid_rect
.left
624 || record
->invalid_rect
.bottom
<= record
->invalid_rect
.top
) {
625 return general_failure
;
627 *inval_rect
= record
->invalid_rect
;
629 if (EmptyRgn(record
->invalid_part
)) {
630 return general_failure
;
632 *inval_rect
= (*(record
->invalid_part
))->rgnBBox
;
638 set_invalid_region(WindowPtr window
, Rect
*inval_rect
)
640 RECORD_EXISTS(record
);
641 accumulate_rect(record
, inval_rect
);
646 * Invert the specified position
649 curs_pos(tty_record
*record
, short x_pos
, short y_pos
, short to_state
)
653 if (record
->curs_state
== to_state
) {
656 record
->curs_state
= to_state
;
657 pos_rect(record
, &r
, x_pos
, y_pos
, x_pos
, y_pos
);
662 save_port(record
, &old_port
);
663 select_onscreen_window(record
);
665 use_port(record
, old_port
);
667 accumulate_rect(record
, &r
);
672 * Move the cursor (both as displayed and where drawing goes)
673 * HOWEVER: The cursor is NOT stored in the bitmap!
676 move_tty_cursor(WindowPtr window
, short x_pos
, short y_pos
)
678 RECORD_EXISTS(record
);
680 if (record
->x_curs
== x_pos
&& record
->y_curs
== y_pos
) {
683 if (record
->x_size
<= x_pos
|| x_pos
< 0 || record
->y_size
<= y_pos
685 return general_failure
;
687 curs_pos(record
, record
->x_curs
, record
->y_curs
, 0);
688 record
->x_curs
= x_pos
;
689 record
->y_curs
= y_pos
;
690 curs_pos(record
, x_pos
, y_pos
, 1);
696 * Update the screen to match the current bitmap, after adding stuff
697 * with add_tty_char etc.
700 update_tty(WindowPtr window
)
703 RECORD_EXISTS(record
);
706 if (record
->invalid_rect
.right
<= record
->invalid_rect
.left
707 || record
->invalid_rect
.bottom
<= record
->invalid_rect
.top
) {
710 r
= record
->invalid_rect
;
712 if (EmptyRgn(record
->invalid_part
)) {
715 r
= (*(record
->invalid_part
))->rgnBBox
;
717 select_onscreen_window(record
);
718 copy_bits(record
, &r
, srcCopy
, (RgnHandle
) 0);
720 empty_rect(&(record
->invalid_rect
));
722 SetEmptyRgn(record
->invalid_part
);
724 if (record
->curs_state
) {
725 pos_rect(record
, &r
, record
->x_curs
, record
->y_curs
, record
->x_curs
,
734 * Low level add to screen
737 do_add_string(tty_record
*record
, char *str
, short len
)
744 select_offscreen_port(record
);
746 MoveTo(record
->x_curs
* record
->char_width
,
747 record
->y_curs
* record
->row_height
+ record
->ascent_height
);
748 DrawText(str
, 0, len
);
750 pos_rect(record
, &r
, record
->x_curs
, record
->y_curs
,
751 record
->x_curs
+ len
- 1, record
->y_curs
);
752 select_onscreen_window(record
);
754 copy_bits(record
, &r
, srcCopy
, (RgnHandle
) 0);
756 accumulate_rect(record
, &r
);
761 * Low-level cursor handling routine
764 do_add_cursor(tty_record
*record
, short x_pos
)
766 record
->x_curs
= x_pos
;
767 if (record
->x_curs
>= record
->x_size
) {
768 if (0L != (record
->attribute
[TTY_ATTRIB_FLAGS
] & TA_WRAP_AROUND
)) {
771 if (record
->y_curs
>= record
->y_size
) {
772 if (0L != (record
->attribute
[TTY_ATTRIB_FLAGS
]
773 & TA_INHIBIT_VERT_SCROLL
)) {
774 record
->y_curs
= record
->y_size
;
776 scroll_tty(record
->its_window
, 0,
777 1 + record
->y_curs
- record
->y_size
);
781 record
->x_curs
= record
->x_size
;
787 * Do control character
790 do_control(tty_record
*record
, short character
)
795 * Check recursion because nl_add_cr and cr_add_nl may both be set and
803 && (record
->attribute
[TTY_ATTRIB_CURSOR
] & TA_CR_ADD_NL
)) {
808 } /* FALL-THROUGH: if CR-LF, don't bother with loop */
811 if (record
->y_curs
>= record
->y_size
) {
812 scroll_tty(record
->its_window
, 0,
813 1 + record
->y_curs
- record
->y_size
);
816 && (record
->attribute
[TTY_ATTRIB_CURSOR
] & TA_NL_ADD_CR
)) {
826 if (record
->x_curs
> 0)
835 * Add a single character. It is drawn directly if the correct flag is set,
836 * else deferred to the next update event or call of update_tty()
839 add_tty_char(WindowPtr window
, short character
)
841 register char is_control
;
843 RECORD_EXISTS(record
);
845 if (!(record
->attribute
[TTY_ATTRIB_FLAGS
] & TA_WRAP_AROUND
)
846 && record
->x_curs
>= record
->x_size
)
847 return noErr
; /* Optimize away drawing across border without wrap */
849 if (record
->curs_state
!= 0)
850 curs_pos(record
, record
->x_curs
, record
->y_curs
, 0);
853 is_control
= (ch
< sizeof(long) * 8) && ((s_control
& (1 << ch
)) != 0L);
855 do_control(record
, ch
);
857 do_add_string(record
, (char *) &ch
, 1);
858 do_add_cursor(record
, record
->x_curs
+ 1);
865 * Add a null-terminated string of characters
868 add_tty_string(WindowPtr window
, const char *string
)
870 register const unsigned char *start_c
;
871 register const unsigned char *the_c
;
872 register unsigned char ch
, is_control
= 0, tty_wrap
;
873 register short max_x
, pos_x
;
874 RECORD_EXISTS(record
);
876 if (record
->curs_state
!= 0)
877 curs_pos(record
, record
->x_curs
, record
->y_curs
, 0);
879 the_c
= (const unsigned char *) string
;
880 max_x
= record
->x_size
;
881 tty_wrap
= (record
->attribute
[TTY_ATTRIB_FLAGS
] & TA_WRAP_AROUND
);
883 pos_x
= record
->x_curs
;
884 if (!tty_wrap
&& pos_x
>= max_x
)
885 break; /* Optimize away drawing across border without wrap */
889 while (pos_x
< max_x
) {
891 (ch
< sizeof(long) * 8) && ((s_control
& (1 << ch
)) != 0L);
898 do_add_string(record
, (char *) start_c
, the_c
- start_c
);
899 do_add_cursor(record
, pos_x
);
904 do_control(record
, ch
);
913 * Read or change attributes for the tty. Note that some attribs may
914 * very well clear and reallocate the bitmap when changed, whereas
915 * others (color, highlight, ...) are guaranteed not to.
918 get_tty_attrib(WindowPtr window
, tty_attrib attrib
, long *value
)
920 RECORD_EXISTS(record
);
922 if (attrib
< 0 || attrib
>= TTY_NUMBER_ATTRIBUTES
) {
923 return general_failure
;
925 *value
= record
->attribute
[attrib
];
931 set_tty_attrib(WindowPtr window
, tty_attrib attrib
, long value
)
934 RECORD_EXISTS(record
);
936 if (attrib
< 0 || attrib
>= TTY_NUMBER_ATTRIBUTES
) {
937 return general_failure
;
939 record
->attribute
[attrib
] = value
;
941 * Presently, no attributes generate a new bitmap.
944 case TTY_ATTRIB_CURSOR
:
946 * Check if we should change tables
948 if (0L != (value
& TA_RAW_OUTPUT
)) {
949 s_control
= RAW_CONTROLS
;
951 s_control
= COOKED_CONTROLS
;
954 case TTY_ATTRIB_FLAGS
:
956 * Check if we should flush the output going from cached to
959 if (0L != (value
& TA_ALWAYS_REFRESH
)) {
963 case TTY_ATTRIB_FOREGROUND
:
965 * Set foreground color
967 TA_TO_RGB(value
, rgb_color
);
968 select_offscreen_port(record
);
969 RGBForeColor(&rgb_color
);
970 select_onscreen_window(record
);
972 case TTY_ATTRIB_BACKGROUND
:
974 * Set background color
976 TA_TO_RGB(value
, rgb_color
);
977 select_offscreen_port(record
);
978 RGBBackColor(&rgb_color
);
979 select_onscreen_window(record
);
988 * Scroll the window. Positive is up/left. scroll_tty ( window, 0, 1 ) is a
990 * Scroll flushes the accumulated update area by calling update_tty().
994 scroll_tty(WindowPtr window
, short delta_x
, short delta_y
)
998 RECORD_EXISTS(record
);
1000 s_err
= update_tty(window
);
1004 select_offscreen_port(record
);
1005 ScrollRect(&(record
->its_bits
.bounds
), -delta_x
* record
->char_width
,
1006 -delta_y
* record
->row_height
, rgn
);
1010 select_onscreen_window(record
);
1011 ScrollRect(&(record
->its_bits
.bounds
), -delta_x
* record
->char_width
,
1012 -delta_y
* record
->row_height
, rgn
);
1016 record
->y_curs
-= delta_y
;
1017 record
->x_curs
-= delta_x
;
1023 * Clear the screen. Immediate.
1026 clear_tty(WindowPtr window
)
1028 RECORD_EXISTS(record
);
1030 record
->curs_state
= 0;
1031 select_offscreen_port(record
);
1032 erase_rect(record
, &(record
->its_bits
.bounds
));
1033 accumulate_rect(record
, &(record
->its_bits
.bounds
));
1040 * Blink cursor on window if necessary
1043 blink_cursor(WindowPtr window
, long when
)
1045 RECORD_EXISTS(record
);
1047 if ((record
->attribute
[TTY_ATTRIB_CURSOR
] & TA_BLINKING_CURSOR
)) {
1048 if (when
> record
->last_cursor
+ GetCaretTime()) {
1049 curs_pos(record
, record
->x_curs
, record
->y_curs
,
1050 !record
->curs_state
);
1051 record
->last_cursor
= when
;
1059 * Draw an image of the tty - used for update events and can be called
1063 image_tty(EventRecord
*theEvent
, WindowPtr window
)
1065 #if defined(__SC__) || defined(__MRC__)
1066 #pragma unused(theEvent)
1068 RECORD_EXISTS(record
);
1071 record
->invalid_rect
= record
->its_bits
.bounds
;
1073 RgnHandle rh
= NewRgn();
1075 RectRgn(rh
, record
->its_bits
.bounds
);
1076 UnionRgn(record
->invalid_part
, rh
, record
->invalid_part
);
1079 return update_tty(window
);
1086 clear_tty_window(WindowPtr window
, short from_x
, short from_y
, short to_x
,
1090 RECORD_EXISTS(record
);
1092 if (from_x
> to_x
|| from_y
> to_y
) {
1093 return general_failure
;
1095 pos_rect(record
, &r
, from_x
, from_y
, to_x
, to_y
);
1096 select_offscreen_port(record
);
1097 erase_rect(record
, &r
);
1098 accumulate_rect(record
, &r
);
1102 select_onscreen_window(record
);
1106 #if EXTENDED_SUPPORT
1108 * Delete or insert operations used by many terminals can bottleneck through
1109 * here. Note that the order of executin for row/colum insertions is NOT
1110 * specified. Negative values for num_ mean delete, zero means no effect.
1113 mangle_tty_rows_columns(WindowPtr window
, short from_row
, short num_rows
,
1114 short from_column
, short num_columns
)
1117 RgnHandle rh
= NewRgn();
1118 RECORD_EXISTS(record
);
1120 update_tty(window
); /* Always make sure screen is OK */
1121 curs_pos(record
, record
->x_curs
, record
->y_curs
, 0);
1124 pos_rect(record
, &r
, 0, from_row
, record
->x_size
- 1,
1125 record
->y_size
- 1);
1126 select_offscreen_port(record
);
1127 ScrollRect(&r
, 0, num_rows
* record
->row_height
, rh
);
1130 select_onscreen_window(record
);
1131 ScrollRect(&r
, 0, num_rows
* record
->row_height
, rh
);
1136 pos_rect(record
, &r
, from_column
, 0, record
->x_size
- 1,
1137 record
->y_size
- 1);
1138 select_offscreen_port(record
);
1139 ScrollRect(&r
, num_columns
* record
->char_width
, 0, rh
);
1142 select_onscreen_window(record
);
1143 ScrollRect(&r
, num_columns
* record
->char_width
, 0, rh
);
1148 if (record
->x_curs
>= from_column
) {
1149 record
->x_curs
+= num_columns
;
1151 if (record
->y_curs
>= from_row
) {
1152 record
->y_curs
+= num_rows
;
1154 curs_pos(record
, record
->x_curs
, record
->y_curs
, 1);
1160 * Frame an area in an aesthetically pleasing way.
1163 frame_tty_window(WindowPtr window
, short from_x
, short from_y
, short to_x
,
1164 short to_y
, short frame_fatness
)
1167 RECORD_EXISTS(record
);
1169 if (from_x
> to_x
|| from_y
> to_y
) {
1170 return general_failure
;
1172 pos_rect(record
, &r
, from_x
, from_y
, to_x
, to_y
);
1173 select_offscreen_port(record
);
1174 PenSize(frame_fatness
, frame_fatness
);
1177 accumulate_rect(record
, &r
);
1181 select_onscreen_window(record
);
1185 * Highlighting a specific part of the tty window
1188 invert_tty_window(WindowPtr window
, short from_x
, short from_y
, short to_x
,
1192 RECORD_EXISTS(record
);
1194 if (from_x
> to_x
|| from_y
> to_y
) {
1195 return general_failure
;
1197 pos_rect(record
, &r
, from_x
, from_y
, to_x
, to_y
);
1198 select_offscreen_port(record
);
1200 accumulate_rect(record
, &r
);
1204 select_onscreen_window(record
);
1208 canonical_rect(Rect
*r
, short x1
, short y1
, short x2
, short y2
)
1212 SetRect(r
, x1
, x2
, y1
, y2
);
1214 SetRect(r
, x1
, x2
, y2
, y1
);
1218 SetRect(r
, x2
, x1
, y1
, y2
);
1220 SetRect(r
, x2
, x1
, y2
, y1
);
1226 * Line drawing - very device dependent
1229 draw_tty_line(WindowPtr window
, short from_x
, short from_y
, short to_x
,
1233 RECORD_EXISTS(record
);
1235 select_offscreen_port(record
);
1236 MoveTo(from_x
, from_y
);
1238 canonical_rect(&r
, from_x
, from_y
, to_x
, to_y
);
1239 accumulate_rect(record
, &r
);
1243 select_onscreen_window(record
);
1246 #endif /* EXTENDED_SUPPORT */