1/****************************************************************/ 2/* file logscr.inc 3 4ARIBAS interpreter for Arithmetic 5Copyright (C) 1996 O.Forster 6 7This program is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 2 of the License, or 10(at your option) any later version. 11 12This program is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with this program; if not, write to the Free Software 19Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 21Address of the author 22 23 Otto Forster 24 Math. Institut der LMU 25 Theresienstr. 39 26 D-80333 Muenchen, Germany 27 28Email forster@mathematik.uni-muenchen.de 29*/ 30/****************************************************************/ 31 32/* 33** logscr.inc 34** logical screen 35** 36** date of last change 37** 1995-03-22: Bremse in L_strappend 38** 1998-01-03: cosmetic changes 39** 1998-05-31: #define-s for Win32GUI 40** 2002-02-16: L_text2blatt, L_insidecomment 41*/ 42 43#if defined(UNiXorGCC) || defined(Win32GUI) 44#define LINELEN 162 45#define BUFLINES 200 46#else 47#define LINELEN 82 48#define BUFLINES 50 49#endif 50 51 52typedef char zeile[LINELEN]; 53 54#define LOCAL static 55LOCAL zeile *Blatt = NULL; 56 57/* 58** Zeilen-Nummern beginnen bei 0 59** Die einzelnen Zeilen haben in Position 0 die Zeilenlaenge 60** Die Strings werden durch ein Null-Byte abgeschlossen 61** Es gilt also stets fuer ptr = Blatt[n], dass ptr[ptr[0]+1] = 0 62*/ 63 64LOCAL int L_iniscr _((zeile *Buf, char *prompt)); 65LOCAL int L_insert _((int n)); 66LOCAL void L_strappend _((int n, int i, char *str)); 67LOCAL int L_len _((int n)); 68LOCAL int L_pagelen _((void)); 69LOCAL int L_efflen _((void)); 70LOCAL int L_efffirst _((void)); 71LOCAL int L_indent _((int n)); 72LOCAL int L_trimlen _((int n)); 73LOCAL int L_compress _((void)); 74LOCAL int L_expand _((byte *buf)); 75LOCAL char *L_linerest _((int n, int k)); 76LOCAL char *L_line _((int n)); 77 78PRIVATE void L_nulline _((int n)); 79PRIVATE void L_linecpy _((char *z1, char *z2)); 80 81PRIVATE int L_makebstream(int lineno); 82PRIVATE int L_bnextch(void); 83PRIVATE int L_bpeekch(void); 84PRIVATE int L_bskiptoeol(void); 85PRIVATE int L_bskiptoeostr(void); 86PRIVATE int L_bstream(int mode); 87LOCAL int L_insidecomment(int lineno); 88 89#ifdef genWinGUI 90LOCAL int L_text2blatt(char *buf); 91#endif 92 93#ifdef PAGEINPUT 94LOCAL void L_clreol _((int n, int i)); 95LOCAL void L_delete _((int n)); 96LOCAL int L_spaceins _((int n, int i, int anz, int bound)); 97LOCAL int L_charins _((int n, int i, int ch, int bound)); 98LOCAL int L_chardel _((int n, int i)); 99LOCAL int L_charndel _((int n, int i, int anz)); 100LOCAL int L_nextgroup _((int n, int k)); 101LOCAL int L_prevgroup _((int n, int k)); 102LOCAL int L_nextword _((int n, int k)); 103LOCAL int L_merge _((int n, int bound)); 104LOCAL int L_retbreak _((int n, int k)); 105#endif 106 107LOCAL int Col0; /* in der 0-ten Zeile nach Prompt */ 108PRIVATE int Actlen = 0; 109/*--------------------------------------------------------------------*/ 110LOCAL int L_iniscr(Buf,prompt) 111zeile *Buf; 112char *prompt; 113{ 114 int n; 115 int ch; 116 char *ptr; 117 118 Blatt = Buf; 119 Actlen = 1; 120 ptr = Blatt[0]; 121 n = 0; 122 while((ch = *prompt++)) { 123 n++; 124 ptr[n] = ch; 125 } 126 ptr[n+1] = 0; 127 ptr[0] = n; 128 Col0 = n+1; 129 for(n=1; n<BUFLINES; n++) 130 L_nulline(n); 131 return(Col0); 132} 133/*-------------------------------------------------------------------*/ 134PRIVATE void L_nulline(n) 135int n; 136{ 137 char *ptr; 138 139 ptr = Blatt[n]; 140 *ptr++ = 0; 141 *ptr = 0; 142} 143/*-------------------------------------------------------------------*/ 144/* 145** Fuegt in Blatt eine neue leere n-te Zeile ein; 146** alle folgenden Zeilen werden um eins nach unten verschoben 147** Es wird vorausgesetzt, dass n <= Actlen < BUFLINES 148*/ 149LOCAL int L_insert(n) 150int n; 151{ 152 int i; 153 154 if(Actlen >= BUFLINES) 155 return(0); 156 for(i=Actlen; i>n; i--) 157 L_linecpy(Blatt[i],Blatt[i-1]); 158 L_nulline(n); 159 Actlen++; 160 return(1); 161} 162/*-------------------------------------------------------------------*/ 163PRIVATE void L_linecpy(z1,z2) 164char *z1, *z2; 165{ 166 *z1++ = *z2++; 167 strcpy(z1,z2); 168} 169/*-------------------------------------------------------------------*/ 170/* 171** Schreibt in Zeile n ab Position i den String str; 172** Es wird vorausgesetzt, dass n < Actlen und 1 <= i < LINELEN-1 173** Falls str zu lang ist, wird abgeschnitten 174*/ 175LOCAL void L_strappend(n,i,str) 176int n,i; 177char *str; 178{ 179 char *ptr, *ptr0; 180 181 ptr0 = Blatt[n]; 182 ptr = ptr0 + i; 183 while((*ptr++ = *str++) && (i < LINELEN-1)) 184 i++; 185 ptr0[i] = 0; 186 ptr0[0] = i - 1; 187} 188/*-------------------------------------------------------------------*/ 189/* 190** Laenge der n-ten Zeile 191*/ 192LOCAL int L_len(n) 193int n; 194{ 195 return(Blatt[n][0]); 196} 197/*-------------------------------------------------------------------*/ 198LOCAL int L_pagelen() 199{ 200 return(Actlen); 201} 202/*-------------------------------------------------------------------*/ 203/* 204** effektive Laenge; leere Zeilen am Ende zaehlen nicht 205*/ 206LOCAL int L_efflen() 207{ 208 int n; 209 210 n = Actlen; 211 while(n > 1 && Blatt[n-1][0] == 0) 212 n--; 213 return(n); 214} 215/*-------------------------------------------------------------------*/ 216/* 217** effektive erste Zeile 218*/ 219LOCAL int L_efffirst() 220{ 221 int i; 222 223 if(Blatt[0][0] > Col0) 224 return(0); 225 for(i=1; i<Actlen; i++) { 226 if(Blatt[i][0] != 0) 227 return(i); 228 } 229 return(0); 230} 231/*-------------------------------------------------------------------*/ 232/* 233** Anzahl der Spaces am Anfang von Zeile n 234*/ 235LOCAL int L_indent(n) 236int n; 237{ 238 char *ptr; 239 int k; 240 241 if(n >= Actlen) 242 return(0); 243 ptr = Blatt[n]; 244 k = (n > 0 ? 1 : Col0); 245 while(ptr[k] == ' ') 246 k++; 247 return(k-1); 248} 249/*-------------------------------------------------------------------*/ 250/* 251** Laenge der Zeile n ohne Leerzeichen am Ende 252*/ 253LOCAL int L_trimlen(n) 254int n; 255{ 256 int k, k0; 257 char *ptr; 258 259 if(n >= Actlen) 260 return(0); 261 ptr = Blatt[n]; 262 k = ptr[0]; 263 k0 = (n > 0 ? 1 : Col0); 264 while(k >= k0 && ptr[k] == ' ') 265 k--; 266 return(k); 267} 268/*-------------------------------------------------------------------*/ 269/* 270** Komprimiert den Text in Blatt durch Ersetzen von Leerzeichen 271** am Anfang der Zeile durch verallgemeinerte TAB's. 272** Der entstehende String wird in den Puffer Blatt geschrieben. 273** Rueckgabewert: Laenge des entstehenden Strings 274*/ 275LOCAL int L_compress() 276{ 277 char *ptr1, *str; 278 int i, k, len, n; 279 280 n = L_efflen(); 281 ptr1 = Blatt[0]; 282 for(i=0; i<n; i++) { 283 k = L_indent(i); 284 len = L_trimlen(i) - k; 285 str = L_linerest(i,k+1); 286 if(k < TABESC-1) { 287 *ptr1++ = k+1; 288 } 289 else { 290 *ptr1++ = TABESC; 291 *ptr1++ = k; 292 } 293 while(--len >= 0) 294 *ptr1++ = *str++; 295 } 296 *ptr1 = 0; 297 return(ptr1 - Blatt[0]); 298} 299/*-------------------------------------------------------------------*/ 300/* 301** Umkehrung von L_compress 302** Der komprimierte String steht in buf; das Ergebnis in Blatt 303** Rueckgabewert: Laenge in Zeilen; 304*/ 305LOCAL int L_expand(buf) 306byte *buf; 307{ 308 int i, k, n; 309 int ch; 310 char *ptr; 311 312 for(n=0, ch=*buf++; ch && n<BUFLINES; n++) { 313 if(ch < TABESC) 314 k = ch - 1; 315 else 316 k = *buf++; 317 ptr = Blatt[n]; 318 i = (n > 0 ? 1 : Col0); 319 while(i <= k) 320 ptr[i++] = ' '; 321 while((ch = *buf++) > TABESC) 322 ptr[i++] = ch; 323 ptr[i] = 0; 324 ptr[0] = i-1; 325 } 326 Actlen = n; 327 return(n); 328} 329/*-------------------------------------------------------------------*/ 330LOCAL char *L_linerest(n,k) 331int n, k; 332{ 333 char *ptr; 334 335 ptr = Blatt[n]; 336 if(k > ptr[0]) 337 k = ptr[0] + 1; 338 return(ptr + k); 339} 340/*-------------------------------------------------------------------*/ 341LOCAL char *L_line(n) 342int n; 343{ 344 char *ptr; 345 346 ptr = Blatt[n]; 347 return(ptr + 1); 348} 349/*-------------------------------------------------------------------*/ 350#ifdef genWinGUI 351/*-------------------------------------------------------------------*/ 352/* 353** copies text from buffer buf to Blatt 354** return value: actual length of Blatt 355** or -1 if text is too long 356*/ 357LOCAL int L_text2blatt(buf) 358char *buf; 359{ 360 int i, n; 361 int ch; 362 char *ptr; 363 364 for(n=0, ch=*buf++; ch && n<BUFLINES; n++) { 365 ptr = Blatt[n]; 366 i = (n > 0 ? 1 : Col0); 367 while(ch && ch != '\n' && i<LINELEN-2) { 368 ptr[i++] = ch; 369 ch = *buf++; 370 } 371 while(ch == '\n' || ch == '\r') { 372 ch = *buf++; 373 } 374 ptr[i] = 0; 375 ptr[0] = i-1; 376 } 377 Actlen = n; 378 if(ch) 379 return(-1); 380 else 381 return(n); 382} 383/*-------------------------------------------------------------------*/ 384#endif 385/*-------------------------------------------------------------------*/ 386/* 387** Tests whether line with number lineno in Blatt 388** is inside a comment 389*/ 390LOCAL int L_insidecomment(lineno) 391int lineno; 392{ 393 int insidecomm = 0; 394 int ch; 395 396 if(L_makebstream(lineno) < 0) 397 return(-1); 398 ch = 'A'; 399 while(ch != EOF) { 400 ch = L_bnextch(); 401 switch(ch) { 402 case '#': 403 if(insidecomm) 404 break; 405 L_bskiptoeol(); 406 if(L_bpeekch() == EOF) 407 return(1); 408 else 409 insidecomm = 0; 410 break; 411 case '(': 412 if(insidecomm) 413 break; 414 ch = L_bnextch(); 415 if(ch == '*') 416 insidecomm = 1; 417 break; 418 case '*': 419 if(!insidecomm) 420 break; 421 ch = L_bpeekch(); 422 if(ch == ')') { 423 insidecomm = 0; 424 L_bnextch(); 425 } 426 break; 427 case '"': 428 if(!insidecomm) 429 L_bskiptoeostr(); 430 break; 431 default: 432 break; 433 } 434 } 435 return(insidecomm); 436} 437/*-------------------------------------------------------------------*/ 438PRIVATE int L_makebstream(lineno) 439int lineno; 440{ 441 return(L_bstream(lineno)); 442} 443/*-------------------------------------------------------------------*/ 444PRIVATE int L_bnextch() 445{ 446 return L_bstream(-1); 447} 448/*-------------------------------------------------------------------*/ 449PRIVATE int L_bpeekch() 450{ 451 return L_bstream(-2); 452} 453/*-------------------------------------------------------------------*/ 454PRIVATE int L_bskiptoeol() 455{ 456 return L_bstream(-3); 457} 458/*-------------------------------------------------------------------*/ 459PRIVATE int L_bskiptoeostr() 460{ 461 return L_bstream(-4); 462} 463/*-------------------------------------------------------------------*/ 464PRIVATE int L_bstream(mode) 465int mode; 466{ 467 static int curline = 0; 468 static int curlen = 0; 469 static int lastline = 0; 470 static int col = 0; 471 int ch; 472 473 if(mode >= 0) { /* makebstream */ 474 if(Blatt == NULL) 475 return(-1); 476 lastline = mode; 477 if(lastline >= BUFLINES) 478 lastline = BUFLINES-1; 479 curline = 0; 480 curlen = Blatt[curline][0]; 481 col = 1; 482 return(lastline); 483 } 484 nochmal: 485 switch(mode) { 486 case -1: /* bnextch */ 487 if(curline > lastline) 488 return(EOF); 489 else if(col > curlen) { 490 curline++; 491 col = 1; 492 if(curline <= lastline) 493 curlen = Blatt[curline][0]; 494 else 495 curlen = 0; 496 return(EOL); 497 } 498 else { 499 ch = Blatt[curline][col]; 500 col++; 501 return(ch); 502 } 503 break; 504 case -2: /* bpeekch */ 505 if(curline > lastline) 506 return(EOF); 507 else if(col > curlen) 508 return(EOL); 509 else 510 return Blatt[curline][col]; 511 break; 512 case -3: /* skiptoeol */ 513 curline++; 514 col = 1; 515 if(curline <= lastline) 516 curlen = Blatt[curline][0]; 517 else 518 curlen = 0; 519 return(EOL); 520 break; 521 case -4: /* skip to end of string */ 522 if(col > curlen || curline > lastline) { 523 mode = -1; 524 goto nochmal; 525 } 526 while(col <= curlen) { 527 ch = Blatt[curline][col]; 528 col++; 529 if(ch == '"') 530 break; 531 } 532 break; 533 default: 534 break; 535 } 536 return(-1); 537} 538/*-------------------------------------------------------------------*/ 539/*-------------------------------------------------------------------*/ 540#ifdef PAGEINPUT 541/*-------------------------------------------------------------------*/ 542LOCAL void L_clreol(n,i) 543int n, i; 544{ 545 char *ptr; 546 547 ptr = Blatt[n]; 548 ptr[i] = 0; 549 ptr[0] = i - 1; 550} 551/*-------------------------------------------------------------------*/ 552/* 553** Loescht in Blatt die n-te Zeile; 554** alle folgenden Zeilen werden um eins nach oben verschoben 555*/ 556LOCAL void L_delete(n) 557int n; 558{ 559 int i; 560 561 if(n >= Actlen) 562 return; 563 for(i=n+1; i<Actlen; i++) 564 L_linecpy(Blatt[i-1],Blatt[i]); 565 Actlen--; 566 L_nulline(Actlen); 567} 568/*-------------------------------------------------------------------*/ 569/* 570** Fuegt in Zeile n ab Position i insgesamt n Spaces ein, falls 571** dadurch Zeilenlaenge nicht groesser als bound wird. 572** Sonst (oder falls i > Zeilenlaenge), keine Aktion, Rueckgabewert 0 573** Andernfalls Rueckgabewert anz 574*/ 575LOCAL int L_spaceins(n,i,anz,bound) 576int n,i,anz,bound; 577{ 578 char *ptr; 579 int k, len; 580 581 ptr = Blatt[n]; 582 len = ptr[0]; 583 if(n >= Actlen || i > len || len+anz > bound) 584 return(0); 585 ptr[0] = len + anz; 586 for(k=len+1; k>=i; k--) 587 ptr[k+anz] = ptr[k]; 588 for(k=0; k<anz; k++) 589 ptr[i+k] = ' '; 590 return(anz); 591} 592/*-------------------------------------------------------------------*/ 593/* 594** Fuegt in Zeile n an der Stelle i den Buchstaben ch ein, falls 595** dadurch die Zeile nicht laenger als bound wird. 596** Falls bound ueberschritten wuerde, keine Aktion und Rueckgabewert 0. 597** Sonst: Rueckgebewert neue Zeilenlaenge. 598** Falls i > Zeilenlaenge+1, werden vor ch Leerzeichen eingefuellt 599*/ 600LOCAL int L_charins(n,i,ch,bound) 601int n,i,ch,bound; 602{ 603 char *ptr; 604 int k, len; 605 606 ptr = Blatt[n]; 607 len = ptr[0]; 608 if(len >= bound) 609 return(0); 610 if(i <= len) { 611 len++; 612 for(k=len; k>=i; k--) 613 ptr[k+1] = ptr[k]; 614 ptr[i] = ch; 615 } 616 else { 617 for(k=len+1; k<i; k++) 618 ptr[k] = ' '; 619 ptr[i] = ch; 620 ptr[i+1] = 0; 621 len = i; 622 } 623 ptr[0] = len; 624 return(len); 625} 626/*-------------------------------------------------------------------*/ 627/* 628** Loescht in Zeile n den i-ten Buchstaben und zieht alle 629** folgenden um eins nach vorne 630*/ 631LOCAL int L_chardel(n,i) 632int n,i; 633{ 634 return(L_charndel(n,i,1)); 635} 636/*-------------------------------------------------------------------*/ 637/* 638** Loescht in Zeile n ab Position i insgesamt anz Buchstaben 639** und zieht die folgenden um anz nach vorne 640** Es wird vorausgesetzt, dass i >= anz ist 641** Falls i > Zeilenlaenge, werden entsprechend weniger 642** Buchstaben gestrichen. 643** Rueckgabewert: Anzahl der tatsaechlich entfernten Zeichen 644*/ 645LOCAL int L_charndel(n,i,anz) 646{ 647 char *ptr; 648 int k, len; 649 650 ptr = Blatt[n]; 651 len = ptr[0]; 652 if(i > len) 653 return(0); 654 else if(i >= len - anz + 1) { 655 ptr[i] = 0; 656 ptr[0] = i - 1; 657 return(len - i + 1); 658 } 659 else { 660 ptr[0] = len - anz; 661 for(k=i; k<=len+1-anz; k++) 662 ptr[k] = ptr[k+anz]; 663 return(anz); 664 } 665} 666/*-------------------------------------------------------------------*/ 667/* 668** Fuer Cursor-Bewegung mit CTRL-Pfeilrechts: 669** Gibt Position der naechsten Gruppe von Zeichen ohne Spaces 670*/ 671LOCAL int L_nextgroup(n,k) 672int n,k; 673{ 674 char *ptr; 675 int ch; 676 677 if(n >= Actlen) 678 return(k); 679 ptr = Blatt[n]; 680 if(k > ptr[0]) 681 return(k); 682 while((ch = ptr[k]) && ch != ' ') 683 k++; 684 while((ch = ptr[k]) && ch == ' ') 685 k++; 686 return(k); 687} 688/*-------------------------------------------------------------------*/ 689/* 690** Fuer Cursor-Bewegung mit CTRL-Pfeillinks: 691** Gibt Anfang der vorherigen Gruppe von Zeichen ohne Spaces 692*/ 693LOCAL int L_prevgroup(n,k) 694int n,k; 695{ 696 char *ptr; 697 int len; 698 int k0; 699 700 if(n >= Actlen) 701 return(k); 702 k0 = (n > 0 ? Col0 : 1); 703 704 ptr = Blatt[n]; 705 len = ptr[0]; 706 if(len == 0) 707 return(1); 708 else if(k > len) 709 k = len; 710 else if(k > k0) 711 k--; 712 while(k > k0 && ptr[k] == ' ') 713 k--; 714 while(k > k0 && ptr[k-1] != ' ') 715 k--; 716 return(k); 717} 718/*-------------------------------------------------------------------*/ 719/* 720** gibt Postion des Anfangs des naechsten Wortes fuer das 721** Kommando Wort loeschen. 722** Es wird bis zu dieser Position ausschliesslich geloescht 723** 724*/ 725LOCAL int L_nextword(n,k) 726int n,k; 727{ 728 char *ptr; 729 int ch; 730 731 if(n >= Actlen) 732 return(k); 733 ptr = Blatt[n]; 734 if(k > ptr[0]) 735 return(k); 736 ch = ptr[k]; 737 if(isdigalfa(ch)) { 738 k++; 739 while((ch = ptr[k]) && isdigalfa(ch)) 740 k++; 741 } 742 else if(ch != ' ') { 743 k++; 744 while((ch = ptr[k]) && ch != ' ' && !isdigalfa(ch)) 745 k++; 746 } 747 else { 748 k++; 749 while(ptr[k] == ' ') 750 k++; 751 } 752 return(k); 753} 754/*-------------------------------------------------------------------*/ 755/* 756** Die Zeile n wird mit der Zeile n+1 zusammengefuegt und der 757** Rest des Blattes nach oben gezogen. 758** Voraussetzung ist, dass die Summe der Zeilenlaengen 759** <= bound ist. In diesem Fall ist der Rueckgabewert die 760** Position des Anfangs der angehaengten Zeile in Zeile n. 761** Falls die Summe der Zeilenlaengen > bound ist, wird 762** das Blatt unveraendert gelassen und 0 zurueckgegeben. 763** Ausserdem wird vorausgesetzt, dass die Zeile n+1 existiert; 764** andernfalls keine Aktion und Rueckgabewert 0. 765*/ 766LOCAL int L_merge(n, bound) 767int n, bound; 768{ 769 int k; 770 char *str; 771 772 if(n >= L_pagelen() - 1) 773 return(0); 774 k = L_len(n); 775 if(k + L_len(n+1) > bound) 776 return(0); 777 else { 778 str = L_linerest(n+1,1); 779 L_strappend(n,k+1,str); 780 L_delete(n+1); 781 return(k+1); 782 } 783} 784/*-------------------------------------------------------------------*/ 785/* 786** Fuehrt einen Umbruch (wie bei Betaetigung der Return-Taste) 787** von Zeile n ab Position k in eine neuzuschaffende naechste 788** Zeile durch. 789** Falls Blatt zu lang wuerde, wird keine Aktion durchgefuehrt 790** und 0 zurueckgegeben; sonst Rueckgabewert 1. 791*/ 792LOCAL int L_retbreak(n,k) 793int n,k; 794{ 795 char *str; 796 int len; 797 798 len = L_pagelen(); 799 if(len >= BUFLINES || n >= len) 800 return(0); 801 L_insert(n+1); 802 if(k <= L_len(n)) { 803 str = L_linerest(n,k); 804 L_strappend(n+1,1,str); 805 L_clreol(n,k); 806 } 807 return(1); 808} 809/*-------------------------------------------------------------------*/ 810#endif /* PAGEINPUT */ 811#undef LOCAL 812/*********************************************************************/ 813