home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / c / c-bat-0.1n / c-bat-0 / c-bat-0.1 / src / brs_client.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-16  |  84.7 KB  |  2,643 lines

  1. /*
  2.     client  : Browsing an Analysis Tool for C-source code;
  3.           Test-Client-Application
  4.  
  5.     Copyright (C) 1993  Eckehard Stolz
  6.  
  7.     This program is free software; you can redistribute it and/or modify
  8.     it under the terms of the GNU General Public License as published by
  9.     the Free Software Foundation (version 2 of the License).
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20.  
  21.  
  22. /* This is just an example of how to use the toolkit-functions in your
  23.    own applications.
  24.  
  25.    Most of the code is purely for the "nice" output of the information
  26.    returned by these functions.
  27.  
  28.    look in the main-function first to see how to use them
  29.  */
  30.  
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include <malloc.h>
  35. #include <ncurses.h>
  36. #include <sys/stat.h>
  37. #include <unistd.h>
  38. #include <errno.h>
  39.  
  40. #include "c-bat.h"
  41. #include "clients.h"
  42.  
  43.  
  44. #define LINESIZE  256  /* maximum of 256 characters per line */
  45.  
  46. #define L_MEM_INIT_SIZE   1024    /* initial values for data-output memory */
  47. #define LL_MEM_INIT_SIZE    32
  48.  
  49. #define L_MEM_EXPAND      1024
  50. #define LL_MEM_EXPAND       32
  51.  
  52. #define R_MEM_INIT_SIZE   1024
  53. #define RL_MEM_INIT_SIZE    32
  54.  
  55. #define R_MEM_EXPAND      1024
  56. #define RL_MEM_EXPAND       32
  57.  
  58. #define F_MEM_INIT_SIZE   1024   /* initial memory for file view memory */
  59. #define FL_MEM_INIT_SIZE    32   /* choosen small for testing purposes */
  60.  
  61. #define F_MEM_EXPAND      1024
  62. #define FL_MEM_EXPAND       32
  63.  
  64. #define SORT_BY_ITEM         1
  65. #define SORT_BY_FILE         2
  66.  
  67. #define TAB_EXP_VALUE            8  /* value to expand TAB characters    */
  68. #define INTERESTING_LINE_OUTPUT  0  /* first line is the interesting one */
  69.  
  70. #define INTERESTING_LINE_FILE    9  /* we print 18 lines, the middle is 9*/
  71.  
  72. static char *l_mem  = NULL;  /* memory for left part of lines    */
  73. static long *ll_mem = NULL;  /* memory for left-line-indizes     */
  74. static long l_size = 0;      /* size of l_mem-memory allocated   */
  75. static long ll_size = 0;     /* size of ll_mem-memory allocated  */
  76. static long cnt_ll = 0;      /* number of left lines             */
  77.  
  78. static char *r_mem  = NULL;  /* memory for right part of lines   */
  79. static long *rl_mem = NULL;  /* memory for right-line-indizes    */
  80. static long r_size = 0;      /* size of r_mem-memory allocated   */
  81. static long rl_size = 0;     /* size of rl_mem-memory allocated  */
  82. static long cnt_rl = 0;      /* number of right lines            */
  83.  
  84. static char *f_mem  = NULL;  /* memory for file to view          */
  85. static long *fl_mem = NULL;  /* memory for lines                 */
  86. static long f_size = 0;      /* size of f_mem-memory allocated   */
  87. static long fl_size = 0;     /* size of fl_mem-memory allocated  */
  88. static long cnt_fl = 0;      /* number of lines in file          */
  89.  
  90. static short vi_flag = 0;           /* if 1, use vi as viewer */
  91. static short Sort_flag = 0;         /* No Sorting             */
  92. static char  vi_call[LINESIZE+2];   /* line to call vi        */
  93.  
  94. static  char funct[STRINGSIZE],     /* Strings to hold brs-parameter    */
  95.              file[STRINGSIZE],      /* could be a local variable, but   */
  96.              module[STRINGSIZE],    /* we need it in so many functions, */
  97.              left[ 2 * STRINGSIZE], /* so I made it global              */
  98.              right[2 * STRINGSIZE];
  99.  
  100. /* last error-message, printed on the screen
  101.  */
  102. static char last_error_msg[LINESIZE+2] = "No Errors";
  103.  
  104. /* global data for file-viewer
  105.  */
  106. static char last_filename[MAX_FILENAME] = "";
  107. static char master_dir[MAX_FILENAME] = "";
  108. static char new_dir[MAX_FILENAME] = "";
  109. static char interesting_file[MAX_FILENAME] = "";
  110. static long interesting_line = 0;
  111.  
  112. /* marking of an item in the window:
  113.    don't have to type item in again
  114.  */
  115. static long marked_number = -1; /* -1 ... marking not allowed, cnt_ll ... marking allowed */
  116.  
  117. static char marked_file[MAX_FILENAME] = "";
  118. static char marked_item[STRINGSIZE] = "";
  119.   
  120. static long  interesting_line_output; /* The highlighted line in the output-window */
  121.  
  122. /* possible types:  
  123.    1 ... file
  124.    2 ... function
  125.    3 ... variable
  126.    4 ... struct, enum, union, typedef
  127.  */
  128. #define MARK_NULL       0
  129. #define MARK_FILE       1
  130. #define MARK_FUNCTION   2
  131. #define MARK_VARIABLE   3
  132. #define MARK_TYPE       4
  133. #define MARK_MACRO      5
  134.  
  135. #define MAX_MARKED  0x7fffffff
  136.  
  137. static short type_marked_item = MARK_NULL;
  138. static short type_marked_file = MARK_NULL;
  139. static short next_type_m_item = MARK_NULL;
  140. static short next_type_m_file = MARK_NULL;
  141.  
  142. #define SET_MARK_TYPES(x,y);  {next_type_m_item = x; next_type_m_file = y;}
  143. #define SET_MARK();           {type_marked_item = next_type_m_item; \
  144.                                type_marked_file = next_type_m_file;}
  145. #define CHECK_MARK_ITEM_TYPE(x)  ((type_marked_item == (x)) && marked_item[0])
  146. #define CHECK_MARK_FILE_TYPE(x)  ((type_marked_file == (x)) && marked_file[0])
  147. #define MARKING_ALLOWED()         marked_number = MAX_MARKED;
  148. #define MARKING_NOT_ALLOWED()     marked_number = -1
  149.  
  150. extern int timeout_value; /* timeout used for client-server connection */
  151.  
  152. #ifndef min 
  153. #define min(x,y) ((x < y)? (x):(y))
  154. #define max(x,y) ((x > y)? (x):(y))
  155. #endif 
  156.  
  157.  
  158. char * menu_functions =
  159. "             FUNCTION-MENU\n\n"
  160. "   'F'  Print all functions defined in project\n"
  161. "   'c'  Print all functions called by a given function\n"
  162. "   'C'  Like 'c', but print EVERY function call position)\n"
  163. "   'u'  Print all variables used by a function\n"
  164. "   'U'  Like 'U', but print EVERY usage position\n"
  165. "   'b'  Print all functions calling a given function\n"
  166. "   'B'  Like 'b', but for EVERY calling position\n"
  167. "   'd'  Print definition position of a function\n\n"
  168. "   '?'  Help screen\n"
  169. "   '+'  Next menu-screen (variable-menu)\n"
  170. "   '-'  Previous menu-screen (misc-menu)\n"  ;
  171.  
  172. char * menu_variables =
  173. "             VARIABLE-MENU\n\n"
  174. "   'V'  Print all variables in project\n"
  175. "   't'  Print all structs in project\n"
  176. "   'n'  Print all unions in project\n"
  177. "   'm'  Print all enums in project\n"
  178. "   'y'  Print all typdefs in project\n"
  179. "   's'  Print all functions using a variable\n"
  180. "   'S'  Like 's', but for EVERY usage position\n"
  181. "   'D'  Print definition position of a variable\n"
  182. "   '.'  Print usage of a struct component\n"
  183. "   ':'  Print usage of a struct component with a variable\n\n"
  184. "   '?'  Help screen\n"
  185. "   '+'  Next menu-screen (file-menu)\n"
  186. "   '-'  Previous menu-screen (function-menu)\n"  ;
  187.  
  188. char * menu_files =
  189. "               FILE-MENU\n\n"
  190. "   'f'  Print all source-files in project\n"
  191. "   'i'  Print all includes of a source-file\n"
  192. "   'I'  Print all source files including a given file\n"
  193. "   '#'  Print all macro defininitions in project\n"
  194. "   '*'  Print position of a macro defininition\n"
  195. "   'W'  What is ...\n"
  196. "   'w'  Print working directory of a file\n\n"
  197. "   '?'  Help screen\n"
  198. "   '+'  Next menu-screen (misc-menu)\n"
  199. "   '-'  Previous menu-screen (variable-menu)\n"  ;
  200.  
  201. char * menu_misc =
  202. "               MISC-MENU\n\n"
  203. "   'l'  Clear Marking\n"
  204. "   'o'  Toggle Sort-flags (%s)\n"
  205. "   'T'  Set new Timeout-Time\n"
  206. "   'a'  Get all messages in queue\n"
  207. "   '['  Change viewer (currently: %s)\n"
  208. "   'R'  Set new browsing-datafile in actual server\n"
  209. "   'r'  Switch to a new server\n"
  210. "   'k'  Kill server and exit\n"
  211. "   'q'  Exit client (not killing server)\n\n"
  212. "   '?'  Help screen\n"
  213. "   '+'  Next menu-screen (function-menu)\n"
  214. "   '-'  Previous menu-screen (files-menu)\n"  ;
  215.  
  216. extern void help(int nr);
  217.  
  218. /* reset curses
  219.  */
  220. void Exit(int val )
  221. {  erase();
  222.    refresh();
  223.    nocbreak();
  224.    echo();
  225.    exit( val );
  226.  }
  227.  
  228.  
  229. /* Initialize memory for line-output
  230.  */
  231. void init_lines(void)
  232. {
  233.    l_mem = malloc(L_MEM_INIT_SIZE);
  234.    if( !l_mem )
  235.      { fprintf(stderr, "Not enough memory available: aborting !\n" );
  236.        Exit(1);
  237.       }
  238.    l_size = L_MEM_INIT_SIZE;
  239.    
  240.    ll_mem = malloc(LL_MEM_INIT_SIZE);
  241.    if( !ll_mem )
  242.      { fprintf(stderr, "Not enough memory available: aborting !\n" );
  243.        Exit(1);
  244.       }
  245.    ll_size = LL_MEM_INIT_SIZE;
  246.    
  247.    ll_mem[0] = 0;
  248.    
  249.    r_mem = malloc(R_MEM_INIT_SIZE);
  250.    if( !r_mem )
  251.      { fprintf(stderr, "Not enough memory available: aborting !\n" );
  252.        Exit(1);
  253.       }
  254.    r_size = R_MEM_INIT_SIZE;
  255.    
  256.    rl_mem = malloc(RL_MEM_INIT_SIZE);
  257.    if( !rl_mem )
  258.      { fprintf(stderr, "Not enough memory available: aborting !\n" );
  259.        Exit(1);
  260.       }
  261.    rl_size = RL_MEM_INIT_SIZE;
  262.    
  263.    rl_mem[0] = 0;
  264.  }
  265.  
  266. /* Initialize memory for file-view
  267.  */
  268. void init_file_memory(void)
  269. {
  270.    f_mem = malloc(F_MEM_INIT_SIZE);
  271.    if( !f_mem )
  272.      { fprintf(stderr, "Not enough memory available: aborting !\n" );
  273.        Exit(1);
  274.       }
  275.    f_size = F_MEM_INIT_SIZE;
  276.    
  277.    fl_mem = malloc(FL_MEM_INIT_SIZE);
  278.    if( !fl_mem )
  279.      { fprintf(stderr, "Not enough memory available: aborting !\n" );
  280.        Exit(1);
  281.       }
  282.    fl_size = FL_MEM_INIT_SIZE;
  283.    
  284.    fl_mem[0] = 0;
  285.    
  286.  }
  287.  
  288.  
  289.  
  290. /* Checks for sufficient memory to store cnt_needed bytes
  291.  */
  292. void check_memory(void *ptr, long used, long cnt_needed)
  293. { long *p_size,
  294.         exp_value,
  295.         to_expand = 0;
  296.   long **p_long = NULL;
  297.   char **p_char = NULL;
  298.    
  299.   if( ptr == l_mem )
  300.    { p_size = &l_size;
  301.      p_char = &l_mem;
  302.      exp_value = L_MEM_EXPAND;
  303.     }
  304.   else if( ptr == ll_mem )
  305.    { p_size = &ll_size;
  306.      p_long = &ll_mem;
  307.      exp_value = LL_MEM_EXPAND;
  308.     }
  309.   else if( ptr == r_mem )
  310.    { p_size = &r_size;
  311.      p_char = &r_mem;
  312.      exp_value = R_MEM_EXPAND;
  313.     }
  314.   else if( ptr == rl_mem )
  315.    { p_size = &rl_size;
  316.      p_long = &rl_mem;
  317.      exp_value = RL_MEM_EXPAND;
  318.     }
  319.   else if( ptr == f_mem )
  320.    { p_size = &f_size;
  321.      p_char = &f_mem;
  322.      exp_value = F_MEM_EXPAND;
  323.     }
  324.   else if( ptr == fl_mem )
  325.    { p_size = &fl_size;
  326.      p_long = &fl_mem;
  327.      exp_value = FL_MEM_EXPAND;
  328.     }
  329.   else
  330.    { fprintf(stderr, "UNKNOWN POINTER: expand failed\n" );
  331.      exit(1);
  332.     }
  333.    
  334.   /* calculate number of bytes we have to expand
  335.    */
  336.   while( (used + cnt_needed) >= (*p_size + to_expand) )
  337.    { to_expand += exp_value;
  338.     }
  339.  
  340.   /* if needed, expand memory 
  341.    */  
  342.   if( to_expand )
  343.    { if( p_char )
  344.        { *p_char = (char *)realloc( *p_char, *p_size + to_expand );
  345.          if( !*p_char )
  346.            { fprintf(stderr, "Memory-expand not possible\n" );
  347.              Exit(1);
  348.             }
  349.         }
  350.      else if( p_long )
  351.        { *p_long = (long *)realloc( *p_long, *p_size + to_expand );
  352.          if( !*p_long )
  353.            { fprintf(stderr, "Memory-expand not possible\n" );
  354.              Exit(1);
  355.             }
  356.         }
  357.       
  358.      *p_size += to_expand;
  359.     }
  360.    
  361. }       
  362.     
  363. /* checks for sufficient memory to store strings p1, p2, p3 and
  364.    terminating '\0'-bytes
  365.    for adding 4 Bytes, call with: (.., ..., " ", NULL, NULL)
  366.  */
  367. void check_line_memory(void *ptr, long used, char *p1, char *p2, char *p3)
  368. { long cnt;
  369.    
  370.   cnt =  (p1) ? strlen(p1) + 1 : 1 ;
  371.   cnt += (p2) ? strlen(p2) + 1 : 1 ;
  372.   cnt += (p3) ? strlen(p3) + 1 : 1 ;
  373.    
  374.   check_memory( ptr, used, cnt);
  375.   }
  376.  
  377. /* loads a file into memory (if not allready in memory)
  378.  
  379.    returns 0 on success, else error-code
  380.  
  381.    -1  file error
  382.    -2  directory error
  383.  */
  384. short load_file( char *filename )
  385. { struct stat  stat_buffer;
  386.   FILE  *fp; 
  387.   off_t  size_left;
  388.   register long   p = 0, i;
  389.   size_t cnt_read;
  390.    
  391.   if( !strcmp(last_filename, filename) )
  392.     return( 0 ); /* allready loaded */
  393.    
  394.   if( brs_get_file_dir( filename, new_dir) )
  395.      return( -2 );
  396.   
  397.   if( !getcwd( master_dir, MAX_FILENAME) )
  398.     return( -2 );
  399.    
  400.   if( chdir( new_dir ) )
  401.     { /* error: cannot set new working directory
  402.        */
  403.       return( -2 );
  404.      } 
  405.    
  406.   if(  stat( filename, &stat_buffer )  )
  407.      return( -1 );  /* file does not exist */
  408.    
  409.   size_left = stat_buffer.st_size;
  410.    
  411.   fp = fopen( filename, "r" );
  412.    
  413.   cnt_fl = 0;     /* clear memory */
  414.   fl_mem[0] = 0; 
  415.    
  416.   p = 0;  /* start at the beginning */
  417.    
  418.   while( size_left )
  419.    { /* Check for memory to store next block
  420.       */
  421.      check_memory( f_mem , p , stat_buffer.st_blksize );
  422.       
  423.      cnt_read = fread( f_mem + p, 1, stat_buffer.st_blksize, fp );
  424.       
  425.      size_left -= cnt_read;
  426.      
  427.      p += cnt_read;
  428.     }
  429.    
  430.   /* We have the file in memory, now calculate the lines
  431.    */
  432.    
  433.   for( i = 0; i < p; i++ )
  434.    { if( f_mem[i] == '\n' )
  435.        { /* Check for memory to store next line-offset
  436.           */
  437.          check_memory( fl_mem, cnt_fl * sizeof(long), sizeof(long) );
  438.          
  439.          /* Next line starts one character after the Newline
  440.           */
  441.          cnt_fl++;
  442.          fl_mem[cnt_fl] = i + 1;
  443.         }
  444.     }
  445.  
  446.   cnt_fl++;           /* Numer of lines */
  447.   fl_mem[cnt_fl] = p; /* end of text */
  448.  
  449.   fclose( fp );
  450.   strcpy(last_filename, filename);
  451.    
  452.   if( chdir( master_dir ) )
  453.     { /* error: cannot set back old working directory
  454.          ignore, because loading of the file suceeded !
  455.        */
  456.       return( 0 );
  457.      } 
  458.   
  459.   return( 0 );
  460.    
  461. }
  462.  
  463.  
  464. static char blank_string[LINESIZE+2];
  465.  
  466. /* prints the file in file-memory beginning from line 'line' with the 
  467.    column offset 'col_offset'. This is to be used for viewing lines
  468.    which are longer than the size of the window
  469.  
  470.    TAB's are expanded to TAB_EXP_VALUE blanks
  471.  
  472.    cnt_lines  ...  number of lines in the window
  473.    cnt_cols   ...  numer of cols in the window
  474.    line       ...  starting line
  475.    col_offset ...  number of visible outermost left column (normally 0)
  476.    int_line   ...  interesting line
  477.  */
  478. void print_file_win(short cnt_lines, short cnt_cols, long line, 
  479.                     short col_offset, long int_line, char *identifier, short *token_no)
  480. { register long i,j, k, l, m;
  481.   char line_buf[LINESIZE+2];
  482.   char  *l1, *file_buffer;
  483.   long  ll1, end, k_start;
  484.   short   tmp;
  485.    
  486.    cnt_cols = min( cnt_cols, LINESIZE );
  487.    
  488.    cnt_cols -= 6; /* 6 Bytes for Linenumber */
  489.    
  490.    for( j = 0, i = line; (i < line + cnt_lines) ; i++, j++ )
  491.      { move( j + 1, 0 );
  492.       
  493.        if( i == int_line )
  494.          attron( A_REVERSE );
  495.        else
  496.          attroff( A_REVERSE );
  497.  
  498.        /* we start line-counting with 0, but the compiler with 1 !
  499.         */
  500.        printw("%5d ", i + 1); 
  501.       
  502.        if( i == int_line )
  503.          attroff( A_REVERSE );
  504.  
  505.        if( i < cnt_fl )
  506.          { /* The current line is a valid linenumber !
  507.             */
  508.            l1  = f_mem + fl_mem[i] ;
  509.            ll1 = strlen( l1 );
  510.  
  511.            l = 0;  /* true column number (TAB's count as blanks) */
  512.       
  513.           /* walk the whole line, expand TAB's and start to write
  514.              char's into line_buf as l exceeds col_offset
  515.            */
  516.           line_buf[0] = 0;
  517.  
  518.           end = fl_mem[i+1];
  519.  
  520.           k_start = fl_mem[i];
  521.           file_buffer = f_mem;
  522.          }
  523.        else
  524.          { /* "faked" line - since we do not clear the output window (due to output
  525.                speed), we have to fill up the sub-bottom-lines with blanks
  526.             */
  527.            k_start = 0;
  528.            end = 1;
  529.            file_buffer = "\n";
  530.           }
  531.  
  532.        for( k = k_start; k < end; k++ )
  533.           { switch( file_buffer[k] )
  534.               { case '\t' : /* TAB: expand by tmp blanks 
  535.                              */
  536.                             tmp = 8 - (l % 8);
  537.                             for( m = 0; m < tmp; m++ )
  538.                               { if( (l - col_offset) >= cnt_cols )
  539.                                    break;
  540.                                 if( l >= col_offset )
  541.                                   line_buf[l-col_offset] = ' ';
  542.                                 l++;
  543.                                }
  544.                             break;
  545.  
  546.                case '\n':   /* end of line */
  547.                             line_buf[l - col_offset] = 0;
  548.                             l = cnt_cols + col_offset; /* stop line */
  549.                             break;
  550.             
  551.                default:     if( (l - col_offset) >= cnt_cols )
  552.                                break; /* end of line reached */
  553.             
  554.                             if( l >= col_offset )
  555.                               { /* after first visible column 
  556.                                  */
  557.                                 if( isprint( f_mem[k] ) )
  558.                                   line_buf[l-col_offset] = file_buffer[k];
  559.                                 else
  560.                                   line_buf[l-col_offset] = ' ';
  561.                                }
  562.                             l++;
  563.                             break;
  564.                }
  565.             
  566.             if( (l - col_offset) >= cnt_cols )
  567.               break; /* line ends */
  568.            } /* next */
  569.        line_buf[l - col_offset] = 0;
  570.  
  571.        /* do not use printw, because this results in troubles with 
  572.           '%..' in the strings
  573.         */
  574.        if( *token_no >= 0 && i == int_line )
  575.          { short state = 0;
  576.          
  577.            /* finit-state-automaton
  578.          
  579.               state-0  --[char]---------> state-1
  580.               state-1  --[char/digit]---> state-1
  581.               state-1  --[else]---------> state-0
  582.             */
  583.            for( l = 0, m = 0, k = 0; k < strlen(line_buf); k++ )
  584.              { switch( state )
  585.                 { case 0: if( isalpha(line_buf[k]) || line_buf[k] == '_' )
  586.                             { state = 1;
  587.                               if( l == *token_no )
  588.                                 { attron( A_REVERSE );
  589.                                   identifier[m++] = line_buf[k];
  590.                                  }
  591.                              }
  592.                           break;
  593.                   case 1: if( isalnum(line_buf[k]) || line_buf[k] == '_' )
  594.                             { if( m )
  595.                                 identifier[m++] = line_buf[k];
  596.                               break;
  597.                              }
  598.                           else
  599.                             { state = 0;
  600.                               if( l == *token_no )
  601.                                 attroff( A_REVERSE );
  602.                               l++;
  603.                               if( m )
  604.                                 { identifier[m] = 0;
  605.                                   m = 0;
  606.                                  }
  607.                              }
  608.                  }
  609.                addch( line_buf[k] );
  610.               }
  611.             if( l <= *token_no )
  612.               *token_no = -1;
  613.           }
  614.        else
  615.          { /* normal output */
  616.            addstr( line_buf );
  617.           }
  618.        addstr(blank_string + LINESIZE - cnt_cols + strlen(line_buf) );
  619.      }
  620.    
  621.   attroff( A_REVERSE );
  622.   
  623.   refresh();
  624. }  
  625.  
  626. /* used to store the file-call-stack
  627.    if user requests to follow a calling
  628.    structure
  629.  */
  630. struct file_stack
  631. { char *filename;
  632.   long  line;
  633.   long  start;
  634.   short col;
  635.  };
  636.  
  637. #define MAX_STACK         50  
  638. #define MAX_IDENTIFIER    50
  639.  
  640. /* loads and views a given file and views at the
  641.    given line (note: counting begins with 0)
  642.  */
  643. short print_file(char *filename, long line)
  644. { long  start_line = 0, init_start_line, init_line, line_end;
  645.   short start_col = 0, ret;
  646.   short win_size;
  647.   short ident_mode = 0; /* 0 .. normal mode,  1 .. ident mode,  2 .. view position */
  648.   int   c;
  649.   struct file_stack f_stack[MAX_STACK];
  650.   char   identifier[MAX_IDENTIFIER];
  651.   char   info_line[80] = "";
  652.   short  stack_pointer = 0;
  653.   short  token_no = -1;
  654.    
  655.   memset( blank_string, ' ', LINESIZE );
  656.  
  657.   if( vi_flag )
  658.     { /* use vi instead of the internal viewer
  659.        */
  660.       if( brs_get_file_dir( filename, new_dir) )
  661.          return( -1 );
  662.   
  663.       if( !getcwd( master_dir, MAX_FILENAME) )
  664.         return( -1 );
  665.    
  666.       if( chdir( new_dir ) )
  667.         { /* error: cannot set new working directory
  668.            */
  669.           return( -1 );
  670.          } 
  671.       sprintf( vi_call, "vi -R +%ld %s", line + 1, filename );
  672.       system( vi_call );
  673.       
  674.       chdir( master_dir );
  675.       return( 0 );
  676.      }
  677.     
  678.   strcpy(file, filename);
  679.  
  680.   if( load_file( filename )  )
  681.     return( -1 );
  682.  
  683.   start_line = line - INTERESTING_LINE_FILE; 
  684.    
  685.   if( start_line < 0 )
  686.      start_line = 0;
  687.    
  688.   if( start_line > cnt_fl - 1) 
  689.     start_line = cnt_fl - 1;
  690.    
  691.   init_start_line = start_line;
  692.   init_line       = line;
  693.  
  694.   win_size = LINES - 6;
  695.   
  696.   erase();
  697.  
  698.   while(1)
  699.    { /* erase(); */
  700.      move( 0, (COLS - strlen(file)) / 2);
  701.      addstr(file);
  702.      print_file_win( win_size + 1, COLS - 1 /*79*/, start_line, 
  703.                      start_col, line, identifier, &token_no);
  704.       
  705.      move( LINES-4 /*20*/, 0 );
  706.      if( !ident_mode )
  707.       { printw("k ... Up,      j ... Down,    ^U ... Page up,     ^D ... Page down      \n");
  708.         printw("l ... Right,   h ... Left,     ^ ... Beg. of line  q ... Quit   ?...Help\n");
  709.         printw("t ... Top,     b ... Bottom,   B ... Back          i ... Ident-mode     ");
  710.        }
  711.      else if( ident_mode == 1 )
  712.       { printw("c ... Call (%2d)  d ... Definition     i ... Next token    ? ... Help     \n", 
  713.                 stack_pointer);
  714.         printw("r ... Return     w ... What is        q ... Quit Mode     ? ... Help     \n");
  715.         printw("Info: %s", info_line);
  716.         addstr(blank_string + LINESIZE - COLS + strlen(info_line) + 6 );
  717.         info_line[0] = 0;
  718.        }
  719.      else 
  720.       { printw("                                                                         \n");
  721.         printw("r ... Return                                                             \n");
  722.         printw("Info: %s", info_line);
  723.         addstr(blank_string + LINESIZE - COLS + strlen(info_line) + 6 );
  724.         info_line[0] = 0;
  725.        }
  726.      refresh();
  727.  
  728.      c = getch();
  729.       
  730.      if( ident_mode == 2 )
  731.        { /* In view position mode just cursor-keys allowed
  732.             every other key returns to the previous position
  733.           */
  734.          switch( c )
  735.            { case 'k': case KEY_UP:
  736.              case 'j': case KEY_DOWN:
  737.              case 0x15: case KEY_PPAGE:
  738.              case 0x4: case KEY_NPAGE:
  739.              case '^':
  740.                    break;
  741.              default: c = 'r';  /* return */
  742.                       ident_mode = 1;
  743.                       break;
  744.             }
  745.         }
  746.       
  747.      switch( c )
  748.       { case '?': help(5);
  749.                   break;
  750.         case 'c': /* call function */
  751.                   if( ident_mode )
  752.                    { /* push current file */
  753.                      if( stack_pointer >= MAX_STACK - 1 )
  754.                         break;
  755.                      f_stack[stack_pointer].filename = strdup(file);
  756.                      f_stack[stack_pointer].line     = line;
  757.                      f_stack[stack_pointer].start    = start_line;
  758.                      f_stack[stack_pointer].col      = start_col;
  759.                      stack_pointer++;
  760.                      
  761.                      /* Try to find the definition-position of this function
  762.                         first in the file, later global
  763.                       */
  764.                      strcpy( left, file );
  765.                      ret = brs_get_funct_pos( identifier, left, file, 
  766.                            &line, &line_end, module);
  767.                      if( ret )
  768.                        { ret = brs_get_funct_pos( identifier, "", file, 
  769.                            &line, &line_end, module);
  770.                          if( ret )
  771.                            { sprintf(info_line, "Definition position of %s unknown", 
  772.                                              identifier );
  773.                              stack_pointer--;
  774.                              strcpy( file, f_stack[stack_pointer].filename );
  775.                              free(f_stack[stack_pointer].filename);
  776.                              break;
  777.                             }
  778.                         }
  779.             
  780.                      line--; /* Line counting starts with 1, here with 0 */
  781.             
  782.                      if( load_file( file )  )
  783.                        goto ret_pos;
  784.  
  785.                      start_line = line - INTERESTING_LINE_FILE; 
  786.    
  787.                      if( start_line < 0 )
  788.                         start_line = 0;
  789.    
  790.                      if( start_line > cnt_fl - 1) 
  791.                        start_line = cnt_fl - 1;
  792.    
  793.                      token_no = 0;
  794.                     }
  795.                   break;
  796.          
  797.         case 'k': case KEY_UP:
  798.                   line -= (line > 0 ) ? 1 : 0;
  799.                   if( line < start_line )
  800.                      start_line -= (start_line > 0) ? 1 : 0;
  801.                   break;
  802.          
  803.         case 'j': case KEY_DOWN:
  804.                   line += (line < cnt_fl - 1 ) ? 1 : 0;
  805.                   if( line > start_line + win_size)
  806.                      start_line += (start_line < cnt_fl - 1) ? 1 : 0;
  807.                   break;
  808.          
  809.         case 'i': if( !ident_mode )
  810.                     token_no = 0; /* first time ident_mode */
  811.                   else
  812.                     token_no++;
  813.                   ident_mode = 1;
  814.                   break;
  815.          
  816.         case 0x15: case KEY_PPAGE:
  817.                   start_line -= (start_line > win_size) ? win_size : start_line;
  818.                   line -= (line > win_size) ? win_size : line;
  819.                   break;
  820.          
  821.         case 0x4: case KEY_NPAGE:
  822.                   start_line += (start_line < cnt_fl - win_size) ? win_size : 0;
  823.                   line += (line < cnt_fl - win_size) ? win_size : 0;
  824.                   break;
  825.          
  826.         case '^': /* begin of line */
  827.                   if( ident_mode )
  828.                      break;
  829.                   start_col = 0;
  830.                   break;
  831.          
  832.         case 'l': case KEY_RIGHT:
  833.                   if( ident_mode )
  834.                      break;
  835.                   start_col += (start_col < 256) ? 1 : 0;
  836.                   break;
  837.          
  838.         case 'h': case KEY_LEFT:
  839.                   if( ident_mode )
  840.                      break;
  841.                   start_col -= (start_col > 0) ? 1 : 0;
  842.                   break;
  843.          
  844.         case 'q': if( ident_mode ) /* quit */
  845.                     { ident_mode = 0;
  846.                       token_no = -1;
  847.                      }
  848.                   else
  849.                     { erase();
  850.                       refresh();
  851.                       return;
  852.                      }
  853.                   break;
  854.          
  855.         case 't': case KEY_HOME: /* Top of file */
  856.                   start_line = 0;
  857.           line = 0;
  858.                   break;
  859.          
  860.         case 'b': case '~': /* end of file */
  861.                   start_line = cnt_fl - win_size;
  862.           line = cnt_fl - 1;
  863.                   break;
  864.          
  865.         case 'r': /* return */
  866.                   if( ident_mode )
  867.                    { /* pop file */
  868. ret_pos:
  869.                      if( stack_pointer == 0 )
  870.                         break;
  871.                      stack_pointer--;
  872.                      strcpy( file, f_stack[stack_pointer].filename);
  873.                      line       = f_stack[stack_pointer].line;
  874.                      start_line = f_stack[stack_pointer].start;
  875.                      start_col  = f_stack[stack_pointer].col;
  876.                      free(f_stack[stack_pointer].filename);
  877.                                  
  878.                      if( load_file( file )  )
  879.                       return;
  880.                      token_no = 0;
  881.                     }
  882.                   break;
  883.  
  884.         case 'd': /* jump to definition position */
  885.                   if( !ident_mode )
  886.                      break;
  887.                   /* 
  888.                    */
  889.                   strcpy( left, file );
  890.                   strcpy(info_line, "" );
  891.                   ret = brs_get_item_pos( identifier, file, line + 1,
  892.                                           left, &line_end);
  893.                   if( !ret )
  894.                     { /* Jump to this position */
  895.                       if( stack_pointer >= MAX_STACK - 1 )
  896.                          break;
  897.                       f_stack[stack_pointer].filename = strdup(file);
  898.                       f_stack[stack_pointer].line     = line;
  899.                       f_stack[stack_pointer].start    = start_line;
  900.                       f_stack[stack_pointer].col      = start_col;
  901.                       stack_pointer++;
  902.                      
  903.                       line = line_end - 1; /* counting starts with 1, here with 0 */
  904.  
  905.                       strcpy( file, left );
  906.                       if( load_file( file )  )
  907.                         goto ret_pos;
  908.  
  909.                       start_line = line - INTERESTING_LINE_FILE; 
  910.    
  911.                       if( start_line < 0 )
  912.                          start_line = 0;
  913.    
  914.                       if( start_line > cnt_fl - 1) 
  915.                         start_line = cnt_fl - 1;
  916.  
  917.                       ident_mode = 2;
  918.                       token_no = 0;
  919.                      }
  920.                   else
  921.                     sprintf( info_line, "Error: %d %s", ret, left );
  922.                   break;
  923.  
  924.         case 'w': /* print what is */
  925.                   if( !ident_mode )
  926.                      break;
  927.                   /* 
  928.                    */
  929.                   strcpy( left, file );
  930.                   strcpy(info_line, "" );
  931.                   ret = brs_what_is( identifier, file, line,
  932.                                      left, &line_end, right );
  933.  
  934.                   switch( ret )
  935.                     { case RET_MACRO:
  936.                          strcat(info_line, "Macro" );
  937.                          break;
  938.                       case RET_VAR:
  939.                          strcat(info_line, "Variable" );
  940.                          break;
  941.                       case RET_FUNCT:
  942.                          strcat(info_line, "Function" );
  943.                          break;
  944.                       case RET_STRUCT:
  945.                          strcat(info_line, "Struct" );
  946.                          break;
  947.                       case RET_UNION:
  948.                          strcat(info_line, "Union" );
  949.                          break;
  950.                       case RET_ENUM:
  951.                          strcat(info_line, "Enum" );
  952.                          break;
  953.                       case RET_TYPEDEF:
  954.                          strcat(info_line, "Typedef" );
  955.                          break;
  956.                       case RET_COMP:
  957.                          strcat(info_line, "struct/union comp" );
  958.                          break;
  959.                       case RET_ENUM_C:
  960.                          strcat(info_line, "enum constant" );
  961.                          break;
  962.                       case RET_END: 
  963.                       case RET_ERROR:
  964.                       case RET_TIMEOUT:
  965.                          info_line[0] = 0;
  966.                          break;
  967.                       default:
  968.                          break;
  969.                      }
  970.                  if( ret != RET_END && ret != RET_ERROR && ret != RET_TIMEOUT )
  971.                     { sprintf( right, " %s %ld", left, line_end );
  972.    
  973.                       /* Quick & Dirty-test not to overwrite info_line-buffer */
  974.                       if( strlen( info_line ) + strlen( right ) < 50 )
  975.                          strcat( info_line, right );
  976.                      }
  977.  
  978.                   while( ret != RET_END )
  979.                      ret = brs_what_is( identifier, file, line,
  980.                                      left, &line_end, right );
  981.  
  982.                   break;
  983.  
  984.         case 'B': /* back */
  985.                   if( ident_mode )
  986.                     break;
  987.                   start_line = init_start_line;
  988.                   line       = init_line;
  989.                   break;
  990.  
  991.         default : break;
  992.        }
  993.     }
  994. }
  995.    
  996.  
  997. /* used to get two strings and store them in the data-output-memory
  998.    for the left part of the lines
  999.  */
  1000. void push_data_left(char *left1, char *left2)
  1001. { long p;
  1002.   char empty[3] = ""; 
  1003.       
  1004.   p = ll_mem[cnt_ll];
  1005.    
  1006.   check_line_memory( l_mem, p, left1, left2, NULL);
  1007.    
  1008.   /* check for 4 Bytes */
  1009.   check_memory( ll_mem, cnt_ll * sizeof(long), sizeof(long) );
  1010.    
  1011.   if( !left1 )
  1012.     left1 = empty;
  1013.   memcpy( l_mem + p, left1, strlen(left1) + 1 );
  1014.   p += strlen( left1 ) + 1;
  1015.    
  1016.   if( !left2 )
  1017.     left2 = empty;
  1018.   memcpy( l_mem + p, left2, strlen(left2) + 1 );
  1019.   p += strlen( left2 ) + 1;
  1020.    
  1021.   cnt_ll++;
  1022.   ll_mem[cnt_ll] = p;
  1023.  }
  1024.  
  1025.  
  1026. /* used to get three strings and store them in the data-output-memory
  1027.    for the right part of the lines
  1028.  */
  1029. void push_data_right(char *right1, char *right2, char *right3)
  1030. { long p;
  1031.   char  empty[3] = "";
  1032.    
  1033.   p = rl_mem[cnt_rl];
  1034.    
  1035.   check_line_memory( r_mem, p, right1, right2, right3);
  1036.    
  1037.   /* check for 4 Bytes */
  1038.   check_memory( rl_mem, cnt_rl * sizeof(long), sizeof(long));
  1039.    
  1040.   if( !right1 )
  1041.     right1 = empty;
  1042.    
  1043.   memcpy( r_mem + p, right1, strlen(right1) + 1 );
  1044.   p += strlen( right1 ) + 1;
  1045.    
  1046.   if( !right2 )
  1047.     right2 = empty;
  1048.   memcpy( r_mem + p, right2, strlen(right2) + 1 );
  1049.   p += strlen( right2 ) + 1;
  1050.  
  1051.   if( !right3 )
  1052.     right3 = empty;
  1053.   memcpy( r_mem + p, right3, strlen(right3) + 1 );
  1054.   p += strlen( right3 ) + 1;
  1055.    
  1056.   cnt_rl++;
  1057.   rl_mem[cnt_rl] = p;
  1058.  }
  1059.  
  1060.  
  1061. /* save output-window to a file
  1062.  */
  1063. void output_to_file(char *head, short cnt_lines, short cnt_cols, long line )
  1064. { char filename[MAX_FILENAME] = "";
  1065.   FILE  *fp;
  1066.   int   c = 'o';
  1067.   long i,j;
  1068.   char line_buf[LINESIZE+2];
  1069.   char  *l1, *l2, *r1, *r2, *r3;
  1070.   long  ll1, ll2, rl1, rl2, rl3, l_right;
  1071.   
  1072.   move( LINES-4, 0 );
  1073.   printw("                                                                            \n");
  1074.   printw("                                                                            ");
  1075.   move( LINES-4, 0 );
  1076.   printw("Filename : " );
  1077.   refresh();
  1078.   
  1079.   getstr(filename);
  1080.    
  1081.   fp = fopen( filename, "r" );
  1082.   if( fp )
  1083.     { /* filename does exist, ask if overwrite or append
  1084.        */
  1085.       fclose(fp);
  1086.       move( LINES-3, 0 );
  1087.       printw("'%s' exists : (o)verwrite, (a)ppend or (q)uit", filename );
  1088.       refresh();
  1089.       do
  1090.        { c = getch();
  1091.         } while ( c != 'o' && c != 'a' && c != 'q' );
  1092.       if( c == 'q' )
  1093.         { strcpy( last_error_msg, "Command aborted !");
  1094.           return;
  1095.          }
  1096.      }
  1097.    
  1098.   if( c == 'o' )
  1099.     fp = fopen( filename, "w" );
  1100.   else
  1101.     fp = fopen( filename, "a" );
  1102.       
  1103.   if( !fp )
  1104.     {  sprintf(last_error_msg, "
  1105.           Could not open '%s' for writing (errno: %d)", 
  1106.           filename, errno );
  1107.        return;
  1108.      }
  1109.    
  1110.   /* first print headline : */
  1111.   fprintf( fp, "\n%s\n\n", head );
  1112.    
  1113.   /* This is mainly the code from print_output_win:
  1114.    */
  1115.    
  1116.   cnt_cols = min( cnt_cols, LINESIZE );
  1117.  
  1118.   for( j = 0, i = line; (i < line + cnt_lines) && (i < cnt_ll); i++, j++ )
  1119.     { fprintf( fp, "%4d ", i + 1);
  1120.       
  1121.       l1  = l_mem + ll_mem[i] ;
  1122.       ll1 = strlen( l1 );
  1123.       l2  = l1 + strlen(l1) + 1;
  1124.       ll2 = strlen( l2 );
  1125.       
  1126.       r1  = r_mem + rl_mem[i] ;
  1127.       rl1 = strlen( r1 );
  1128.       r2  = r1 + strlen( r1 ) + 1;
  1129.       rl2 = strlen( r2 );
  1130.       r3  = r2 + strlen( r2 ) + 1;
  1131.       rl3 = strlen( r3 );
  1132.  
  1133.       if( rl1 + rl2 + rl3 > 0 )
  1134.         memset( line_buf, '.', cnt_cols - 5);
  1135.       else
  1136.         memset( line_buf, ' ', cnt_cols - 5);
  1137.       
  1138.       
  1139.       memcpy(line_buf, l1, ll1 );
  1140.       line_buf[ll1] = ' ';
  1141.       if( l2[0] )
  1142.        { memcpy(line_buf + ll1 + 1, l2, ll2 );
  1143.          line_buf[ll1 + 1 + ll2] = ' ';
  1144.         }
  1145.    
  1146.       l_right = rl1;
  1147.       if( r2[0] )
  1148.         { l_right += 1 + rl2;
  1149.           if( r3[0] )
  1150.             l_right += 1 + rl3;
  1151.          }
  1152.    
  1153.       if( r3[0] )
  1154.         sprintf(line_buf + cnt_cols - 6 - l_right, " %s %s %s", r1, r2, r3 );
  1155.       else if( r2[0] )
  1156.         sprintf(line_buf + cnt_cols - 6 - l_right, " %s %s", r1, r2 );
  1157.       else if( r1[0] )
  1158.         sprintf(line_buf + cnt_cols - 6 - l_right, " %s", r1 );
  1159.       else
  1160.         sprintf(line_buf + cnt_cols - 6 - l_right, " " );
  1161.       
  1162.  
  1163.       fprintf( fp, "%s\n", line_buf );
  1164.     }
  1165.    
  1166.   fclose( fp );
  1167.   sprintf( last_error_msg, "%d lines saved !", j + 3);
  1168.    
  1169. }
  1170.   
  1171.    
  1172.   
  1173.    
  1174. /* views one window of output-data 
  1175. (combined of left and right parts)
  1176.    may be sorted if an index-array is given
  1177. */
  1178. void print_output_win(long *idx_array, short cnt_lines, short cnt_cols, 
  1179.                       long line, short file_name_info, short line_name_info)
  1180. { long i,j, k;
  1181.   char line_buf[LINESIZE+2];
  1182.   char  *l1, *l2, *r1, *r2, *r3;
  1183.   long  ll1, ll2, rl1, rl2, rl3, l_right;
  1184.     
  1185.    cnt_cols = min( cnt_cols, LINESIZE );
  1186.    
  1187.    interesting_line_output = cnt_lines / 2;
  1188.    interesting_line_output = min( interesting_line_output, cnt_ll - line - 1);
  1189.    
  1190.    if( line < 0 )
  1191.      { /* go to a line above the middle-line */
  1192.        interesting_line_output = min(cnt_lines / 2, cnt_ll - 1) + line;
  1193.        line = 0;
  1194.        if( interesting_line_output < 0 )
  1195.          interesting_line_output = 0;
  1196.       }
  1197.    
  1198.    for( j = 0, i = line; (i < line + cnt_lines) && (i < cnt_ll); i++, j++ )
  1199.      { move( j + 1, 0 );
  1200.        if( j == interesting_line_output  /* INTERESTING_LINE_OUTPUT */ )
  1201.          attron( A_REVERSE );
  1202.        else
  1203.          attroff( A_REVERSE );
  1204.       
  1205.        if( idx_array )
  1206.          k = idx_array[i];
  1207.        else
  1208.          k = i;
  1209.             
  1210.        l1  = l_mem + ll_mem[k] ;
  1211.        ll1 = strlen( l1 );
  1212.        l2  = l1 + strlen(l1) + 1;
  1213.        ll2 = strlen( l2 );
  1214.       
  1215.        r1  = r_mem + rl_mem[k] ;
  1216.        rl1 = strlen( r1 );
  1217.        r2  = r1 + strlen( r1 ) + 1;
  1218.        rl2 = strlen( r2 );
  1219.        r3  = r2 + strlen( r2 ) + 1;
  1220.        rl3 = strlen( r3 );
  1221.       
  1222.        if( marked_number == i ) 
  1223.          { printw("%4d*", i + 1);
  1224.            /* assume marked item in l1, interesting file in r2
  1225.             */
  1226.            strcpy( marked_item, l1 );
  1227.            strcpy( marked_file, r1 );
  1228.            SET_MARK();
  1229.           }
  1230.        else
  1231.          printw("%4d ", i + 1);
  1232.       
  1233.  
  1234.  
  1235.        if( j == interesting_line_output /* INTERESTING_LINE_OUTPUT */ )
  1236.          { switch( file_name_info )
  1237.              { case 0:  strcpy( interesting_file, l1 ); break;
  1238.                case 1:  strcpy( interesting_file, l2 ); break;
  1239.                case 2:  strcpy( interesting_file, r1 ); break;
  1240.                case 3:  strcpy( interesting_file, r2 ); break;
  1241.                case 4:  strcpy( interesting_file, r3 ); break;
  1242.                default: strcpy( interesting_file, "" ); break;
  1243.               }
  1244.            switch( line_name_info )
  1245.              { case 0:  interesting_line = atoi(l1); break;
  1246.                case 1:  interesting_line = atoi(l2); break;
  1247.                case 2:  interesting_line = atoi(r1); break;
  1248.                case 3:  interesting_line = atoi(r2); break;
  1249.                case 4:  interesting_line = atoi(r3); break;
  1250.                default: interesting_line = 1;
  1251.               }
  1252.           }
  1253.       
  1254.        if( rl1 + rl2 + rl3 > 0 )
  1255.          memset( line_buf, '.', cnt_cols - 5);
  1256.        else
  1257.          memset( line_buf, ' ', cnt_cols - 5);
  1258.       
  1259.       
  1260.        memcpy(line_buf, l1, ll1 );
  1261.        line_buf[ll1] = ' ';
  1262.        if( l2[0] )
  1263.         { memcpy(line_buf + ll1 + 1, l2, ll2 );
  1264.           line_buf[ll1 + 1 + ll2] = ' ';
  1265.          }
  1266.    
  1267.        l_right = rl1;
  1268.        if( r2[0] )
  1269.          { l_right += 1 + rl2;
  1270.            if( r3[0] )
  1271.              l_right += 1 + rl3;
  1272.           }
  1273.    
  1274.        if( r3[0] )
  1275.          sprintf(line_buf + cnt_cols - 6 - l_right, " %s %s %s", r1, r2, r3 );
  1276.        else if( r2[0] )
  1277.          sprintf(line_buf + cnt_cols - 6 - l_right, " %s %s", r1, r2 );
  1278.        else if( r1[0] )
  1279.          sprintf(line_buf + cnt_cols - 6 - l_right, " %s", r1 );
  1280.        else
  1281.          sprintf(line_buf + cnt_cols - 6 - l_right, " " );
  1282.       
  1283.  
  1284.        printw( line_buf );
  1285.      }
  1286.    
  1287.   if( j == interesting_line_output /* INTERESTING_LINE_OUTPUT */ + 1 )
  1288.     attroff( A_REVERSE );
  1289.   
  1290.   refresh();
  1291. }
  1292.  
  1293.  
  1294. void reset_line_data(void)
  1295. {
  1296.   cnt_ll = 0;
  1297.   cnt_rl = 0;
  1298.  }
  1299.  
  1300.  
  1301. /* print_output stores the number of the right-line-part, where
  1302.    the filename is stored
  1303.  */
  1304. static short  local_file_name_info;
  1305.  
  1306. /* compare-function for sorting output-lines
  1307.  */
  1308. int output_compare(const void * buff_1, const void * buff_2 )
  1309. { char  *l1, *l2, *r1, *r2;
  1310.   long  idx1, idx2, rl1, rl2;
  1311.       
  1312.   idx1 = *((long *)buff_1);
  1313.   idx2 = *((long *)buff_2);
  1314.    
  1315.   if( Sort_flag == SORT_BY_ITEM || local_file_name_info < 2)
  1316.    { /* Sort by ITEM or if filename is not in the right part
  1317.       */
  1318.      l1  = l_mem + ll_mem[idx1];
  1319.      l2  = l_mem + ll_mem[idx2];
  1320.      return( strcmp( l1, l2) );
  1321.     }
  1322.   else /* filename is in the right part of the line */
  1323.    { r1  = r_mem + rl_mem[idx1];
  1324.      r2  = r_mem + rl_mem[idx2];
  1325.       
  1326.      if( local_file_name_info == 2 ) /* filename in right1 */
  1327.        return( strcmp( r1, r2) );
  1328.       
  1329.      rl1 = strlen( r1 );
  1330.      rl2 = strlen( r2 );
  1331.      r1  = r1 + strlen( r1 ) + 1;
  1332.      r2  = r2 + strlen( r2 ) + 1;
  1333.       
  1334.      if( local_file_name_info == 3 ) /* filename in right2 */
  1335.        return( strcmp( r1, r2) );
  1336.       
  1337.      /* else: filename in right-3 */
  1338.      rl1 = strlen( r1 );
  1339.      rl2 = strlen( r2 );
  1340.      r1  = r1 + strlen( r1 ) + 1;
  1341.      r2  = r2 + strlen( r2 ) + 1;
  1342.      return( strcmp( r1, r2) );
  1343.     }
  1344.  }
  1345.  
  1346.  
  1347. /* prints the output generated by push_data_left and push_data_right.
  1348.  
  1349.    file_name_info tells this routine, which part of the line is the 
  1350.    filename if the user wants to view the file
  1351.  
  1352.    line_name_info tells this routine, which part of the line is the 
  1353.    linenumber if the user wants to view the file at this position
  1354.  
  1355.    possible values:
  1356.  
  1357.    0  ...  left 1
  1358.    1  ...  left 2
  1359.    2  ...  right 1
  1360.    3  ...  right 2
  1361.    4  ...  right 3
  1362.  
  1363.   -1  ...  no given
  1364. */
  1365. void print_output(char *head, short file_name_info, short line_name_info)
  1366. { long start_line = 0, i;
  1367.   int   c;
  1368.   short  win_size;
  1369.   static long *sort_indices = NULL;
  1370.   static long cnt_sort_idx = 0;
  1371.  
  1372.   win_size = LINES - 6; /* 18 lines on 24-line-terminal */
  1373.    
  1374.   if( Sort_flag )
  1375.     { if( cnt_sort_idx < max( cnt_ll, cnt_rl) )
  1376.        { if( sort_indices )
  1377.             free( sort_indices );
  1378.          sort_indices = malloc( 2 * max( cnt_ll, cnt_rl) * sizeof( long ) );
  1379.          if( !sort_indices )
  1380.            { fprintf(stderr, "Not enough memory available: aborting !\n" );
  1381.              Exit(1);
  1382.             }
  1383.          cnt_sort_idx = 2 * max( cnt_ll, cnt_rl);
  1384.         }
  1385.       for( i = 0; i < cnt_sort_idx; i++ )
  1386.         sort_indices[i] = i;
  1387.  
  1388.       local_file_name_info = file_name_info;
  1389.       
  1390.       /* Now sort the sort_indices, but use the ll_mem-buffer for the comparing
  1391.        */
  1392.       qsort( sort_indices, cnt_ll, sizeof(long), output_compare );
  1393.      }
  1394.    
  1395.   last_error_msg[0] = 0; 
  1396.   while(1)
  1397.    { erase();
  1398.      move( 0, (COLS - strlen(head)) / 2);
  1399.      addstr(head);
  1400.      print_output_win( (Sort_flag) ? sort_indices : NULL, win_size, COLS-1 /*79*/, 
  1401.                        start_line, file_name_info, line_name_info);
  1402.       
  1403.      move( LINES-4/*20*/, 0 );
  1404.      printw("k .. Up,       j .. Down,        ^U .. Pg up,       ^D .. Pg down  ? .. Help\n");
  1405.      printw("v .. View src  f .. Win to file,  F .. All to file   q .. Quit     %s",
  1406.              (marked_number == -1) ? "" : "m  .. mark" );
  1407.      
  1408.      move( LINES-2/*22*/, 15 );
  1409.      printw("Error: %s", last_error_msg );
  1410.      move( LINES-2/*22*/, 0 );
  1411.      printw("command: " );
  1412.      refresh();
  1413.      last_error_msg[0] = 0;
  1414.       
  1415.      c = getch();
  1416.       
  1417.      switch( c )
  1418.       { case '?': help(4);
  1419.                   break;
  1420.         case 't': case KEY_HOME:
  1421.                   start_line = 0;
  1422.                   break;
  1423.         case 'b': case '~':
  1424.                   start_line = cnt_ll - win_size;
  1425.                   break;
  1426.         case 'k': case KEY_UP:
  1427.                   start_line -= (start_line > (- min(win_size / 2, cnt_ll - 1) )) ? 1 : 0;
  1428.                   break;
  1429.         case 'j': case KEY_DOWN:
  1430.                   start_line += (start_line < cnt_ll - 1) ? 1 : 0;
  1431.                   break;
  1432.         case 0x15: case KEY_PPAGE:
  1433.                   start_line -= (start_line > win_size) ? win_size : start_line;
  1434.                   break;
  1435.         case 0x4: case KEY_NPAGE:
  1436.                   start_line += (start_line < cnt_ll - win_size) ? win_size : 0;
  1437.                   break;
  1438.         case 'q': erase();
  1439.                   refresh();
  1440.                   return;
  1441.         case 'v': if( interesting_file[0] )
  1442.                     { if( print_file( interesting_file, 
  1443.                                      interesting_line - 1) )
  1444.                         { /* error loading file */
  1445.                           sprintf(last_error_msg, 
  1446.                                   "Error loading file \"%s\" !",
  1447.                                   interesting_file );
  1448.                          }
  1449.                      }
  1450.                   else
  1451.                     { /* not possible */                          
  1452.                       sprintf(last_error_msg, 
  1453.                               "Operation not allowed here !" );
  1454.                      }
  1455.                   break;
  1456.         case 'f': /* output to file (just the window)
  1457.                    */
  1458.                   output_to_file(head, win_size, COLS-1 , start_line );
  1459.                   break;
  1460.          
  1461.         case 'F': /* output to file (all)
  1462.                    */
  1463.                   output_to_file(head, cnt_ll, COLS-1 , 0 );
  1464.                   break;
  1465.         
  1466.         case 'm': if( marked_number == -1 ) 
  1467.                     /* marking not allowed */
  1468.                     break;
  1469.                   marked_number = start_line + interesting_line_output;
  1470.                   break;
  1471.          
  1472.         default : 
  1473.                    sprintf(last_error_msg, 
  1474.                             "Unknown Command '%c' (0x%02x)", c, c );
  1475.                    break;
  1476.        }
  1477.     }
  1478. }
  1479.    
  1480. /* Print a context sensitive help screen 
  1481.    Well, this is more than exagerating :-)
  1482.  */
  1483. void help(int nr)
  1484. { int in;
  1485.            
  1486.    erase();
  1487.    switch( nr )
  1488.      { case 0:
  1489.           printw("BRS_CLIENT              OVERVIEW                      HELP-SCREEN\n\n");
  1490.           printw("This is the main menu of the browser-client. If you have started a\n");
  1491.           printw("browser-server with a browser-control-file, there should be an\n");
  1492.           printw("established IPC-connection (no connection is reported otherwise).\n");
  1493.           printw("The menu is divided into 4 pages (accessable with '+' or '-'), but\n");
  1494.           printw("you can type any command at any time.\n");
  1495.           printw("After pressing one of the Print-Commands, the client issues a query\n");
  1496.           printw("to the server and will print a list with the query-results (in the\n");
  1497.           printw("order of the occurence - this can be changed by the 'o' command)\n");
  1498.           printw("This may take a little time, depending on the size of the project.\n");
  1499.           printw("You can choose one of the results by the KEY-UP/KEY-DOWN (k/j) keys\n");
  1500.           printw("and view the source-position. With 'm', you can mark the highlighted\n");
  1501.           printw("item so it will be used as argument for the next command.\n\n");
  1502.           printw("The 4 menu-pages are:\n");
  1503.           printw("  FUNCTION-menu : definition position and calls of functions \n");
  1504.           printw("  VARIABLE-menu : definition and usage of variables and data-types\n");
  1505.           printw("  FILE-menu     : include files / #define's \n");
  1506.           printw("  MISC-menu     : communication, sorting and misc. options\n");
  1507.           break;
  1508.        case 1:
  1509.           printw("BRS_CLIENT             VARIABLE-MENU                  HELP-SCREEN\n\n");
  1510.           printw("This menu shows all commands concerning variables and data-types.\n");
  1511.           printw("Most of them should be clear. An interesting command is the \n");
  1512.           printw("possibility to show the usage of a struct or union component, esp.\n");
  1513.           printw("with a specified variable-identifier ('.' and ':')\n");
  1514.           break;
  1515.        case 2:
  1516.           printw("BRS_CLIENT               FILE-MENU                    HELP-SCREEN\n\n");
  1517.           printw("This menu shows all commands concerning source-files and macros.\n");
  1518.           printw("('#define'). The 'What is' command tells the type of an identifier.\n");
  1519.           printw("Since there is no possibility to have two source-files with the same\n");
  1520.           printw("name in a project (at least at the moment), you can retrieve the\n");
  1521.           printw("working directory of a specified source file by entering its name.");
  1522.           break;
  1523.        case 3:
  1524.           printw("BRS_CLIENT               MISC-MENU                    HELP-SCREEN\n\n");
  1525.           printw("This menu shows all commands which do not fit into one of the others.\n");
  1526.           printw("With 'l', you clear the marking you have set within a result-list.\n");
  1527.           printw("By pressing 'o', you cycle between 'no order', 'sort by identifier'\n");
  1528.           printw("and 'sort by filename'. You can set a new Timeout-value for the\n");
  1529.           printw("client-server communication. The 'a' command is mainly for debugging\n");
  1530.           printw("purposes, but we still are in ALPHA-stage :-). You can switch between\n");
  1531.           printw("the very slow internal viewer (with special functions) and the 'vi'.\n");
  1532.           printw("Since there is a support for multiple servers at a time, you can \n");
  1533.           printw("connect to a different server or tell the actual server to process a\n");
  1534.           printw("new project.\n");
  1535.           printw("At last, you can quit this program with ('k') or without ('q') killing\n");
  1536.           printw("the server. When killing the server, the IPC connection will be cleaned\n");
  1537.           break;
  1538.        case 4:
  1539.           printw("BRS_CLIENT               RESULT-LIST                    HELP-SCREEN\n\n");
  1540.           printw("This is a list with the result of the command issued. You can move \n");
  1541.           printw("around with the KEY-UP/KEY-DOWN keys ('k'/'j' respectivly), the PAGE-\n");
  1542.           printw("UP/PAGE-DOWN keys (CTRL-U / CTRL-D), the 't' (top of list) and the 'b'\n");
  1543.           printw("(bottom of list) keys. The highlighted line is the currently active\n");
  1544.           printw("one. You can mark it with the 'm' key, so this file and the identifier\n");
  1545.           printw("will be stored in a buffer and will be used as argument for the next \n");
  1546.           printw("command. By pressing 'v', the position in the source file will be dis-\n");
  1547.           printw("played in the file-windows.\n");
  1548.           printw("You can save the results (currently displayed window only or all \n");
  1549.           printw("results to a file by pressing 'w' or 'f'\n");
  1550.           break;
  1551.        case 5:
  1552.           printw("\nBRS_CLIENT               FILE-WINDOW                   HELP-SCREEN\n\n");
  1553.           printw("You can see the source-file at the selected position. You can move\n");
  1554.           printw("around like in all other windows. With the 'B'-command, you get back\n");
  1555.           printw("to the line you started.\n");
  1556.           printw("By pressing 'i', you enter the IDENT-Mode and the first valid token\n");
  1557.           printw("in the current line (marked linenumber) will be highlighted. Typing\n");
  1558.           printw("'i' again, you select the next token. If the token is a valid function\n");
  1559.           printw("identifier, you can 'jump' the the definition position of the function\n");
  1560.           printw("with 'c' (call). The current position will be saved in a stack, so you\n");
  1561.           printw("can return to it by pressing 'r' (return). The definition position of\n");
  1562.           printw("any other identifier can be viewed by 'd'. You can also issue the 'What\n");
  1563.           printw("is'-command for this identifier.");
  1564.           break;
  1565.       }
  1566.    move(LINES - 3,0);
  1567.    printw("   press a key: ");
  1568.    refresh();
  1569.  
  1570.    in =  getch();
  1571.  }
  1572.    
  1573.    
  1574. /* print simple menu
  1575.  */
  1576. int menu(void)
  1577. { int in = 0;
  1578.   static short  menu_nr = 0;
  1579.        
  1580.   do { 
  1581.      erase();
  1582.      move( LINES - 1, 0  );
  1583.      printw("last Error: %s", last_error_msg );
  1584.    
  1585.      move(0,0);
  1586.      printw("Choose command:" );
  1587.      if( marked_item[0] )
  1588.        printw(" (marked: '%s' '%s')\n\n", marked_item, marked_file);
  1589.      else
  1590.        printw("                                            \n\n");
  1591.       
  1592.      switch( menu_nr )
  1593.       { case 0 : /* function menu */
  1594.              printw( menu_functions );
  1595.              break;
  1596.         case 1 :
  1597.              printw( menu_variables);
  1598.              break;
  1599.         case 2 :
  1600.              printw( menu_files);
  1601.              break;
  1602.         case 3 :
  1603.              printw( menu_misc, (Sort_flag == SORT_BY_ITEM) ? "sort by item" :
  1604.                                 ((Sort_flag == SORT_BY_FILE) ? "sort by file" : "none"),
  1605.                                 (vi_flag) ? "vi" : "internal");
  1606.              break;
  1607.        }
  1608.          
  1609.      move(LINES - 3,0);
  1610.      printw("   Your choice: ");
  1611.  
  1612.      refresh();
  1613.  
  1614.      in =  getch();
  1615.      switch( in )
  1616.        { case '+': 
  1617.             menu_nr = (menu_nr < 3) ? menu_nr + 1 : 0;
  1618.             in = 0;
  1619.             break;
  1620.          case '-': 
  1621.             menu_nr = (menu_nr > 0) ? menu_nr - 1 : 3;
  1622.             in = 0;
  1623.             break;
  1624.          case '[': 
  1625.             vi_flag = !vi_flag;
  1626.             in = 0;
  1627.             break;
  1628.          case 'o': 
  1629.             Sort_flag++;
  1630.             if( Sort_flag > SORT_BY_FILE && Sort_flag > SORT_BY_ITEM )
  1631.               Sort_flag = 0;
  1632.             in = 0;
  1633.             break;
  1634.          case '?':
  1635.             help( menu_nr );
  1636.             in = 0;
  1637.             break;
  1638.                         
  1639.         }
  1640.          
  1641.     } while( !in );
  1642.    
  1643.    erase();
  1644.    
  1645.    return( in );
  1646.  }
  1647.  
  1648.  
  1649. main( int argc, char *argv[] )
  1650. { int  server;
  1651.   short  ret,
  1652.          code,
  1653.          static_flag;
  1654.   long   line,
  1655.          line_end,
  1656.          m_id;
  1657.    
  1658.   short  cmd, flag;
  1659.   int    pid, mtype, cnt, m_char;
  1660.   char   buffer[INTRFACE_BUFSIZE];
  1661.  
  1662.    
  1663.   initscr();
  1664.   cbreak();
  1665.   noecho();
  1666.   keypad( stdscr, TRUE );
  1667.  
  1668.   init_lines();   
  1669.   init_file_memory();   
  1670.    
  1671.   while(1)     
  1672.    {  m_char = menu();
  1673.       strcpy( last_error_msg, "No Error" );
  1674.       MARKING_ALLOWED();
  1675.       SET_MARK_TYPES( MARK_FUNCTION, MARK_FILE);
  1676.       
  1677.       switch( m_char )
  1678.        { case 'F': /* Print all functions in project */
  1679.            do 
  1680.              { ret = brs_get_all_funct( funct, file, &line, module, &static_flag);
  1681.                if( !ret )
  1682.                  { push_data_left( funct, (static_flag) ? "(static)" : "" );
  1683.                    sprintf(right, "%ld", line );
  1684.                    push_data_right(file, right, module );
  1685.                   }
  1686.                if( ret == RET_VAR )
  1687.                  ret = 0;
  1688.                } while( !ret );     
  1689.       
  1690.            switch( ret )
  1691.             { case RET_TIMEOUT: 
  1692.                    sprintf( last_error_msg, "No connection !\n");
  1693.                    break;
  1694.             
  1695.               case RET_ERROR:
  1696.                    sprintf( last_error_msg, "%s %s !\n", funct, file);
  1697.                    break;
  1698.          
  1699.               case RET_END:
  1700.                    /* r1: filem r2: line 
  1701.                     */
  1702.                    print_output( "All functions in project", 2, 3);
  1703.                    break;
  1704.          
  1705.               default:
  1706.                    sprintf( last_error_msg, "\n**** Error: Code %hd %s %s\n", ret, funct, file );
  1707.              }
  1708.          
  1709.            /* reset function for next call
  1710.             */
  1711.            brs_get_all_funct( NULL, NULL, NULL, NULL, NULL);
  1712.  
  1713.            reset_line_data();
  1714.            break;
  1715.          
  1716.          case 'c': case 'C': /* print functions called by target */
  1717.            MARKING_ALLOWED();
  1718.            left[0] = 0;
  1719.            right[0] = 0;
  1720.            if( CHECK_MARK_ITEM_TYPE( MARK_FUNCTION) )
  1721.              { strcpy( left, marked_item );
  1722.                if( CHECK_MARK_FILE_TYPE( MARK_FILE) )
  1723.                  strcpy( right, marked_file );
  1724.               }
  1725.            else
  1726.             { printw("\nEnter function-name      : ");
  1727.               refresh();
  1728.               echo();
  1729.               getstr( left );
  1730.               printw("\nFilename if static symbol: ");
  1731.               refresh();
  1732.               getstr( right );
  1733.               noecho();
  1734.              }
  1735.            SET_MARK_TYPES( MARK_FUNCTION, MARK_FILE);
  1736.            do 
  1737.              { /* if 'c', set the sym_once-flag causing the browser to
  1738.                   just return the first calling-position instead of all */
  1739.                ret = brs_get_funct_calls( left, right, 
  1740.                                  ( m_char == 'c' ) ? 1 : 0,
  1741.                                  funct, file, &line, module, &static_flag);
  1742.                if( !ret )
  1743.                  { push_data_left( funct, (static_flag) ? "(static)" : "" );
  1744.                    sprintf(right, "%ld", line );
  1745.                    push_data_right(file, right, module );
  1746.                   }
  1747.                } while( !ret );     
  1748.       
  1749.            switch( ret )
  1750.             { case RET_TIMEOUT: 
  1751.                    sprintf( last_error_msg, "No connection !\n");
  1752.                    break;
  1753.          
  1754.               case RET_ERROR:
  1755.                    sprintf( last_error_msg, "%s %s !\n", funct, file);
  1756.                    break;
  1757.          
  1758.               case RET_END:
  1759.                    /* r1: filem r2: line 
  1760.                     */
  1761.                    sprintf( right, "Functions called by '%s'%s", left, 
  1762.                               (m_char == 'c') ? "" : " (all)");
  1763.                    print_output( right, 2, 3);
  1764.                    break;
  1765.  
  1766.               /* case RET_ERROR: */
  1767.          
  1768.               default:
  1769.                    sprintf( last_error_msg, "\n**** Error: Code %hd %s %s\n", ret, funct, file );
  1770.              }
  1771.          
  1772.  
  1773.            /* reset */
  1774.            brs_get_funct_calls( NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
  1775.  
  1776.            reset_line_data();
  1777.            break;
  1778.          
  1779.          case 'b': case 'B': /* print functions calling target-function */
  1780.            MARKING_ALLOWED();
  1781.            left[0] = 0;
  1782.            right[0] = 0;
  1783.            if( CHECK_MARK_ITEM_TYPE( MARK_FUNCTION) )
  1784.              { strcpy( left, marked_item );
  1785.                if( CHECK_MARK_FILE_TYPE( MARK_FILE) )
  1786.                  strcpy( right, marked_file );
  1787.               }
  1788.            else
  1789.             { printw("\nEnter function-name      : ");
  1790.               refresh();
  1791.               echo();
  1792.               getstr( left );
  1793.               printw("\nFilename if static symbol: ");
  1794.               refresh();
  1795.               getstr( right );
  1796.               noecho();
  1797.              }
  1798.            SET_MARK_TYPES( MARK_FUNCTION, MARK_FILE);
  1799.            do 
  1800.              { /* if 'b', set the sym_once-flag causing the browser to
  1801.                   just return the first calling-position instead of all */
  1802.                ret = brs_get_funct_called_by( left, right, 
  1803.                                  ( m_char == 'b' ) ? 1 : 0,
  1804.                                  funct, file, &line, module, &static_flag);
  1805.                if( !ret )
  1806.                  { push_data_left( funct, (static_flag) ? "(static)" : "" );
  1807.                    sprintf(right, "%ld", line );
  1808.                    push_data_right(file, right, module );
  1809.                   }
  1810.                } while( !ret );     
  1811.       
  1812.            switch( ret )
  1813.             { case RET_TIMEOUT: 
  1814.                    sprintf( last_error_msg, "No connection !\n");
  1815.                    break;
  1816.          
  1817.               case RET_ERROR:
  1818.                    sprintf( last_error_msg, "%s %s !\n", funct, file);
  1819.                    break;
  1820.          
  1821.               case RET_END:
  1822.                    /* r1: file r2: line 
  1823.                     */
  1824.                    sprintf( right, "Functions calling '%s'%s", left, 
  1825.                               (m_char == 'b') ? "" : " (all)");
  1826.                    print_output( right, 2, 3);
  1827.                    break;
  1828.  
  1829.               /* case RET_ERROR: */
  1830.          
  1831.               default:
  1832.                    sprintf( last_error_msg, "\n**** Error: Code %hd %s %s\n", ret, funct, file );
  1833.              }
  1834.          
  1835.  
  1836.            /* reset */
  1837.            brs_get_funct_called_by( NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
  1838.  
  1839.            reset_line_data();
  1840.            break;
  1841.          
  1842.          case 's': case 'S': /* print functions using target-variable */
  1843.            MARKING_ALLOWED();
  1844.            left[0] = 0;
  1845.            right[0] = 0;
  1846.            if( CHECK_MARK_ITEM_TYPE( MARK_VARIABLE) )
  1847.              { strcpy( left, marked_item );
  1848.                if( CHECK_MARK_FILE_TYPE( MARK_FILE) )
  1849.                  strcpy( right, marked_file );
  1850.               }
  1851.            else
  1852.             { printw("\nEnter variable-name      : ");
  1853.               refresh();
  1854.               echo();
  1855.               getstr( left );
  1856.               printw("\nFilename if static symbol: ");
  1857.               refresh();
  1858.               getstr( right );
  1859.               noecho();
  1860.              }
  1861.            SET_MARK_TYPES( MARK_FUNCTION, MARK_FILE);
  1862.            do 
  1863.              { /* if 'c', set the sym_once-flag causing the browser to
  1864.                   just return the first calling-position instead of all */
  1865.                ret = brs_get_var_used_by( left, right, 
  1866.                                  ( m_char == 's' ) ? 1 : 0,
  1867.                                  funct, file, &line, module, &static_flag);
  1868.                if( !ret )
  1869.                  { push_data_left( funct, (static_flag) ? "(static)" : "" );
  1870.                    sprintf(right, "%ld", line );
  1871.                    push_data_right(file, right, module );
  1872.                   }
  1873.                } while( !ret );     
  1874.       
  1875.            switch( ret )
  1876.             { case RET_TIMEOUT: 
  1877.                    sprintf( last_error_msg, "No connection !\n");
  1878.                    break;
  1879.          
  1880.               case RET_ERROR:
  1881.                    sprintf( last_error_msg, "%s %s !\n", funct, file);
  1882.                    break;
  1883.          
  1884.               case RET_END:
  1885.                    /* r1: file r2: line 
  1886.                     */
  1887.                    sprintf( right, "Functions using '%s'%s", left, 
  1888.                               (m_char == 's') ? "" : " (all)");
  1889.                    print_output( right, 2, 3);
  1890.                    break;
  1891.  
  1892.               /* case RET_ERROR: */
  1893.          
  1894.               default:
  1895.                    sprintf( last_error_msg, "\n**** Error: Code %hd %s %s\n", ret, funct, file );
  1896.              }
  1897.          
  1898.  
  1899.            /* reset */
  1900.            brs_get_var_used_by( NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
  1901.  
  1902.            reset_line_data();
  1903.            break;
  1904.          
  1905.          case 'd':  /* print definition position */
  1906.            MARKING_NOT_ALLOWED();
  1907.            left[0] = 0;
  1908.            right[0] = 0;
  1909.            if( CHECK_MARK_ITEM_TYPE( MARK_FUNCTION) )
  1910.              { strcpy( left, marked_item );
  1911.                if( CHECK_MARK_FILE_TYPE( MARK_FILE) )
  1912.                  strcpy( right, marked_file );
  1913.               }
  1914.            else
  1915.             { printw("\nEnter function-name      : ");
  1916.               refresh();
  1917.               echo();
  1918.               getstr( left );
  1919.               printw("\nFilename if static symbol: ");
  1920.               refresh();
  1921.               getstr( right );
  1922.               noecho();
  1923.              }
  1924.            ret = brs_get_funct_pos( left, right, file, &line, &line_end, module);
  1925.          
  1926.            if( !ret )
  1927.              { push_data_left( left, "" );
  1928.                sprintf(right, "%ld - %ld", line, line_end );
  1929.                push_data_right(file, right, module );
  1930.                /* r1: file r2: line 
  1931.                 */
  1932.                sprintf( right, "Definition of function '%s'", left );
  1933.                print_output( right, 2, 3);
  1934.               }
  1935.       
  1936.            else
  1937.             { switch( ret )
  1938.                { case RET_TIMEOUT: 
  1939.                       sprintf( last_error_msg, "No connection !\n");
  1940.                       break;
  1941.          
  1942.                  case RET_ERROR:
  1943.                       sprintf( last_error_msg, "%s %s !\n", file, module);
  1944.                       break;
  1945.          
  1946.                  /* case RET_ERROR: */
  1947.          
  1948.                  default:
  1949.                       sprintf( last_error_msg, "\n**** Error: Code %hd %s %s\n", ret, file, module );
  1950.                 }
  1951.              }
  1952.          
  1953.  
  1954.            reset_line_data();
  1955.            break;
  1956.  
  1957.          case 'u': case 'U':  /* get variables used by a function */
  1958.            MARKING_ALLOWED();
  1959.            left[0] = 0;
  1960.            right[0] = 0;
  1961.            if( CHECK_MARK_ITEM_TYPE( MARK_FUNCTION) )
  1962.              { strcpy( left, marked_item );
  1963.                if( CHECK_MARK_FILE_TYPE( MARK_FILE) )
  1964.                  strcpy( right, marked_file );
  1965.               }
  1966.            else
  1967.             { printw("\nEnter function-name      : ");
  1968.               refresh();
  1969.               echo();
  1970.               getstr( left );
  1971.               printw("\nFilename if static symbol: ");
  1972.               refresh();
  1973.               gets( right );
  1974.               noecho();
  1975.              }
  1976.            SET_MARK_TYPES( MARK_VARIABLE, MARK_FILE);
  1977.            
  1978.            do 
  1979.              { ret = brs_get_var_uses( left, right, 
  1980.                                  ( m_char == 'u' ) ? 1 : 0,
  1981.                                funct, file, &line, module, &static_flag);
  1982.                if( !ret )
  1983.                  { push_data_left( funct, (static_flag) ? "(static)" : "" );
  1984.                    sprintf(right, "%ld", line );
  1985.                    push_data_right(file, right, module );
  1986.                   }
  1987.                } while( !ret );     
  1988.       
  1989.            switch( ret )
  1990.             { case RET_TIMEOUT: 
  1991.                    sprintf( last_error_msg, "No connection !\n");
  1992.                    break;
  1993.          
  1994.               case RET_ERROR:
  1995.                    sprintf( last_error_msg, "%s %s !\n", funct, file);
  1996.                    break;
  1997.          
  1998.               case RET_END:
  1999.                    /* r1: filem r2: line 
  2000.                     */
  2001.                    sprintf( right, "Variables used by '%s'%s", left, 
  2002.                               (m_char == 'u') ? "" : " (all)");
  2003.                    print_output( right, 2, 3);
  2004.                    break;
  2005.  
  2006.               /* case RET_ERROR: */
  2007.          
  2008.               default:
  2009.                    sprintf( last_error_msg, "\n**** Error: Code %hd %s %s\n", ret, funct, file );
  2010.              }
  2011.          
  2012.  
  2013.            /* reset */
  2014.            brs_get_var_uses( NULL, NULL, 0, NULL, NULL, NULL, NULL, NULL);
  2015.                     
  2016.            reset_line_data();
  2017.            break;
  2018.          
  2019.          case 'V': /* print all variables in project */
  2020.            MARKING_ALLOWED();
  2021.            SET_MARK_TYPES( MARK_VARIABLE, MARK_FILE);
  2022.            do 
  2023.              { ret = brs_get_all_global_vars( funct, file, &line, module, &static_flag);
  2024.                if( !ret )
  2025.                  { push_data_left( funct, (static_flag) ? "(static)" : "" );
  2026.                    sprintf(right, "%ld", line );
  2027.                    push_data_right(file, right, module );
  2028.                   }
  2029.                } while( !ret );     
  2030.       
  2031.            switch( ret )
  2032.             { case RET_TIMEOUT: 
  2033.                    sprintf( last_error_msg, "No connection !\n");
  2034.                    break;
  2035.          
  2036.               case RET_ERROR:
  2037.                    sprintf( last_error_msg, "%s %s !\n", funct, file);
  2038.                    break;
  2039.          
  2040.               case RET_END:
  2041.                    /* r1: filem r2: line 
  2042.                     */
  2043.                    print_output( "All global variables defined in project", 2, 3);
  2044.                    break;
  2045.          
  2046.               default:
  2047.                    sprintf( last_error_msg, "\n**** Error: Code %hd %s %s\n", ret, funct, file );
  2048.              }
  2049.          
  2050.            /* reset function for next call
  2051.             */
  2052.            brs_get_all_global_vars( NULL, NULL, NULL, NULL, NULL);
  2053.          
  2054.            reset_line_data();
  2055.            break;
  2056.          
  2057.          case 'D':  /* definition position of a variable */
  2058.            MARKING_NOT_ALLOWED();
  2059.            left[0] = 0;
  2060.            right[0] = 0;
  2061.            if( CHECK_MARK_ITEM_TYPE( MARK_VARIABLE) )
  2062.              { strcpy( left, marked_item );
  2063.                if( CHECK_MARK_FILE_TYPE( MARK_FILE) )
  2064.                  strcpy( right, marked_file );
  2065.               }
  2066.            else
  2067.             { printw("\nEnter variable-name      : ");
  2068.               refresh();
  2069.               echo();
  2070.               getstr( left );
  2071.               printw("\nFilename if static symbol: ");
  2072.               refresh();
  2073.               getstr( right );
  2074.               noecho();
  2075.              }
  2076.            ret = brs_get_var_pos( left, right, file, &line, module);
  2077.            if( !ret )
  2078.              { push_data_left( left, "" );
  2079.                sprintf(right, "%ld", line );
  2080.                push_data_right(file, right, module );
  2081.                /* r1: filem r2: line 
  2082.                 */
  2083.                sprintf( right, "Definition of variable '%s'", left );
  2084.                print_output( right, 2, 3);
  2085.               }
  2086.       
  2087.            else
  2088.             { switch( ret )
  2089.                { case RET_TIMEOUT: 
  2090.                       sprintf( last_error_msg, "No connection !\n");
  2091.                       break;
  2092.          
  2093.                  case RET_ERROR:
  2094.                       sprintf( last_error_msg, "%s %s !\n", file, module);
  2095.                       break;
  2096.          
  2097.                  /* case RET_ERROR: */
  2098.          
  2099.                  default:
  2100.                       sprintf( last_error_msg, "\n**** Error: Code %hd %s %s\n", ret, file, module );
  2101.                 }
  2102.              }
  2103.          
  2104.            reset_line_data();
  2105.            break;
  2106.          
  2107.          case 't': /* structs  */
  2108.          case 'n': /* unions   */
  2109.          case 'm': /* enums    */
  2110.          case 'y': /* typedefs */
  2111.            MARKING_NOT_ALLOWED();  /* for now, maybe later allowed if we reuse types */
  2112.          
  2113.            switch( m_char )
  2114.             { case 't': code = 0; strcpy( left, "All structs in project" ); break;
  2115.               case 'n': code = 1; strcpy( left, "All unions in project" ); break;
  2116.               case 'm': code = 2; strcpy( left, "All enums in project" ); break;
  2117.               case 'y': code = 3; strcpy( left, "All typedefs in project" ); break;
  2118.              }
  2119.              
  2120.            do 
  2121.              { ret = brs_get_all_types( code, funct, file, &line);
  2122.                if( !ret )
  2123.                  { push_data_left( funct, "" );
  2124.                    sprintf(right, "%ld", line );
  2125.                    push_data_right(file, right, "" );
  2126.                   }
  2127.                } while( !ret );     
  2128.       
  2129.            switch( ret )
  2130.             { case RET_TIMEOUT: 
  2131.                    sprintf( last_error_msg, "No connection !\n");
  2132.                    break;
  2133.          
  2134.               case RET_ERROR:
  2135.                    sprintf( last_error_msg, "%s %s!\n", funct, file);
  2136.                    break;
  2137.          
  2138.               case RET_END:
  2139.                    /* r1: filem r2: line 
  2140.                     */
  2141.                    print_output( left, 2, 3);
  2142.                    break;
  2143.          
  2144.               default:
  2145.                    sprintf( last_error_msg, "\n**** Error: Code %hd %s %s\n", ret, funct, file );
  2146.              }
  2147.          
  2148.            /* reset function for next call
  2149.             */
  2150.            brs_get_all_types( 0, NULL, NULL, NULL);
  2151.  
  2152.            reset_line_data();
  2153.            break;
  2154.          
  2155.          case '.': /* reference components  */
  2156.          case ':': /* reference components with variables  */
  2157.            MARKING_NOT_ALLOWED();  /* for now, maybe later allowed if we reuse types */
  2158.          
  2159.            left[0] = 0;
  2160.            right[0] = 0;
  2161.            printw("\nEnter component-name      : ");
  2162.            refresh();
  2163.            echo();
  2164.            getstr( left );
  2165.            noecho();
  2166.          
  2167.            switch( m_char )
  2168.             { case '.': 
  2169.                   code = 1;
  2170.                   if( CHECK_MARK_ITEM_TYPE( MARK_FUNCTION) )
  2171.                     { strcpy( right, marked_item );
  2172.                      }
  2173.                   else
  2174.                    { 
  2175.                      printw("\n\nFunction-name (or \"\" if global) : ");
  2176.                      refresh();
  2177.                      echo();
  2178.                      gets( right );
  2179.                      noecho();
  2180.                     }
  2181.             
  2182.                   if( right[0] == 0 )
  2183.                    { if( CHECK_MARK_FILE_TYPE( MARK_FILE) )
  2184.                        { strcpy( right, marked_item );
  2185.                         }
  2186.                      else
  2187.                       { 
  2188.                         printw("\n\nNo Function specified, select file-name \n");
  2189.                         printw("\nFile-name (or \"\" if global) : ");
  2190.                         refresh();
  2191.                         echo();
  2192.                         gets( right );
  2193.                         noecho();
  2194.                        }
  2195.                      code = 0;
  2196.                     }
  2197.                   break;
  2198.             
  2199.               case ':': 
  2200.                   code = 2;
  2201.             
  2202.                   if( CHECK_MARK_ITEM_TYPE( MARK_VARIABLE) )
  2203.                     { strcpy( right, marked_item );
  2204.                      }
  2205.                   else
  2206.                    { 
  2207.                      printw("\n\nVariable-name          : ");
  2208.                      refresh();
  2209.                      echo();
  2210.                      gets( right );
  2211.                      noecho();
  2212.                     }
  2213.                   break;
  2214.              }
  2215.              
  2216.            do 
  2217.              { ret = brs_get_component_use( code, left, right, file, &line, funct);
  2218.                if( !ret )
  2219.                  { push_data_left( file, "" );
  2220.                    sprintf(right, "%ld", line );
  2221.                    push_data_right(funct, right, "" );
  2222.                   }
  2223.                } while( !ret );     
  2224.       
  2225.            switch( ret )
  2226.             { case RET_TIMEOUT: 
  2227.                    sprintf( last_error_msg, "No connection !\n");
  2228.                    break;
  2229.          
  2230.               case RET_ERROR:
  2231.                    sprintf( last_error_msg, "%s %s!\n", funct, file);
  2232.                    break;
  2233.          
  2234.               case RET_END:
  2235.                    /* l1: filem r2: line 
  2236.                     */
  2237.                    sprintf(right, "Usage of component '%s'", left);
  2238.                    print_output( right, 0, 3);
  2239.                    break;
  2240.          
  2241.               default:
  2242.                    sprintf( last_error_msg, "\n**** Error: Code %hd %s %s\n", ret, funct, file );
  2243.              }
  2244.          
  2245.            /* reset function for next call
  2246.             */
  2247.            brs_get_component_use( 0, NULL, NULL, NULL, NULL, NULL);
  2248.  
  2249.            reset_line_data();
  2250.            break;
  2251.          
  2252.          case 'f': /* Print all files in project */
  2253.            MARKING_NOT_ALLOWED();
  2254.            do 
  2255.              { ret = brs_get_all_files( file, module);
  2256.                if( !ret )
  2257.                  { push_data_left( file, "" );
  2258.                    push_data_right( module, "", "" );
  2259.                   }
  2260.                } while( !ret );     
  2261.       
  2262.            switch( ret )
  2263.             { case RET_TIMEOUT: 
  2264.                    sprintf( last_error_msg, "No connection !\n");
  2265.                    break;
  2266.             
  2267.               case RET_ERROR:
  2268.                    sprintf( last_error_msg, "%s %s !\n", file, module);
  2269.                    break;
  2270.          
  2271.               case RET_END:
  2272.                    /* l1: filem  line: none
  2273.                     */
  2274.                    print_output( "All files in project", 0, -1);
  2275.                    break;
  2276.          
  2277.               default:
  2278.                    sprintf( last_error_msg, "\n**** Error: Code %hd %s %s\n", ret, file, module );
  2279.              }
  2280.          
  2281.            /* reset function for next call
  2282.             */
  2283.            brs_get_all_files( NULL, NULL);
  2284.  
  2285.            reset_line_data();
  2286.            break;
  2287.  
  2288.          case 'W': /* Print Whatis */
  2289.            MARKING_NOT_ALLOWED();
  2290.            left[0] = 0;
  2291.            right[0] = 0;
  2292.            printw("\nEnter ident-name      : ");
  2293.            refresh();
  2294.            echo();
  2295.            getstr( left );
  2296.            printw("\nFilename (or \"\")      : ");
  2297.            refresh();
  2298.            getstr( right );
  2299.            noecho();
  2300.            do 
  2301.              { ret = brs_what_is( left, right, 0, file, &line, module );
  2302.                switch( ret )
  2303.                  { case RET_MACRO:
  2304.                       push_data_left( left, "Macro" );
  2305.                       break;
  2306.                    case RET_VAR:
  2307.                       push_data_left( left, "Variable" );
  2308.                       break;
  2309.                    case RET_FUNCT:
  2310.                       push_data_left( left, "Function" );
  2311.                       break;
  2312.                    case RET_STRUCT:
  2313.                       push_data_left( left, "Struct" );
  2314.                       break;
  2315.                    case RET_UNION:
  2316.                       push_data_left( left, "Union" );
  2317.                       break;
  2318.                    case RET_ENUM:
  2319.                       push_data_left( left, "Enum" );
  2320.                       break;
  2321.                    case RET_TYPEDEF:
  2322.                       push_data_left( left, "Typedef" );
  2323.                       break;
  2324.                    case RET_COMP:
  2325.                       push_data_left( left, "struct/union comp" );
  2326.                       break;
  2327.                    case RET_ENUM_C:
  2328.                       push_data_left( left, "enum constant" );
  2329.                       break;
  2330.                    case RET_END: 
  2331.                    case RET_ERROR:
  2332.                    case RET_TIMEOUT:
  2333.                       break;
  2334.                    default:
  2335.                       break;
  2336.                   }
  2337.               if( ret != RET_END && ret != RET_ERROR && ret != RET_TIMEOUT )
  2338.                  { sprintf(right, "%ld", line );
  2339.                    push_data_right(file, right, module );
  2340.                   }
  2341.               } while( ret != RET_END && ret != RET_ERROR && ret != RET_TIMEOUT );     
  2342.       
  2343.            switch( ret )
  2344.             { case RET_TIMEOUT: 
  2345.                    sprintf( last_error_msg, "No connection !\n");
  2346.                    break;
  2347.             
  2348.               case RET_ERROR:
  2349.                    sprintf( last_error_msg, "%s %s !\n", funct, file);
  2350.                    break;
  2351.          
  2352.               case RET_END:
  2353.                    /* r1: filem r2: line 
  2354.                     */
  2355.                    print_output( "Whatis ...", 2, 3);
  2356.                    break;
  2357.          
  2358.               default:
  2359.                    sprintf( last_error_msg, "\n**** Error: Code %hd %s %s\n", ret, funct, file );
  2360.              }
  2361.          
  2362.            /* reset function for next call
  2363.             */
  2364.            brs_what_is( NULL, NULL, 0, NULL, NULL, NULL );
  2365.  
  2366.            reset_line_data();
  2367.            break;
  2368.  
  2369.          case '#': /* Print all macro-definitions in project */
  2370.            MARKING_ALLOWED();
  2371.            SET_MARK_TYPES( MARK_MACRO, MARK_FILE);
  2372.            do 
  2373.              { ret = brs_get_all_macro( funct, file, &line);
  2374.                if( !ret )
  2375.                  { push_data_left( funct, "" );
  2376.                    sprintf(right, "%ld", line );
  2377.                    push_data_right(file, right, "" );
  2378.                   }
  2379.                } while( !ret );     
  2380.       
  2381.            switch( ret )
  2382.             { case RET_TIMEOUT: 
  2383.                    sprintf( last_error_msg, "No connection !\n");
  2384.                    break;
  2385.             
  2386.               case RET_ERROR:
  2387.                    sprintf( last_error_msg, "%s %s !\n", funct, file);
  2388.                    break;
  2389.          
  2390.               case RET_END:
  2391.                    /* r1: filem r2: line 
  2392.                     */
  2393.                    print_output( "All macro definitions in project", 2, 3);
  2394.                    break;
  2395.          
  2396.               default:
  2397.                    sprintf( last_error_msg, "\n**** Error: Code %hd %s %s\n", ret, funct, file );
  2398.              }
  2399.          
  2400.            /* reset function for next call
  2401.             */
  2402.            brs_get_all_funct( NULL, NULL, NULL, NULL, NULL);
  2403.  
  2404.            reset_line_data();
  2405.            break;
  2406.  
  2407.          case '*':  /* definition position of a macro */
  2408.            MARKING_NOT_ALLOWED();
  2409.            left[0] = 0;
  2410.            right[0] = 0;
  2411.            if( CHECK_MARK_ITEM_TYPE( MARK_MACRO) )
  2412.              { strcpy( left, marked_item );
  2413.                if( CHECK_MARK_FILE_TYPE( MARK_FILE) )
  2414.                  strcpy( right, marked_file );
  2415.               }
  2416.            else
  2417.             { printw("\nEnter macro-name  : ");
  2418.               refresh();
  2419.               echo();
  2420.               getstr( left );
  2421.               printw("\nFilename          : ");
  2422.               refresh();
  2423.               getstr( right );
  2424.               noecho();
  2425.              }
  2426.            ret = brs_get_macro_pos( left, right, file, &line, module);
  2427.            if( !ret )
  2428.              { push_data_left( left, "" );
  2429.                sprintf(right, "%ld", line );
  2430.                push_data_right(file, right, module );
  2431.                /* r1: filem r2: line 
  2432.                 */
  2433.                sprintf( right, "Definition of macro '%s'", left );
  2434.                print_output( right, 2, 3);
  2435.               }
  2436.       
  2437.            else
  2438.             { switch( ret )
  2439.                { case RET_TIMEOUT: 
  2440.                       sprintf( last_error_msg, "No connection !\n");
  2441.                       break;
  2442.          
  2443.                  case RET_ERROR:
  2444.                       sprintf( last_error_msg, "%s %s !\n", file, module);
  2445.                       break;
  2446.          
  2447.                  /* case RET_ERROR: */
  2448.          
  2449.                  default:
  2450.                       sprintf( last_error_msg, "\n**** Error: Code %hd %s %s\n", ret, file, module );
  2451.                 }
  2452.              }
  2453.          
  2454.            reset_line_data();
  2455.            break;
  2456.          
  2457.          case 'i':  /* include files */
  2458.            MARKING_NOT_ALLOWED();
  2459.            funct[0] = 0;
  2460.            if( CHECK_MARK_FILE_TYPE( MARK_FILE) )
  2461.              { strcpy( funct, marked_file );
  2462.               }
  2463.            else
  2464.             { printw("\nEnter main filename: ");
  2465.               refresh();
  2466.               echo();
  2467.               getstr( funct );
  2468.               noecho();
  2469.              }
  2470.            
  2471.            do 
  2472.              { ret = brs_get_includes( funct, file, module, &static_flag);
  2473.                if( !ret )
  2474.                  { push_data_left( file, (static_flag) ? "(system)" : "" );
  2475.                    push_data_right( module, "", "" );
  2476.                   }
  2477.                } while( !ret );     
  2478.       
  2479.            switch( ret )
  2480.             { case RET_TIMEOUT: 
  2481.                    sprintf( last_error_msg, "No connection !\n");
  2482.                    break;
  2483.          
  2484.               case RET_ERROR:
  2485.                    sprintf( last_error_msg, "%s %s !\n", file, module);
  2486.                    break;
  2487.          
  2488.               case RET_END:
  2489.                    /* l1: file  no line
  2490.                     */
  2491.                    sprintf( right, "Include-files of '%s'", funct );
  2492.                    print_output( right, 0, -1);
  2493.                    break;
  2494.          
  2495.               default:
  2496.                    sprintf( last_error_msg, "\n**** Error: Code %hd %s\n", ret, file );
  2497.                    break;
  2498.              }
  2499.          
  2500.            /* reset function for next call
  2501.             */
  2502.            brs_get_includes( NULL, NULL, NULL, NULL);
  2503.                   
  2504.            reset_line_data();
  2505.            break;
  2506.          
  2507.          case 'w':  /* working directory of a file */
  2508.            MARKING_NOT_ALLOWED();
  2509.            file[0] = 0;
  2510.            if( CHECK_MARK_FILE_TYPE( MARK_FILE) )
  2511.              { strcpy( file, marked_file );
  2512.               }
  2513.            else
  2514.             { printw("\nEnter filename: ");
  2515.               refresh();
  2516.               echo();
  2517.               getstr( file );
  2518.               noecho();
  2519.              }
  2520.            
  2521.            ret = brs_get_file_dir( file, module );
  2522.            if( !ret )
  2523.              { push_data_left( file, "" );
  2524.                push_data_right( module, "", "" );
  2525.               }
  2526.       
  2527.            switch( ret )
  2528.             { case RET_TIMEOUT: 
  2529.                    sprintf( last_error_msg, "No connection !\n");
  2530.                    break;
  2531.          
  2532.               case RET_ERROR:
  2533.                    sprintf( last_error_msg, "%s %s !\n", file, module);
  2534.                    break;
  2535.          
  2536.               case 0:
  2537.                    /* l1: file  no line
  2538.                     */
  2539.                    sprintf( right, "Working directory of '%s'", file );
  2540.                    print_output( right, -1, -1);
  2541.                    break;
  2542.          
  2543.               default:
  2544.                    sprintf( last_error_msg, "\n**** Error: Code %hd %s\n", ret, file );
  2545.                    break;
  2546.              }
  2547.          
  2548.            reset_line_data();
  2549.            break;
  2550.          
  2551.          case 'l': /* clear marking */
  2552.            SET_MARK_TYPES( MARK_NULL, MARK_NULL);
  2553.            marked_item[0] = 0;
  2554.            marked_file[0] = 0;
  2555.            break;
  2556.          
  2557.          case 'T': /* new timeout*/
  2558.            right[0] = 0;
  2559.            printw("Old Timeout-value: %ld seconds \n", timeout_value);
  2560.            printw("Enter new value:  ");
  2561.            refresh();
  2562.            echo();
  2563.            getstr( right );
  2564.            noecho();
  2565.            timeout_value = atoi( right );
  2566.            sprintf( last_error_msg, "New Timeout set to %ld seconds", timeout_value );
  2567.            break;
  2568.          
  2569.          case 'R':  /* browser filename */
  2570.            printw("Enter new browser filename: ");
  2571.            refresh();
  2572.            echo();
  2573.            getstr( funct );
  2574.            noecho();
  2575.            ret = brs_reinit_browser( funct, left, right );
  2576.            if( ret )
  2577.              { printw("\nError: Code %hd %s %s\n", ret, left, right );
  2578.                Exit(1);
  2579.               }
  2580.            break;
  2581.          
  2582.          case 'r':  /* New server */
  2583.            printw("Enter browser filename to look for: ");
  2584.            refresh();
  2585.            echo();
  2586.            getstr( funct );
  2587.            noecho();
  2588.            ret = brs_get_server_id( funct );
  2589.            if( ret < 0 )
  2590.              { printw("\nError: Code %hd \n", ret );
  2591.                Exit(1);
  2592.               }
  2593.            brs_disconnect_server();
  2594.            server = brs_connect_server( ret );
  2595.            if( server != 0 )
  2596.              { printw("\nError: Code %hd \n", server );
  2597.                Exit(1);
  2598.               }
  2599.            break;
  2600.          
  2601.          case 'k':
  2602.            ret = brs_kill_server();
  2603.            if( ret )
  2604.              { printw("\nError: Code %hd \n", ret );
  2605.                Exit(1);
  2606.               }
  2607.            Exit(0);
  2608.          
  2609.          case 'q': /* quit */
  2610.            brs_disconnect_server();
  2611.            Exit(0);
  2612.          
  2613.          case 'a': /* get all messages in queue */
  2614.            while(1)
  2615.             { buffer[0] = 0;
  2616.               cnt = brs_get_any_message( &mtype, &cmd, &flag, &pid, &m_id, buffer);
  2617.               if( cnt == -1 )
  2618.                 break;
  2619.               sprintf(left, "Message (%d bytes): mtype: %d, cmd: %hd, flag %hx, pid: %d, msg-id: %ld",
  2620.                                cnt, mtype, cmd, flag, pid, m_id );
  2621.               sprintf(right, "Buffer            : \"%s\"", buffer );
  2622.             
  2623.               push_data_left( left, "" );
  2624.               push_data_right("", "", "" );
  2625.             
  2626.               push_data_left( right, "" );
  2627.               push_data_right("", "", "" );
  2628.             
  2629.              }
  2630.          
  2631.            print_output( "All messages in message queue", -1, -1);
  2632.            reset_line_data();
  2633.            break; 
  2634.            
  2635.          default:
  2636.            sprintf( last_error_msg, "Unknown Command '%c' (0x%02x)", m_char );
  2637.            break;
  2638.         }
  2639.     } /* endwhile */
  2640. }
  2641.          
  2642.    
  2643.