home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / tcpp / examples / tcalc / tcutil.c < prev   
Encoding:
C/C++ Source or Header  |  1990-06-10  |  14.9 KB  |  633 lines

  1. /* Turbo C - (C) Copyright 1987,1988,1990 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 "tcalc.h"
  12.  
  13. int alloctext(int col, int row, char *s)
  14. /* Belegt Speicherplatz für eine Text-Zelle */
  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. /* Belegt Speicherplatz für eine Wert-Zelle */
  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. /* Belegt Speicherplatz für eine Formel-Zelle */
  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. /* Löscht eine Zelle */
  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. /* Gibt den freien Speicherplatz aus */
  94. {
  95.  writef(strlen(MSGMEMORY) + 2, 1, MEMORYCOLOR, 6, "%6ld", memleft);
  96. } /* printfreemem */
  97.  
  98. int rowwidth(int row)
  99. /* Gibt die Zeilenlänge in Leerzeichen an */
  100. {
  101.  return((row == 0) ? 1 : (int)log10(row + 1) + 1);
  102. } /* rowwidth */
  103.  
  104. int formulastart(char **input, int *col, int *row)
  105. /* Liefert TRUE, wenn der String der Anfang einer Formel ist, andernfalls
  106.    FALSE. Gibt ebenfalls die Zeile und Spalte der Formel an.
  107. */
  108. {
  109.  int len, maxlen = rowwidth(MAXROWS);
  110.  char *start, numstring[10];
  111.  
  112.  if (!isalpha(**input))
  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. /* Gibt eine Fehlermeldung am unteren Bildschirmrand aus */
  143. {
  144.  printf("%c", 7);          /* Piepston */
  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. /* Modifiziert eine Formel, wenn deren Zeilen- oder Spaltenbezeichnung */
  154. /* geändert werden muß. */
  155. {
  156.  char *colstart, *rowstart, s[6], newformula[MAXINPUT + 1],
  157.       *curpos = newformula;
  158.  int fcol, frow;
  159.  CELLPTR cellptr = cell[col][row];
  160.  double value;
  161.  
  162.  strcpy(newformula, cellptr->v.f.formula);
  163.  while (*curpos != 0)
  164.  {
  165.   if (formulastart(&curpos, &fcol, &frow))
  166.   {
  167.    rowstart = curpos - rowwidth(frow);
  168.    colstart = rowstart - ((fcol > 25) ? 2 : 1);
  169.    switch (action)
  170.    {
  171.     case COLADD :
  172.      if (fcol < place)
  173.       break;
  174.      if (fcol == 25)
  175.      {
  176.       if (strlen(newformula) == MAXINPUT)
  177.       {
  178.        deletecell(col, row, NOUPDATE);
  179.        alloctext(col, row, newformula);
  180.        return;
  181.       }
  182.       movmem(colstart, colstart + 1, strlen(colstart) + 1);
  183.      }
  184.      colstring(fcol + 1, s);
  185.      movmem(s, colstart, strlen(s));
  186.      break;
  187.     case ROWADD :
  188.      if (frow < place)
  189.       break;
  190.      if (rowwidth(frow + 1) != rowwidth(frow))
  191.      {
  192.       if (strlen(newformula) == MAXINPUT)
  193.       {
  194.        deletecell(col, row, NOUPDATE);
  195.        alloctext(col, row, newformula);
  196.        return;
  197.       }
  198.       movmem(rowstart, rowstart + 1, strlen(rowstart) + 1);
  199.      }
  200.      sprintf(s, "%d", frow + 2);
  201.      movmem(s, rowstart, strlen(s));
  202.      break;
  203.     case COLDEL :
  204.      if (fcol <= place)
  205.       break;
  206.      if (fcol == 26)
  207.       movmem(colstart + 1, colstart, strlen(colstart) + 1);
  208.      colstring(fcol - 1, s);
  209.      movmem(s, colstart, strlen(s));
  210.      break;
  211.     case ROWDEL :
  212.      if (frow <= place)
  213.       break;
  214.      if (rowwidth(frow) != rowwidth(frow - 1))
  215.       movmem(rowstart + 1, rowstart, strlen(rowstart) + 1);
  216.      sprintf(s, "%d", frow);
  217.      movmem(s, rowstart, strlen(s));
  218.      break;
  219.    } /* switch */
  220.   }
  221.   else
  222.    curpos++;
  223.  }
  224.  if (strlen(newformula) != strlen(cellptr->v.f.formula))
  225.  {
  226.   value = cellptr->v.f.fvalue;
  227.   deletecell(col, row, NOUPDATE);
  228.   allocformula(col, row, newformula, value);
  229.  }
  230.  else
  231.   strcpy(cellptr->v.f.formula, newformula);
  232. } /* fixformula */
  233.  
  234. void colstring(int col, char *colstr)
  235. /* Ändert die Spaltennummer zu einem String */
  236. {
  237.  setmem(colstr, 3, 0);
  238.  if (col < 26)
  239.   colstr[0] = col + 'A';
  240.  else
  241.  {
  242.   colstr[0] = (col / 26) - 1 + 'A';
  243.   colstr[1] = (col % 26) + 'A';
  244.  }
  245. } /* colstring */
  246.  
  247. void centercolstring(int col, char *colstr)
  248. /* Ändert die Spalte zu einem zentrierten String */
  249. {
  250.  char s[3];
  251.  int spaces1, spaces2;
  252.  
  253.  colstring(col, s);
  254.  spaces1 = (colwidth[col] - strlen(s)) >> 1;
  255.  spaces2 = colwidth[col] - strlen(s) - spaces1;
  256.  sprintf(colstr, "%*s%s%*s", spaces1, "", s, spaces2, "");
  257. } /* centercolstring */
  258.  
  259. void setleftcol(void)
  260. /* Setzt den Wert von leftcol in Abhängigkeit von rightcol */
  261. {
  262.  int total = 80, col = 0;
  263.  
  264.  while ((total >= LEFTMARGIN) && (rightcol - col >= 0))
  265.  {
  266.   colstart[SCREENCOLS - col - 1] = total - colwidth[rightcol - col];
  267.   total -= colwidth[rightcol - col++];
  268.  }
  269.  if (total >= LEFTMARGIN)
  270.   col++;
  271.  movmem(&colstart[SCREENCOLS - col + 1], colstart, col - 1);
  272.  leftcol = rightcol - col + 2;
  273.  total = colstart[0] - LEFTMARGIN;
  274.  if (total != 0)
  275.  {
  276.   for (col = leftcol; col <= rightcol; col++)
  277.    colstart[col - leftcol] -= total;
  278.  }
  279.  printcol();
  280. } /* setleftcol */
  281.  
  282. void setrightcol(void)
  283. /* Setzt den Wert von rightcol in Abhängigkeit von leftcol */
  284. {
  285.  int total = LEFTMARGIN, col = 0;
  286.  
  287.  do
  288.  {
  289.   colstart[col] = total;
  290.   total += colwidth[leftcol + col++];
  291.  }
  292.  while ((total <= 80) && (leftcol + col <= MAXCOLS));
  293.  rightcol = leftcol + col - 2;
  294.  printcol();
  295. } /* setrightcol */
  296.  
  297. void settoprow(void)
  298. /* Findet den Wert von toprow in Abhängigkeit von bottomrow */
  299. {
  300.  if (bottomrow - SCREENROWS < -1)
  301.   bottomrow = 19;
  302.  toprow = bottomrow - 19;
  303.  printrow();
  304. } /* settoprow */
  305.  
  306. void setbottomrow(void)
  307. /* Findet den Wert von bottomrow in Abhängigkeit von toprow */
  308. {
  309.  if (toprow + SCREENROWS > MAXROWS)
  310.   toprow = MAXROWS - 20;
  311.  bottomrow = toprow + 19;
  312.  printrow();
  313. } /* setbottomrow */
  314.  
  315. void setlastcol(void)
  316. /* Setzt den Wert von lastcol in Abhängigkeit vom aktuellen Wert */
  317. {
  318.  register int row, col;
  319.  
  320.  for (col = lastcol; col >= 0; col--)
  321.  {
  322.   for (row = 0; row <= lastrow; row++)
  323.   {
  324.    if (cell[col][row] != NULL)
  325.    {
  326.     lastcol = col;
  327.     return;
  328.    }
  329.   }
  330.  }
  331.  lastcol = 0;
  332. } /* setlastcol */
  333.  
  334. void setlastrow(void)
  335. /* Setzt den Wert von lastrow in Abhängikeit vom aktuellen Wert */
  336. {
  337.  register int row, col;
  338.  
  339.  for (row = lastrow; row >= 0; row--)
  340.  {
  341.   for (col = 0; col <= lastcol; col++)
  342.   {
  343.    if (cell[col][row] != NULL)
  344.    {
  345.     lastrow = row;
  346.     return;
  347.    }
  348.   }
  349.  }
  350.  lastrow = 0;
  351. } /* setlastrow */
  352.  
  353. void act(char *s)
  354. /* Bearbeitet eine bestimmte Eingabe */
  355. {
  356.  int attrib, allocated;
  357.  double value;
  358.  
  359.  deletecell(curcol, currow, UPDATE);
  360.  value = parse(s, &attrib);
  361.  switch(attrib)
  362.  {
  363.   case TEXT :
  364.    allocated = alloctext(curcol, currow, s);
  365.    if (allocated)
  366.     displaycell(curcol, currow, NOHIGHLIGHT, NOUPDATE);
  367.    break;
  368.   case VALUE :
  369.    allocated = allocvalue(curcol, currow, value);
  370.    break;
  371.   case FORMULA :
  372.    allocated = allocformula(curcol, currow, s, value);
  373.    break;
  374.  } /* switch */
  375.  if (allocated)
  376.  {
  377.   format[curcol][currow] &= ~OVERWRITE;
  378.   clearoflags(curcol + 1, currow, UPDATE);
  379.   if (attrib == TEXT)
  380.     setoflags(curcol, currow, UPDATE);
  381.   if (curcol > lastcol)
  382.    lastcol = curcol;
  383.   if (currow > lastrow)
  384.    lastrow = currow;
  385.   if (autocalc)
  386.    recalc();
  387.  }
  388.  else
  389.   errormsg(MSGLOMEM);
  390.  printfreemem();
  391. } /* act */
  392.  
  393. int setoflags(int col, int row, int display)
  394. /* Setzt den Overwrite-Flag auf Zellen, die mit (col + 1, row) beginnen - 
  395.    liefert die Nummer der Spalte nach der letzten gesetzten Spalte.
  396. */
  397. {
  398.  int len;
  399.  
  400.  len = strlen(cell[col][row]->v.text) - colwidth[col];
  401.  while ((++col < MAXCOLS) && (len > 0) && (cell[col][row] == NULL))
  402.  {
  403.   format[col][row] |= OVERWRITE;
  404.   len -= colwidth[col];
  405.   if (display && (col >= leftcol) && (col <= rightcol))
  406.    displaycell(col, row, NOHIGHLIGHT, NOUPDATE);
  407.  }
  408.  return(col);
  409. } /* setoflags */
  410.  
  411. void clearoflags(int col, int row, int display)
  412. /* Löscht den Overwrite-Flag bei den Zellen, die bei (col, row) beginnen */
  413. {
  414.  while ((format[col][row] >= OVERWRITE) && (col < MAXCOLS) &&
  415.         (cell[col][row] == NULL))
  416.  {
  417.   format[col][row] &= ~OVERWRITE;
  418.   if (display && (col >= leftcol) && (col <= rightcol))
  419.    displaycell(col, row, NOHIGHLIGHT, NOUPDATE);
  420.   col++;
  421.  }
  422. } /* clearoflags */
  423.  
  424. void updateoflags(int col, int row, int display)
  425. /* Beginnt bei col, geht zurück zur letzten TEXT-Zelle und aktualisiert
  426.    alle Flags 
  427. */
  428. {
  429.  while ((cell[col][row] == NULL) && (col-- > 0));
  430.  if ((cell[col][row] != NULL) && (cell[col][row]->attrib == TEXT) && 
  431.      (col >= 0))
  432.   setoflags(col, row, display);
  433. } /* updateoflags */
  434.  
  435. void textstring(char *instring, char *outstring, int col, int fvalue,
  436.                 int formatting)
  437. /* Bestimmt die Stringdarstellung eines Textes */
  438. {
  439.  char *just, *ljust = "%-*s", *rjust = "%*s";
  440.  
  441.  if ((fvalue & RJUSTIFY) && (formatting))
  442.   just = rjust;
  443.  else
  444.   just = ljust;
  445.  sprintf(outstring, just, colwidth[col], instring);
  446.  if (formatting)
  447.   outstring[colwidth[col]] = 0;
  448. } /* textstring */
  449.  
  450. void valuestring(CELLPTR cellptr, double value, char *vstring, int col,
  451.                  int fvalue, int *color, int formatting)
  452. /* Bestimmt die Stringdarstellung eines Wertes */
  453. {
  454.  char s[81];
  455.  char *fstring;
  456.  int width, pos;
  457.  
  458.  if (value == HUGE_VAL)
  459.  {
  460.   strcpy(vstring, MSGERROR);
  461.   *color = ERRORCOLOR;
  462.  }
  463.  else
  464.  {
  465.   if (formatting)
  466.   {
  467.    sprintf(vstring, "%1.*f", fvalue & 15, cellptr->v.value);
  468.    if (fvalue & COMMAS)
  469.    {
  470.     pos = strcspn(vstring, ".");
  471.     while (pos > 3)
  472.     {
  473.      pos -= 3;
  474.      if (vstring[pos - 1] != '-')
  475.      {
  476.       movmem(&vstring[pos], &vstring[pos + 1], strlen(vstring) - pos + 1);
  477.       vstring[pos] = ',';
  478.      }
  479.     }
  480.    }
  481.    if (fvalue & DOLLAR)
  482.    {
  483.     if (vstring[0] == '-')
  484.     {
  485.      fstring = " $";
  486.      width = colwidth[col] - 2;
  487.     }
  488.     else
  489.     {
  490.      fstring = " $ ";
  491.      width = colwidth[col] - 3;
  492.     }
  493.    }
  494.    else
  495.    {
  496.     fstring = "";
  497.     width = colwidth[col];
  498.    }
  499.    strcpy(s, vstring);
  500.    if (fvalue & RJUSTIFY)
  501.    {
  502.     if (strlen(vstring) > width)
  503.      vstring[width] = 0;
  504.     else
  505.      sprintf(vstring, "%*s", width, s);
  506.    }
  507.    else
  508.     sprintf(vstring, "%-*s", width, s);
  509.    movmem(vstring, &vstring[strlen(fstring)], strlen(vstring) + 1);
  510.    strncpy(vstring, fstring, strlen(fstring));
  511.   }
  512.   else
  513.    sprintf(vstring, "%.*f", MAXPLACES, value);
  514.   *color = VALUECOLOR;
  515.  }
  516. } /* valuestring */
  517.  
  518. char *cellstring(int col, int row, int *color, int formatting)
  519. /* Erzeugt einen Ausgabestring für die Daten in der Zelle (col, row) und
  520.    liefert auch die Farbe der Zelle  */
  521. {
  522.  CELLPTR cellptr = cell[col][row];
  523.  int newcol, formatvalue;
  524.  static char s[81], temp[MAXCOLWIDTH + 1];
  525.  char *p;
  526.  double value;
  527.  
  528.  if (cellptr == NULL)
  529.  {
  530.   if (!formatting || (format[col][row] < OVERWRITE))
  531.   {
  532.    sprintf(s, "%*s", colwidth[col], "");
  533.    *color = BLANKCOLOR;
  534.   }
  535.   else
  536.   {
  537.    newcol = col;
  538.    while (cell[--newcol][row] == NULL);
  539.    p = cell[newcol][row]->v.text;
  540.    while (newcol < col)
  541.     p += colwidth[newcol++];
  542.    strncpy(temp, p, colwidth[col]);
  543.    temp[colwidth[col]] = 0;
  544.    sprintf(s, "%s%*s", temp, colwidth[col] - strlen(temp), "");
  545.    *color = TEXTCOLOR;
  546.   }
  547.  }
  548.  else
  549.  {
  550.   formatvalue = format[col][row];
  551.   switch (cellptr->attrib)
  552.   {
  553.    case TEXT :
  554.     textstring(cellptr->v.text, s, col, formatvalue, formatting);
  555.     *color = TEXTCOLOR;
  556.     break;
  557.    case FORMULA :
  558.     if (formdisplay)
  559.     {
  560.      textstring(cellptr->v.f.formula, s, col, formatvalue, formatting);
  561.      *color = FORMULACOLOR;
  562.      break;
  563.     }
  564.     else
  565.      value = cellptr->v.f.fvalue;
  566.    case VALUE :
  567.     if (cellptr->attrib == VALUE)
  568.      value = cellptr->v.value;
  569.     valuestring(cellptr, value, s, col, formatvalue, color,
  570.                 formatting);
  571.     break;
  572.   } /* switch */
  573.  }
  574.  return(s);
  575. } /* cellstring */
  576.  
  577. void writeprompt(char *prompt)
  578. /* Gibt ein Prompt am Bildschirm aus */
  579. {
  580.  writef(1, 24, PROMPTCOLOR, 80, prompt);
  581. } /* writeprompt */
  582.  
  583. void swap(int *val1, int *val2)
  584. /* Vertauscht den ersten Wert mit dem zweiten */
  585. {
  586.  int temp;
  587.  
  588.  temp = *val1;
  589.  *val1 = *val2;
  590.  *val2 = temp;
  591. } /* swap */
  592.  
  593. void checkforsave(void)
  594. /* Wurde das Rechenblatt geändert, wird der Benutzer gefragt, ob es
  595.    gespeichert werden soll.
  596. */
  597. {
  598.  int save;
  599.  
  600.  if (changed && getyesno(&save, MSGSAVESHEET) && (save == 'Y'))
  601.   savesheet();
  602. } /* checkforsave */
  603.  
  604. void initvars(void)
  605. /* Initialisiert verschiedene globale Variablen */
  606. {
  607.  leftcol = toprow = curcol = currow = lastcol = lastrow = 0;
  608.  setmem(colwidth, sizeof(colwidth), DEFAULTWIDTH);
  609.  setmem(cell, sizeof(cell), 0);
  610.  setmem(format, sizeof(format), DEFAULTFORMAT);
  611. } /* initvars */
  612.  
  613. int getcommand(char *msgstr, char *comstr)
  614. /* Liest einen Befehl und bearbeitet ihn */
  615. {
  616.  int ch, counter, len = strlen(msgstr);
  617.  
  618.  scroll(UP, 0, 1, 24, 80, 24, WHITE);
  619.  for (counter = 0; counter < len; counter++)
  620.  {
  621.   if (isupper(msgstr[counter]))
  622.    writef(counter + 1, 24, COMMANDCOLOR, 1, "%c", msgstr[counter]);
  623.   else
  624.    writef(counter + 1, 24, LOWCOMMANDCOLOR, 1, "%c", msgstr[counter]);
  625.  }
  626.  do
  627.   ch = toupper(getkey());
  628.  while ((strchr(comstr, ch) == NULL) && (ch != ESC));
  629.  clearinput();
  630.  return((ch == ESC) ? -1 : strlen(comstr) - strlen(strchr(comstr, ch)));
  631. } /* getcommand */
  632.  
  633.