/* brace.c: layout/dimentioning and drawing routines for braces. */
/* This file is part of asciiTeX.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
The Free Software Foundation, Inc.
59 Temple Place, Suite 330
Boston, MA 02111 USA
Authors:
Original program (eqascii): Przemek Borys
Fork by: Bart Pieters
*************************************************************************/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "utils.h"
#include "asciiTeX_struct.h"
#include "parsedef.h"
#include "dim.h"
#include "draw.h"
int
dimBrace(char *found, char **Gpos, Tdim * Our, struct Tgraph *graph)
/*
The dimXxx routines all have the forllowing arguments:
found -- Pointer to a sting containing the remaining part of the equation
Gpos -- Pointer to a string which will contain the part of the equation
relevant to the current parent with flags to indicate which drawing
routines to use.
Our -- dimention of the parent
graph -- The parent
The routines returns the number of characters it used of the found vector.
*/
{
#define gpos (*Gpos)
#define our (*Our)
char *start,
*end,
*tmp,
c;
Tdim out;
*gpos = 1; /* See parsedef.h for the keyword
* definitions */
gpos++;
*gpos = (char) BRACES;
gpos++;
*gpos = 0;
start = found + 5;
end = findClosingLRBrace(start);
c = (*end);
*end = 0;
tmp = strdup(found + 6);
*end = c;
out = dim(tmp, newChild(graph));
free(tmp);
tmp = malloc(sizeof(char) * 3);
tmp[0] = (*start);
tmp[1] = (*(end + 6));
tmp[2] = '\0';
/*
* Store the brace type in the options string of the child
*/
/*
* We will use it in the drawing routine
*/
graph->down[graph->children - 1]->options = strdup(tmp);
free(tmp);
if ((graph->down[graph->children - 1]->options[0] == '[')
&& (graph->down[graph->children - 1]->options[1] == ']'))
{
if (out.y > 1)
{
out.y++; /* make room for an underscore at
* the top */
out.x += 2; /* two braces of two chars wide */
}
} else if ((graph->down[graph->children - 1]->options[0] == '[')
|| (graph->down[graph->children - 1]->options[1] ==
']'))
{
if (out.y > 1)
{
out.y++; /* make room for an underscore at
* the top */
out.x += 1; /* one brace is two chars wide */
}
}
if (our.baseline < out.baseline)
{
our.y += (out.baseline - our.baseline);
our.baseline = out.baseline;
}
if (our.y - our.baseline < (out.y - out.baseline))
{
/*
* our.baseline++;
*/
our.y = (out.y - out.baseline) + our.baseline;
}
if ((graph->down[graph->children - 1]->options[0] == '{')
|| (graph->down[graph->children - 1]->options[1] == '}'))
our.y += (!(our.y % 2)); /* ensure y is uneven with
* room at the top */
our.x += out.x + 3;
return end + 6 - (found);
#undef gpos
#undef our
}
void
drawBrace(int *Kid, int *Curx, int *Cury, char ***screen,
struct Tgraph *graph)
/*
The drawXxx routines all have the forllowing arguments:
Kid -- Ineger index of the current child
Curx -- Current x position in the 2D character field
Cury -- Current y position in the 2D character field
screen -- pointer to the 2D character field
graph -- The parent
*/
{
#define kid (*Kid)
#define curx (*Curx)
#define cury (*Cury)
int low = cury + graph->down[kid]->dim.baseline;
int i;
/*
* the options of our child contains the brace type
*/
switch (graph->down[kid]->options[0])
{
case '(':
if (graph->down[kid]->dim.y > 2)
{
(*screen)[low][curx] = '\\';
for (i = 1; i < graph->down[kid]->dim.y - 1; i++)
(*screen)[low - i][curx] = '|';
(*screen)[low - graph->down[kid]->dim.y +
1][curx] = '/';
curx++;
} else
(*screen)[cury][curx++] = '(';
break;
case '|':
if (graph->down[kid]->dim.y > 2)
{
for (i = 0; i < graph->down[kid]->dim.y; i++)
(*screen)[low - i][curx] = '|';
curx++;
} else
(*screen)[cury][curx++] = '|';
break;
case '[':
if (graph->down[kid]->dim.y > 2)
{
(*screen)[low][curx + 1] = '_';
for (i = 0; i < graph->down[kid]->dim.y; i++)
(*screen)[low - i][curx] = '|';
(*screen)[low - graph->down[kid]->dim.y][curx +
1] = '_';
curx += 2;
} else
(*screen)[cury][curx++] = '[';
break;
case '{':
if (graph->down[kid]->dim.y > 2)
{
(*screen)[low][curx] = '\\';
(*screen)[low -
graph->down[kid]->dim.y / 2][curx] = '<';
for (i = 1;
i <
graph->down[kid]->dim.y -
(graph->down[kid]->dim.y % 2); i++)
if (!(i == graph->down[kid]->dim.y / 2))
(*screen)[low - i][curx] = '|';
(*screen)[low - graph->down[kid]->dim.y +
graph->down[kid]->dim.y % 2][curx] = '/';
curx++;
} else
(*screen)[cury + graph->dim.baseline][curx++] =
'{';
break;
case '.': /* dummy brace to open or close any type *
* of brace */
break;
default:
if (graph->down[kid]->dim.y > 2)
{
for (i = 0; i < graph->down[kid]->dim.y; i++)
(*screen)[low - i][curx] =
graph->down[kid]->options[0];
curx++;
} else
(*screen)[cury][curx++] =
*(graph->down[kid]->options);
break;
}
/*
* drawInternal (screen, graph->down[kid], curx, cury - (graph->dim.y
* - (graph->dim.baseline + 1)));
*/
drawInternal(screen, graph->down[kid], curx,
low - graph->down[kid]->dim.y + 1);
curx += graph->down[kid]->dim.x;
switch (graph->down[kid]->options[1])
{
case ')':
if (graph->down[kid]->dim.y > 2)
{
(*screen)[low][curx] = '/';
for (i = 1; i < graph->down[kid]->dim.y - 1; i++)
(*screen)[low - i][curx] = '|';
(*screen)[low - graph->down[kid]->dim.y +
1][curx] = '\\';
} else
(*screen)[cury][curx] = ')';
break;
case '|':
if (graph->down[kid]->dim.y > 2)
{
for (i = 0; i < graph->down[kid]->dim.y; i++)
(*screen)[low - i][curx] = '|';
} else
(*screen)[cury][curx] = '|';
break;
case ']':
if (graph->down[kid]->dim.y > 2)
{
(*screen)[low][curx] = '_';
for (i = 0; i < graph->down[kid]->dim.y; i++)
(*screen)[low - i][curx + 1] = '|';
(*screen)[low - graph->down[kid]->dim.y][curx] =
'_';
curx++;
} else
(*screen)[cury][curx] = ']';
break;
case '}':
if (graph->down[kid]->dim.y > 2)
{
(*screen)[low][curx] = '/';
(*screen)[low -
graph->down[kid]->dim.y / 2][curx] = '>';
for (i = 1;
i <
graph->down[kid]->dim.y -
(graph->down[kid]->dim.y % 2); i++)
if (!(i == graph->down[kid]->dim.y / 2))
(*screen)[low - i][curx] = '|';
(*screen)[low - graph->down[kid]->dim.y +
(graph->down[kid]->dim.y % 2)][curx] =
'\\';
} else
(*screen)[cury][curx] = '}';
break;
case '.': /* dummy brace to open or close any type *
* of brace */
break;
default:
if (graph->down[kid]->dim.y > 2)
{
for (i = 0; i < graph->down[kid]->dim.y; i++)
(*screen)[low - i][curx] =
graph->down[kid]->options[1];
} else
(*screen)[cury][curx] =
graph->down[kid]->options[1];
break;
}
curx++;
kid++;
}