This is cm.c in view mode; [Download] [Up]
/* Optimal cursor motion functions. Copyright (C) 1985 Free Software Foundation, Inc. Based primarily on public domain code written by Chris Torek Originally part of GNU Emacs. Vastly edited and modified for use within ne. Copyright (C) 1993 Sebastiano Vigna This file is part of ne, the nice editor. 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, 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 Mass Ave, Cambridge, MA 02139, USA. In other words, you are welcome to use, share and improve this program. You are forbidden to forbid anyone else to use, share and improve what you give them. Help stamp out software-hoarding! */ #include <stdio.h> #ifndef TERMCAP #include <curses.h> #include <term.h> #else #include "info2cap.h" #endif #include "cm.h" #define BIG 9999 int cost; /* sums up costs */ /* This function is used in place of putchar() in tputs() so can we can computed the padded length of a capability string. Note that they should be putchar()-like, so we have to care about the returned value. */ int evalcost (int c) { cost++; return(c); } /* This function is used in tputs(). */ int cmputc (int c) { return(putchar(c & 0xff)); } /* This function (Re)Initializes the cost factors. */ void cmcostinit (void) { char *p; #define COST(x,e) (x ? (cost = 0, tputs (x, 1, e), cost) : BIG) #define CMCOST(x,e) ((x == 0) ? BIG : (p = tparm(x, 0, 0), COST(p ,e))) Wcm.cc_up = COST (Wcm.cm_up, evalcost); Wcm.cc_down = COST (Wcm.cm_down, evalcost); Wcm.cc_left = COST (Wcm.cm_left, evalcost); Wcm.cc_right = COST (Wcm.cm_right, evalcost); Wcm.cc_home = COST (Wcm.cm_home, evalcost); Wcm.cc_cr = COST (Wcm.cm_cr, evalcost); Wcm.cc_ll = COST (Wcm.cm_ll, evalcost); /* These last three are actually minimum costs. When (if) they are candidates for the least-cost motion, the real cost is computed. (Note that "0" is the assumed to generate the minimum cost. While this is not necessarily true, I have yet to see a terminal for which is not; all the terminals that have variable-cost cursor motion seem to take straight numeric values. --ACT) */ Wcm.cc_abs = CMCOST (Wcm.cm_abs, evalcost); Wcm.cc_habs = CMCOST (Wcm.cm_habs, evalcost); Wcm.cc_vabs = CMCOST (Wcm.cm_vabs, evalcost); #undef CMCOST #undef COST } /* This function calculates the cost to move from (srcy, srcx) to (dsty, dstx) using up and down, and left and right motions. If doit is set actually perform the motion. Originally, this function was also considering the existence of tabs, but it is clear that almost all new systems will not allow usage of tabs because of the lack of a clear semantics. */ static int calccost (int srcy, int srcx, int dsty, int dstx, int doit) { int deltay, deltax, c, totalcost; char *p; /* If have just wrapped on a terminal with xn, don't believe the cursor position: give up here and force use of absolute positioning. */ if (curX == Wcm.cm_cols) { if (doit) assert(FALSE); return(BIG); } totalcost = 0; if ((deltay = dsty - srcy) != 0) { if (deltay < 0) { p = Wcm.cm_up; c = Wcm.cc_up; deltay = -deltay; } else { p = Wcm.cm_down; c = Wcm.cc_down; } if (c == BIG) { if (doit) assert(FALSE); return c; } totalcost = c * deltay; if (doit) while (--deltay >= 0) tputs (p, 1, cmputc); } if ((deltax = dstx - srcx) == 0) return(totalcost); if (deltax > 0) { p = Wcm.cm_right; c = Wcm.cc_right; } else { p = Wcm.cm_left; c = Wcm.cc_left; deltax = -deltax; } if (c == BIG) { if (doit) assert(FALSE); return BIG; } totalcost += c * deltax; if (doit) while (--deltax >= 0) tputs (p, 1, cmputc); return(totalcost); } /* This function marks the cursor position as unknown. It is mainly useful for capabilities like set_scroll_region, which destroy the cursor position. */ void losecursor(void) { curY = -1; } #define USEREL 0 #define USEHOME 1 #define USELL 2 #define USECR 3 /* This function moves the cursor to a given position. */ void cmgoto (int row, int col) { int homecost, crcost, llcost, relcost, directcost; int use; char *p, *dcm; /* First the degenerate case */ if (row == curY && col == curX) /* already there */ return; if (curY >= 0 && curX >= 0) { /* * Pick least-cost motions */ relcost = calccost (curY, curX, row, col, 0); use = USEREL; if ((homecost = Wcm.cc_home) < BIG) homecost += calccost (0, 0, row, col, 0); if (homecost < relcost) relcost = homecost, use = USEHOME; if ((llcost = Wcm.cc_ll) < BIG) llcost += calccost (Wcm.cm_rows - 1, 0, row, col, 0); if (llcost < relcost) relcost = llcost, use = USELL; if ((crcost = Wcm.cc_cr) < BIG) { if (Wcm.cm_autolf) if (curY + 1 >= Wcm.cm_rows) crcost = BIG; else crcost += calccost (curY + 1, 0, row, col, 0); else crcost += calccost (curY, 0, row, col, 0); } if (crcost < relcost) relcost = crcost, use = USECR; directcost = Wcm.cc_abs, dcm = Wcm.cm_abs; if (row == curY && Wcm.cc_habs < BIG) directcost = Wcm.cc_habs, dcm = Wcm.cm_habs; else if (col == curX && Wcm.cc_vabs < BIG) directcost = Wcm.cc_vabs, dcm = Wcm.cm_vabs; } else { directcost = 0, relcost = 100000; dcm = Wcm.cm_abs; } /* * In the following comparison, the = in <= is because when the costs * are the same, it looks nicer (I think) to move directly there. */ if (directcost <= relcost) { /* compute REAL direct cost */ cost = 0; p = (dcm == Wcm.cm_habs) ? tparm (dcm, col) : (dcm == Wcm.cm_vabs) ? tparm (dcm, row) : tparm (dcm, row, col); tputs (p, 1, evalcost); if (cost <= relcost) { tputs (p, 1, cmputc); curY = row; curX = col; return; } } switch (use) { case USEHOME: tputs (Wcm.cm_home, 1, cmputc); curY = curX = 0; break; case USELL: tputs (Wcm.cm_ll, 1, cmputc); curY = Wcm.cm_rows - 1; curX = 0; break; case USECR: tputs (Wcm.cm_cr, 1, cmputc); if (Wcm.cm_autolf) curY++; curX = 0; break; } calccost (curY, curX, row, col, 1); curY = row; curX = col; } /* This function checks, after initialization of Wcm, that we have enough capabilities to move the cursor. */ int Wcm_init (void) { /* Check that we know the size of the screen.... */ if (Wcm.cm_rows <= 0 || Wcm.cm_cols <= 0) return(-1); if (Wcm.cm_abs && !Wcm.cm_ds) return(0); /* Require up and left, and, if no absolute, down and right */ if (!Wcm.cm_up || !Wcm.cm_left) return(-1); if (!Wcm.cm_abs && (!Wcm.cm_down || !Wcm.cm_right)) return(-1); return(0); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.