/* @(#)txjustify.c 17.1.1.1 (ES0-DMD) 01/25/02 17:48:08 */ /*=========================================================================== 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 txjustify.c .AUTHOR Francois Ochsenbein [ESO-IPG] .LANGUAGE C .KEYWORDS Window Management .ENVIRONMENT TermWindows .COMMENTS This module provides justification utilities for the window functions, without any physical i/o. Only for TermDisplay use. \begin{TeX} \end{TeX} .VERSION 1.0 14-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 3.0 20-Mar-1988: Version '3' .VERSION 3.1 31-Jan-1989: Modif tx_crosses to avoid corners at top/bottom .VERSION 3.2 29-Jun-1989: Removed tx_crosses. ----------------------------------------------------------------------------*/ #define DEBUG 0 /* For debugging only */ #define PM_LEVEL LEVEL_STR #define TW_import 0 /* Do not use macro window definitions */ #include #if DEBUG #define ENTER_DEBUG(x) ENTER(x) #define EXIT_DEBUG(x) EXIT(x) #else #define ENTER_DEBUG(x) #define EXIT_DEBUG(x) return(x) #endif #define VBar GraphicAchar(_VERTICAL_) #define HBar GraphicAchar(_HORIZONTAL_) #define Corner GraphicAchar(_CORNER_+_CROSS_) #define V _VERTICAL_ #define H _HORIZONTAL_ #define UL (_CORNER_+_UPLEFT_) #define UR (_CORNER_+_UPRIGHT_) #define DL (_CORNER_+_DOWNLEFT_) #define DR (_CORNER_+_DOWNRIGHT_) #define HV (_CORNER_+_CROSS_) #define TL (_TEE_+_LEFT_) #define TR (_TEE_+_RIGHT_) #define TU (_TEE_+_UP_) #define TD (_TEE_+_DOWN_) MONITOR(TXJUSTIFY); /*========================================================================== * tx_jl *==========================================================================*/ int tx_jl (str, len, blank) /*+++ .PURPOSE Justify to the left (suppress blanks) the string made of `ACHAR's. .RETURNS OK .REMARKS ---*/ ACHAR *str; /* IN: string to justify */ int len; /* IN: Length of str */ ACHAR blank; /* IN: The `blank' ACHAR */ { register ACHAR *p1, *p2, *pe; ENTER_DEBUG("tx_jl"); #if DEBUG TRACE_ED_STR2("Before left justify", str, sizeof(ACHAR)*(len+1)); #endif for (p1 = str, pe = p1 + len; (p1 < pe) && (*p1 == blank); p1++) ; for (p2 = str; p1 < pe; p1++, p2++) *p2 = *p1; for (; p2 < pe; p2++) *p2 = blank; #if DEBUG TRACE_ED_STR2(" After left justify", str, sizeof(ACHAR)*(len+1)); #endif EXIT_DEBUG(OK); } /*========================================================================== * tx_jr *==========================================================================*/ int tx_jr (str, len, blank) /*+++ .PURPOSE Justify to the right (insert blanks at the left) the string made of `ACHAR's. .RETURNS OK .REMARKS ---*/ ACHAR *str; /* IN: string to justify */ int len; /* IN: Length of str */ ACHAR blank; /* IN: The `blank' ACHAR */ { register ACHAR *p1, *p2; ENTER_DEBUG("tx_jr"); for (p1 = str + len, p2 = p1 - 1; (--p1 >= str) && (*p1 == blank); ) ; for (; p1 >= str; p1--, p2--) *p2 = *p1; for (; p2 >= str; p1--, p2--) *p2 = blank; EXIT_DEBUG(OK); } /*========================================================================== * tx_jc *==========================================================================*/ int tx_jc (str, len, blank) /*+++ .PURPOSE Center the string made of `ACHAR's. .RETURNS OK .REMARKS ---*/ ACHAR *str; /* IN: string to justify */ int len; /* IN: Length of str */ ACHAR blank; /* IN: The `blank' ACHAR */ { register ACHAR *p; register int nb; ENTER_DEBUG("tx_jc"); tx_jl(str, len, blank); /* First, push to left */ /* ... and count trailing blanks. Put half of them at left */ for (p = str + len, nb = 0; (--p >= str) && (*p == blank); nb++) ; EXIT_DEBUG(tx_jr(str, len - nb/2, blank)); } /*========================================================================== * tx_justify *==========================================================================*/ int tx_justify (str, len, blank) /*+++ .PURPOSE Justify (left & right) the string made of `ACHAR's. .RETURNS OK .REMARKS ---*/ ACHAR *str; /* IN: string to justify */ int len; /* IN: Length of str */ ACHAR blank; /* IN: The `blank' ACHAR */ { register ACHAR *p1, *p2; register int ls; int sb, rb, pb, i, nb; ENTER_DEBUG("tx_justify"); #if DEBUG TRACE_ED_STR2("Before justification", str, sizeof(ACHAR)*(len+1)); #endif /* First, start at first non-blank char */ while ( (*str == blank) && (len > 0)) { str++; len--; } /* ... and count trailing blanks. * This gives the length ls of the source string */ for (p1 = str + len, nb = 0; (--p1 >= str) && (*p1 == blank); nb++) ; if (nb == 0) FINISH; ls = len - nb; /* Now, count existing blanks in the string */ nb = 0; while (--p1 >= str) if (*p1 == blank) nb++; if (nb == 0) FINISH; /* Can't be justified... */ sb = (len - ls)/nb; /* Systematic blanks */ rb = (len - ls)%nb; /* Random blanks */ pb = 0; /* Periodic blanks */ if (rb) pb = nb / rb; for (nb=0, p1=str+ls, p2=str+len; --p1>=str; ) { *(--p2) = *p1; if (*p1 == blank) { nb++; for (i=sb; --i>=0; ) *(--p2) = blank; if (rb>0) { if (nb%pb == 0) { *(--p2) = blank; rb--; } } } } #if DEBUG TRACE_ED_STR2(" After justification", str, sizeof(ACHAR)*(len+1)); #endif FIN: EXIT_DEBUG(OK); } #if 0 /*========================================================================== * tx_crosses *==========================================================================*/ int tx_crosses(w, tab_lim) /*+++ .PURPOSE Modifies the crosses / tees in a table between lines[0] and lines[1] .RETURNS OK .REMARKS To be called at end of table environment. ---*/ WINDOW *w; /* IN: The concernced window */ short int tab_lim[2]; /* IN: Line limits of table, limits INCLUSIVE */ { MID_STATIC ACHAR An[2] = {' ', ' '}; ACHAR *pa, *pad; int j; int i,k,c, dir; MID_STATIC ACHAR *pn[4]; MID_RSTATIC ACHAR as = ' '; MID_RSTATIC unsigned char mod_tees[5][4][11] = { /* First index = kind of char * Second index = kind of neighbour char * Third = neighbour char */ /* | -- UL DL DR UR + TU TD TL TR */ { /* Crosses */ {HV, TU, HV, TU, TU, HV, HV, HV, TU, HV, HV}, /* UP char */ {HV, TD, TD, HV, HV, TD, HV, TD, HV, HV, HV}, /* DOWN char */ {TL, HV, HV, HV, TL, TL, HV, HV, HV, HV, TL}, /* LEFT char */ {TR, HV, TR, TR, HV, HV, HV, HV, HV, TR, HV} /* Right char */ }, { /* Up Tee */ {TU, TU, TU, TU, TU, TU, TU, TU, TU, TU, TU}, /* UP char */ {TU, H, H, TU, TU, H, TU, H, TU, TU, TU}, /* DOWN char */ {UL, TU, TU, TU, UL, UL, TU, TU, TU, TU, UL}, /* LEFT char */ {UR, TU, UR, UR, TU, TU, TU, TU, TU, UR, TU} /* Right char */ }, { /* Down Tee */ {TD, H, TD, H, H, TD, TD, TD, H, TD, TD}, /* UP char */ {TD, TD, TD, TD, TD, TD, TD, TD, TD, TD, TD}, /* DOWN char */ {DL, TD, TD, TD, DL, DL, TD, TD, TD, TD, DL}, /* LEFT char */ {DR, TD, DR, DR, TD, TD, TD, TD, TD, DR, TD} /* Right char */ }, { /* Left Tee */ {TL, UR, TL, UR, UR, TL, TL, TL, UR, TL, TL}, /* UP char */ {TL, DR, DR, TL, TL, DR, TL, DR, TL, TL, TL}, /* DOWN char */ {TL, TL, TL, TL, TL, TL, TL, TL, TL, TL, TL}, /* LEFT char */ { V, TL, V, V, TL, TL, TL, TL, TL, V, TL} /* Right char */ }, { /* Right Tee */ {TR, UR, TR, UR, UR, TR, TR, TR, UR, TR, TR}, /* UP char */ {TR, DR, DR, TR, TR, DR, TR, DR, TR, TR, TR}, /* DOWN char */ { V, TR, TR, TR, V, V, TR, TR, TR, TR, V}, /* LEFT char */ {TR, TR, TR, TR, TR, TR, TR, TR, TR, TR, TR} /* Right char */ } }; ENTER("tx_crosses"); if (tab_lim[0] < 0) tab_lim[0] = 0, An[_UP_] = Corner; else An[_UP_] = ' '; if (tab_lim[1] >= w->dim[0]) tab_lim[1] = w->dim[0] - 1, An[_DOWN_] = Corner; else An[_DOWN_] = ' '; for (i = tab_lim[0]; i <= tab_lim[1]; i++) { for (j=0, pa = Aij(w, i, 0); j < w->dim[1]; pa++, j++) { if (!(isGraphic(*pa))) continue; c = *pa & 0xff; if (c < CornerChar(_CROSS_)) continue; if (c >= RubbishChar()) continue; pn[_UP_] = (i == tab_lim[0] ? &An[_UP_] : Aij(w, i-1, j)); pn[_DOWN_] = (i >= tab_lim[1] ? &An[_DOWN_] : Aij(w, i+1, j)); pn[_LEFT_] = (j == 0 ? &as : pa-1); pn[_RIGHT_] = (j >= w->dim[1] - 1 ? &as : pa+1); for (dir=0; dir<4; dir++) { c = (*pa & 0xff) - CornerChar(_CROSS_); if (c < 0) break; k = -1; pad = pn[dir]; if (isGraphic(*pad)) k = ((*pad) & 0xff) - GraphicChar(0); if( (k<0) || (k >= 11)) k = (dir >> 1) ^ 1; *pa = (*pa & 0xff00) | GraphicChar(mod_tees[c][dir][k]); } switch(*pa & 0xff) { case CornerChar(_UPLEFT_): case CornerChar(_DOWNLEFT_): pad = pn[_RIGHT_]; if_not(isGraphic(*pad)) /* If no rule at top / bottom */ *pa = (*pa & 0xff00) | GraphicChar(V); continue; case CornerChar(_UPRIGHT_): case CornerChar(_DOWNRIGHT_): pad = pn[_LEFT_]; if_not(isGraphic(*pad)) /* If no rule at top / bottom */ *pa = (*pa & 0xff00) | GraphicChar(V); default: continue; } } } EXIT(OK); } #endif