ChipMaster's bwBASIC This also includes history going back to v2.10. *WARN* some binary files might have been corrupted by CRLF.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

817 lines
18 KiB

  1. /***************************************************************
  2. bwx_ncu.c Environment-dependent implementation
  3. of Bywater BASIC Interpreter
  4. for Linux (and others?) using Ncurses
  5. library,
  6. This BWBASIC file hacked together by L.C. Benschop,
  7. Eindhoven, The Netherlands. 1997/01/14 and
  8. 1997/01/15 derived from the iqc version.
  9. (benschop@eb.ele.tue.nl)
  10. All the shell commands (like FILES) interact badly
  11. with curses. I should replace them with popen/addch
  12. Copyright (c) 1993, Ted A. Campbell
  13. Bywater Software
  14. email: tcamp@delphi.com
  15. Copyright and Permissions Information:
  16. All U.S. and international rights are claimed by the author,
  17. Ted A. Campbell.
  18. This software is released under the terms of the GNU General
  19. Public License (GPL), which is distributed with this software
  20. in the file "COPYING". The GPL specifies the terms under
  21. which users may copy and use the software in this distribution.
  22. A separate license is available for commercial distribution,
  23. for information on which you should contact the author.
  24. ***************************************************************/
  25. /*---------------------------------------------------------------*/
  26. /* NOTE: Modifications marked "JBV" were made by Jon B. Volkoff, */
  27. /* 11/1995 (eidetics@cerf.net). */
  28. /* */
  29. /* Those additionally marked with "DD" were at the suggestion of */
  30. /* Dale DePriest (daled@cadence.com). */
  31. /*---------------------------------------------------------------*/
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <curses.h> /* Should be the ncurses version */
  35. #include <setjmp.h>
  36. #include <signal.h>
  37. #undef TRUE
  38. #undef FALSE
  39. /* So curses TRUE and FALSE conflict with the ones defined by bwbasic.
  40. Doesn't this suck big time?
  41. */
  42. #include "bwbasic.h"
  43. #include "bwb_mes.h"
  44. extern int prn_col;
  45. extern jmp_buf mark;
  46. short oldfgd;
  47. long oldbgd;
  48. int reset_mode = FALSE;
  49. static int ncu_setpos( void );
  50. /***************************************************************
  51. FUNCTION: main()
  52. DESCRIPTION: As in any C program, main() is the basic
  53. function from which the rest of the
  54. program is called. Some environments,
  55. however, provide their own main() functions
  56. (Microsoft Windows (tm) is an example).
  57. In these cases, the following code will
  58. have to be included in the initialization
  59. function that is called by the environment.
  60. ***************************************************************/
  61. static int col_arr[]={COLOR_BLACK,COLOR_RED,COLOR_GREEN,COLOR_YELLOW,
  62. COLOR_BLUE,COLOR_MAGENTA,COLOR_CYAN,COLOR_WHITE};
  63. int /* Nobody shall declare main() as void!!!!! (L.C. Benschop)*/
  64. main( int argc, char **argv )
  65. {
  66. int i,j;
  67. initscr();
  68. start_color();
  69. if(has_colors()) {
  70. /* so there are 63 color pairs, from 1 to 63. Just 1 too few for
  71. all the foreground/background combinations. */
  72. for(i=0;i<8;i++)
  73. for(j=0;j<8;j++)
  74. if(i||j) init_pair(i*8+j,col_arr[i],col_arr[j]);
  75. }
  76. cbreak();
  77. nonl();
  78. noecho();
  79. scrollok(stdscr,1);
  80. bwb_init( argc, argv );
  81. #if INTERACTIVE
  82. setjmp( mark );
  83. #endif
  84. while( !feof( stdin ) ) /* condition !feof( stdin ) added in v1.11 */
  85. {
  86. bwb_mainloop();
  87. }
  88. return (0);
  89. }
  90. /***************************************************************
  91. FUNCTION: bwx_signon()
  92. DESCRIPTION:
  93. ***************************************************************/
  94. int
  95. bwx_signon( void )
  96. {
  97. sprintf( bwb_ebuf, "\r%s %s\n", MES_SIGNON, VERSION );
  98. prn_xprintf( stdout, bwb_ebuf );
  99. sprintf( bwb_ebuf, "\r%s\n", MES_COPYRIGHT );
  100. prn_xprintf( stdout, bwb_ebuf );
  101. sprintf( bwb_ebuf, "\r%s\n", MES_COPYRIGHT_2 ); /* JBV 1/97 */
  102. prn_xprintf( stdout, bwb_ebuf );
  103. #if PERMANENT_DEBUG
  104. sprintf( bwb_ebuf, "\r%s\n", "Debugging Mode" );
  105. prn_xprintf( stdout, bwb_ebuf );
  106. #else
  107. sprintf( bwb_ebuf, "\r%s\n", MES_LANGUAGE );
  108. prn_xprintf( stdout, bwb_ebuf );
  109. #endif
  110. return TRUE;
  111. }
  112. /***************************************************************
  113. FUNCTION: bwx_message()
  114. DESCRIPTION:
  115. ***************************************************************/
  116. int
  117. bwx_message( char *m )
  118. {
  119. #if DEBUG
  120. addstr( "<MES>" );
  121. #endif
  122. addstr( m );
  123. refresh();
  124. return TRUE;
  125. }
  126. /***************************************************************
  127. FUNCTION: bwx_putc()
  128. DESCRIPTION:
  129. ***************************************************************/
  130. extern int
  131. bwx_putc( char c )
  132. {
  133. addch(c);
  134. refresh();
  135. }
  136. /***************************************************************
  137. FUNCTION: bwx_error()
  138. DESCRIPTION:
  139. ***************************************************************/
  140. int
  141. bwx_errmes( char *m )
  142. {
  143. static char tbuf[ MAXSTRINGSIZE + 1 ]; /* this memory should be
  144. permanent in case of memory
  145. overrun errors */
  146. if (( prn_col != 1 ) && ( errfdevice == stderr ))
  147. {
  148. prn_xprintf( errfdevice, "\n" );
  149. }
  150. if ( CURTASK number == 0 )
  151. {
  152. sprintf( tbuf, "\n%s: %s\n", ERRD_HEADER, m );
  153. }
  154. else
  155. {
  156. sprintf( tbuf, "\n%s %d: %s\n", ERROR_HEADER, CURTASK number, m );
  157. }
  158. #if INTENSIVE_DEBUG
  159. prn_xprintf( stderr, "<ERR>" );
  160. #endif
  161. prn_xprintf( errfdevice, tbuf );
  162. return TRUE;
  163. }
  164. /***************************************************************
  165. FUNCTION: bwx_input()
  166. DESCRIPTION: (w)get(n)str seems to interact badly with last line
  167. on screen condition and scrolling.
  168. ***************************************************************/
  169. int
  170. bwx_input( char *prompt, char *buffer )
  171. {
  172. int y,x,my,mx;
  173. #if INTENSIVE_DEBUG
  174. prn_xprintf( stdout, "<INP>" );
  175. #endif
  176. prn_xprintf( stdout, prompt );
  177. getyx(stdscr,y,x);
  178. echo();
  179. wgetnstr(stdscr, buffer, MAXREADLINESIZE);
  180. noecho();
  181. getmaxyx(stdscr,my,mx);
  182. /* printf("%d %d",my,mx);*/
  183. if(y+1==my)scroll(stdscr);
  184. /* So this is an extreeeeemely ugly kludge to work around some
  185. bug/feature/wart in ncurses FIXME
  186. I should replace it with getch/addch in a loop */
  187. /* prn_xprintf( stdout, "\n" );*/ /* let _outtext catch up */
  188. * prn_getcol( stdout ) = 1; /* reset column */
  189. return TRUE;
  190. }
  191. /***************************************************************
  192. FUNCTION: bwx_terminate()
  193. DESCRIPTION:
  194. ***************************************************************/
  195. void
  196. bwx_terminate( void )
  197. {
  198. nodelay(stdscr,FALSE);
  199. echo();
  200. nl();
  201. nocbreak();
  202. endwin();
  203. exit( 0 );
  204. }
  205. /***************************************************************
  206. FUNCTION: bwx_shell()
  207. DESCRIPTION:
  208. ***************************************************************/
  209. #if COMMAND_SHELL
  210. extern int
  211. bwx_shell( struct bwb_line *l )
  212. {
  213. static char *s_buffer;
  214. static int init = FALSE;
  215. static int position;
  216. /* get memory for temporary buffer if necessary */
  217. if ( init == FALSE )
  218. {
  219. init = TRUE;
  220. /* Revised to CALLOC pass-thru call by JBV */
  221. if ( ( s_buffer = CALLOC( MAXSTRINGSIZE + 1, sizeof( char ),"bwx_shell" )) == NULL )
  222. {
  223. bwb_error( err_getmem );
  224. return FALSE;
  225. }
  226. }
  227. /* get the first element and check for a line number */
  228. #if INTENSIVE_DEBUG
  229. sprintf( bwb_ebuf, "in bwx_shell(): line buffer is <%s>.", l->buffer );
  230. bwb_debug( bwb_ebuf );
  231. #endif
  232. position = 0;
  233. adv_element( l->buffer, &position, s_buffer );
  234. if ( is_numconst( s_buffer ) != TRUE ) /* not a line number */
  235. {
  236. #if INTENSIVE_DEBUG
  237. sprintf( bwb_ebuf, "in bwx_shell(): no line number, command <%s>.",
  238. l->buffer );
  239. bwb_debug( bwb_ebuf );
  240. #endif
  241. nl();
  242. endwin(); /* Added by JBV 10/11/97 */
  243. if ( system( l->buffer ) == 0 )
  244. {
  245. refresh(); /* Added by JBV 10/11/97 */
  246. nonl();
  247. ncu_setpos();
  248. return TRUE;
  249. }
  250. else
  251. {
  252. refresh(); /* Added by JBV 10/11/97 */
  253. nonl();
  254. ncu_setpos();
  255. return FALSE;
  256. }
  257. }
  258. else /* advance past line number */
  259. {
  260. adv_ws( l->buffer, &position ); /* advance past whitespace */
  261. #if INTENSIVE_DEBUG
  262. sprintf( bwb_ebuf, "in bwx_shell(): line number, command <%s>.",
  263. l->buffer );
  264. bwb_debug( bwb_ebuf );
  265. #endif
  266. nl();
  267. endwin(); /* Added by JBV 10/11/97 */
  268. if ( system( &( l->buffer[ position ] ) ) == 0 )
  269. {
  270. refresh(); /* Added by JBV 10/11/97 */
  271. nonl();
  272. ncu_setpos();
  273. return TRUE;
  274. }
  275. else
  276. {
  277. refresh(); /* Added by JBV 10/11/97 */
  278. nonl();
  279. ncu_setpos();
  280. return FALSE;
  281. }
  282. }
  283. }
  284. #endif
  285. /***************************************************************
  286. FUNCTION: ncu_setpos()
  287. DESCRIPTION:
  288. ***************************************************************/
  289. static int
  290. ncu_setpos( void )
  291. {
  292. int x,y;
  293. getyx(stdscr,y,x);
  294. move(y,x);
  295. /* and move down one position */
  296. prn_xprintf( stdout, "\n" );
  297. return TRUE;
  298. }
  299. #if COMMON_CMDS
  300. /***************************************************************
  301. FUNCTION: bwb_edit()
  302. DESCRIPTION:
  303. ***************************************************************/
  304. struct bwb_line *
  305. bwb_edit( struct bwb_line *l )
  306. {
  307. char tbuf[ MAXSTRINGSIZE + 1 ];
  308. char edname[ MAXSTRINGSIZE + 1 ];
  309. struct bwb_variable *ed;
  310. FILE *loadfile;
  311. ed = var_find( DEFVNAME_EDITOR );
  312. str_btoc( edname, var_getsval( ed ));
  313. sprintf( tbuf, "%s %s", edname, CURTASK progfile );
  314. #if INTENSIVE_DEBUG
  315. sprintf( bwb_ebuf, "in bwb_edit(): command line <%s>", tbuf );
  316. bwb_debug( bwb_ebuf );
  317. #else
  318. nl();
  319. endwin(); /* Added by JBV 10/11/97 */
  320. system( tbuf );
  321. /*-----------------------*/
  322. /* Added by JBV 10/11/97 */
  323. /*-----------------------*/
  324. fprintf( stderr, "Press RETURN when ready..." );
  325. fgets( tbuf, MAXREADLINESIZE, stdin );
  326. refresh();
  327. nonl();
  328. #endif
  329. /* open edited file for read */
  330. if ( ( loadfile = fopen( CURTASK progfile, "r" )) == NULL )
  331. {
  332. sprintf( bwb_ebuf, err_openfile, CURTASK progfile );
  333. bwb_error( bwb_ebuf );
  334. ncu_setpos();
  335. return bwb_zline( l );
  336. }
  337. /* clear current contents */
  338. bwb_new( l ); /* Relocated by JBV (bug found by DD) */
  339. /* and (re)load the file into memory */
  340. bwb_fload( loadfile );
  341. ncu_setpos();
  342. return bwb_zline( l );
  343. }
  344. /***************************************************************
  345. FUNCTION: bwb_renum()
  346. DESCRIPTION: This function implements the BASIC RENUM
  347. command by shelling out to a default
  348. renumbering program called "renum".
  349. Added by JBV 10/95
  350. SYNTAX: RENUM
  351. ***************************************************************/
  352. #if ANSI_C
  353. struct bwb_line *
  354. bwb_renum( struct bwb_line *l )
  355. #else
  356. struct bwb_line *
  357. bwb_renum( l )
  358. struct bwb_line *l;
  359. #endif
  360. {
  361. char tbuf[ MAXSTRINGSIZE + 1 ];
  362. FILE *loadfile;
  363. sprintf( tbuf, "renum %s\0", CURTASK progfile );
  364. #if INTENSIVE_DEBUG
  365. sprintf( bwb_ebuf, "in bwb_renum(): command line <%s>", tbuf );
  366. bwb_debug( bwb_ebuf );
  367. #else
  368. nl();
  369. endwin(); /* Added by JBV 10/11/97 */
  370. system( tbuf );
  371. /*-----------------------*/
  372. /* Added by JBV 10/11/97 */
  373. /*-----------------------*/
  374. fprintf( stderr, "Press RETURN when ready..." );
  375. fgets( tbuf, MAXREADLINESIZE, stdin );
  376. refresh();
  377. nonl();
  378. #endif
  379. /* open edited file for read */
  380. if ( ( loadfile = fopen( CURTASK progfile, "r" )) == NULL )
  381. {
  382. sprintf( bwb_ebuf, err_openfile, CURTASK progfile );
  383. bwb_error( bwb_ebuf );
  384. ncu_setpos();
  385. return bwb_zline( l );
  386. }
  387. /* clear current contents */
  388. bwb_new( l ); /* Relocated by JBV (bug found by DD) */
  389. /* and (re)load the file into memory */
  390. bwb_fload( loadfile );
  391. ncu_setpos();
  392. return bwb_zline( l );
  393. }
  394. /***************************************************************
  395. FUNCTION: bwb_files()
  396. DESCRIPTION:
  397. ***************************************************************/
  398. struct bwb_line *
  399. bwb_files( struct bwb_line *l )
  400. {
  401. char tbuf[ MAXVARNAMESIZE + 1 ];
  402. char finame[ MAXVARNAMESIZE + 1 ];
  403. char argument[ MAXVARNAMESIZE + 1 ];
  404. struct bwb_variable *fi;
  405. struct exp_ese *e;
  406. fi = var_find( DEFVNAME_FILES );
  407. str_btoc( finame, var_getsval( fi ));
  408. /* get argument */
  409. adv_ws( l->buffer, &( l->position ));
  410. switch( l->buffer[ l->position ] )
  411. {
  412. case '\0':
  413. case '\r':
  414. case '\n':
  415. argument[ 0 ] = '\0';
  416. break;
  417. default:
  418. e = bwb_exp( l->buffer, FALSE, &( l->position ) );
  419. if ( e->type != STRING )
  420. {
  421. bwb_error( err_mismatch );
  422. return bwb_zline( l );
  423. }
  424. str_btoc( argument, exp_getsval( e ) );
  425. break;
  426. }
  427. sprintf( tbuf, "%s %s", finame, argument );
  428. #if INTENSIVE_DEBUG
  429. sprintf( bwb_ebuf, "in bwb_files(): command line <%s>", tbuf );
  430. bwb_debug( bwb_ebuf );
  431. #else
  432. nl();
  433. endwin(); /* Added by JBV 10/11/97 */
  434. system( tbuf );
  435. /*-----------------------*/
  436. /* Added by JBV 10/11/97 */
  437. /*-----------------------*/
  438. fprintf( stderr, "Press RETURN when ready..." );
  439. fgets( tbuf, MAXREADLINESIZE, stdin );
  440. refresh();
  441. nonl();
  442. #endif
  443. ncu_setpos();
  444. return bwb_zline( l );
  445. }
  446. #endif /* COMMON_CMDS */
  447. #if INTERACTIVE
  448. /***************************************************************
  449. FUNCTION: fnc_inkey()
  450. DESCRIPTION: This C function implements the BASIC INKEY$
  451. function. It is implementation-specific.
  452. ***************************************************************/
  453. extern struct bwb_variable *
  454. fnc_inkey( int argc, struct bwb_variable *argv,int unique)
  455. {
  456. static struct bwb_variable nvar;
  457. char tbuf[ MAXSTRINGSIZE + 1 ];
  458. static int init = FALSE;
  459. int c;
  460. /* initialize the variable if necessary */
  461. if ( init == FALSE )
  462. {
  463. init = TRUE;
  464. var_make( &nvar, STRING);
  465. }
  466. /* check arguments */
  467. #if PROG_ERRORS
  468. if ( argc > 0 )
  469. {
  470. sprintf( bwb_ebuf, "Two many arguments to function INKEY$()" );
  471. bwb_error( bwb_ebuf );
  472. return &nvar;
  473. }
  474. #else
  475. if ( fnc_checkargs( argc, argv, 0, 0 ) == FALSE )
  476. {
  477. return NULL;
  478. }
  479. #endif
  480. /* body of the INKEY$ function */
  481. nodelay(stdscr,1);
  482. if ( (c=getch())==EOF )
  483. {
  484. tbuf[ 0 ] = '\0';
  485. }
  486. else
  487. {
  488. tbuf[ 0 ] = (char) c;
  489. tbuf[ 1 ] = '\0';
  490. }
  491. nodelay(stdscr,0);
  492. /* assign value to nvar variable */
  493. str_ctob( var_findsval( &nvar, nvar.array_pos ), tbuf );
  494. /* return value contained in nvar */
  495. return &nvar;
  496. }
  497. #endif /* INTERACTIVE */
  498. #if MS_CMDS
  499. /***************************************************************
  500. FUNCTION: bwb_cls()
  501. DESCRIPTION: This C function implements the BASIC CLS
  502. command. It is implementation-specific.
  503. ***************************************************************/
  504. extern struct bwb_line *
  505. bwb_cls( struct bwb_line *l )
  506. {
  507. clear();
  508. refresh();
  509. return bwb_zline( l );
  510. }
  511. /***************************************************************
  512. FUNCTION: bwb_locate()
  513. DESCRIPTION: This C function implements the BASIC LOCATE
  514. command. It is implementation-specific.
  515. ***************************************************************/
  516. extern struct bwb_line *
  517. bwb_locate( struct bwb_line *l )
  518. {
  519. struct exp_ese *e;
  520. int row, column;
  521. /* get first argument */
  522. e = bwb_exp( l->buffer, FALSE, &( l->position ));
  523. row = (int) exp_getnval( e );
  524. /* advance past comma */
  525. adv_ws( l->buffer, &( l->position ));
  526. if ( l->buffer[ l->position ] != ',' )
  527. {
  528. bwb_error( err_syntax );
  529. return bwb_zline( l );
  530. }
  531. ++( l->position );
  532. /* get second argument */
  533. e = bwb_exp( l->buffer, FALSE, &( l->position ));
  534. column = (int) exp_getnval( e );
  535. /* position the cursor */
  536. move( row-1, column-1 );
  537. return bwb_zline( l );
  538. }
  539. /***************************************************************
  540. FUNCTION: bwb_color()
  541. DESCRIPTION: This C function implements the BASIC COLOR
  542. command. It is implementation-specific.
  543. ***************************************************************/
  544. extern struct bwb_line *
  545. bwb_color( struct bwb_line *l )
  546. {
  547. struct exp_ese *e;
  548. int fgcolor,bgcolor;
  549. /* get first argument */
  550. e = bwb_exp( l->buffer, FALSE, &( l->position ));
  551. fgcolor = (int) exp_getnval( e );
  552. #if INTENSIVE_DEBUG
  553. sprintf( bwb_ebuf, "Setting text color to %d", fgcolor );
  554. bwb_debug( bwb_ebuf );
  555. #endif
  556. #if INTENSIVE_DEBUG
  557. sprintf( bwb_ebuf, "Set text color to %d", fgcolor );
  558. bwb_debug( bwb_ebuf );
  559. #endif
  560. /* advance past comma */
  561. adv_ws( l->buffer, &( l->position ));
  562. if ( l->buffer[ l->position ] == ',' )
  563. {
  564. ++( l->position );
  565. /* get second argument */
  566. e = bwb_exp( l->buffer, FALSE, &( l->position ));
  567. bgcolor = (int) exp_getnval( e );
  568. #if INTENSIVE_DEBUG
  569. sprintf( bwb_ebuf, "Setting background color to %d", bgcolor );
  570. bwb_debug( bwb_ebuf );
  571. #endif
  572. /* set the foreground and background color */
  573. if (has_colors()) {
  574. attrset(A_NORMAL);
  575. bkgdset(COLOR_PAIR((bgcolor&7))|' ');
  576. if((fgcolor&7)==0 && (bgcolor&7)==0){
  577. /* we didn't reserve a color pair for fg and bg both black.
  578. Bright black(color 8)==dark gray as foreground color A_DIM
  579. A_INVIS doesn't seem to work. wait for next version of
  580. ncurses, don't bother for now.*/
  581. if(fgcolor<8) attrset(A_INVIS); else attrset(A_DIM);
  582. } else
  583. attrset(COLOR_PAIR((8*(fgcolor&7)+(bgcolor&7))) |
  584. ((fgcolor>7)*A_BOLD));
  585. /* fg colors 8--15 == extra brightness */
  586. } else { /* no colors, have a go at it with reverse/bold/dim */
  587. attrset(A_NORMAL);
  588. bkgdset(A_REVERSE*((fgcolor&7)<(bgcolor&7))|' ');
  589. attrset(A_BOLD*(fgcolor>8)|
  590. A_REVERSE*((fgcolor&7)<(bgcolor&7))|A_INVIS*(fgcolor==bgcolor));
  591. }
  592. #if INTENSIVE_DEBUG
  593. sprintf( bwb_ebuf, "Setting background color to %d\n", bgcolor );
  594. bwb_debug( bwb_ebuf );
  595. #endif
  596. }
  597. return bwb_zline( l );
  598. }
  599. #endif /* MS_CMDS */