Logo Search packages:      
Sourcecode: deal version File versions  Download package

stringbox.c

/*
 * Copyright (C) 1996-2001, Thomas Andrews
 *
 * 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, or
 * (at your option) any later version.
 * 
 * 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; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <stdio.h>
#include "stringbox.h"
#include <string.h>

00023 typedef struct string_box_base {
  int rows, columns;
  char *start;
  int refcount;
} *StringBoxBase;

00029 typedef struct string_box {
  StringBoxBase parent;
  int rows,columns;
  char **strings;
} *StringBox;

static void clearStringBox(box)
     StringBox box;
{
  int rows=box->rows, columns=box->columns;
  int r,c;
  for (r=0; r<rows; r++) {
    for (c=0; c<columns; c++) {
      box->strings[r][c] = ' ';
    }
  }
}

static int writeStringBox(interp,box,row,column,string)
     Tcl_Interp *interp; /* May be null.  For error messages */
     StringBox box;
     int row;
     int column;
     char *string;
{
  int rowcount=box->rows, columncount=box->columns;
  char *boxstring;
  int startcolumn=column;
  char c;
  if (row<0 || row>=rowcount || column>=columncount || column<0) {
    if (interp != (Tcl_Interp *)NULL) {
      char s[20];
      sprintf(s,"%d %d",row,column);
      Tcl_AppendResult(interp,"illegal parameters \"",s,"\"",NULL);
    }
    return TCL_ERROR;
  }
  boxstring=box->strings[row]+column;
  while ((c=*(string++))!=0) {
    if (c=='\n') {
      row++;
      if (row>=rowcount) return TCL_OK;
      column=startcolumn;
      boxstring=box->strings[row]+column;
      continue;
    }
    if (column<columncount) {
      *boxstring=c;
      boxstring++;
      column++;
    }
  }
  return TCL_OK;
}

static char *formatStringBox(box)
     StringBox box;
{
  int row=0,col=0;
  char *result=Tcl_Alloc(box->rows*(box->columns+1)+1);
  char *rindex=result;
  for (row=0; row<box->rows; row++) {
    for (col=0; col<box->columns; col++) {
      *(rindex++)=box->strings[row][col];
    }
    *(rindex++)='\n';
  }
  *(--rindex)=0;
  return result;
}

static char *compactStringBox(box)
     StringBox box;
{
  int row,col;
  char *result=Tcl_Alloc((box->rows)*(box->columns+1)+1);
  char *rindex=result;
  char c,*lastnonspace;
  for (row=0; row<box->rows; row++) {
    lastnonspace=rindex;
    for (col=0; col<box->columns; col++) {
      *(rindex++)=c=box->strings[row][col];
      if (c!=' ') {
      lastnonspace=rindex;
      }
    }
    rindex=lastnonspace;
    *(rindex++)='\n';
  }
  *(--rindex)=0;
  return result;
}


static StringBox newStringBox(rows,columns)
     int rows;
     int columns;
{
  StringBoxBase parent;
  StringBox result;
  int i;
  if (rows<=0 || columns<=0) {
    return 0;
  }
  parent=(StringBoxBase)Tcl_Alloc(sizeof(struct string_box_base));
  parent->rows=rows;
  parent->columns=columns;
  parent->start=Tcl_Alloc(rows*columns*sizeof(char));
  parent->refcount=1;

  result=(StringBox)Tcl_Alloc(sizeof(struct string_box));
  result->rows=rows;
  result->columns=columns;
  result->strings=(char **)Tcl_Alloc(rows*sizeof(char **));

  for (i=0; i<rows; i++) {
    result->strings[i]=parent->start+i*columns;
  }
      
  result->parent=parent;

  clearStringBox(result);
  return result;
}

