home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / tc20 / mcutil.c < prev    next >
Text File  |  1988-10-13  |  15KB  |  630 lines

  1. /* Turbo C - (C) Copyright 1987,1988 by Borland International */
  2.  
  3. #include <math.h>
  4. #include <alloc.h>
  5. #include <ctype.h>
  6. #include <string.h>
  7. #include <stdlib.h>
  8. #include <mem.h>
  9. #include <stdio.h>
  10. #include <conio.h>
  11. #include "mcalc.h"
  12.  
  13. int alloctext(int col, int row, char *s)
  14. /* Allocates space for a text cell */
  15. {
  16.  int size;
  17.  CELLPTR cellptr;
  18.  
  19.  if (memleft < (size = textcellsize(s)))
  20.   return(FALSE);
  21.  memleft -= size;
  22.  cellptr = (CELLPTR)(malloc(strlen(s) + 2));
  23.  cellptr->attrib = TEXT;
  24.  strcpy(cellptr->v.text, s);
  25.  cell[col][row] = cellptr;
  26.  return(TRUE);
  27. } /* alloctext */
  28.  
  29. int allocvalue(int col, int row, double amt)
  30. /* Allocates space for a value cell */
  31. {
  32.  CELLPTR cellptr;
  33.  
  34.  if (memleft < valuecellsize)
  35.   return(FALSE);
  36.  memleft -= valuecellsize;
  37.  cellptr = (CELLPTR)(malloc(sizeof(double) + 1));
  38.  cellptr->attrib = VALUE;
  39.  cellptr->v.value = amt;
  40.  cell[col][row] = cellptr;
  41.  return(TRUE);
  42. } /* allocvalue */
  43.  
  44. int allocformula(int col, int row, char *s, double amt)
  45. /* Allocates space for a formula cell */
  46. {
  47.  int size;
  48.  CELLPTR cellptr;
  49.  
  50.  if (memleft < (size = formulacellsize(s)))
  51.   return(FALSE);
  52.  memleft -= size;
  53.  cellptr = (CELLPTR)(malloc(strlen(s) + sizeof(double) + 2));
  54.  cellptr->attrib = FORMULA;
  55.  strcpy(cellptr->v.f.formula, s);
  56.  cellptr->v.f.fvalue = amt;
  57.  cell[col][row] = cellptr;
  58.  return(TRUE);
  59. } /* allocformula */
  60.  
  61. void deletecell(int col, int row, int display)
  62. /* Deletes a cell */
  63. {
  64.  CELLPTR cellptr = cell[col][row];
  65.  
  66.  if (cellptr == NULL)
  67.   return;
  68.  switch (cellptr->attrib)
  69.  {
  70.   case TEXT :
  71.    memleft += textcellsize(cellptr->v.text);
  72.    clearoflags(col + 1, row, display);
  73.    break;
  74.   case VALUE :
  75.    memleft += valuecellsize;
  76.    break;
  77.   case FORMULA :
  78.    memleft += formulacellsize(cellptr->v.f.formula);
  79.    break;
  80.  } /* switch */
  81.  format[col][row] &= ~OVERWRITE;
  82.  free(cell[col][row]);
  83.  cell[col][row] = NULL;
  84.  if (col == lastcol)
  85.   setlastcol();
  86.  if (row == lastrow)
  87.   setlastrow();
  88.  updateoflags(col, row, display);
  89.  changed = TRUE;
  90. } /* deletecell */
  91.  
  92. void printfreemem(void)
  93. /* Prints the amount of free memory */
  94. {
  95.  writef(strlen(MSGMEMORY) + 1, 1, MEMORYCOLOR, 6, "%6ld", memleft);
  96. } /* printfreemem */
  97.  
  98. int rowwidth(int row)
  99. /* Returns the width in spaces of row */
  100. {
  101.  return((row == 0) ? 1 : (int)log10(row + 1) + 1);
  102. } /* rowwidth */
  103.  
  104. int formulastart(char **input, int *col, int *row)
  105. /* Returns TRUE if the string is the start of a formula, FALSE otherwise.
  106.    Also returns the column and row of the formula.
  107. */
  108. {
  109.  int len, maxlen = rowwidth(MAXROWS);
  110.  char *start, numstring[10];
  111.  
  112.  if (**input > 127 || !isalpha(**input))  /* isalpha ! for Umlauts! */
  113.   return(FALSE);
  114.  *col = *((*input)++) - 'A';
  115.  if (isalpha(**input))
  116.  {
  117.   *col *= 26;
  118.   *col += *((*input)++) - 'A' + 26;
  119.  }
  120.  if (*col >= MAXCOLS)
  121.   return(FALSE);
  122.  start = *input;
  123.  for (len = 0; len < maxlen; len++)
  124.  {
  125.   if (!isdigit(*((*input)++)))
  126.   {
  127.    (*input)--;
  128.    break;
  129.   }
  130.  }
  131.  if (len == 0)
  132.   return(FALSE);
  133.  strncpy(numstring, start, len);
  134.  numstring[len] = 0;
  135.  *row = atoi(numstring) - 1;
  136.  if ((*row >= MAXROWS) || (*row == -1))
  137.   return(FALSE);
  138.  return(TRUE);
  139. } /* formulastart */
  140.  
  141. void errormsg(char *s)
  142. /* Prints an error message at the bottom of the screen */
  143. {
  144.  printf("%c", 7);      /* Beeps the speaker */
  145.  writef(1, 25, ERRORCOLOR, 79, "%s  %s", s, MSGKEYPRESS);
  146.  gotoxy(strlen(s) + strlen(MSGKEYPRESS) + 3, 25);
  147.  getkey();
  148.  gotoxy(1, 25);
  149.  writef(1, 25, WHITE, 79, "");
  150. } /* errormsg */
  151.  
  152. void fixformula(int col, int row, int action, int place)
  153. /* Modifies a formula when its column or row designations need to change. */
  154. {
  155.  char *colstart, *rowstart, s[6], newformula[MAXINPUT + 1],
  156.       *curpos = newformula;
  157.  int fcol, frow;
  158.  CELLPTR cellptr = cell[col][row];
  159.  double value;
  160.  
  161.  strcpy(newformula, cellptr->v.f.formula);
  162.  while (*curpos != 0)
  163.  {
  164.   if (formulastart(&curpos, &fcol, &frow))
  165.   {
  166.    rowstart = curpos - rowwidth(frow);
  167.    colstart = rowstart - ((fcol > 25) ? 2 : 1);
  168.    switch (action)
  169.    {
  170.     case COLADD :
  171.      if (fcol < place)
  172.       break;
  173.      if (fcol == 25)
  174.      {
  175.       if (strlen(newformula) == MAXINPUT)
  176.       {
  177.        deletecell(col, row, NOUPDATE);
  178.        alloctext(col, row, newformula);
  179.        return;
  180.       }
  181.       movmem(colstart, colstart + 1, strlen(colstart) + 1);
  182.      }
  183.      colstring(fcol + 1, s);
  184.      movmem(s, colstart, strlen(s));
  185.      break;
  186.     case ROWADD :
  187.      if (frow < place)
  188.       break;
  189.      if (rowwidth(frow + 1) != rowwidth(frow))
  190.      {
  191.       if (strlen(newformula) == MAXINPUT)
  192.       {
  193.        deletecell(col, row, NOUPDATE);
  194.        alloctext(col, row, newformula);
  195.        return;
  196.       }
  197.       movmem(rowstart, rowstart + 1, strlen(rowstart) + 1);
  198.      }
  199.      sprintf(s, "%d", frow + 2);
  200.      movmem(s, rowstart, strlen(s));
  201.      break;
  202.     case COLDEL :
  203.      if (fcol <= place)
  204.       break;
  205.      if (fcol == 26)
  206.       movmem(colstart + 1, colstart, strlen(colstart) + 1);
  207.      colstring(fcol - 1, s);
  208.      movmem(s, colstart, strlen(s));
  209.      break;
  210.     case ROWDEL :
  211.      if (frow <= place)
  212.       break;
  213.      if (rowwidth(frow) != rowwidth(frow - 1))
  214.       movmem(rowstart + 1, rowstart, strlen(rowstart) + 1);
  215.      sprintf(s, "%d", frow);
  216.      movmem(s, rowstart, strlen(s));
  217.      break;
  218.    } /* switch */
  219.   }
  220.   else
  221.    curpos++;
  222.  }
  223.  if (strlen(newformula) != strlen(cellptr->v.f.formula))
  224.  {
  225.   value = cellptr->v.f.fvalue;
  226.   deletecell(col, row, NOUPDATE);
  227.   allocformula(col, row, newformula, value);
  228.  }
  229.  else
  230.   strcpy(cellptr->v.f.formula, newformula);
  231. } /* fixformula */
  232.  
  233. void colstring(int col, char *colstr)
  234. /* Changes a column number to a string */
  235. {
  236.  setmem(colstr, 3, 0);
  237.  if (col < 26)
  238.   colstr[0] = col + 'A';
  239.  else
  240.  {
  241.   colstr[0] = (col / 26) - 1 + 'A';
  242.   colstr[1] = (col % 26) + 'A';
  243.  }
  244. } /* colstring */
  245.  
  246. void centercolstring(int col, char *colstr)
  247. /* Changes a column to a centered string */
  248. {
  249.  char s[3];
  250.  int spaces1, spaces2;
  251.  
  252.  colstring(col, s);
  253.  spaces1 = (colwidth[col] - strlen(s)) >> 1;
  254.  spaces2 = colwidth[col] - strlen(s) - spaces1;
  255.  sprintf(colstr, "%*s%s%*s", spaces1, "", s, spaces2, "");
  256. } /* centercolstring */
  257.  
  258. void setleftcol(void)
  259. /* Sets the value of leftcol based on the value of rightcol */
  260. {
  261.  int total = 80, col = 0;
  262.  
  263.  while ((total >= LEFTMARGIN) && (rightcol - col >= 0))
  264.  {
  265.   colstart[SCREENCOLS - col - 1] = total - colwidth[rightcol - col];
  266.   total -= colwidth[rightcol - col++];
  267.  }
  268.  if (total >= LEFTMARGIN)
  269.   col++;
  270.  movmem(&colstart[SCREENCOLS - col + 1], colstart, col - 1);
  271.  leftcol = rightcol - col + 2;
  272.  total = colstart[0] - LEFTMARGIN;
  273.  if (total != 0)
  274.  {
  275.   for (col = leftcol; col <= rightcol; col++)
  276.    colstart[col - leftcol] -= total;
  277.  }
  278.  printcol();
  279. } /* setleftcol */
  280.  
  281. void setrightcol(void)
  282. /* Sets the value of rightcol based on the value of leftcol */
  283. {
  284.  int total = LEFTMARGIN, col = 0;
  285.  
  286.  do
  287.  {
  288.   colstart[col] = total;
  289.   total += colwidth[leftcol + col++];
  290.  }
  291.  while ((total <= 80) && (leftcol + col <= MAXCOLS));
  292.  rightcol = leftcol + col - 2;
  293.  printcol();
  294. } /* setrightcol */
  295.  
  296. void settoprow(void)
  297. /* Figures out the value of toprow based on the value of bottomrow */
  298. {
  299.  if (bottomrow - SCREENROWS < -1)
  300.   bottomrow = 19;
  301.  toprow = bottomrow - 19;
  302.  printrow();
  303. } /* settoprow */
  304.  
  305. void setbottomrow(void)
  306. /* Figures out the value of bottomrow based on the value of toprow */
  307. {
  308.  if (toprow + SCREENROWS > MAXROWS)
  309.   toprow = MAXROWS - 20;
  310.  bottomrow = toprow + 19;
  311.  printrow();
  312. } /* setbottomrow */
  313.  
  314. void setlastcol(void)
  315. /* Sets the value of lastcol based on the current value */
  316. {
  317.  register int row, col;
  318.  
  319.  for (col = lastcol; col >= 0; col--)
  320.  {
  321.   for (row = 0; row <= lastrow; row++)
  322.   {
  323.    if (cell[col][row] != NULL)
  324.    {
  325.     lastcol = col;
  326.     return;
  327.    }
  328.   }
  329.  }
  330.  lastcol = 0;
  331. } /* setlastcol */
  332.  
  333. void setlastrow(void)
  334. /* Sets the value of lastrow based on the current value */
  335. {
  336.  register int row, col;
  337.  
  338.  for (row = lastrow; row >= 0; row--)
  339.  {
  340.   for (col = 0; col <= lastcol; col++)
  341.   {
  342.    if (cell[col][row] != NULL)
  343.    {
  344.     lastrow = row;
  345.     return;
  346.    }
  347.   }
  348.  }
  349.  lastrow = 0;
  350. } /* setlastrow */
  351.  
  352. void act(char *s)
  353. /* Acts on a particular input */
  354. {
  355.  int attrib, allocated;
  356.  double value;
  357.  
  358.  deletecell(curcol, currow, UPDATE);
  359.  value = parse(s, &attrib);
  360.  switch(attrib)
  361.  {
  362.   case TEXT :
  363.    allocated = alloctext(curcol, currow, s);
  364.    if (allocated)
  365.     displaycell(curcol, currow, NOHIGHLIGHT, NOUPDATE);
  366.    break;
  367.   case VALUE :
  368.    allocated = allocvalue(curcol, currow, value);
  369.    break;
  370.   case FORMULA :
  371.    allocated = allocformula(curcol, currow, s, value);
  372.    break;
  373.  } /* switch */
  374.  if (allocated)
  375.  {
  376.   format[curcol][currow] &= ~OVERWRITE;
  377.   clearoflags(curcol + 1, currow, UPDATE);
  378.   if (attrib == TEXT)
  379.     setoflags(curcol, currow, UPDATE);
  380.   if (curcol > lastcol)
  381.    lastcol = curcol;
  382.   if (currow > lastrow)
  383.    lastrow = currow;
  384.   if (autocalc)
  385.    recalc();
  386.  }
  387.  else
  388.   errormsg(MSGLOMEM);
  389.  printfreemem();
  390. } /* act */
  391.  
  392. int setoflags(int col, int row, int display)
  393. /* Sets the overwrite flag on cells starting at (col + 1, row) - returns
  394.    the number of the column after the last column set.
  395. */
  396. {
  397.  int len;
  398.  
  399.  len = strlen(cell[col][row]->v.text) - colwidth[col];
  400.  while ((++col < MAXCOLS) && (len > 0) && (cell[col][row] == NULL))
  401.  {
  402.   format[col][row] |= OVERWRITE;
  403.   len -= colwidth[col];
  404.   if (display && (col >= leftcol) && (col <= rightcol))
  405.    displaycell(col, row, NOHIGHLIGHT, NOUPDATE);
  406.  }
  407.  return(col);
  408. } /* setoflags */
  409.  
  410. void clearoflags(int col, int row, int display)
  411. /* Clears the overwrite flag on cells starting at (col, row) */
  412. {
  413.  while ((format[col][row] >= OVERWRITE) && (col < MAXCOLS) &&
  414.         (cell[col][row] == NULL))
  415.  {
  416.   format[col][row] &= ~OVERWRITE;
  417.   if (display && (col >= leftcol) && (col <= rightcol))
  418.    displaycell(col, row, NOHIGHLIGHT, NOUPDATE);
  419.   col++;
  420.  }
  421. } /* clearoflags */
  422.  
  423. void updateoflags(int col, int row, int display)
  424. /* Starting in col, moves back to the last TEXT cell and updates all flags */
  425. {
  426.  while ((cell[col][row] == NULL) && (col-- > 0));
  427.  if ((cell[col][row] != NULL) && (cell[col][row]->attrib == TEXT) && 
  428.      (col >= 0))
  429.   setoflags(col, row, display);
  430. } /* updateoflags */
  431.  
  432. void textstring(char *instring, char *outstring, int col, int fvalue,
  433.                 int formatting)
  434. /* Sets the string representation of text */
  435. {
  436.  char *just, *ljust = "%-*s", *rjust = "%*s";
  437.  
  438.  if ((fvalue & RJUSTIFY) && (formatting))
  439.   just = rjust;
  440.  else
  441.   just = ljust;
  442.  sprintf(outstring, just, colwidth[col], instring);
  443.  if (formatting)
  444.   outstring[colwidth[col]] = 0;
  445. } /* textstring */
  446.  
  447. void valuestring(CELLPTR cellptr, double value, char *vstring, int col,
  448.                  int fvalue, int *color, int formatting)
  449. /* Sets the string representation of a value */
  450. {
  451.  char s[81];
  452.  char *fstring;
  453.  int width, pos;
  454.  
  455.  if (value == HUGE_VAL)
  456.  {
  457.   strcpy(vstring, MSGERROR);
  458.   *color = ERRORCOLOR;
  459.  }
  460.  else
  461.  {
  462.   if (formatting)
  463.   {
  464.    sprintf(vstring, "%1.*f", fvalue & 15, cellptr->v.value);
  465.    if (fvalue & COMMAS)
  466.    {
  467.     pos = strcspn(vstring, ".");
  468.     while (pos > 3)
  469.     {
  470.      pos -= 3;
  471.      if (vstring[pos - 1] != '-')
  472.      {
  473.       movmem(&vstring[pos], &vstring[pos + 1], strlen(vstring) - pos + 1);
  474.       vstring[pos] = ',';
  475.      }
  476.     }
  477.    }
  478.    if (fvalue & DOLLAR)
  479.    {
  480.     if (vstring[0] == '-')
  481.     {
  482.      fstring = " DM";
  483.      width = colwidth[col] - 3;
  484.     }
  485.     else
  486.     {
  487.      fstring = " DM ";
  488.      width = colwidth[col] - 4;
  489.     }
  490.    }
  491.    else
  492.    {
  493.     fstring = "";
  494.     width = colwidth[col];
  495.    }
  496.    strcpy(s, vstring);
  497.    if (fvalue & RJUSTIFY)
  498.    {
  499.     if (strlen(vstring) > width)
  500.      vstring[width] = 0;
  501.     else
  502.      sprintf(vstring, "%*s", width, s);
  503.    }
  504.    else
  505.     sprintf(vstring, "%-*s", width, s);
  506.    movmem(vstring, &vstring[strlen(fstring)], strlen(vstring) + 1);
  507.    strncpy(vstring, fstring, strlen(fstring));
  508.   }
  509.   else
  510.    sprintf(vstring, "%.*f", MAXPLACES, value);
  511.   *color = VALUECOLOR;
  512.  }
  513. } /* valuestring */
  514.  
  515. char *cellstring(int col, int row, int *color, int formatting)
  516. /* Creates an output string for the data in the cell in (col, row), and
  517.    also returns the color of the cell */
  518. {
  519.  CELLPTR cellptr = cell[col][row];
  520.  int newcol, formatvalue;
  521.  static char s[81], temp[MAXCOLWIDTH + 1];
  522.  char *p;
  523.  double value;
  524.  
  525.  if (cellptr == NULL)
  526.  {
  527.   if (!formatting || (format[col][row] < OVERWRITE))
  528.   {
  529.    sprintf(s, "%*s", colwidth[col], "");
  530.    *color = BLANKCOLOR;
  531.   }
  532.   else
  533.   {
  534.    newcol = col;
  535.    while (cell[--newcol][row] == NULL);
  536.    p = cell[newcol][row]->v.text;
  537.    while (newcol < col)
  538.     p += colwidth[newcol++];
  539.    strncpy(temp, p, colwidth[col]);
  540.    temp[colwidth[col]] = 0;
  541.    sprintf(s, "%s%*s", temp, colwidth[col] - strlen(temp), "");
  542.    *color = TEXTCOLOR;
  543.   }
  544.  }
  545.  else
  546.  {
  547.   formatvalue = format[col][row];
  548.   switch (cellptr->attrib)
  549.   {
  550.    case TEXT :
  551.     textstring(cellptr->v.text, s, col, formatvalue, formatting);
  552.     *color = TEXTCOLOR;
  553.     break;
  554.    case FORMULA :
  555.     if (formdisplay)
  556.     {
  557.      textstring(cellptr->v.f.formula, s, col, formatvalue, formatting);
  558.      *color = FORMULACOLOR;
  559.      break;
  560.     }
  561.     else
  562.      value = cellptr->v.f.fvalue;
  563.    case VALUE :
  564.     if (cellptr->attrib == VALUE)
  565.      value = cellptr->v.value;
  566.     valuestring(cellptr, value, s, col, formatvalue, color,
  567.                 formatting);
  568.     break;
  569.   } /* switch */
  570.  }
  571.  return(s);
  572. } /* cellstring */
  573.  
  574. void writeprompt(char *prompt)
  575. /* Prints a prompt on the screen */
  576. {
  577.  writef(1, 24, PROMPTCOLOR, 80, prompt);
  578. } /* writeprompt */
  579.  
  580. void swap(int *val1, int *val2)
  581. /* Swaps the first and second values */
  582. {
  583.  int temp;
  584.  
  585.  temp = *val1;
  586.  *val1 = *val2;
  587.  *val2 = temp;
  588. } /* swap */
  589.  
  590. void checkforsave(void)
  591. /* If the spreadsheet has been changed, will ask the user if they want to
  592.    save it.
  593. */
  594. {
  595.  int save;
  596.  
  597.  if (changed && getyesno(&save, MSGSAVESHEET) && (save == 'J'))
  598.   savesheet();
  599. } /* checkforsave */
  600.  
  601. void initvars(void)
  602. /* Initializes various global variables */
  603. {
  604.  leftcol = toprow = curcol = currow = lastcol = lastrow = 0;
  605.  setmem(colwidth, sizeof(colwidth), DEFAULTWIDTH);
  606.  setmem(cell, sizeof(cell), 0);
  607.  setmem(format, sizeof(format), DEFAULTFORMAT);
  608. } /* initvars */
  609.  
  610. int getcommand(char *msgstr, char *comstr)
  611. /* Reads in a command and acts on it */
  612. {
  613.  int ch, counter, len = strlen(msgstr);
  614.  
  615.  scroll(UP, 0, 1, 24, 80, 24, WHITE);
  616.  for (counter = 0; counter < len; counter++)
  617.  {
  618.   if (isupper(msgstr[counter]))
  619.    writef(counter + 1, 24, COMMANDCOLOR, 1, "%c", msgstr[counter]);
  620.   else
  621.    writef(counter + 1, 24, LOWCOMMANDCOLOR, 1, "%c", msgstr[counter]);
  622.  }
  623.  do
  624.   ch = toupper(getkey());
  625.  while ((strchr(comstr, ch) == NULL) && (ch != ESC));
  626.  clearinput();
  627.  return((ch == ESC) ? -1 : strlen(comstr) - strlen(strchr(comstr, ch)));
  628. } /* getcommand */
  629.  
  630.