428
+ − 1 /* Cursor motion subroutines for XEmacs.
+ − 2 Copyright (C) 1985, 1994, 1995 Free Software Foundation, Inc.
+ − 3 loosely based primarily on public domain code written by Chris Torek
+ − 4
+ − 5 This file is part of XEmacs.
+ − 6
+ − 7 XEmacs is free software; you can redistribute it and/or modify it
+ − 8 under the terms of the GNU General Public License as published by the
+ − 9 Free Software Foundation; either version 2, or (at your option) any
+ − 10 later version.
+ − 11
+ − 12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
+ − 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ − 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ − 15 for more details.
+ − 16
+ − 17 You should have received a copy of the GNU General Public License
+ − 18 along with XEmacs; see the file COPYING. If not, write to
+ − 19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ − 20 Boston, MA 02111-1307, USA. */
+ − 21
+ − 22 /* Synched up with: FSF 19.30. Substantially different from FSF. */
+ − 23
+ − 24 /* #### This file is extremely junky and needs major fixup. */
+ − 25
+ − 26 #include <config.h>
+ − 27 #include "lisp.h"
+ − 28
800
+ − 29 #include "device.h"
428
+ − 30 #include "frame.h"
+ − 31 #include "lstream.h"
+ − 32 #include "redisplay.h"
+ − 33
872
+ − 34 #include "console-tty-impl.h"
800
+ − 35
428
+ − 36 #define EXPENSIVE 2000
+ − 37
442
+ − 38 EXTERN_C char *tgoto (const char *cm, int hpos, int vpos);
+ − 39 EXTERN_C int tputs (const char *, int, void (*)(int));
428
+ − 40
+ − 41 static void cmgoto_for_real (struct console *c, int row, int col);
+ − 42
+ − 43 static int cm_cost_counter; /* sums up costs */
+ − 44
+ − 45 static void
2286
+ − 46 evalcost (int UNUSED (c))
428
+ − 47 {
+ − 48 cm_cost_counter++;
+ − 49 }
+ − 50
+ − 51 /* Ugh -- cmputc() can't take a console argument, so we pass it in a global */
+ − 52 struct console *cmputc_console;
+ − 53
+ − 54 void
+ − 55 send_string_to_tty_console (struct console *c, unsigned char *str, int len)
+ − 56 {
+ − 57 /* #### Ben sez: don't some terminals need nulls outputted
+ − 58 for proper timing? */
+ − 59 Lstream *lstr = XLSTREAM (CONSOLE_TTY_DATA (c)->outstream);
+ − 60
+ − 61 if (CONSOLE_TTY_REAL_CURSOR_X (c) != CONSOLE_TTY_CURSOR_X (c)
+ − 62 || CONSOLE_TTY_REAL_CURSOR_Y (c) != CONSOLE_TTY_CURSOR_Y (c))
+ − 63 {
+ − 64 int row = CONSOLE_TTY_CURSOR_Y (c);
+ − 65 int col = CONSOLE_TTY_CURSOR_X (c);
+ − 66 cmgoto_for_real (c, row, col);
+ − 67 }
+ − 68
+ − 69 if (len == 1)
+ − 70 Lstream_putc (lstr, *str);
+ − 71 else if (len > 0)
+ − 72 Lstream_write (lstr, str, len);
+ − 73 }
+ − 74
+ − 75 void
+ − 76 cmputc (int c)
+ − 77 {
+ − 78 unsigned char ch = (unsigned char) c;
+ − 79
+ − 80 if (termscript)
+ − 81 fputc (c, termscript);
+ − 82
+ − 83 send_string_to_tty_console (cmputc_console, &ch, 1);
+ − 84 }
+ − 85
+ − 86 #if 0
+ − 87
+ − 88 /*
+ − 89 * Terminals with magicwrap (xn) don't all behave identically.
+ − 90 * The VT100 leaves the cursor in the last column but will wrap before
+ − 91 * printing the next character. I hear that the Concept terminal does
+ − 92 * the wrap immediately but ignores the next newline it sees. And some
+ − 93 * terminals just have buggy firmware, and think that the cursor is still
+ − 94 * in limbo if we use direct cursor addressing from the phantom column.
+ − 95 * The only guaranteed safe thing to do is to emit a CRLF immediately
+ − 96 * after we reach the last column; this takes us to a known state.
+ − 97 */
+ − 98 void
+ − 99 cmcheckmagic (void)
+ − 100 {
+ − 101 if (curX == FrameCols)
+ − 102 {
+ − 103 if (!MagicWrap || curY >= FrameRows - 1)
2500
+ − 104 ABORT ();
428
+ − 105 if (termscript)
+ − 106 putc ('\r', termscript);
+ − 107 putchar ('\r');
+ − 108 if (termscript)
+ − 109 putc ('\n', termscript);
+ − 110 putchar ('\n');
+ − 111 curX = 0;
+ − 112 curY++;
+ − 113 }
+ − 114 }
+ − 115
+ − 116 #endif /* 0 */
+ − 117
+ − 118 /*
+ − 119 * (Re)Initialize the cost factors, given the output speed of the
+ − 120 * terminal in DEVICE_TTY_DATA (dev)->ospeed. (Note: this holds B300,
+ − 121 * B9600, etc -- ie stuff out of <sgtty.h>.)
+ − 122 */
+ − 123 void
+ − 124 cm_cost_init (struct console *c)
+ − 125 {
+ − 126 char *tmp;
+ − 127
+ − 128 cm_cost_counter = 0;
+ − 129 #define COST(x,e) (x \
+ − 130 ? (cm_cost_counter = 0, tputs (x, 1, e), cm_cost_counter) \
+ − 131 : EXPENSIVE)
+ − 132 #define MINCOST(x,e) ((x == 0) \
+ − 133 ? EXPENSIVE \
+ − 134 : (tmp = tgoto(x, 0, 0), COST(tmp,e)))
+ − 135
+ − 136 TTY_COST (c).cm_up = COST (TTY_CM (c).up, evalcost);
+ − 137 TTY_COST (c).cm_down = COST (TTY_CM (c).down, evalcost);
+ − 138 TTY_COST (c).cm_left = COST (TTY_CM (c).left, evalcost);
+ − 139 TTY_COST (c).cm_right = COST (TTY_CM (c).right, evalcost);
+ − 140 TTY_COST (c).cm_home = COST (TTY_CM (c).home, evalcost);
+ − 141 TTY_COST (c).cm_low_left = COST (TTY_CM (c).low_left, evalcost);
+ − 142 TTY_COST (c).cm_car_return = COST (TTY_CM (c).car_return, evalcost);
+ − 143
+ − 144 /*
+ − 145 * These last three are actually minimum costs. When (if) they are
+ − 146 * candidates for the least-cost motion, the real cost is computed.
+ − 147 * (Note that "0" is the assumed to generate the minimum cost.
+ − 148 * While this is not necessarily true, I have yet to see a terminal
+ − 149 * for which is not; all the terminals that have variable-cost
+ − 150 * cursor motion seem to take straight numeric values. --ACT)
+ − 151 */
+ − 152
+ − 153 TTY_COST (c).cm_abs = MINCOST (TTY_CM (c).abs, evalcost);
+ − 154 TTY_COST (c).cm_hor_abs = MINCOST (TTY_CM (c).hor_abs, evalcost);
+ − 155 TTY_COST (c).cm_ver_abs = MINCOST (TTY_CM (c).ver_abs, evalcost);
+ − 156
+ − 157 #undef MINCOST
+ − 158 #undef COST
+ − 159 }
+ − 160
+ − 161 /*
+ − 162 * Calculate the cost to move from (srcy, srcx) to (dsty, dstx) using
+ − 163 * up and down, and left and right, and motions. If doit is set
+ − 164 * actually perform the motion.
+ − 165 */
+ − 166
+ − 167 #ifdef NOT_YET
+ − 168 static int
+ − 169 calccost (struct frame *f, int srcy, int srcx, int dsty, int dstx, int doit)
+ − 170 {
+ − 171 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
+ − 172 int totalcost = 0;
+ − 173 int deltay, deltax;
+ − 174 char *motion;
+ − 175 int motion_cost;
+ − 176
+ − 177 #if 0
+ − 178 int ntabs, n2tabs, tabx, tab2x, tabcost;
+ − 179 #endif
+ − 180
+ − 181 cmputc_console = c;
+ − 182 #if 0
+ − 183 /* If have just wrapped on a terminal with xn,
+ − 184 don't believe the cursor position: give up here
+ − 185 and force use of absolute positioning. */
+ − 186 if (curX == Wcm.cm_cols)
+ − 187 goto fail;
+ − 188 #endif
+ − 189
+ − 190 deltay = dsty - srcy;
+ − 191 if (!deltay)
+ − 192 goto calculate_x;
+ − 193
+ − 194 if (deltay < 0)
+ − 195 {
+ − 196 motion = TTY_CM (c).up;
+ − 197 motion_cost = TTY_COST (c).cm_up;
+ − 198 deltay = -deltay;
+ − 199 }
+ − 200 else
+ − 201 {
+ − 202 motion = TTY_CM (c).down;
+ − 203 motion_cost = TTY_COST (c).cm_down;
+ − 204 }
+ − 205
+ − 206 if (motion_cost == EXPENSIVE)
+ − 207 {
+ − 208 /* if (doit) */
+ − 209 /* #### printing OOF is not acceptable */
+ − 210 return motion_cost;
+ − 211 }
+ − 212
+ − 213 totalcost = motion_cost * deltay;
+ − 214
+ − 215 if (doit)
+ − 216 while (--deltay >= 0)
+ − 217 tputs (motion, 1, cmputc);
+ − 218
+ − 219 calculate_x:
+ − 220
+ − 221 deltax = dstx - srcx;
+ − 222 if (!deltax)
+ − 223 goto done;
+ − 224
+ − 225 if (deltax < 0)
+ − 226 {
+ − 227 motion = TTY_CM (c).left;
+ − 228 motion_cost = TTY_COST (c).cm_left;
+ − 229 deltax = -deltax;
+ − 230 }
+ − 231 else
+ − 232 {
+ − 233 motion = TTY_CM (c).right;
+ − 234 motion_cost = TTY_COST (c).cm_right;
+ − 235 }
+ − 236
+ − 237 if (motion_cost == EXPENSIVE)
+ − 238 {
+ − 239 /* if (doit) */
+ − 240 /* #### printing OOF is not acceptable */
+ − 241 return motion_cost;
+ − 242 }
+ − 243
+ − 244 totalcost += motion_cost * deltax;
+ − 245
+ − 246 if (doit)
+ − 247 while (--deltax >= 0)
+ − 248 tputs (motion, 1, cmputc);
+ − 249
+ − 250 done:
+ − 251 return totalcost;
+ − 252 }
+ − 253 #endif /* NOT_YET */
+ − 254
+ − 255 #define USEREL 0
+ − 256 #define USEHOME 1
+ − 257 #define USELL 2
+ − 258 #define USECR 3
+ − 259
778
+ − 260 #ifdef OLD_CURSOR_MOTION_SHIT
428
+ − 261 void
+ − 262 cmgoto (struct frame *f, int row, int col)
+ − 263 {
+ − 264 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
+ − 265 char *motion;
+ − 266 #if 0
+ − 267 int frame_x = FRAME_CURSOR_X(f);
+ − 268 int frame_y = FRAME_CURSOR_Y(f);
+ − 269 int relcost, directcost, llcost;
+ − 270 int homecost;
+ − 271 int use;
+ − 272 char *dcm;
+ − 273 #endif
+ − 274
+ − 275 cmputc_console = c;
+ − 276
+ − 277 /* First the degenerate case */
+ − 278 #if 0
+ − 279 if (row == frame_y && col == frame_x)
+ − 280 return;
+ − 281 #endif
+ − 282
+ − 283 /* #### something is fucked with the non-absolute cases */
+ − 284 motion = tgoto (TTY_CM (c).abs, col, row);
+ − 285 tputs (motion, 1, cmputc);
+ − 286 CONSOLE_TTY_DATA (c)->cursor_x = col;
+ − 287 CONSOLE_TTY_DATA (c)->cursor_y = row;
+ − 288 return;
+ − 289
+ − 290 #if 0
+ − 291 if (frame_y >= 0 && frame_x >= 0)
+ − 292 {
+ − 293 /*
+ − 294 * Pick least-cost motions
+ − 295 */
+ − 296
+ − 297 relcost = calccost (f, frame_y, frame_x, row, col, 0);
+ − 298 use = USEREL;
+ − 299
+ − 300 homecost = TTY_COST (c).cm_home;
+ − 301 if (homecost < EXPENSIVE)
+ − 302 homecost += calccost (f, 0, 0, row, col, 0);
+ − 303
+ − 304 if (homecost < relcost)
+ − 305 {
+ − 306 relcost = homecost;
+ − 307 use = USEHOME;
+ − 308 }
+ − 309
+ − 310 llcost = TTY_COST (c).cm_low_left;
+ − 311 if (llcost < EXPENSIVE)
+ − 312 llcost += calccost (f, frame_y - 1, 0, row, col, 0);
+ − 313
+ − 314 if (llcost < relcost)
+ − 315 {
+ − 316 relcost = llcost;
+ − 317 use = USELL;
+ − 318 }
+ − 319
+ − 320 #if 0
+ − 321 if ((crcost = Wcm.cc_cr) < BIG) {
+ − 322 if (Wcm.cm_autolf)
+ − 323 if (curY + 1 >= Wcm.cm_rows)
+ − 324 crcost = BIG;
+ − 325 else
+ − 326 crcost += calccost (curY + 1, 0, row, col, 0);
+ − 327 else
+ − 328 crcost += calccost (curY, 0, row, col, 0);
+ − 329 }
+ − 330 if (crcost < relcost)
+ − 331 relcost = crcost, use = USECR;
+ − 332 #endif
+ − 333
+ − 334 directcost = TTY_COST (c).cm_abs;
+ − 335 dcm = TTY_CM (c).abs;
+ − 336
+ − 337 if (row == frame_y && TTY_COST (c).cm_hor_abs < EXPENSIVE)
+ − 338 {
+ − 339 directcost = TTY_COST (c).cm_hor_abs;
+ − 340 dcm = TTY_CM (c).hor_abs;
+ − 341 }
+ − 342 else if (col == frame_x && TTY_COST (c).cm_ver_abs < EXPENSIVE)
+ − 343 {
+ − 344 directcost = TTY_COST (c).cm_ver_abs;
+ − 345 dcm = TTY_CM (c).ver_abs;
+ − 346 }
+ − 347 }
+ − 348 else
+ − 349 {
+ − 350 directcost = 0;
+ − 351 relcost = 100000;
+ − 352 dcm = TTY_CM (c).abs;
+ − 353 }
+ − 354
+ − 355 /*
+ − 356 * In the following comparison, the = in <= is because when the costs
+ − 357 * are the same, it looks nicer (I think) to move directly there.
+ − 358 */
+ − 359 if (directcost <= relcost)
+ − 360 {
+ − 361 /* compute REAL direct cost */
+ − 362 cm_cost_counter = 0;
+ − 363 motion = (dcm == TTY_CM (c).hor_abs
+ − 364 ? tgoto (dcm, row, col)
+ − 365 : tgoto (dcm, col, row));
+ − 366 tputs (motion, 1, evalcost);
+ − 367 if (cm_cost_counter <= relcost)
+ − 368 { /* really is cheaper */
+ − 369 tputs (motion, 1, cmputc);
+ − 370 FRAME_CURSOR_Y (f) = row;
+ − 371 FRAME_CURSOR_X (f) = col;
+ − 372 return;
+ − 373 }
+ − 374 }
+ − 375
+ − 376 switch (use)
+ − 377 {
+ − 378 case USEHOME:
+ − 379 tputs (TTY_CM (c).home, 1, cmputc);
+ − 380 FRAME_CURSOR_X (f) = 0;
+ − 381 FRAME_CURSOR_Y (f) = 0;
+ − 382 break;
+ − 383
+ − 384 case USELL:
+ − 385 tputs (TTY_CM (c).low_left, 1, cmputc);
+ − 386 FRAME_CURSOR_Y (f) = FRAME_HEIGHT (f) - 1;
+ − 387 FRAME_CURSOR_X (f) = 0;
+ − 388 break;
+ − 389
+ − 390 #if 0
+ − 391 case USECR:
+ − 392 tputs (Wcm.cm_cr, 1, cmputc);
+ − 393 if (Wcm.cm_autolf)
+ − 394 curY++;
+ − 395 curX = 0;
+ − 396 break;
+ − 397 #endif
+ − 398 }
+ − 399
+ − 400 calccost (f, FRAME_CURSOR_Y (f), FRAME_CURSOR_X (f), row, col, 1);
+ − 401 FRAME_CURSOR_Y (f) = row;
+ − 402 FRAME_CURSOR_X (f) = col;
+ − 403 #endif
+ − 404 }
+ − 405 #endif /* OLD_CURSOR_MOTION_SHIT */
+ − 406
+ − 407 /*****************************************************************************
+ − 408 cmgoto
+ − 409
+ − 410 This function is responsible for getting the cursor from its current
+ − 411 location to the passed location in the most efficient manner
+ − 412 possible.
+ − 413 ****************************************************************************/
+ − 414 static void
+ − 415 cmgoto_for_real (struct console *c, int row, int col)
+ − 416 {
+ − 417 char *motion;
+ − 418
+ − 419 cmputc_console = c;
+ − 420
+ − 421 /* First make sure that we actually have to do any work at all. */
+ − 422 if (CONSOLE_TTY_REAL_CURSOR_X (c) == col
+ − 423 && CONSOLE_TTY_REAL_CURSOR_Y (c) == row)
+ − 424 return;
+ − 425
+ − 426 CONSOLE_TTY_REAL_CURSOR_X (c) = col;
+ − 427 CONSOLE_TTY_REAL_CURSOR_Y (c) = row;
+ − 428
+ − 429 /* #### Need to reimplement cost analysis and potential relative
+ − 430 movement. */
+ − 431
+ − 432 /* If all else fails, use absolute movement. */
+ − 433 motion = tgoto (TTY_CM (c).abs, col, row);
+ − 434 tputs (motion, 1, cmputc);
+ − 435 CONSOLE_TTY_CURSOR_X (c) = col;
+ − 436 CONSOLE_TTY_CURSOR_Y (c) = row;
+ − 437 }
+ − 438
+ − 439 void
+ − 440 cmgoto (struct frame *f, int row, int col)
+ − 441 {
+ − 442 /* We delay cursor motion until we do something other than cursor motion,
+ − 443 to optimize the case where cmgoto() is called twice in a row. */
+ − 444 struct console *c = XCONSOLE (FRAME_CONSOLE (f));
+ − 445 CONSOLE_TTY_CURSOR_X (c) = col;
+ − 446 CONSOLE_TTY_CURSOR_Y (c) = row;
+ − 447 }
+ − 448
+ − 449 #if 0
+ − 450 /* Clear out all terminal info.
+ − 451 Used before copying into it the info on the actual terminal.
+ − 452 */
+ − 453
+ − 454 void
+ − 455 Wcm_clear (void)
+ − 456 {
+ − 457 xzero (Wcm);
+ − 458 UP = 0;
+ − 459 BC = 0;
+ − 460 }
+ − 461 #endif
+ − 462
+ − 463 #if 0
+ − 464 /*
+ − 465 * Initialized stuff
+ − 466 * Return 0 if can do CM.
+ − 467 * Return -1 if cannot.
+ − 468 * Return -2 if size not specified.
+ − 469 */
+ − 470
+ − 471 int
+ − 472 Wcm_init (void)
+ − 473 {
+ − 474 #if 0
+ − 475 if (Wcm.cm_abs && !Wcm.cm_ds)
+ − 476 return 0;
+ − 477 #endif
+ − 478 if (Wcm.cm_abs)
+ − 479 return 0;
+ − 480 /* Require up and left, and, if no absolute, down and right */
+ − 481 if (!Wcm.cm_up || !Wcm.cm_left)
+ − 482 return - 1;
+ − 483 if (!Wcm.cm_abs && (!Wcm.cm_down || !Wcm.cm_right))
+ − 484 return - 1;
+ − 485 /* Check that we know the size of the frame.... */
+ − 486 if (Wcm.cm_rows <= 0 || Wcm.cm_cols <= 0)
+ − 487 return - 2;
+ − 488 return 0;
+ − 489 }
+ − 490 #endif