rllib  1
rlspreadsheet.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                           rlspreadsheet.h  -  description
00003                              -------------------
00004     begin                : Tue Jan 02 2001
00005     copyright            : (C) 2001 by Rainer Lehrig
00006     email                : lehrig@t-online.de
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This library is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as        *
00013  *   published by the Free Software Foundation                             *
00014  *                                                                         *
00015  ***************************************************************************/
00016 #include <stdio.h>
00017 #include <stdarg.h>
00018 #include <string.h>
00019 #include "rlspreadsheet.h"
00020 #include "rlcutil.h"
00021 
00022 static const char null_string[] = "";
00023 
00024 // rlSpreadsheetCell
00025 rlSpreadsheetCell::rlSpreadsheetCell(const char *Text)
00026 {
00027   if(Text != NULL)
00028   {
00029     txt = new char[strlen(Text)+1];
00030     strcpy(txt,Text);
00031   }
00032   else
00033   {
00034     txt = NULL;
00035   }
00036   nextCell = NULL;
00037 }
00038 
00039 rlSpreadsheetCell::~rlSpreadsheetCell()
00040 {
00041   if(txt != NULL) delete [] txt;
00042 }
00043 
00044 const char *rlSpreadsheetCell::text()
00045 {
00046   if(txt == NULL) return null_string;
00047   return txt;
00048 }
00049 
00050 void rlSpreadsheetCell::setText(const char *Text)
00051 {
00052   if(txt  != NULL) delete [] txt;
00053   if(Text == NULL)
00054   {
00055     txt = NULL;
00056     return;
00057   }
00058   txt = new char[strlen(Text)+1];
00059   strcpy(txt,Text);
00060 }
00061 
00062 int rlSpreadsheetCell::printf(const char *format, ...)
00063 {
00064   int ret;
00065   char buf[rl_PRINTF_LENGTH_SPREADSHEET]; // should be big enough
00066 
00067   va_list ap;
00068   va_start(ap,format);
00069   ret = rlvsnprintf(buf, rl_PRINTF_LENGTH_SPREADSHEET - 1, format, ap);
00070   va_end(ap);
00071   setText(buf);
00072   return ret;
00073 }
00074 
00075 void rlSpreadsheetCell::clear()
00076 {
00077   if(txt != NULL) delete [] txt;
00078   txt = NULL;
00079 }
00080 
00081 void rlSpreadsheetCell::setNextCell(rlSpreadsheetCell *next)
00082 {
00083   nextCell = next;
00084 }
00085 
00086 rlSpreadsheetCell  *rlSpreadsheetCell::getNextCell()
00087 {
00088   return nextCell;
00089 }
00090 
00091 int rlSpreadsheetCell::exists()
00092 {
00093   return 1;
00094 }
00095 
00096 // rlSpreadsheetRow
00097 rlSpreadsheetRow::rlSpreadsheetRow()
00098 {
00099   firstCell = NULL;
00100   nextRow   = NULL;
00101 }
00102 
00103 rlSpreadsheetRow::~rlSpreadsheetRow()
00104 {
00105   rlSpreadsheetCell *item,*last;
00106   item = firstCell;
00107   while(item != NULL)
00108   {
00109     last = item;
00110     item = item->getNextCell();
00111     if(item != last) delete last;
00112   }
00113 }
00114 
00115 const char *rlSpreadsheetRow::text(int column)
00116 {
00117   int c = 1;
00118   rlSpreadsheetCell *item;
00119 
00120   item = firstCell;
00121   while(item != NULL)
00122   {
00123     if(c == column) return item->text();
00124     item = item->getNextCell();
00125     c++;
00126   }
00127   return null_string;
00128 }
00129 
00130 void rlSpreadsheetRow::setText(int column, const char *text)
00131 {
00132   int c = 1;
00133   rlSpreadsheetCell *item;
00134 
00135   if(column < 1) return;
00136   if(firstCell == NULL) firstCell = new rlSpreadsheetCell;
00137 
00138   item = firstCell;
00139   while(1)
00140   {
00141     if(c == column)  { item->setText(text); return; }
00142     if(item->getNextCell() == NULL) item->setNextCell(new rlSpreadsheetCell);
00143     item = item->getNextCell();
00144     c++;
00145   }
00146 }
00147 
00148 int rlSpreadsheetRow::printf(int column, const char *format, ...)
00149 {
00150   int ret;
00151   char buf[rl_PRINTF_LENGTH_SPREADSHEET]; // should be big enough
00152   
00153   va_list ap;
00154   va_start(ap,format);
00155   ret = rlvsnprintf(buf, rl_PRINTF_LENGTH_SPREADSHEET - 1, format, ap);
00156   va_end(ap);
00157   setText(column,buf);
00158   return ret;
00159 }
00160 
00161 void rlSpreadsheetRow::clear()
00162 {
00163   rlSpreadsheetCell *item;
00164 
00165   item = firstCell;
00166   while(item != NULL)
00167   {
00168     item->clear();
00169     item = item->getNextCell();
00170   }
00171 }
00172 
00173 void rlSpreadsheetRow::setNextRow(rlSpreadsheetRow *next)
00174 {
00175   nextRow = next;
00176 }
00177 
00178 rlSpreadsheetRow  *rlSpreadsheetRow::getNextRow()
00179 {
00180   return nextRow;
00181 }
00182 
00183 rlSpreadsheetCell *rlSpreadsheetRow::getFirstCell()
00184 {
00185   return firstCell;
00186 }
00187 
00188 void rlSpreadsheetRow::readRow(const unsigned char *line, char delimitor)
00189 {
00190   int i,tab1,tab2,col;
00191   unsigned char *celltext;
00192 
00193   clear();
00194 
00195   tab1 = tab2 = -1;
00196   col = 1;
00197   i = 0;
00198   while(line[i] != '\0')
00199   {
00200     if(line[i] == delimitor || line[i] == '\n' || line[i] == 0x0d) // normally delimitor='\t'
00201     {
00202       tab1 = tab2;
00203       tab2 = i;
00204       celltext = new unsigned char[tab2-tab1+1];
00205       if(tab2 > tab1)
00206       {
00207         strncpy((char *) celltext,(const char *) &line[tab1+1],tab2-tab1);
00208         celltext[tab2-tab1-1] = '\0';
00209       }
00210       else
00211       {
00212         celltext[0] = '\0';
00213       }
00214       setText(col++, (char *) celltext);
00215       delete [] celltext;
00216     }
00217     i++;
00218   }
00219 
00220   return;
00221 }
00222 
00223 void rlSpreadsheetRow::writeRow(void *fp, char delimitor)
00224 {
00225   rlSpreadsheetCell *cell;
00226   if(fp == NULL) return;
00227   cell = firstCell;
00228   while(cell != NULL)
00229   {
00230     fprintf((FILE *) fp,"%s",cell->text());
00231     cell = cell->getNextCell();
00232     if(cell != NULL) fprintf((FILE *) fp, "%c", delimitor);
00233   }
00234   fprintf((FILE *) fp,"\n");
00235 }
00236 
00237 int rlSpreadsheetRow::exists(int column)
00238 {
00239   rlSpreadsheetCell *item;
00240   int c;
00241 
00242   c = 1;
00243   item = firstCell;
00244   while(item != NULL)
00245   {
00246     if(c == column) return 1;
00247     c++;
00248     item = item->getNextCell();
00249   }
00250   return 0;
00251 }
00252 
00253 // rlSpreadsheetTable
00254 rlSpreadsheetTable::rlSpreadsheetTable(char del)
00255 {
00256   firstRow  = NULL;
00257   nextTable = NULL;
00258   delimitor = del;
00259 }
00260 
00261 rlSpreadsheetTable::~rlSpreadsheetTable()
00262 {
00263   rlSpreadsheetRow *item,*last;
00264   item = firstRow;
00265   while(item != NULL)
00266   {
00267     last = item;
00268     item = item->getNextRow();
00269     if(item != last) delete last;
00270   }
00271 }
00272 
00273 const char *rlSpreadsheetTable::text(int column, int row)
00274 {
00275   int r = 1;
00276   rlSpreadsheetRow *item;
00277 
00278   item = firstRow;
00279   while(item != NULL)
00280   {
00281     if(r == row) return item->text(column);
00282     item = item->getNextRow();
00283     r++;
00284   }
00285   return null_string;
00286 }
00287 
00288 void rlSpreadsheetTable::setText(int column, int row, const char *text)
00289 {
00290   int r = 1;
00291   rlSpreadsheetRow *item,*nextitem;
00292 
00293   if(row < 1) return;
00294   if(firstRow == NULL) firstRow = new rlSpreadsheetRow;
00295   item = firstRow;
00296   while(1)
00297   {
00298     if(r == row) { item->setText(column,text); return; }
00299     nextitem = item->getNextRow();
00300     if(nextitem == NULL) item->setNextRow(new rlSpreadsheetRow);
00301     item = item->getNextRow();
00302     r++;
00303   }
00304 }
00305 
00306 int rlSpreadsheetTable::printf(int column, int row, const char *format, ...)
00307 {
00308   int ret;
00309   char buf[rl_PRINTF_LENGTH_SPREADSHEET]; // should be big enough
00310 
00311   va_list ap;
00312   va_start(ap,format);
00313   ret = rlvsnprintf(buf, rl_PRINTF_LENGTH_SPREADSHEET - 1, format, ap);
00314   va_end(ap);
00315   setText(column,row,buf);
00316   return ret;
00317 }
00318 
00319 void rlSpreadsheetTable::clear()
00320 {
00321   rlSpreadsheetRow *item;
00322 
00323   item = firstRow;
00324   while(item != NULL)
00325   {
00326     item->clear();
00327     item = item->getNextRow();
00328   }
00329 }
00330 
00331 int rlSpreadsheetTable::read(const char *filename)
00332 {
00333   FILE *fp;
00334   rlSpreadsheetRow *item,*last,*next;
00335   unsigned char *line;
00336   int r = 1;
00337   if(filename == NULL) return -1;
00338 
00339   // delete old table
00340   item = firstRow;
00341   while(item != NULL)
00342   {
00343     last = item;
00344     item = item->getNextRow();
00345     if(item != last) delete last;
00346   }
00347 
00348   // read new table
00349   fp = fopen(filename,"r");
00350   if(fp == NULL) return -1;
00351   line = new unsigned char[256*256+1];
00352   while(fgets((char *) line,256*256,fp) != NULL)
00353   {
00354     if(r==1)
00355     {
00356       item = firstRow = new rlSpreadsheetRow;
00357     }
00358     else
00359     {
00360       next = new rlSpreadsheetRow;
00361       item->setNextRow(next);
00362       item = next;
00363     }
00364     item->readRow(line,delimitor);
00365     r++;
00366   }
00367   delete [] line;
00368   fclose(fp);
00369   return r - 1; // number of lines that have been read
00370 }
00371 
00372 int rlSpreadsheetTable::write(const char *filename)
00373 {
00374   rlSpreadsheetRow *item;
00375   FILE *fp;
00376   if(filename == NULL) return -1;
00377   fp = fopen(filename,"w");
00378   if(fp == NULL) return -1;
00379 
00380   item = firstRow;
00381   while(item != NULL)
00382   {
00383     item->writeRow((void *) fp);
00384     item = item->getNextRow();
00385   }
00386 
00387   fclose(fp);
00388   return 0;
00389 }
00390 
00391 void rlSpreadsheetTable::setNextTable(rlSpreadsheetTable *next)
00392 {
00393   nextTable = next;
00394 }
00395 
00396 rlSpreadsheetRow *rlSpreadsheetTable::getFirstRow()
00397 {
00398   return firstRow;
00399 }
00400 
00401 rlSpreadsheetTable  *rlSpreadsheetTable::getNextTable()
00402 {
00403   return nextTable;
00404 }
00405 
00406 int rlSpreadsheetTable::exists(int column, int row)
00407 {
00408   rlSpreadsheetRow *item;
00409   int r;
00410 
00411   r = 1;
00412   item = firstRow;
00413   while(item != NULL)
00414   {
00415     if(r == row) return item->exists(column);
00416     r++;
00417     item = item->getNextRow();
00418   }
00419   return 0;
00420 }
00421 
00422 void rlSpreadsheetTable::setDelimitor(char _delimitor)
00423 {
00424   delimitor = _delimitor;
00425 }
00426 
00427 // rlSpreadsheetWorkbook
00428 rlSpreadsheetWorkbook::rlSpreadsheetWorkbook(char del)
00429 {
00430   firstTable = NULL;
00431   delimitor = del;
00432 }
00433 
00434 rlSpreadsheetWorkbook::~rlSpreadsheetWorkbook()
00435 {
00436   rlSpreadsheetTable *item,*last;
00437   item = firstTable;
00438   while(item != NULL)
00439   {
00440     last = item;
00441     item = item->getNextTable();
00442     if(item != last) delete last;
00443   }
00444 }
00445 
00446 const char *rlSpreadsheetWorkbook::text(int column, int row, int page)
00447 {
00448   int p = 1;
00449   rlSpreadsheetTable *item;
00450 
00451   item = firstTable;
00452   while(item != NULL)
00453   {
00454     if(p == page) return item->text(column, row);
00455     item = item->getNextTable();
00456     p++;
00457   }
00458   return null_string;
00459 }
00460 
00461 void rlSpreadsheetWorkbook::setText(int column, int row, int page, const char *text)
00462 {
00463   int p = 1;
00464   rlSpreadsheetTable *item,*nextitem;
00465 
00466   if(page < 1) return;
00467   if(firstTable == NULL) firstTable = new rlSpreadsheetTable;
00468   item = firstTable;
00469   while(1)
00470   {
00471     if(p == page) { item->setText(column, row, text); return; }
00472     nextitem = item->getNextTable();
00473     if(nextitem == NULL) item->setNextTable(new rlSpreadsheetTable);
00474     item = item->getNextTable();
00475     p++;
00476   }
00477 }
00478 
00479 int rlSpreadsheetWorkbook::printf(int column, int row, int page, const char *format, ...)
00480 {
00481   int ret;
00482   char buf[rl_PRINTF_LENGTH_SPREADSHEET]; // should be big enough
00483 
00484   va_list ap;
00485   va_start(ap,format);
00486   ret = rlvsnprintf(buf, rl_PRINTF_LENGTH_SPREADSHEET - 1, format, ap);
00487   va_end(ap);
00488   setText(column,row,page,buf);
00489   return ret;
00490 }
00491 
00492 void rlSpreadsheetWorkbook::clear()
00493 {
00494   rlSpreadsheetTable *item;
00495 
00496   item = firstTable;
00497   while(item != NULL)
00498   {
00499     item->clear();
00500     item = item->getNextTable();
00501   }
00502 }
00503 
00504 int rlSpreadsheetWorkbook::read(const char *filename)
00505 {
00506   FILE *fp;
00507   rlSpreadsheetTable *item,*last,*next;
00508   int p = 1;
00509   char buf[16],*fname;
00510   if(filename == NULL) return -1;
00511 
00512   // delete old workbook
00513   item = firstTable;
00514   while(item != NULL)
00515   {
00516     last = item;
00517     item = item->getNextTable();
00518     if(item != last) delete last;
00519   }
00520 
00521   // read new workbook
00522   fname = new char[strlen(filename)+16];
00523   while(1)
00524   {
00525     strcpy(fname,filename);
00526     sprintf(buf,"%d.txt",p);
00527     strcat(fname,buf);
00528     // test if file exists
00529     fp = fopen(fname,"r");
00530     if(fp == NULL) break;
00531     fclose(fp);
00532     if(p==1)
00533     {
00534       item = firstTable = new rlSpreadsheetTable(delimitor);
00535     }
00536     else
00537     {
00538       next = new rlSpreadsheetTable(delimitor);
00539       item->setNextTable(next);
00540       item = next;
00541     }
00542     if(item->read(fname) < 0) break;
00543     p++;
00544   }
00545 
00546   delete [] fname;
00547   return 0;
00548 }
00549 
00550 int rlSpreadsheetWorkbook::write(const char *filename)
00551 {
00552   rlSpreadsheetTable *item = NULL;
00553   int p = 1;
00554   char buf[16],*fname;
00555   if(filename == NULL) return -1;
00556 
00557   // write workbook
00558   fname = new char[strlen(filename)+16];
00559   while(1)
00560   {
00561     strcpy(fname,filename);
00562     sprintf(buf,"%d.txt",p);
00563     strcat(fname,buf);
00564     if(p==1) item = firstTable;
00565     else     item = item->getNextTable();
00566     if(item == NULL)     break;
00567     if(item->write(fname) < 0) break;
00568     p++;
00569   }
00570 
00571   delete [] fname;
00572   return 0;
00573 }
00574 
00575 int rlSpreadsheetWorkbook::exists(int column, int row, int page)
00576 {
00577   rlSpreadsheetTable *item;
00578   int p;
00579 
00580   p = 1;
00581   item = firstTable;
00582   while(item != NULL)
00583   {
00584     if(p == page) return item->exists(column,row);
00585     p++;
00586     item = item->getNextTable();
00587   }
00588   return 0;
00589 }
00590 
00591 rlSpreadsheetTable *rlSpreadsheetWorkbook::getFirstTable()
00592 {
00593   return firstTable;
00594 }
00595 
00596 void rlSpreadsheetWorkbook::setDelimitor(char _delimitor)
00597 {
00598   delimitor = _delimitor;
00599 }
00600 
00601