declarations
[scilab.git] / scilab / routines / xsci / x_util.c
1 /*
2  *      $XConsortium: util.c,v 1.31 91/06/20 18:34:47 gildea Exp $
3  */
4
5 /*
6  * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
7  *
8  *                         All Rights Reserved
9  *
10  * Permission to use, copy, modify, and distribute this software and its
11  * documentation for any purpose and without fee is hereby granted,
12  * provided that the above copyright notice appear in all copies and that
13  * both that copyright notice and this permission notice appear in
14  * supporting documentation, and that the name of Digital Equipment
15  * Corporation not be used in advertising or publicity pertaining to
16  * distribution of the software without specific, written prior permission.
17  *
18  *
19  * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
20  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
21  * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
22  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
23  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
25  * SOFTWARE.
26  */
27
28 /* util.c */
29
30 #include "x_ptyxP.h"
31 #include "x_data.h"
32 #include "x_error.h"
33 #include "x_menu.h"
34
35 #include "../machine.h"
36 #include "All-extern-x.h"
37
38 #include <stdio.h>
39
40 static void horizontal_copy_area();
41 static void vertical_copy_area();
42
43 /*
44  * These routines are used for the jump scroll feature
45  */
46
47 void FlushScroll(screen)
48 register TScreen *screen;
49 {
50         register int i;
51         register int shift = -screen->topline;
52         register int bot = screen->max_row - shift;
53         register int refreshtop;
54         register int refreshheight;
55         register int scrolltop;
56         register int scrollheight;
57
58         if(screen->cursor_state)
59                 HideCursor();
60         if(screen->scroll_amt > 0) {
61                 refreshheight = screen->refresh_amt;
62                 scrollheight = screen->bot_marg - screen->top_marg -
63                  refreshheight + 1;
64                 if((refreshtop = screen->bot_marg - refreshheight + 1 + shift) >
65                  (i = screen->max_row - screen->scroll_amt + 1))
66                         refreshtop = i;
67                 if(screen->scrollWidget && !screen->alternate
68                  && screen->top_marg == 0) {
69                         scrolltop = 0;
70                         if((scrollheight += shift) > i)
71                                 scrollheight = i;
72                         if((i = screen->bot_marg - bot) > 0 &&
73                          (refreshheight -= i) < screen->scroll_amt)
74                                 refreshheight = screen->scroll_amt;
75                         if((i = screen->savedlines) < screen->savelines) {
76                                 if((i += screen->scroll_amt) >
77                                   screen->savelines)
78                                         i = screen->savelines;
79                                 screen->savedlines = i;
80                                 ScrollBarDrawThumb(screen->scrollWidget);
81                         }
82                 } else {
83                         scrolltop = screen->top_marg + shift;
84                         if((i = bot - (screen->bot_marg - screen->refresh_amt +
85                          screen->scroll_amt)) > 0) {
86                                 if(bot < screen->bot_marg)
87                                         refreshheight = screen->scroll_amt + i;
88                         } else {
89                                 scrollheight += i;
90                                 refreshheight = screen->scroll_amt;
91                                 if((i = screen->top_marg + screen->scroll_amt -
92                                  1 - bot) > 0) {
93                                         refreshtop += i;
94                                         refreshheight -= i;
95                                 }
96                         }
97                 }
98         } else {
99                 refreshheight = -screen->refresh_amt;
100                 scrollheight = screen->bot_marg - screen->top_marg -
101                  refreshheight + 1;
102                 refreshtop = screen->top_marg + shift;
103                 scrolltop = refreshtop + refreshheight;
104                 if((i = screen->bot_marg - bot) > 0)
105                         scrollheight -= i;
106                 if((i = screen->top_marg + refreshheight - 1 - bot) > 0)
107                         refreshheight -= i;
108         }
109         scrolling_copy_area(screen, scrolltop+screen->scroll_amt,
110                             scrollheight, screen->scroll_amt);
111         ScrollSelection(screen, -(screen->scroll_amt));
112         screen->scroll_amt = 0;
113         screen->refresh_amt = 0;
114         if(refreshheight > 0) {
115                 XClearArea (
116                     screen->display,
117                     TextWindow(screen),
118                     (int) screen->border + screen->scrollbar,
119                     (int) refreshtop * FontHeight(screen) + screen->border,
120                     (unsigned) Width(screen),
121                     (unsigned) refreshheight * FontHeight(screen),
122                     FALSE);
123                 ScrnRefresh(screen, refreshtop, 0, refreshheight,
124                  screen->max_col + 1, False);
125         }
126 }
127
128
129 int AddToRefresh(screen)
130 register TScreen *screen;
131 {
132         register int amount = screen->refresh_amt;
133         register int row = screen->cur_row;
134
135         if(amount == 0)
136                 return(0);
137         if(amount > 0) {
138                 register int bottom;
139
140                 if(row == (bottom = screen->bot_marg) - amount) {
141                         screen->refresh_amt++;
142                         return(1);
143                 }
144                 return(row >= bottom - amount + 1 && row <= bottom);
145         } else {
146                 register int top;
147
148                 amount = -amount;
149                 if(row == (top = screen->top_marg) + amount) {
150                         screen->refresh_amt--;
151                         return(1);
152                 }
153                 return(row <= top + amount - 1 && row >= top);
154         }
155 }
156
157 /* 
158  * scrolls the screen by amount lines, erases bottom, doesn't alter 
159  * cursor position (i.e. cursor moves down amount relative to text).
160  * All done within the scrolling region, of course. 
161  * requires: amount > 0
162  */
163 void Scroll(screen, amount)
164 register TScreen *screen;
165 register int amount;
166 {
167         register int i = screen->bot_marg - screen->top_marg + 1;
168         register int shift;
169         register int bot;
170         register int refreshtop = 0;
171         register int refreshheight;
172         register int scrolltop;
173         register int scrollheight;
174
175         if(screen->cursor_state)
176                 HideCursor();
177         if (amount > i)
178                 amount = i;
179     if(screen->jumpscroll) {
180         if(screen->scroll_amt > 0) {
181                 if(screen->refresh_amt + amount > i)
182                         FlushScroll(screen);
183                 screen->scroll_amt += amount;
184                 screen->refresh_amt += amount;
185         } else {
186                 if(screen->scroll_amt < 0)
187                         FlushScroll(screen);
188                 screen->scroll_amt = amount;
189                 screen->refresh_amt = amount;
190         }
191         refreshheight = 0;
192     } else {
193         ScrollSelection(screen, -(amount));
194         if (amount == i) {
195                 ClearScreen(screen);
196                 return;
197         }
198         shift = -screen->topline;
199         bot = screen->max_row - shift;
200         scrollheight = i - amount;
201         refreshheight = amount;
202         if((refreshtop = screen->bot_marg - refreshheight + 1 + shift) >
203          (i = screen->max_row - refreshheight + 1))
204                 refreshtop = i;
205         if(screen->scrollWidget && !screen->alternate
206          && screen->top_marg == 0) {
207                 scrolltop = 0;
208                 if((scrollheight += shift) > i)
209                         scrollheight = i;
210                 if((i = screen->savedlines) < screen->savelines) {
211                         if((i += amount) > screen->savelines)
212                                 i = screen->savelines;
213                         screen->savedlines = i;
214                         ScrollBarDrawThumb(screen->scrollWidget);
215                 }
216         } else {
217                 scrolltop = screen->top_marg + shift;
218                 if((i = screen->bot_marg - bot) > 0) {
219                         scrollheight -= i;
220                         if((i = screen->top_marg + amount - 1 - bot) >= 0) {
221                                 refreshtop += i;
222                                 refreshheight -= i;
223                         }
224                 }
225         }
226
227         if (screen->multiscroll && amount == 1 &&
228             screen->topline == 0 && screen->top_marg == 0 &&
229             screen->bot_marg == screen->max_row) {
230             if (screen->incopy < 0 && screen->scrolls == 0)
231                 CopyWait(screen);
232             screen->scrolls++;
233         }
234         scrolling_copy_area(screen, scrolltop+amount, scrollheight, amount);
235         if(refreshheight > 0) {
236                 XClearArea (
237                    screen->display,
238                    TextWindow(screen),
239                    (int) screen->border + screen->scrollbar,
240                    (int) refreshtop * FontHeight(screen) + screen->border,
241                    (unsigned) Width(screen),
242                    (unsigned) refreshheight * FontHeight(screen),
243                    FALSE);
244                 if(refreshheight > shift)
245                         refreshheight = shift;
246         }
247     }
248         if(screen->scrollWidget && !screen->alternate && screen->top_marg == 0)
249                 ScrnDeleteLine(screen->allbuf, screen->bot_marg +
250                  screen->savelines, 0, amount, screen->max_col + 1);
251         else
252                 ScrnDeleteLine(screen->buf, screen->bot_marg, screen->top_marg,
253                  amount, screen->max_col + 1);
254         if(refreshheight > 0)
255                 ScrnRefresh(screen, refreshtop, 0, refreshheight,
256                  screen->max_col + 1, False);
257 }
258
259
260 /*
261  * Reverse scrolls the screen by amount lines, erases top, doesn't alter
262  * cursor position (i.e. cursor moves up amount relative to text).
263  * All done within the scrolling region, of course.
264  * Requires: amount > 0
265  */
266 void RevScroll(screen, amount)
267 register TScreen *screen;
268 register int amount;
269 {
270         register int i = screen->bot_marg - screen->top_marg + 1;
271         register int shift;
272         register int bot;
273         register int refreshtop;
274         register int refreshheight;
275         register int scrolltop;
276         register int scrollheight;
277
278         if(screen->cursor_state)
279                 HideCursor();
280         if (amount > i)
281                 amount = i;
282     if(screen->jumpscroll) {
283         if(screen->scroll_amt < 0) {
284                 if(-screen->refresh_amt + amount > i)
285                         FlushScroll(screen);
286                 screen->scroll_amt -= amount;
287                 screen->refresh_amt -= amount;
288         } else {
289                 if(screen->scroll_amt > 0)
290                         FlushScroll(screen);
291                 screen->scroll_amt = -amount;
292                 screen->refresh_amt = -amount;
293         }
294     } else {
295         shift = -screen->topline;
296         bot = screen->max_row - shift;
297         refreshheight = amount;
298         scrollheight = screen->bot_marg - screen->top_marg -
299          refreshheight + 1;
300         refreshtop = screen->top_marg + shift;
301         scrolltop = refreshtop + refreshheight;
302         if((i = screen->bot_marg - bot) > 0)
303                 scrollheight -= i;
304         if((i = screen->top_marg + refreshheight - 1 - bot) > 0)
305                 refreshheight -= i;
306
307         if (screen->multiscroll && amount == 1 &&
308             screen->topline == 0 && screen->top_marg == 0 &&
309             screen->bot_marg == screen->max_row) {
310             if (screen->incopy < 0 && screen->scrolls == 0)
311                 CopyWait(screen);
312             screen->scrolls++;
313         }
314         scrolling_copy_area(screen, scrolltop-amount, scrollheight, -amount);
315         if(refreshheight > 0)
316                 XClearArea (
317                     screen->display,
318                     TextWindow(screen),
319                     (int) screen->border + screen->scrollbar,
320                     (int) refreshtop * FontHeight(screen) + screen->border,
321                     (unsigned) Width(screen),
322                     (unsigned) refreshheight * FontHeight(screen),
323                     FALSE);
324     }
325         ScrnInsertLine (screen->buf, screen->bot_marg, screen->top_marg,
326                         amount, screen->max_col + 1);
327 }
328
329 /*
330  * If cursor not in scrolling region, returns.  Else,
331  * inserts n blank lines at the cursor's position.  Lines above the
332  * bottom margin are lost.
333  */
334 void InsertLine (screen, n)
335 register TScreen *screen;
336 register int n;
337 {
338         register int i;
339         register int shift;
340         register int bot;
341         register int refreshtop;
342         register int refreshheight;
343         register int scrolltop;
344         register int scrollheight;
345
346         if (screen->cur_row < screen->top_marg ||
347          screen->cur_row > screen->bot_marg)
348                 return;
349         if(screen->cursor_state)
350                 HideCursor();
351         screen->do_wrap = 0;
352         if (n > (i = screen->bot_marg - screen->cur_row + 1))
353                 n = i;
354     if(screen->jumpscroll) {
355         if(screen->scroll_amt <= 0 &&
356          screen->cur_row <= -screen->refresh_amt) {
357                 if(-screen->refresh_amt + n > screen->max_row + 1)
358                         FlushScroll(screen);
359                 screen->scroll_amt -= n;
360                 screen->refresh_amt -= n;
361         } else if(screen->scroll_amt)
362                 FlushScroll(screen);
363     }
364     if(!screen->scroll_amt) {
365         shift = -screen->topline;
366         bot = screen->max_row - shift;
367         refreshheight = n;
368         scrollheight = screen->bot_marg - screen->cur_row - refreshheight + 1;
369         refreshtop = screen->cur_row + shift;
370         scrolltop = refreshtop + refreshheight;
371         if((i = screen->bot_marg - bot) > 0)
372                 scrollheight -= i;
373         if((i = screen->cur_row + refreshheight - 1 - bot) > 0)
374                 refreshheight -= i;
375         vertical_copy_area(screen, scrolltop-n, scrollheight, -n);
376         if(refreshheight > 0)
377                 XClearArea (
378                     screen->display,
379                     TextWindow(screen),
380                     (int) screen->border + screen->scrollbar,
381                     (int) refreshtop * FontHeight(screen) + screen->border,
382                     (unsigned) Width(screen),
383                     (unsigned) refreshheight * FontHeight(screen),
384                     FALSE);
385     }
386         /* adjust screen->buf */
387         ScrnInsertLine(screen->buf, screen->bot_marg, screen->cur_row, n,
388                         screen->max_col + 1);
389 }
390
391 /*
392  * If cursor not in scrolling region, returns.  Else, deletes n lines
393  * at the cursor's position, lines added at bottom margin are blank.
394  */
395
396 void DeleteLine(screen, n)
397 register TScreen *screen;
398 register int n;
399 {
400         register int i;
401         register int shift;
402         register int bot;
403         register int refreshtop;
404         register int refreshheight;
405         register int scrolltop;
406         register int scrollheight;
407
408         if (screen->cur_row < screen->top_marg ||
409          screen->cur_row > screen->bot_marg)
410                 return;
411         if(screen->cursor_state)
412                 HideCursor();
413         screen->do_wrap = 0;
414         if (n > (i = screen->bot_marg - screen->cur_row + 1))
415                 n = i;
416     if(screen->jumpscroll) {
417         if(screen->scroll_amt >= 0 && screen->cur_row == screen->top_marg) {
418                 if(screen->refresh_amt + n > screen->max_row + 1)
419                         FlushScroll(screen);
420                 screen->scroll_amt += n;
421                 screen->refresh_amt += n;
422         } else if(screen->scroll_amt)
423                 FlushScroll(screen);
424     }
425     if(!screen->scroll_amt) {
426
427         shift = -screen->topline;
428         bot = screen->max_row - shift;
429         scrollheight = i - n;
430         refreshheight = n;
431         if((refreshtop = screen->bot_marg - refreshheight + 1 + shift) >
432          (i = screen->max_row - refreshheight + 1))
433                 refreshtop = i;
434         if(screen->scrollWidget && !screen->alternate && screen->cur_row == 0) {
435                 scrolltop = 0;
436                 if((scrollheight += shift) > i)
437                         scrollheight = i;
438                 if((i = screen->savedlines) < screen->savelines) {
439                         if((i += n) > screen->savelines)
440                                 i = screen->savelines;
441                         screen->savedlines = i;
442                         ScrollBarDrawThumb(screen->scrollWidget);
443                 }
444         } else {
445                 scrolltop = screen->cur_row + shift;
446                 if((i = screen->bot_marg - bot) > 0) {
447                         scrollheight -= i;
448                         if((i = screen->cur_row + n - 1 - bot) >= 0) {
449                                 refreshheight -= i;
450                         }
451                 }
452         }
453         vertical_copy_area(screen, scrolltop+n, scrollheight, n);
454         if(refreshheight > 0)
455                 XClearArea (
456                     screen->display,
457                     TextWindow(screen),
458                     (int) screen->border + screen->scrollbar,
459                     (int) refreshtop * FontHeight(screen) + screen->border,
460                     (unsigned) Width(screen),
461                     (unsigned) refreshheight * FontHeight(screen),
462                     FALSE);
463     }
464         /* adjust screen->buf */
465         if(screen->scrollWidget && !screen->alternate && screen->cur_row == 0)
466                 ScrnDeleteLine(screen->allbuf, screen->bot_marg +
467                  screen->savelines, 0, n, screen->max_col + 1);
468         else
469                 ScrnDeleteLine(screen->buf, screen->bot_marg, screen->cur_row,
470                  n, screen->max_col + 1);
471 }
472
473 /*
474  * Insert n blanks at the cursor's position, no wraparound
475  */
476
477 void InsertChar (screen, n)
478     register TScreen *screen;
479     register int n;
480 {
481         register int cx, cy;
482
483         if(screen->cursor_state)
484                 HideCursor();
485         screen->do_wrap = 0;
486         if(screen->cur_row - screen->topline <= screen->max_row) {
487             if(!AddToRefresh(screen)) {
488                 if(screen->scroll_amt)
489                         FlushScroll(screen);
490
491                 /*
492                  * prevent InsertChar from shifting the end of a line over
493                  * if it is being appended to
494                  */
495                 if (non_blank_line (screen->buf, screen->cur_row, 
496                                     screen->cur_col, screen->max_col + 1))
497                     horizontal_copy_area(screen, screen->cur_col,
498                                          screen->max_col+1 - (screen->cur_col+n),
499                                          n);
500         
501                 cx = CursorX (screen, screen->cur_col);
502                 cy = CursorY (screen, screen->cur_row);
503
504                 XFillRectangle(
505                     screen->display,
506                     TextWindow(screen), 
507                     screen->reverseGC,
508                     cx, cy,
509                     (unsigned) n * FontWidth(screen), (unsigned) FontHeight(screen));
510             }
511         }
512         /* adjust screen->buf */
513         ScrnInsertChar(screen->buf, screen->cur_row, screen->cur_col, n,
514                         screen->max_col + 1);
515 }
516
517 /*
518  * Deletes n chars at the cursor's position, no wraparound.
519  */
520 void DeleteChar (screen, n)
521     register TScreen *screen;
522     register int        n;
523 {
524         register int width;
525
526         if(screen->cursor_state)
527                 HideCursor();
528         screen->do_wrap = 0;
529         if (n > (width = screen->max_col + 1 - screen->cur_col))
530                 n = width;
531                 
532         if(screen->cur_row - screen->topline <= screen->max_row) {
533             if(!AddToRefresh(screen)) {
534                 if(screen->scroll_amt)
535                         FlushScroll(screen);
536         
537                 horizontal_copy_area(screen, screen->cur_col+n,
538                                      screen->max_col+1 - (screen->cur_col+n),
539                                      -n);
540         
541                 XFillRectangle
542                     (screen->display, TextWindow(screen),
543                      screen->reverseGC,
544                      screen->border + screen->scrollbar
545                        + Width(screen) - n*FontWidth(screen),
546                      CursorY (screen, screen->cur_row),(unsigned) n * FontWidth(screen),
547                      (unsigned) FontHeight(screen));
548             }
549         }
550         /* adjust screen->buf */
551         ScrnDeleteChar (screen->buf, screen->cur_row, screen->cur_col, n,
552                         screen->max_col + 1);
553
554 }
555
556 /*
557  * Clear from cursor position to beginning of display, inclusive.
558  */
559
560 void ClearAbove (screen)
561      register TScreen *screen;
562 {
563   register int top, height;
564
565   if(screen->cursor_state)
566                 HideCursor();
567         if((top = -screen->topline) <= screen->max_row) {
568                 if(screen->scroll_amt)
569                         FlushScroll(screen);
570                 if((height = screen->cur_row + top) > screen->max_row)
571                         height = screen->max_row;
572                 if((height -= top) > 0)
573                         XClearArea(screen->display, TextWindow(screen),
574                          screen->border + screen->scrollbar, top *
575                          FontHeight(screen) + screen->border,
576                          (unsigned)Width(screen), (unsigned)height * FontHeight(screen), FALSE);
577
578                 if(screen->cur_row - screen->topline <= screen->max_row)
579                         ClearLeft(screen);
580         }
581         ClearBufRows(screen, 0, screen->cur_row - 1);
582 }
583
584 /*
585  * Clear from cursor position to end of display, inclusive.
586  */
587
588 void ClearBelow (screen)
589 register TScreen *screen;
590 {
591   register int top;
592
593         ClearRight(screen);
594         if((top = screen->cur_row - screen->topline) <= screen->max_row) {
595                 if(screen->scroll_amt)
596                         FlushScroll(screen);
597                 if(++top <= screen->max_row)
598                         XClearArea(screen->display, TextWindow(screen),
599                          screen->border + screen->scrollbar, top *
600                          FontHeight(screen) + screen->border,
601                          (unsigned) Width(screen),(unsigned) (screen->max_row - top + 1) *
602                          FontHeight(screen), FALSE);
603         }
604         ClearBufRows(screen, screen->cur_row + 1, screen->max_row);
605 }
606
607 /* 
608  * Clear last part of cursor's line, inclusive.
609  */
610
611 void ClearRight (screen)
612 register TScreen *screen;
613 {
614         if(screen->cursor_state)
615                 HideCursor();
616         screen->do_wrap = 0;
617         if(screen->cur_row - screen->topline <= screen->max_row) {
618             if(!AddToRefresh(screen)) {
619         if(screen->scroll_amt)
620                 FlushScroll(screen);
621                 XFillRectangle(screen->display, TextWindow(screen),
622                   screen->reverseGC,
623                  CursorX(screen, screen->cur_col),
624                  CursorY(screen, screen->cur_row),
625                  (unsigned) Width(screen) - screen->cur_col * FontWidth(screen),
626                  (unsigned)FontHeight(screen));
627             }
628         }
629         bzero((char*) ( screen->buf [2 * screen->cur_row] + screen->cur_col),
630                (screen->max_col - screen->cur_col + 1));
631         bzero((char *) (screen->buf [2 * screen->cur_row + 1] + screen->cur_col),
632                (screen->max_col - screen->cur_col + 1));
633         /* with the right part cleared, we can't be wrapping */
634         screen->buf [2 * screen->cur_row + 1] [0] &= ~LINEWRAPPED;
635 }
636
637 /*
638  * Clear first part of cursor's line, inclusive.
639  */
640
641 void ClearLeft (screen)
642     register TScreen *screen;
643 {
644         int i;
645         Char *cp;
646
647         if(screen->cursor_state)
648                 HideCursor();
649         screen->do_wrap = 0;
650         if(screen->cur_row - screen->topline <= screen->max_row) {
651             if(!AddToRefresh(screen)) {
652                 if(screen->scroll_amt)
653                         FlushScroll(screen);
654                 XFillRectangle (screen->display, TextWindow(screen),
655                      screen->reverseGC,
656                      screen->border + screen->scrollbar,
657                       CursorY (screen, screen->cur_row),
658                      (unsigned)(screen->cur_col + 1) * FontWidth(screen),
659                      (unsigned)FontHeight(screen));
660             }
661         }
662         
663         for ( i=0, cp=screen->buf[2 * screen->cur_row];
664               i < screen->cur_col + 1;
665               i++, cp++)
666             *cp = ' ';
667         for ( i=0, cp=screen->buf[2 * screen->cur_row + 1];
668               i < screen->cur_col + 1;
669               i++, cp++)
670             *cp = CHARDRAWN;
671 }
672
673 /* 
674  * Erase the cursor's line.
675  */
676
677 void ClearLine(screen)
678 register TScreen *screen;
679 {
680         if(screen->cursor_state)
681                 HideCursor();
682         screen->do_wrap = 0;
683         if(screen->cur_row - screen->topline <= screen->max_row) {
684             if(!AddToRefresh(screen)) {
685                 if(screen->scroll_amt)
686                         FlushScroll(screen);
687                 XFillRectangle (screen->display, TextWindow(screen), 
688                      screen->reverseGC,
689                      screen->border + screen->scrollbar,
690                       CursorY (screen, screen->cur_row),
691                      (unsigned) Width(screen), (unsigned) FontHeight(screen));
692             }
693         }
694         bzero ((char *) (screen->buf [2 * screen->cur_row]), (screen->max_col + 1));
695         bzero ((char *) (screen->buf [2 * screen->cur_row + 1]), (screen->max_col + 1));
696 }
697
698 void ClearScreen(screen)
699      register TScreen *screen;
700 {
701         register int top;
702
703         if(screen->cursor_state)
704                 HideCursor();
705         screen->do_wrap = 0;
706         if((top = -screen->topline) <= screen->max_row) {
707                 if(screen->scroll_amt)
708                         FlushScroll(screen);
709                 if(top == 0)
710                         XClearWindow(screen->display, TextWindow(screen));
711                 else
712                         XClearArea(screen->display, TextWindow(screen),
713                          screen->border + screen->scrollbar, 
714                          top * FontHeight(screen) + screen->border,     
715                          (unsigned) Width(screen), (unsigned)(screen->max_row - top + 1) *
716                          FontHeight(screen), FALSE);
717         }
718         ClearBufRows (screen, 0, screen->max_row);
719 }
720
721 void CopyWait(screen)
722 register TScreen *screen;
723 {
724         XEvent reply;
725         XEvent *rep = &reply;
726
727         while (1) {
728                 XWindowEvent (screen->display, VWindow(screen), 
729                   ExposureMask, &reply);
730                 switch (reply.type) {
731                 case Expose:
732                         HandleExposure (screen, &reply);
733                         break;
734                 case NoExpose:
735                 case GraphicsExpose:
736                         if (screen->incopy <= 0) {
737                                 screen->incopy = 1;
738                                 if (screen->scrolls > 0)
739                                         screen->scrolls--;
740                         }
741                         if (reply.type == GraphicsExpose)
742                             HandleExposure (screen, &reply);
743
744                         if ((reply.type == NoExpose) ||
745                             ((XExposeEvent *)rep)->count == 0) {
746                             if (screen->incopy <= 0 && screen->scrolls > 0)
747                                 screen->scrolls--;
748                             if (screen->scrolls == 0) {
749                                 screen->incopy = 0;
750                                 return;
751                             }
752                             screen->incopy = -1;
753                         }
754                         break;
755                 }
756         }
757 }
758
759 /*
760  * used by vertical_copy_area and and horizontal_copy_area
761  */
762 static void
763 copy_area(screen, src_x, src_y, width, height, dest_x, dest_y)
764     TScreen *screen;
765     int src_x, src_y;
766     unsigned int width, height;
767     int dest_x, dest_y;
768 {
769     /* wait for previous CopyArea to complete unless
770        multiscroll is enabled and active */
771     if (screen->incopy  &&  screen->scrolls == 0)
772         CopyWait(screen);
773     screen->incopy = -1;
774
775     /* save for translating Expose events */
776     screen->copy_src_x = src_x;
777     screen->copy_src_y = src_y;
778     screen->copy_width = width;
779     screen->copy_height = height;
780     screen->copy_dest_x = dest_x;
781     screen->copy_dest_y = dest_y;
782
783     XCopyArea(screen->display, 
784               TextWindow(screen), TextWindow(screen),
785               screen->normalGC,
786               src_x, src_y, width, height, dest_x, dest_y);
787 }
788
789 /*
790  * use when inserting or deleting characters on the current line
791  */
792 static void
793 horizontal_copy_area(screen, firstchar, nchars, amount)
794     TScreen *screen;
795     int firstchar;              /* char pos on screen to start copying at */
796     int nchars;
797     int amount;                 /* number of characters to move right */
798 {
799     int src_x = CursorX(screen, firstchar);
800     int src_y = CursorY(screen, screen->cur_row);
801
802     copy_area(screen, src_x, src_y,
803               (unsigned)nchars*FontWidth(screen),(unsigned) FontHeight(screen),
804               src_x + amount*FontWidth(screen), src_y);
805 }
806
807 /*
808  * use when inserting or deleting lines from the screen
809  */
810 static void
811 vertical_copy_area(screen, firstline, nlines, amount)
812     TScreen *screen;
813     int firstline;              /* line on screen to start copying at */
814     int nlines;
815     int amount;                 /* number of lines to move up (neg=down) */
816 {
817     if(nlines > 0) {
818         int src_x = screen->border + screen->scrollbar;
819         int src_y = firstline * FontHeight(screen) + screen->border;
820
821         copy_area(screen, src_x, src_y,
822                   (unsigned)Width(screen),(unsigned) nlines*FontHeight(screen),
823                   src_x, src_y - amount*FontHeight(screen));
824     }
825 }
826
827 /*
828  * use when scrolling the entire screen
829  */
830
831 void scrolling_copy_area(screen, firstline, nlines, amount)
832     TScreen *screen;
833     int firstline;              /* line on screen to start copying at */
834     int nlines;
835     int amount;                 /* number of lines to move up (neg=down) */
836 {
837
838     if(nlines > 0) {
839         vertical_copy_area(screen, firstline, nlines, amount);
840     }
841 }
842
843 /*
844  * Handler for Expose events on the VT widget.
845  * Returns 1 iff the area where the cursor was got refreshed.
846  */
847
848 int HandleExposure (screen, event)
849     register TScreen *screen;
850     register XEvent *event;
851 {
852     register XExposeEvent *reply = (XExposeEvent *)event;
853
854     /* if not doing CopyArea or if this is a GraphicsExpose, don't translate */
855     if(!screen->incopy  ||  event->type != Expose)
856         return handle_translated_exposure (screen, reply->x, reply->y,
857                                            reply->width, reply->height);
858     else {
859         /* compute intersection of area being copied with
860            area being exposed. */
861         int both_x1 = Max(screen->copy_src_x, reply->x);
862         int both_y1 = Max(screen->copy_src_y, reply->y);
863         int both_x2 = Min(screen->copy_src_x+screen->copy_width,
864                           reply->x+reply->width);
865         int both_y2 = Min(screen->copy_src_y+screen->copy_height,
866                           reply->y+reply->height);
867         int value = 0;
868
869         /* was anything copied affected? */
870         if(both_x2 > both_x1  && both_y2 > both_y1) {
871             /* do the copied area */
872             value = handle_translated_exposure
873                 (screen, reply->x + screen->copy_dest_x - screen->copy_src_x,
874                  reply->y + screen->copy_dest_y - screen->copy_src_y,
875                  reply->width, reply->height);
876         }
877         /* was anything not copied affected? */
878         if(reply->x < both_x1 || reply->y < both_y1
879            || reply->x+reply->width > both_x2
880            || reply->y+reply->height > both_y2)
881             value = handle_translated_exposure (screen, reply->x, reply->y,
882                                                 reply->width, reply->height);
883
884         return value;
885     }
886 }
887
888 /*
889  * Called by the ExposeHandler to do the actual repaint after the coordinates
890  * have been translated to allow for any CopyArea in progress.
891  * The rectangle passed in is pixel coordinates.
892  */
893 int handle_translated_exposure (screen, rect_x, rect_y, rect_width, rect_height)
894     register TScreen *screen;
895     register int rect_x, rect_y;
896     register int rect_width, rect_height;
897 {
898   register int toprow, leftcol, nrows, ncols;
899
900         toprow = (rect_y - screen->border) / FontHeight(screen);
901         if(toprow < 0)
902                 toprow = 0;
903         leftcol = (rect_x - screen->border - screen->scrollbar)
904             / FontWidth(screen);
905         if(leftcol < 0)
906                 leftcol = 0;
907         nrows = (rect_y + rect_height - 1 - screen->border) / 
908                 FontHeight(screen) - toprow + 1;
909         ncols =
910          (rect_x + rect_width - 1 - screen->border - screen->scrollbar) /
911                         FontWidth(screen) - leftcol + 1;
912         toprow -= screen->scrolls;
913         if (toprow < 0) {
914                 nrows += toprow;
915                 toprow = 0;
916         }
917         if (toprow + nrows - 1 > screen->max_row)
918                 nrows = screen->max_row - toprow + 1;
919         if (leftcol + ncols - 1 > screen->max_col)
920                 ncols = screen->max_col - leftcol + 1;
921
922         if (nrows > 0 && ncols > 0) {
923                 ScrnRefresh (screen, toprow, leftcol, nrows, ncols, False);
924                 if (screen->cur_row >= toprow &&
925                     screen->cur_row < toprow + nrows &&
926                     screen->cur_col >= leftcol &&
927                     screen->cur_col < leftcol + ncols)
928                         return (1);
929
930         }
931         return (0);
932 }
933
934 void ReverseVideo (termw)
935         XtermWidget termw;
936 {
937         register TScreen *screen = &termw->screen;
938         GC tmpGC;
939         unsigned long tmp;
940
941         tmp = termw->core.background_pixel;
942         if(screen->cursorcolor == screen->foreground)
943                 screen->cursorcolor = tmp;
944         termw->core.background_pixel = screen->foreground;
945         screen->foreground = tmp;
946
947         tmp = screen->mousecolorback;
948         screen->mousecolorback = screen->mousecolor;
949         screen->mousecolor = tmp;
950
951         tmpGC = screen->normalGC;
952         screen->normalGC = screen->reverseGC;
953         screen->reverseGC = tmpGC;
954
955         tmpGC = screen->normalboldGC;
956         screen->normalboldGC = screen->reverseboldGC;
957         screen->reverseboldGC = tmpGC;
958
959         recolor_cursor (screen->pointer_cursor, 
960                         screen->mousecolor, screen->mousecolorback);
961         recolor_cursor (screen->arrow,
962                         screen->mousecolor, screen->mousecolorback);
963
964         termw->misc.re_verse = !termw->misc.re_verse;
965
966         XDefineCursor(screen->display, TextWindow(screen), screen->pointer_cursor);
967         if(screen->scrollWidget)
968                 ScrollBarReverseVideo(screen->scrollWidget);
969
970         XSetWindowBackground(screen->display, TextWindow(screen), termw->core.background_pixel);
971         XClearWindow(screen->display, TextWindow(screen));
972         ScrnRefresh (screen, 0, 0, screen->max_row + 1,
973          screen->max_col + 1, False);
974         update_reversevideo();
975 }
976
977
978 void recolor_cursor (cursor, fg, bg)
979     Cursor cursor;                      /* X cursor ID to set */
980     unsigned long fg, bg;               /* pixel indexes to look up */
981 {
982     register TScreen *screen = &term->screen;
983     register Display *dpy = screen->display;
984     XColor colordefs[2];                /* 0 is foreground, 1 is background */
985
986     colordefs[0].pixel = fg;
987     colordefs[1].pixel = bg;
988     XQueryColors (dpy, DefaultColormap (dpy, DefaultScreen (dpy)),
989                   colordefs, 2);
990     XRecolorCursor (dpy, cursor, colordefs, colordefs+1);
991     return;
992 }
993