/* @(#)twcursor.c 17.1.1.1 (ES0-DMD) 01/25/02 17:48:04 */ /*=========================================================================== Copyright (C) 1995 European Southern Observatory (ESO) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, MA 02139, USA. Corresponding concerning ESO-MIDAS should be addressed as follows: Internet e-mail: midas@eso.org Postal address: European Southern Observatory Data Management Division Karl-Schwarzschild-Strasse 2 D 85748 Garching bei Muenchen GERMANY ===========================================================================*/ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .TYPE Module .IDENTIFICATION twcursor.c .AUTHOR Francois Ochsenbein [ESO-IPG] .LANGUAGE C .KEYWORDS Window Management .ENVIRONMENT TermWindows .COMMENTS This module contains routines to move cursor and scroll windows. \begin{TeX} \end{TeX} .VERSION 1.0 18-Aug-1986: Creation .VERSION 2.0 03-Dec-1986 New terminal-independant graphic characters with output buffering version. .VERSION 2.1 25-Jun-1987: Version '2' .VERSION 2.2 02-Dec-1987: No clear line for a NewLine .VERSION 3.0 20-Mar-1988: Version '3' ----------------------------------------------------------------------------*/ #define DEBUG 0 /* For debugging only */ #define PM_LEVEL LEVEL_TW #define TW_import 0 /* Do not use macro window definitions */ #include MID_EXTERN WINDOW *Screen; #if DEBUG #define ed_level 3 #define ENTER_DEBUG(x) ENTER(x) #define EXIT_DEBUG(x) EXIT(x) #define DISPLAY(opt) tw_ed(w,opt) #else #define DISPLAY(opt) #define ENTER_DEBUG(x) #define EXIT_DEBUG(x) return(x) #endif MID_RSTATIC short int step[2] = {-1, 1}; static int J; MONITOR(TWCURSOR); /*========================================================================== * tw_chars *==========================================================================*/ int tw_chars(w, chars) /*+++ .DES Returns the number of characters before / after the cursor .RET OK .REM Not traced. Depends on _FULL_ mode. ---*/ WINDOW *w; /* MOD: Window concerned */ int chars[2]; /* OUT: chars at left of cursor [0], at right [1]*/ { J = w->Nj; if ((w->flags & FullW) && (w->pos >= w->marker[0]) && (w->pos < w->marker[1])) chars[0] = w->pos - w->marker[0], chars[1] = w->marker[1] - w->pos; else chars[0] = w->pos%J, chars[1] = (w->pos < w->marker[1] ? J - chars[0] : 0); return(OK); } /*========================================================================== * tw_check *==========================================================================*/ int tw_check(w) /*+++ .DES Checks if the cursor position is within range. .RET OK / NOK .REM Not traced. Depends on _FULL_ mode. ---*/ WINDOW *w; /* IN: Window concerned */ { register int st; st = NOK; if (w->pos < w->marker[0]) w->pos = w->marker[0]; else if (w->pos > w->marker[1]) w->pos = w->marker[1]; else st = OK; return(st); } /*========================================================================== * tw_cur() *==========================================================================*/ int tw_cur(saved) /*+++++++++++ .PURPOSE Restore the cursor position. .RETURNS OK .REMARKS -----------------------------------------------------------------------*/ TWSAVE *saved; /* IN: Old position + attribute */ { int status; ENTER_DEBUG("tw_cur"); Screen->pos = saved->pos, status = SetPosition(Screen->pos); tw_attr(Screen, saved->attr); EXIT_DEBUG(status); } /*========================================================================== * tw_cus() *==========================================================================*/ int tw_cus(saved) /*++++++++++++++ .PURPOSE Save the current cursor position. .RETURNS OK .REMARKS Not traced. ---------------*/ TWSAVE *saved; /* OUT: Current position + attribute */ { saved->pos = Screen->pos; saved->attr = (Screen->attr) >> 8; return(OK); } /*========================================================================== * tw_agoto *==========================================================================*/ int tw_agoto(w, p) /*+++ .PURPOSE Position the cursor to a specified position on a window. .RETURNS OK / NOK (Cursor put on an edge) .REMARKS An attempt to position the cursor off the screen will place it on an edge. ---*/ WINDOW *w; /* MOD: Window concerned */ int p; /* IN: Position to move to */ { ENTER_TW("tw_agoto"); CheckScreen(w); w->pos = p; status = tw_check(w); if(w->active) tw_uc(w), /* Update cursor */ SetPosition(Screen->pos); DISPLAY(0); EXIT_TW (status); } /*========================================================================== * tw_goto *==========================================================================*/ int tw_goto(w, l, c) /*+++ .PURPOSE Position the cursor to a specified line and column position on a window. .RETURNS OK / NOK (Cursor put on an edge) .REMARKS An attempt to position the cursor off the screen will place it on an edge. ---*/ WINDOW *w; /* MOD: Window concerned */ int l; /* IN: Line number to move to */ int c; /* IN: Column number to move to */ { short int ij[2]; ENTER_TW("tw_goto"); CheckScreen(w); DISPLAY(0); #if DEBUG TRACE_ED_STR2("Moving on wind ",w->id, 8); TRACE_ED_I(" to line ",l); TRACE_ED_I(" ... col ",c); #endif ij[0] = l; ij[1] = c; status = CheckCursor(ij, w->dim); w->pos = ij[0]*w->Nj + ij[1]; if(w->active) tw_uc(w); /* Update cursor */ SetPosition(Screen->pos); DISPLAY(0); EXIT_TW (status); } /*====================================================================== * tw_home *======================================================================*/ int tw_home(w) /*+++ .PURPOSE Move the cursor to home position of a specified window. .RETURNS OK .REMARKS Moves to beginning of Range. ---*/ WINDOW *w; /* MOD: Window concerned */ { ENTER_DEBUG("tw_home"); status = tw_agoto(w, 0); EXIT_DEBUG(status); } /*====================================================================== * tw_mvc *======================================================================*/ int tw_mvc(w, direction, times) /*+++ .PURPOSE Move the cursor on a window n times in the specified direction: up, down, right, left or newline. .RETURNS OK / NOK (attempt to move outside window, cursor on an edge). .REMARKS A negative number of times asks for the opposite direction. The Insert Mode is switched off for vertical displacements. If the window is in Full Mode, horizontal displacements wrap lines, and displacements are limited within markers. ------*/ WINDOW *w; /* MOD: Window concerned */ int direction; /* IN: The direction of the displacement */ int times; /* IN: Number of times to move */ { register int k, n, d; char state_echo; short int new_pos[2]; ENTER_TW("tw_mvc"); CheckScreen(w); DISPLAY(0); #if DEBUG TRACE_ED_STR2("Moving on wind ",w->id, 8); TRACE_ED_I("... Direction: ",direction); #endif if (times == 0) FINISH; J = w->Nj; k = direction >> 1; /* Leads to Horizontal, vertical, other */ d = direction & 1; new_pos[0] = w->pos/J; /* Current column */ new_pos[1] = w->pos%J; /* Current column */ n = times * step[d]; switch(k) { case _VERTICAL_: /* w->flags &= (~Imode); /* Suppress the Insert Mode */ new_pos[k] += n; n *= J; break; case _HORIZONTAL_: new_pos[k] += n; break; default: n = times; /* Issue New Lines */ if (n <= 0) FINISH; if (w->flags & FullW) { w->pos = ((w->pos + n*J)/J)*J; break; } if (w->hw & Scroll) /* Use Hardware Scrolling */ state_echo = 0; else { state_echo = w->active; tw_st(w, Echo, 0); } while(--n >=0) status = tw_nl(w); if (state_echo) /* Simulated Scrolling */ { tw_st(w, Echo, 1); tw_rw(w, 0, NULL_WINDOW); } FINISH; } if (w->flags & FullW) status = tw_agoto(w, n); else status = tw_goto(w, new_pos[0], new_pos[1]); EXIT_TW(status); } /*========================================================================== * tw_nl *==========================================================================*/ int tw_nl(w) /*+++ .DES New line on a window, taking into account possible scrolling. .RET OK / NOK (was already at bottom, and no scrolling) .REM The cursor position is at the beginning of the next (cleared) line. The insert mode is switched off. ---*/ WINDOW *w; /* MOD: Window concerned */ { ENTER_TW("tw_nl"); CheckScreen(w); J = w->Nj; if (w->pos >= (w->marker[1] - J)) { if(w->scroll) /* Echo performed in scroll fct */ { w->pos = (w->Ni-1)*J; status = tw_scroll(w,_UP_,1); Return; } else w->pos = w->marker[1], status = NOK; } else w->pos = ((w->pos+J)/J)*J; if(w->active) tw_uc(w); /* Update cursor */ SetPosition(Screen->pos); EXIT_TW(status); } /*====================================================================== * tw_scroll *======================================================================*/ int tw_scroll(w, direction, times) /*+++ .PURPOSE Scroll n lines on a window in the specified (_UP_ or _DOWN_) direction. .RETURNS OK .REMARKS A negative number of times asks for the opposite direction; _UP_ is the default. The cursor does not move. ---*/ WINDOW *w; /* MOD: Window concerned */ int direction; /* IN: The direction of the displacement */ int times; /* IN: Number of lines to scroll */ { int i, n, k, L; char hw_scroll; short int home_pos[2]; ENTER_TW("tw_scroll"); CheckScreen(w); #if DEBUG TRACE_ED_STR2("Scrolling window ",w->id, 8); DISPLAY(2); #endif if (times == 0) Return; J = w->Nj; n = (direction == _DOWN_ ? -times : times); k = ABSOLUTE(n); #if DEBUG TRACE_ED_I("Scrolling lines: ",n); #endif /* If number of lines is large enough, window becomes clear */ if (k >= w->Ni) { if (w->attr == Screen->attr_init) w->flags |= Clear; n = w->Ni; k = n; } L = (w->Ni - k)*J; /* Number of chars to copy */ i = k * J; /* Number of blank chars */ /* Scroll the memory copy of window, line per line */ if (n < 0) tw_copw(w, i, w, 0, L), L = 0; /* Scroll Down */ else tw_copw(w, 0, w, i, L); /* Scroll Up */ tw_fill(w, L, i, w->attr_init); DISPLAY(2); /* Update now the screen, and write output */ if(w->active) { hw_scroll = ((w->hw) & Scroll) && (!(w->clear)); if (hw_scroll && (tw_occluded(w,1) == 0)) /* Next((Parent(w) ? Parent(w) : w)) == Screen) */ /* Hardware scrolling is possible; however, if window * is clear, better to use refresh, which is optimized * for clear windows * Don't forget that lines blanked by hardare scrolling * are in screen normal attribute ... */ { if (w->attr_init != Screen->attr_init) /* Attribute of blanked * lines */ tw_fill(w, L, i, Screen->attr_init); tw_uw(w,2); /* Modify screen, but without marking lines * as modified */ tw_geth(w, home_pos); /* Note: home_pos[1] always zero... */ k = home_pos[0] + w->Ni - 1; SetScroll(home_pos[0], k); if (n < 0) k = home_pos[0]; CursorTo(k, 0); CursorDown(n); /* w->pos = (k - home_pos[0]) * J; */ if (w->attr_init != Screen->attr_init) /* Attribute of blanked * lines */ tw_fill(w, L, i, w->attr_init); } tw_rw(w,0,NULL_WINDOW); } EXIT_TW(status); } /*========================================================================== * tw_where *==========================================================================*/ int tw_where(w, coo) /*+++ .DES Returns the current cursor position in specified window. .RET OK / NOK (outside limits of window / Range) .REM Not traced. ---*/ WINDOW *w; /* MOD: Window to close */ short int coo[2]; /* OUT: Returned position: line (0=top), col (0=left) */ { CheckScreen(w); J = w->Nj; coo[0] = w->pos/J; coo[1] = w->pos%J; return ((w->pos >= w->marker[0]) && (w->pos < w->marker[1]) ? OK : NOK); } /*========================================================================== * tw_awhere *==========================================================================*/ int tw_awhere(w) /*+++ .DES Returns the current cursor position in specified window. .RET Byte position .REM Not traced. ---*/ WINDOW *w; /* MOD: Window to close */ { CheckScreen(w); return (w->pos); }