static StringBox subStringBox(interp,parentbox,rowloc,columnloc,rows,columns)
     Tcl_Interp *interp; /* For error messages only */
     StringBox parentbox;
     int rowloc,columnloc;
     int rows;
     int columns;
{
  StringBoxBase parent;
  StringBox result;
  int i;
  
  if (rows<=0 || columns<=0 || rowloc< 0 || columnloc<0) {
    goto error;
  }
  
  if (rows+rowloc>parentbox->rows || rows+columnloc>parentbox->columns) {
    goto error;
  }
  
  parent=parentbox->parent;
  parent->refcount++;
  
  result=(StringBox)Tcl_Alloc(sizeof(struct string_box));
  
  result->rows=rows;
  result->columns=columns;
  result->strings=(char **)Tcl_Alloc(rows*sizeof(char **));
  
  for (i=0; i<rows; i++) {
    result->strings[i]=parentbox->strings[rowloc+i]+columnloc;
  }
  
  result->parent=parent;
  
  clearStringBox(result);
  return result;
 error:

  if (interp != (Tcl_Interp *)NULL) {
    Tcl_AppendResult(interp, "subbox: illegal argument",NULL);
  }
  return 0;
}


      
void deleteStringBox(ClientData boxdata)
{
  StringBox box=(StringBox)boxdata;
  Tcl_Free((char *)box->strings);
#ifdef DEBUG
  fprintf(stderr,"Deleting stringbox\n");
#endif
  if (--(box->parent->refcount) <=0) {
    Tcl_Free((char *)box->parent->start);
    Tcl_Free((char *)box->parent);
#ifdef DEBUG
    fprintf(stderr,"Deleting parent box\n");
#endif
  }
  Tcl_Free((char *)box);
}

