home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 19 / CD_ASCQ_19_010295.iso / vrac / adaada.zip / ADA.ZIP / ADA.C < prev    next >
C/C++ Source or Header  |  1992-11-23  |  13KB  |  522 lines

  1. /* $Header:   E:/new/ada.c_v   1.2   14 May 1992 14:08:12   ericj  $
  2. /*
  3.  *
  4.  *                     Copyright 1991 Premia Corp.
  5.  *                        All rights reserved
  6.  *
  7.  *    This source code is provided to the purchaser of the product
  8.  *    for the purpose of allowing the purchaser to customize and/or
  9.  *    extend the functionality of the product.  The source code   
  10.  *    remains the property of Premia Corp. with all rights reserved.
  11.  *    Any modifications to the source code are considered derivative
  12.  *    works and all rights thereto are reserved to Premia Corp. except
  13.  *    that the purchaser may use the modified product in the same
  14.  *    permitted manner as the unmodified product.  It is expressly
  15.  *    prohibited to distribute in any manner any part of the original
  16.  *    source code, whether in source or object form, without the
  17.  *    express written permission from Premia Corp.
  18.  *
  19.  *    Owner:
  20.  *        Premia Corporation
  21.  *        1075 NW Murray Blvd., Suite 268
  22.  *        Portland OR 97229
  23.  *
  24.  */
  25.  
  26. #include <windows.h>
  27. #include <string.h>
  28. #include <ctype.h>
  29. #include "exports.h"
  30. #include "startup.h"
  31.  
  32.  
  33. #define MAX_BUF_LEN    100
  34.  
  35. static LPVOID _ada_hash_names        = NIL;  /* pointer to the hash table containing */
  36.                                            /* all 'ADA' keyword names. */
  37.  
  38. static LPVOID _ada_hash_templates    = NIL;  /* pointer to the hash table containing */
  39.                                            /* an abbreviated name and its template */
  40.  
  41. /* Define a structure to hold an abbreviation and the template to be
  42.  * expanded when the abbreviation is entered into the buffer.
  43.  * This structure will be the element in the hash table _ada_hash_templates.
  44.  */
  45. typedef struct _LanguageTemplate {         
  46.     LPSTR abbrev;
  47.     LPSTR template;
  48. } LanguageTemplate;
  49.  
  50.  
  51. /* This string contains all keyword names which will be indented an extra level.
  52.  */
  53. LPSTR ADA_INDENT_STR = "PROC\377FOR\377IF\377SCAN\377WHILE\377THEN\377ELSE\377SWITCH\377";
  54.  
  55. /*
  56.  * _ada_templates[] contains the keyword abbreviation and the template for the
  57.  * abbreviation.  To add a new name, insert it before the NIL entry or
  58.  * call _ada_assign_template().
  59.  *
  60.  * The special characters within the template are:
  61.  *
  62.  *     \n - new line
  63.  *     &  - cursor position after template insertion
  64.  *     @  - backspace
  65.  *     \c - insert 'c' literally
  66.  */
  67. LanguageTemplate _ada_templates[] = {
  68.     { "IF",      "IF &\n\tTHEN\n@ENDIF" },
  69.     { NIL,       NIL },
  70. };
  71.  
  72. /* Define the list of 'ADA' keyword names to appear in
  73.  * the keyword color if language coloring is enabled.
  74.  */
  75. LPSTR _ada_names[] = {
  76.     "if",    "then",   "endif",
  77.     "use",   "width",  "package",
  78.     NIL
  79. };
  80.  
  81. static long _ada_in_comment( long offset );
  82.  
  83. void DLL _ada_init( void );
  84. BOOL DLL _ada_expand( void );
  85. void DLL _ada_language_colors_update( long firstline, long lastline );
  86. void DLL _ada_language_colors( long numlines );
  87. void DLL _ada_assign_template( LPSTR abbrev, LPSTR template );
  88. void DLL _ada_add_keyword( LPSTR keyword );
  89. BOOL DLL _ada_indent( void );
  90.  
  91. void DLL 
  92. _init()
  93. {
  94.     _ada_init();
  95. }
  96.  
  97.  
  98. /*
  99.  ** _ada_init()
  100.  *
  101.  *  Initialize this module by exported any required functions and
  102.  *  the hash tables needed to support indenting, template expandion
  103.  *  and keyword coloring.
  104.  */
  105. void DLL
  106. _ada_init( void )
  107. {
  108.     static BOOL firstTime = TRUE;
  109.     int    i;
  110.  
  111.     if (firstTime)
  112.     {
  113.         LibExport( "BOOL _ada_expand");
  114.         LibExport( "_ada_assign_template LPSTR LPSTR");
  115.         LibExport( "_ada_add_keyword LPSTR");
  116.         LibExport( "BOOL _ada_indent");
  117.         LibExport( "_ada_language_colors_update long long");
  118.         LibExport( "_ada_language_colors long");
  119.  
  120.         firstTime = FALSE;
  121.  
  122.         /* Create a hash table to hold all of the 'ADA' keyword names.
  123.          */
  124.         _ada_hash_names = HashCreateTable( 41 /* a prime # */, sizeof( LPSTR ), HASH_IGN_CASE );
  125.         i = 0;
  126.  
  127.         while ( _ada_names[ i ] != NIL )
  128.         {
  129.             *(LPSTR XFAR *)HashGetEntry( _ada_hash_names, _ada_names[i], strlen( _ada_names[i] ) )  
  130.                 = StrNew( _ada_names[i] );
  131.             i++;
  132.         }
  133.  
  134.         /* Create a hash table to hold all of the 'ADA' template names.
  135.          */
  136.         _ada_hash_templates = HashCreateTable( 17 /* a prime # */, sizeof( LPSTR ), HASH_IGN_CASE );
  137.         i = 0;
  138.  
  139.         while ( _ada_templates[ i ].abbrev != NIL )
  140.         {
  141.             _ada_assign_template( _ada_templates[i].abbrev, _ada_templates[i].template );
  142.             i++;
  143.         }
  144.     }
  145. }
  146.  
  147.  
  148. /*
  149.  ** _ada_expand()
  150.  *
  151.  *  DESCRIPTION:
  152.  *    Attempts to perform 'ADA' language template expansion.  This function
  153.  *    is normally bound to the <SPACE> key.  When invoked, it reads the 
  154.  *    previous word.  If the word is in the list of defined templates,
  155.  *    the template is extracted and inserted.  Some characters in the 
  156.  *    templates have special meanings. They are:
  157.  *
  158.  *       \n - new line
  159.  *       &  - cursor position after template insertion
  160.  *       @  - backspace
  161.  *       \  - take next character literally
  162.  */
  163. BOOL DLL
  164. _ada_expand( void )
  165. {
  166.     LPVOID htEntry;
  167.     LPSTR  _ada_string;
  168.     LPSTR  str;
  169.     long   curline;
  170.  
  171.     MarkSavePos();
  172.  
  173.     curline = BufQCurrentLine();
  174.  
  175.     /* Check to see if we are currently positioned inside a 'ADA' comment
  176.      */
  177.     if (_ada_in_comment( -1L ) != -1)
  178.         goto _ada_expand_incomplete;
  179.  
  180.     str = BufReadStr( 65535 );     /* read entire line */
  181.  
  182.     _ada_string = StrTrim( str, " \t" );
  183.     StrFree( str );
  184.  
  185.     if (!_ada_string)
  186.         goto _ada_expand_incomplete;
  187.  
  188.     /* Search for a keyword match in the hash table.
  189.      */
  190.     htEntry = HashFindEntry( _ada_hash_templates, _ada_string, strlen( _ada_string ) );
  191.     StrFree( _ada_string );
  192.  
  193.     if (htEntry)
  194.     {
  195.         /* A template exists for the current keyword, delete the keyword
  196.          * and insert the template.
  197.          */
  198.         MarkDropPos( 1 );
  199.         str = *(LPSTR*)htEntry;
  200.         BufDelToEOL();
  201.  
  202.         _ext_expand_template( str );
  203.  
  204.     } 
  205.     else
  206.         goto _ada_expand_incomplete;
  207.     return TRUE;
  208.  
  209. _ada_expand_incomplete:
  210.     MarkRestorePos();
  211.  
  212.     return FALSE;
  213. }
  214.  
  215. /*
  216.  ** _ada_language_colors_update()
  217.  *
  218.  *  This function does an intermediate update of the colors within
  219.  *  a range of line numbers (firstline and lastline).  It must also
  220.  *  determine if the first and last line specified are within a
  221.  *  comment and act appropriately.
  222.  */
  223. void DLL
  224. _ada_language_colors_update( long firstline, long lastline )
  225. {
  226.     long startoff;
  227.  
  228.     if (firstline && lastline)
  229.     {
  230.         /* Begin coloring at the previous comment if
  231.          * currently located in the middle of one.
  232.          */
  233.         _PosInit( 0 );
  234.         if (firstline == 1)
  235.             _PosPrevLine( 0L );
  236.         else
  237.             _PosNextLine( firstline - 1);
  238.         startoff = _PosQOffset();
  239.  
  240.         /* Clear all attributes for the line range and
  241.          * the reset them within _ada_language_colors.
  242.          */
  243.         AttrSetColor( firstline, lastline, 1L, 0x7FFFFFFFL, 0 );
  244.         _PosInit( startoff );
  245.         _ada_language_colors( lastline - firstline + 1 );
  246.     }
  247. }
  248.  
  249. /*
  250.  ** _ada_language_colors()
  251.  *
  252.  * If numlines == -1, start from the top of the buffer and encode all of them,
  253.  * otherwise start at the current location of the number of lines specified.
  254.  *
  255.  * It is assumed that if numlines != -1, that _PosInit() has been called
  256.  * and numlines is relative to the current position.
  257.  */
  258. void DLL
  259. _ada_language_colors( long numlines )
  260. {
  261.     long  startoff;
  262.     long  startline;
  263.     long  endoff;
  264.     long  inc;
  265.     WORD  ch;
  266.     LPSTR buf;
  267.     int   i = 0;
  268.     int   comment_color = ColorComments( -1 );
  269.     int   keyword_color = ColorKeywords( -1 );
  270.  
  271.     buf = (LPSTR)MemAlloc( MAX_BUF_LEN );
  272.  
  273.     /* Start at the top of the buffer or current position 
  274.      */
  275.     if (numlines == -1)
  276.     {
  277.         _PosInit( 0 );  
  278.         numlines = 0x7FFFFFFF;
  279.     }
  280.     else
  281.     {
  282.         startoff  = _PosQOffset();
  283.         startline = _PosQLine();
  284.         endoff    = _ada_in_comment( startoff );
  285.         if (endoff == -1)
  286.             _PosInit( startoff );
  287.         else
  288.         {
  289.             _PosInit( endoff );
  290.             numlines += (startline - _PosQLine());
  291.         }
  292.     }
  293.     ch = _PosCurrentChar();
  294.     startoff = _PosQOffset();
  295.  
  296.  
  297.     while ((ch != EOF_CHAR) && (numlines > 0))
  298.     {
  299.         if (ch == '\n')
  300.             numlines--;
  301.  
  302.         if (ch == '"' || ch == '\'')
  303.         {
  304.             WORD quote = ch;
  305.  
  306.             do 
  307.             {
  308.                 ch = _PosNextChar();
  309.             } while ((ch != EOF_CHAR) && (ch != '\n') && (ch != quote));
  310.  
  311.             if (ch == quote)
  312.                 ch = _PosNextChar();
  313.             continue;
  314.         }
  315.         else if (isalpha( ch ) || (ch == '_'))
  316.         {
  317.             WORD lastch = _PosPrevChar();
  318.  
  319.             if (lastch != EOF_CHAR)
  320.                 _PosNextChar();
  321.  
  322.             i = 0;
  323.             startoff = _PosQOffset();
  324.  
  325.             do
  326.             {
  327.                 if (i < MAX_BUF_LEN)
  328.                     buf[i++] = (char)ch;
  329.                 ch = _PosNextChar();
  330.             } while (isalpha( ch ) || (ch == '_'));
  331.  
  332.             if ((lastch != ' ' 
  333.                         && lastch != '\t' 
  334.                         && lastch != '\r' 
  335.                         && lastch != '\n' 
  336.                         && !ispunct( lastch ))
  337.                     || (ch == '_'))
  338.                 i = 0;
  339.             continue;
  340.         }
  341.         else if (i)
  342.         {
  343.             if (isalpha( buf[0] ))
  344.             {
  345.                 if (HashFindEntry( _ada_hash_names, buf, i ))
  346.                 {
  347.                     endoff = _PosQOffset();
  348.                     _PosInit( startoff );
  349.                     _PosSetColor( keyword_color, endoff - startoff );
  350.                     _PosInit( endoff );
  351.                 }
  352.             }
  353.             i = 0;
  354.         } 
  355.  
  356.         if (ch == '-')
  357.         {
  358.             startoff = _PosQOffset();
  359.             ch = _PosNextChar();
  360.             if (ch == '-')
  361.             {
  362.                 inc = _PosNextLine( 1 );
  363.                 numlines--;
  364.                 endoff = _PosQOffset();
  365.                 _PosInit( startoff );
  366.                 _PosSetColor( comment_color, endoff - startoff - inc );
  367.                 _PosInit( endoff );
  368.                 ch = _PosCurrentChar();
  369.             }
  370.             continue;
  371.         }
  372.         ch = _PosNextChar();
  373.     }
  374.     MemFree( buf );
  375. }
  376.  
  377.  
  378.  
  379. void DLL
  380. _ada_add_keyword( LPSTR keyword )
  381. {
  382.     if (keyword && *keyword)
  383.         *(LPSTR XFAR *)HashGetEntry( _ada_hash_names, keyword, strlen( keyword ) )  
  384.                 = StrNew( keyword );
  385. }
  386.  
  387.  
  388. /*
  389.  ** _ada_assign_template()
  390.  *
  391.  *  PARAMETERS:
  392.  *    abbrev   - the keyword abreviation used to locate a template
  393.  *    template - the encoded template string associated with 'abbrev'
  394.  *
  395.  *  DESCRIPTION:
  396.  *    Provide a means of adding or modifying 'ADA' template strings
  397.  *    without changing the code.
  398.  */
  399. void DLL
  400. _ada_assign_template( LPSTR abbrev, LPSTR template )
  401. {
  402.     if (abbrev && template)
  403.         *(LPSTR XFAR *)HashGetEntry( _ada_hash_templates, abbrev, strlen( abbrev ) )  
  404.                 = StrNew( template );
  405. }
  406.  
  407.  
  408. /*
  409.  ** _ada_indent()
  410.  *
  411.  *  DESCRIPTION:
  412.  *    Attempts to perform 'ADA' language smart indenting.  This function
  413.  *    will behave differently based on the following conditions:
  414.  *
  415.  *    1. Within a comment - normal indentation
  416.  *
  417.  *    2. Not positioned at end of line - normal indentation
  418.  *
  419.  *    3. Current line prefixed by a name in ADA_INDENT_STR - perform smart
  420.  *       indentation.  
  421.  */
  422. BOOL DLL
  423. _ada_indent( void )
  424. {
  425.     long   curline;
  426.     long   col;
  427.     LPSTR  _ada_string;
  428.     LPSTR  str;
  429.     long   matchpos;
  430.  
  431.     MarkSavePos();
  432.  
  433.     curline = BufQCurrentLine();
  434.  
  435.     /* Check to see if we are currently positioned inside a 'ADA' comment
  436.      */
  437.     if (_ada_in_comment( -1L ) != -1)
  438.         goto _ada_indent_incomplete;
  439.  
  440.     /* Not in a comment so indent according to the current 'ADA' construct.
  441.      */
  442.     if (!SrchFind( "^[ \t]*[a-zA-Z_]+\\c([ \t]|$)", SEARCH_REGEX , NIL )
  443.             || (BufQCurrentLine() != curline) )
  444.         goto _ada_indent_incomplete;
  445.  
  446.     /* Read the keyword at the beginning of the current line.
  447.      */
  448.     col = BufQCurrentCol();
  449.     SrchFind( "(^|[^a-zA-Z_])\\c[a-zA-Z_]", SEARCH_REGEX , NIL );
  450.     str = BufReadStr( col - BufQCurrentCol() );
  451.     _ada_string = StrTrim( str, " \t" );
  452.     StrFree( str );
  453.  
  454.     /* Set prefix and suffix to \377 to perform a quick lookup of the name
  455.      */
  456.     str = StrNew( "\377" );
  457.     _ada_string = StrAppend( _ada_string, str );
  458.     str = StrAppend( str, _ada_string );
  459.     StrFree( _ada_string );
  460.     
  461.     matchpos = StrMatch( str, ADA_INDENT_STR, SEARCH_IGCASE | SEARCH_FORWARD, NIL );
  462.     StrFree( str );
  463.  
  464.     if (!matchpos)
  465.         /* Not an 'ADA' keyword, do normal indentation. */
  466.         goto _ada_indent_incomplete;
  467.         
  468.     MarkRestorePos();
  469.  
  470.     _ext_insert_indented_EOL();
  471.     BufInsertChar( '\t' );
  472.     return TRUE;
  473.  
  474.     _ada_indent_incomplete:
  475.         MarkRestorePos();
  476.  
  477.     return FALSE;
  478. }
  479.  
  480.  
  481.  
  482. /*--  Private functions --*/
  483.  
  484.  
  485. /*
  486.  ** _ada_in_comment()
  487.  *
  488.  *  Determines whether or not the current position in the buffer is
  489.  *  located within a 'ADA' comment by search backward for a // or /* 
  490.  *  comment declaration.
  491.  *
  492.  *  Returns -1 if not in a comment 
  493.  *          >= 0 indicates the offset in the buffer where the comment begins
  494.  */
  495. static long
  496. _ada_in_comment( long offset )
  497. {
  498.     WORD  ch;
  499.  
  500.     /* Check to see if we are currently positioned inside an 'ADA' comment
  501.      */
  502.     _PosInit( offset );
  503.     ch = _PosCurrentChar();
  504.  
  505.     do
  506.     {
  507.         if (ch == '\n')
  508.             return -1;
  509.         else if (ch == '-')
  510.         {
  511.             ch = _PosPrevChar();
  512.             if (ch == '-')
  513.                 return _PosQOffset();  /* currrent line is in a comment */
  514.         }
  515.         else
  516.             ch = _PosPrevChar();
  517.     } while (ch != EOF_CHAR);
  518.  
  519.     return -1L;
  520. }
  521.  
  522.