1/*- 2 * Copyright (c) 1992, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 1992, 1993, 1994, 1995 5 * Keith Bostic. All rights reserved. 6 * Copyright (c) 1995 7 * George V. Neville-Neil. All rights reserved. 8 * 9 * See the LICENSE file for redistribution information. 10 */ 11 12#include "config.h" 13 14#include <sys/cdefs.h> 15#if 0 16#ifndef lint 17static const char sccsid[] = "Id: tcl.c,v 8.19 2001/08/24 12:17:27 skimo Exp (Berkeley) Date: 2001/08/24 12:17:27 "; 18#endif /* not lint */ 19#else 20__RCSID("$NetBSD: tcl.c,v 1.3 2014/01/26 21:43:45 christos Exp $"); 21#endif 22 23#include <sys/types.h> 24#include <sys/queue.h> 25#include <sys/time.h> 26 27#include <bitstring.h> 28#include <errno.h> 29#include <limits.h> 30#include <signal.h> 31#include <stdio.h> 32#include <stdlib.h> 33#include <string.h> 34#include <tcl.h> 35#include <termios.h> 36#include <unistd.h> 37 38#include "../common/common.h" 39#include "tcl_api_extern.h" 40 41static int getint __P((Tcl_Interp *, char *, char *, int *)); 42static int getscreenid __P((Tcl_Interp *, SCR **, char *, char *)); 43static void msghandler __P((SCR *, mtype_t, char *, size_t)); 44 45extern GS *__global_list; /* XXX */ 46 47/* 48 * INITMESSAGE -- 49 * Macros to point messages at the Tcl message handler. 50 */ 51#define INITMESSAGE(sp) \ 52 scr_msg = sp->wp->scr_msg; \ 53 sp->wp->scr_msg = msghandler; 54#define ENDMESSAGE(sp) \ 55 sp->wp->scr_msg = scr_msg; 56 57/* 58 * tcl_fscreen -- 59 * Return the screen id associated with file name. 60 * 61 * Tcl Command: viFindScreen 62 * Usage: viFindScreen file 63 */ 64static int 65tcl_fscreen(clientData, interp, argc, argv) 66 ClientData clientData; 67 Tcl_Interp *interp; 68 int argc; 69 char **argv; 70{ 71 SCR *sp; 72 73 if (argc != 2) { 74 Tcl_SetResult(interp, "Usage: viFindScreen file", TCL_STATIC); 75 return (TCL_ERROR); 76 } 77 78 if (getscreenid(interp, &sp, NULL, argv[1])) 79 return (TCL_ERROR); 80 81 (void)sprintf(interp->result, "%d", sp->id); 82 return (TCL_OK); 83} 84 85/* 86 * tcl_aline -- 87 * -- Append the string text after the line in lineNumber. 88 * 89 * Tcl Command: viAppendLine 90 * Usage: viAppendLine screenId lineNumber text 91 */ 92static int 93tcl_aline(clientData, interp, argc, argv) 94 ClientData clientData; 95 Tcl_Interp *interp; 96 int argc; 97 char **argv; 98{ 99 SCR *sp; 100 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t)); 101 int lno, rval; 102 103 if (argc != 4) { 104 Tcl_SetResult(interp, 105 "Usage: viAppendLine screenId lineNumber text", TCL_STATIC); 106 return (TCL_ERROR); 107 } 108 109 if (getscreenid(interp, &sp, argv[1], NULL) || 110 getint(interp, "line number", argv[2], &lno)) 111 return (TCL_ERROR); 112 INITMESSAGE(sp); 113 rval = api_aline(sp, (db_recno_t)lno, argv[3], strlen(argv[3])); 114 ENDMESSAGE(sp); 115 116 return (rval ? TCL_ERROR : TCL_OK); 117} 118 119/* 120 * tcl_dline -- 121 * Delete lineNum. 122 * 123 * Tcl Command: viDelLine 124 * Usage: viDelLine screenId lineNum 125 */ 126static int 127tcl_dline(clientData, interp, argc, argv) 128 ClientData clientData; 129 Tcl_Interp *interp; 130 int argc; 131 char **argv; 132{ 133 SCR *sp; 134 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t)); 135 int lno, rval; 136 137 if (argc != 3) { 138 Tcl_SetResult(interp, 139 "Usage: viDelLine screenId lineNumber", TCL_STATIC); 140 return (TCL_ERROR); 141 } 142 143 if (getscreenid(interp, &sp, argv[1], NULL) || 144 getint(interp, "line number", argv[2], &lno)) 145 return (TCL_ERROR); 146 INITMESSAGE(sp); 147 rval = api_dline(sp, (db_recno_t)lno); 148 ENDMESSAGE(sp); 149 150 return (rval ? TCL_ERROR : TCL_OK); 151} 152 153/* 154 * tcl_gline -- 155 * Return lineNumber. 156 * 157 * Tcl Command: viGetLine 158 * Usage: viGetLine screenId lineNumber 159 */ 160static int 161tcl_gline(clientData, interp, argc, argv) 162 ClientData clientData; 163 Tcl_Interp *interp; 164 int argc; 165 char **argv; 166{ 167 SCR *sp; 168 size_t len; 169 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t)); 170 int lno, rval; 171 char *line, *p; 172 173 if (argc != 3) { 174 Tcl_SetResult(interp, 175 "Usage: viGetLine screenId lineNumber", TCL_STATIC); 176 return (TCL_ERROR); 177 } 178 if (getscreenid(interp, &sp, argv[1], NULL) || 179 getint(interp, "line number", argv[2], &lno)) 180 return (TCL_ERROR); 181 INITMESSAGE(sp); 182 rval = api_gline(sp, (db_recno_t)lno, &p, &len); 183 ENDMESSAGE(sp); 184 185 if (rval) 186 return (TCL_ERROR); 187 188 if ((line = malloc(len + 1)) == NULL) 189 exit(1); /* XXX */ 190 memmove(line, p, len); 191 line[len] = '\0'; 192 Tcl_SetResult(interp, line, TCL_DYNAMIC); 193 return (TCL_OK); 194} 195 196/* 197 * tcl_iline -- 198 * Insert the string text after the line in lineNumber. 199 * 200 * Tcl Command: viInsertLine 201 * Usage: viInsertLine screenId lineNumber text 202 */ 203static int 204tcl_iline(clientData, interp, argc, argv) 205 ClientData clientData; 206 Tcl_Interp *interp; 207 int argc; 208 char **argv; 209{ 210 SCR *sp; 211 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t)); 212 int lno, rval; 213 214 if (argc != 4) { 215 Tcl_SetResult(interp, 216 "Usage: viInsertLine screenId lineNumber text", TCL_STATIC); 217 return (TCL_ERROR); 218 } 219 220 if (getscreenid(interp, &sp, argv[1], NULL) || 221 getint(interp, "line number", argv[2], &lno)) 222 return (TCL_ERROR); 223 INITMESSAGE(sp); 224 rval = api_iline(sp, (db_recno_t)lno, argv[3], strlen(argv[3])); 225 ENDMESSAGE(sp); 226 227 return (rval ? TCL_ERROR : TCL_OK); 228} 229 230/* 231 * tcl_lline -- 232 * Return the last line in the screen. 233 * 234 * Tcl Command: viLastLine 235 * Usage: viLastLine screenId 236 */ 237static int 238tcl_lline(clientData, interp, argc, argv) 239 ClientData clientData; 240 Tcl_Interp *interp; 241 int argc; 242 char **argv; 243{ 244 SCR *sp; 245 db_recno_t last; 246 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t)); 247 int rval; 248 249 if (argc != 2) { 250 Tcl_SetResult(interp, "Usage: viLastLine screenId", TCL_STATIC); 251 return (TCL_ERROR); 252 } 253 254 if (getscreenid(interp, &sp, argv[1], NULL)) 255 return (TCL_ERROR); 256 INITMESSAGE(sp); 257 rval = api_lline(sp, &last); 258 ENDMESSAGE(sp); 259 if (rval) 260 return (TCL_ERROR); 261 262 (void)sprintf(interp->result, "%lu", (unsigned long)last); 263 return (TCL_OK); 264} 265 266/* 267 * tcl_sline -- 268 * Set lineNumber to the text supplied. 269 * 270 * Tcl Command: viSetLine 271 * Usage: viSetLine screenId lineNumber text 272 */ 273static int 274tcl_sline(clientData, interp, argc, argv) 275 ClientData clientData; 276 Tcl_Interp *interp; 277 int argc; 278 char **argv; 279{ 280 SCR *sp; 281 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t)); 282 int lno, rval; 283 284 if (argc != 4) { 285 Tcl_SetResult(interp, 286 "Usage: viSetLine screenId lineNumber text", TCL_STATIC); 287 return (TCL_ERROR); 288 } 289 290 if (getscreenid(interp, &sp, argv[1], NULL) || 291 getint(interp, "line number", argv[2], &lno)) 292 return (TCL_ERROR); 293 INITMESSAGE(sp); 294 rval = api_sline(sp, (db_recno_t)lno, argv[3], strlen(argv[3])); 295 ENDMESSAGE(sp); 296 297 return (rval ? TCL_ERROR : TCL_OK); 298} 299 300/* 301 * tcl_getmark -- 302 * Return the mark's cursor position as a list with two elements. 303 * {line, column}. 304 * 305 * Tcl Command: viGetMark 306 * Usage: viGetMark screenId mark 307 */ 308static int 309tcl_getmark(clientData, interp, argc, argv) 310 ClientData clientData; 311 Tcl_Interp *interp; 312 int argc; 313 char **argv; 314{ 315 MARK cursor; 316 SCR *sp; 317 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t)); 318 int rval; 319 char buf[20]; 320 321 if (argc != 3) { 322 Tcl_SetResult(interp, 323 "Usage: viGetMark screenId mark", TCL_STATIC); 324 return (TCL_ERROR); 325 } 326 327 if (getscreenid(interp, &sp, argv[1], NULL)) 328 return (TCL_ERROR); 329 INITMESSAGE(sp); 330 rval = api_getmark(sp, (int)argv[2][0], &cursor); 331 ENDMESSAGE(sp); 332 333 if (rval) 334 return (TCL_ERROR); 335 336 (void)snprintf(buf, sizeof(buf), "%lu", (u_long)cursor.lno); 337 Tcl_AppendElement(interp, buf); 338 (void)snprintf(buf, sizeof(buf), "%lu", (u_long)cursor.cno); 339 Tcl_AppendElement(interp, buf); 340 return (TCL_OK); 341} 342 343/* 344 * tcl_setmark -- 345 * Set the mark to the line and column numbers supplied. 346 * 347 * Tcl Command: viSetMark 348 * Usage: viSetMark screenId mark line column 349 */ 350static int 351tcl_setmark(clientData, interp, argc, argv) 352 ClientData clientData; 353 Tcl_Interp *interp; 354 int argc; 355 char **argv; 356{ 357 MARK cursor; 358 SCR *sp; 359 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t)); 360 int i, rval; 361 362 if (argc != 5) { 363 Tcl_SetResult(interp, 364 "Usage: viSetMark screenId mark line column", TCL_STATIC); 365 return (TCL_ERROR); 366 } 367 368 if (getscreenid(interp, &sp, argv[1], NULL)) 369 return (TCL_ERROR); 370 if (getint(interp, "line number", argv[3], &i)) 371 return (TCL_ERROR); 372 cursor.lno = i; 373 if (getint(interp, "column number", argv[4], &i)) 374 return (TCL_ERROR); 375 cursor.cno = i; 376 INITMESSAGE(sp); 377 rval = api_setmark(sp, (int)argv[2][0], &cursor); 378 ENDMESSAGE(sp); 379 380 return (rval ? TCL_ERROR : TCL_OK); 381} 382 383/* 384 * tcl_getcursor -- 385 * Return the current cursor position as a list with two elements. 386 * {line, column}. 387 * 388 * Tcl Command: viGetCursor 389 * Usage: viGetCursor screenId 390 */ 391static int 392tcl_getcursor(clientData, interp, argc, argv) 393 ClientData clientData; 394 Tcl_Interp *interp; 395 int argc; 396 char **argv; 397{ 398 MARK cursor; 399 SCR *sp; 400 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t)); 401 int rval; 402 char buf[20]; 403 404 if (argc != 2) { 405 Tcl_SetResult(interp, 406 "Usage: viGetCursor screenId", TCL_STATIC); 407 return (TCL_ERROR); 408 } 409 410 if (getscreenid(interp, &sp, argv[1], NULL)) 411 return (TCL_ERROR); 412 INITMESSAGE(sp); 413 rval = api_getcursor(sp, &cursor); 414 ENDMESSAGE(sp); 415 416 if (rval) 417 return (TCL_ERROR); 418 419 (void)snprintf(buf, sizeof(buf), "%lu", (u_long)cursor.lno); 420 Tcl_AppendElement(interp, buf); 421 (void)snprintf(buf, sizeof(buf), "%lu", (u_long)cursor.cno); 422 Tcl_AppendElement(interp, buf); 423 return (TCL_OK); 424} 425 426/* 427 * tcl_setcursor -- 428 * Set the cursor to the line and column numbers supplied. 429 * 430 * Tcl Command: viSetCursor 431 * Usage: viSetCursor screenId line column 432 */ 433static int 434tcl_setcursor(clientData, interp, argc, argv) 435 ClientData clientData; 436 Tcl_Interp *interp; 437 int argc; 438 char **argv; 439{ 440 MARK cursor; 441 SCR *sp; 442 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t)); 443 int i, rval; 444 445 if (argc != 4) { 446 Tcl_SetResult(interp, 447 "Usage: viSetCursor screenId line column", TCL_STATIC); 448 return (TCL_ERROR); 449 } 450 451 if (getscreenid(interp, &sp, argv[1], NULL)) 452 return (TCL_ERROR); 453 if (getint(interp, "screen id", argv[2], &i)) 454 return (TCL_ERROR); 455 cursor.lno = i; 456 if (getint(interp, "screen id", argv[3], &i)) 457 return (TCL_ERROR); 458 cursor.cno = i; 459 INITMESSAGE(sp); 460 rval = api_setcursor(sp, &cursor); 461 ENDMESSAGE(sp); 462 463 return (rval ? TCL_ERROR : TCL_OK); 464} 465 466/* 467 * tcl_msg -- 468 * Set the message line to text. 469 * 470 * Tcl Command: viMsg 471 * Usage: viMsg screenId text 472 */ 473static int 474tcl_msg(clientData, interp, argc, argv) 475 ClientData clientData; 476 Tcl_Interp *interp; 477 int argc; 478 char **argv; 479{ 480 SCR *sp; 481 482 if (argc != 3) { 483 Tcl_SetResult(interp, "Usage: viMsg screenId text", TCL_STATIC); 484 return (TCL_ERROR); 485 } 486 487 if (getscreenid(interp, &sp, argv[1], NULL)) 488 return (TCL_ERROR); 489 api_imessage(sp, argv[2]); 490 491 return (TCL_OK); 492} 493 494/* 495 * tcl_iscreen -- 496 * Create a new screen. If a filename is specified then the screen 497 * is opened with that file. 498 * 499 * Tcl Command: viNewScreen 500 * Usage: viNewScreen screenId [file] 501 */ 502static int 503tcl_iscreen(clientData, interp, argc, argv) 504 ClientData clientData; 505 Tcl_Interp *interp; 506 int argc; 507 char **argv; 508{ 509 SCR *sp, *nsp; 510 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t)); 511 int rval; 512 513 if (argc != 2 && argc != 3) { 514 Tcl_SetResult(interp, 515 "Usage: viNewScreen screenId [file]", TCL_STATIC); 516 return (TCL_ERROR); 517 } 518 519 if (getscreenid(interp, &sp, argv[1], NULL)) 520 return (TCL_ERROR); 521 INITMESSAGE(sp); 522 rval = api_edit(sp, argv[2], &nsp, 1); 523 ENDMESSAGE(sp); 524 525 if (rval) 526 return (TCL_ERROR); 527 528 (void)sprintf(interp->result, "%d", nsp->id); 529 return (TCL_OK); 530} 531 532/* 533 * tcl_escreen -- 534 * End a screen. 535 * 536 * Tcl Command: viEndScreen 537 * Usage: viEndScreen screenId 538 */ 539static int 540tcl_escreen(clientData, interp, argc, argv) 541 ClientData clientData; 542 Tcl_Interp *interp; 543 int argc; 544 char **argv; 545{ 546 SCR *sp; 547 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t)); 548 int rval; 549 550 if (argc != 2) { 551 Tcl_SetResult(interp, 552 "Usage: viEndScreen screenId", TCL_STATIC); 553 return (TCL_ERROR); 554 } 555 556 if (getscreenid(interp, &sp, argv[1], NULL)) 557 return (TCL_ERROR); 558 INITMESSAGE(sp); 559 rval = api_escreen(sp); 560 ENDMESSAGE(sp); 561 562 return (rval ? TCL_ERROR : TCL_OK); 563} 564 565/* 566 * tcl_swscreen -- 567 * Change the current focus to screen. 568 * 569 * Tcl Command: viSwitchScreen 570 * Usage: viSwitchScreen screenId screenId 571 */ 572static int 573tcl_swscreen(clientData, interp, argc, argv) 574 ClientData clientData; 575 Tcl_Interp *interp; 576 int argc; 577 char **argv; 578{ 579 SCR *sp, *new; 580 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t)); 581 int rval; 582 583 if (argc != 3) { 584 Tcl_SetResult(interp, 585 "Usage: viSwitchScreen cur_screenId new_screenId", 586 TCL_STATIC); 587 return (TCL_ERROR); 588 } 589 590 if (getscreenid(interp, &sp, argv[1], NULL)) 591 return (TCL_ERROR); 592 if (getscreenid(interp, &new, argv[2], NULL)) 593 return (TCL_ERROR); 594 INITMESSAGE(sp); 595 rval = api_swscreen(sp, new); 596 ENDMESSAGE(sp); 597 598 return (rval ? TCL_ERROR : TCL_OK); 599} 600 601/* 602 * tcl_map -- 603 * Associate a key with a tcl procedure. 604 * 605 * Tcl Command: viMapKey 606 * Usage: viMapKey screenId key tclproc 607 */ 608static int 609tcl_map(clientData, interp, argc, argv) 610 ClientData clientData; 611 Tcl_Interp *interp; 612 int argc; 613 char **argv; 614{ 615 SCR *sp; 616 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t)); 617 int rval; 618 char command[256]; 619 620 if (argc != 4) { 621 Tcl_SetResult(interp, 622 "Usage: viMapKey screenId key tclproc", TCL_STATIC); 623 return (TCL_ERROR); 624 } 625 626 if (getscreenid(interp, &sp, argv[1], NULL)) 627 return (TCL_ERROR); 628 INITMESSAGE(sp); 629 (void)snprintf(command, sizeof(command), ":tcl %s\n", argv[3]); 630 rval = api_map(sp, argv[2], command, strlen(command)); 631 ENDMESSAGE(sp); 632 633 return (rval ? TCL_ERROR : TCL_OK); 634} 635 636/* 637 * tcl_unmap -- 638 * Unmap a key. 639 * 640 * Tcl Command: viUnmapKey 641 * Usage: viUnmMapKey screenId key 642 */ 643static int 644tcl_unmap(clientData, interp, argc, argv) 645 ClientData clientData; 646 Tcl_Interp *interp; 647 int argc; 648 char **argv; 649{ 650 SCR *sp; 651 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t)); 652 int rval; 653 654 if (argc != 3) { 655 Tcl_SetResult(interp, 656 "Usage: viUnmapKey screenId key", TCL_STATIC); 657 return (TCL_ERROR); 658 } 659 660 if (getscreenid(interp, &sp, argv[1], NULL)) 661 return (TCL_ERROR); 662 INITMESSAGE(sp); 663 rval = api_unmap(sp, argv[2]); 664 ENDMESSAGE(sp); 665 666 return (rval ? TCL_ERROR : TCL_OK); 667} 668 669/* 670 * tcl_opts_set -- 671 * Set an option. 672 * 673 * Tcl Command: viSetOpt 674 * Usage: viSetOpt screenId command 675 */ 676static int 677tcl_opts_set(clientData, interp, argc, argv) 678 ClientData clientData; 679 Tcl_Interp *interp; 680 int argc; 681 char **argv; 682{ 683 SCR *sp; 684 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t)); 685 int rval; 686 char *setting; 687 688 if (argc != 3) { 689 Tcl_SetResult(interp, 690 "Usage: viSetOpt screenId command", TCL_STATIC); 691 return (TCL_ERROR); 692 } 693 694 if (getscreenid(interp, &sp, argv[1], NULL)) 695 return (TCL_ERROR); 696 INITMESSAGE(sp); 697 /*rval = api_opts_set(sp, argv[2]);*/ 698 MALLOC(sp, setting, char *, strlen(argv[2])+6); 699 strcpy(setting, ":set "); 700 strcpy(setting+5, argv[2]); 701 rval=api_run_str(sp, setting); 702 free(setting); 703 ENDMESSAGE(sp); 704 705 return (rval ? TCL_ERROR : TCL_OK); 706} 707 708/* 709 * tcl_opts_get -- 710 Return the value of an option. 711 * 712 * Tcl Command: viGetOpt 713 * Usage: viGetOpt screenId option 714 */ 715static int 716tcl_opts_get(clientData, interp, argc, argv) 717 ClientData clientData; 718 Tcl_Interp *interp; 719 int argc; 720 char **argv; 721{ 722 SCR *sp; 723 void (*scr_msg) __P((SCR *, mtype_t, char *, size_t)); 724 int rval; 725 char *value; 726 727 if (argc != 3) { 728 Tcl_SetResult(interp, 729 "Usage: viGetOpt screenId option", TCL_STATIC); 730 return (TCL_ERROR); 731 } 732 733 if (getscreenid(interp, &sp, argv[1], NULL)) 734 return (TCL_ERROR); 735 INITMESSAGE(sp); 736 rval = api_opts_get(sp, argv[2], &value, NULL); 737 ENDMESSAGE(sp); 738 if (rval) 739 return (TCL_ERROR); 740 741 Tcl_SetResult(interp, value, TCL_DYNAMIC); 742 return (TCL_OK); 743} 744 745/* 746 * tcl_init -- 747 * Create the TCL commands used by nvi. 748 * 749 * PUBLIC: int tcl_init __P((GS *)); 750 */ 751int 752tcl_init(gp) 753 GS *gp; 754{ 755 gp->tcl_interp = Tcl_CreateInterp(); 756 if (Tcl_Init(gp->tcl_interp) == TCL_ERROR) 757 return (1); 758 759#define TCC(name, function) { \ 760 Tcl_CreateCommand(gp->tcl_interp, name, function, \ 761 (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); \ 762} 763 TCC("viAppendLine", tcl_aline); 764 TCC("viDelLine", tcl_dline); 765 TCC("viEndScreen", tcl_escreen); 766 TCC("viFindScreen", tcl_fscreen); 767 TCC("viGetCursor", tcl_getcursor); 768 TCC("viGetLine", tcl_gline); 769 TCC("viGetMark", tcl_getmark); 770 TCC("viGetOpt", tcl_opts_get); 771 TCC("viInsertLine", tcl_iline); 772 TCC("viLastLine", tcl_lline); 773 TCC("viMapKey", tcl_map); 774 TCC("viMsg", tcl_msg); 775 TCC("viNewScreen", tcl_iscreen); 776 TCC("viSetCursor", tcl_setcursor); 777 TCC("viSetLine", tcl_sline); 778 TCC("viSetMark", tcl_setmark); 779 TCC("viSetOpt", tcl_opts_set); 780 TCC("viSwitchScreen", tcl_swscreen); 781 TCC("viUnmapKey", tcl_unmap); 782 783 return (0); 784} 785 786/* 787 * getscreenid -- 788 * Get the specified screen pointer. 789 * 790 * XXX 791 * This is fatal. We can't post a message into vi that we're unable to find 792 * the screen without first finding the screen... So, this must be the first 793 * thing a Tcl routine does, and, if it fails, the last as well. 794 */ 795static int 796getscreenid(interp, spp, id, name) 797 Tcl_Interp *interp; 798 SCR **spp; 799 char *id, *name; 800{ 801 int scr_no; 802 char buf[64]; 803 804 if (id != NULL && getint(interp, "screen id", id, &scr_no)) 805 return (1); 806 if ((*spp = api_fscreen(scr_no, name)) == NULL) { 807 (void)snprintf(buf, sizeof(buf), 808 "unknown screen id: %s", name == NULL ? id : name); 809 Tcl_SetResult(interp, buf, TCL_VOLATILE); 810 return (1); 811 } 812 return (0); 813} 814 815/* 816 * getint -- 817 * Get a Tcl integer. 818 * 819 * XXX 820 * This code assumes that both db_recno_t and size_t are larger than ints. 821 */ 822static int 823getint(interp, msg, s, intp) 824 Tcl_Interp *interp; 825 char *msg, *s; 826 int *intp; 827{ 828 char buf[64]; 829 830 if (Tcl_GetInt(interp, s, intp) == TCL_ERROR) 831 return (1); 832 if (*intp < 0) { 833 (void)snprintf(buf, sizeof(buf), 834 "illegal %s %s: may not be negative", msg, s); 835 Tcl_SetResult(interp, buf, TCL_VOLATILE); 836 return (1); 837 } 838 return (0); 839} 840 841/* 842 * msghandler -- 843 * Tcl message routine so that error messages are processed in 844 * Tcl, not in nvi. 845 */ 846static void 847msghandler(sp, mtype, msg, len) 848 SCR *sp; 849 mtype_t mtype; 850 char *msg; 851 size_t len; 852{ 853 /* Replace the trailing <newline> with an EOS. */ 854 msg[len - 1] = '\0'; 855 856 Tcl_SetResult(sp->gp->tcl_interp, msg, TCL_VOLATILE); 857} 858