static int tcl_string_box(TCLOBJ_PARAMS)
     TCLOBJ_DECL
{
  const char *command;
  StringBox box=(StringBox)cd;
  int len;
  if (objc==1) {
    Tcl_SetResult(interp,formatStringBox(box),TCL_DYNAMIC);
    return TCL_OK;
  }

  command=Tcl_GetStringFromObj(objv[1],&len);

  if (command==NULL) {
    return TCL_ERROR;
  }

  if ('w'==(*command) && strcmp(command,"write")==0) {
    int row, col;
    if (objc!=5) {
      Tcl_AppendResult(interp, "wrong # args: should be \"", 
                   Tcl_GetString(objv[0]),
                   " write row column string\"",NULL);
      return TCL_ERROR;
    }
    if  (Tcl_GetIntFromObj(interp,objv[2],&row)!=TCL_OK ||
       Tcl_GetIntFromObj(interp,objv[3],&col)!=TCL_OK) {
      Tcl_AppendResult(interp,"\nbad row or column arguments: row=\"",
                   Tcl_GetString(objv[2]),
                   "\", column=\"",
                   Tcl_GetString(objv[3]),"\"", NULL);
      return TCL_ERROR;
    }

    return writeStringBox(interp,box,row,col,Tcl_GetString(objv[4]));

  }
  
  if (*command=='c' && strcmp(command,"clear")==0) {
    clearStringBox(box);
    return TCL_OK;
  }

  if (*command=='r' && strcmp(command,"rows")==0) {
    if (objc!=2) {
      Tcl_AppendResult(interp, "wrong # args: should be \"", 
                   Tcl_GetString(objv[0]),
                   " ",command,"\"", NULL);
      return TCL_ERROR;
    }
    Tcl_SetObjResult(interp,Tcl_NewIntObj(box->rows));
    return TCL_OK;
  }

  if (*command=='c' && strcmp(command,"columns")==0) {
    if (objc!=2) {
      Tcl_AppendResult(interp, "wrong # args: should be \"", 
                   Tcl_GetString(objv[0]),
                   " ",command,"\"", NULL);
      return TCL_ERROR;
    }
    Tcl_SetObjResult(interp,Tcl_NewIntObj(box->columns));
    return TCL_OK;
  }

  if (*command=='s' && strcmp(command,"subbox")==0) {
    StringBox subbox;
    int rows=0,columns=0,rowloc=0,columnloc=0;
    
    if (objc!=7 && objc!=5) {
      Tcl_AppendResult(interp, "wrong # args: should be \"", 
                   Tcl_GetString(objv[0]),
                   " subbox name rowloc columnloc [ rows columns ]\"",
                   (char *)NULL);
      return TCL_ERROR;
    }
    
    if (Tcl_GetIntFromObj(interp,objv[3],&rowloc) != TCL_OK) {
      if (rowloc<0) {
      Tcl_AppendResult(interp,"Illegal row location \"",
                   Tcl_GetString(objv[3]),"\" passed to subbox routine",NULL);
      }     
      return TCL_ERROR;
    }
    
    if (Tcl_GetIntFromObj(interp,objv[4],&columnloc) != TCL_OK) {
      if (columnloc<0) {
      Tcl_AppendResult(interp,"Illegal column location \"",
                   Tcl_GetString(objv[4]),"\" passed to subbox routine",NULL);
      }
      return TCL_ERROR;
    }
    if (objc==7) {
      if ((Tcl_GetIntFromObj(interp,objv[5],&rows) != TCL_OK)) {
      return TCL_ERROR;
      }
    
      if ((Tcl_GetIntFromObj(interp,objv[6],&columns) != TCL_OK)) {
      return TCL_ERROR;
      }
    }

    if (rowloc<0) {
      rowloc=(box->rows)+rowloc;
    }
    if (columnloc<0) {
      columnloc=(box->columns)+columnloc;
    }

    if (rows<=0) {
      rows=rows+(box->rows)-rowloc;
    }
    if (columns<=0) {
      columns=columns+(box->columns)-columnloc;
    }

    subbox=subStringBox(interp,box,rowloc,columnloc,rows,columns);

    if (subbox==(StringBox)0) {
      return TCL_ERROR;
    }

    Tcl_CreateObjCommand(interp,Tcl_GetString(objv[2]),tcl_string_box,subbox,deleteStringBox);

    return TCL_OK;
  }

  if (*command=='c' && strcmp(command,"compact")==0) {
    Tcl_SetResult(interp,compactStringBox(box),TCL_DYNAMIC); 
    return TCL_OK;
  }

  Tcl_AppendResult(interp, "unknown stringbox operation: \"", 
               Tcl_GetString(objv[0]), " ",
               command," ...\"",NULL);
  return TCL_ERROR;
}

int tcl_create_string_box(TCLOBJ_PARAMS)
     TCLOBJ_DECL
{
  int rows,columns;
  StringBox box;
   
  if (objc!=4) {
    Tcl_AppendResult(interp, "wrong # args: should be \"", 
                 Tcl_GetString(objv[0]),
                 " name rows columns\"",(char *)NULL);
    return TCL_ERROR;
  }
    
  if ((Tcl_GetIntFromObj(interp,objv[2],&rows) != TCL_OK) || (rows<=0)) {
    Tcl_AddErrorInfo(interp,
                 "\n (reading value of <rows>)");
    return TCL_ERROR;
  }

  if (Tcl_GetIntFromObj(interp,objv[3],&columns) != TCL_OK || (columns<=0)) {
    Tcl_AddErrorInfo(interp,
                 "\n (reading value of <columns>)");
    return TCL_ERROR;
  }

  box=newStringBox(rows,columns);
  Tcl_CreateObjCommand(interp,Tcl_GetString(objv[1]),tcl_string_box,box,deleteStringBox);
  return TCL_OK;
}

int Stringbox_Init(interp)
     Tcl_Interp *interp;
{
#if 0
  int code;
  code = Tcl_PkgProvide(interp,"stringbox","1.0");
  if (code != TCL_OK) {
    return code;
  }
#endif
  Tcl_CreateObjCommand(interp,"stringbox",tcl_create_string_box,NULL,NULL);
  return TCL_OK;
}

Generated by  Doxygen 1.6.0   Back to index