Home

   {                 Unidade de Memoria                          }
   {                  Versao      0.01                           }
   {-------------------------------------------------------------}
   { Contem:manipulacao de lista de pointer }
   {        manipulacao de lista de string  }
   {        manipulacao de variavel PChar   }
   {        gerador de lista com diretorio  }
   {        E/S de disco                    }
   {        atribuicao de pointer           }
   {        existencia de arquivo           }
{ Under GNU License            }
{ JOAO PAULO SCHWARZ SCHULER }
{ http://www.schulers.com      }
{ Turbo Pascal Source          }
{ Free Pascal Source for DOS   }
{ Free Pascal Source for Linux }


                     unit UMEM;


                      INTERFACE
    uses crt,
       strings
       ,dos

      ;

function NEW_UTILPOINTER:pointer;
{ aloca tabela de ponteiros realmente uteis }

function PCHARLEN(PC:PChar):word;
{ devolve o tamanho de uma string apontada por PCHAR }

function GETPCHAR(TX:string):PChar;
{ Cria uma PCHAR com o counteudo passado como parametro em TX do tipo string }

function GETSTRING(PC:PChar):string;
{ devolve uma string do tipo STRING armazenada como PCHAR }

procedure PCHARDISPOSE(PC:PCHAR);
{ devolve o numero de caracteres da string apontada por PChar }

function ASPOINTER(PT:pointer):pointer;
{ recebe pointer tipado e devolve pointer nao tipado }

function FileExists(FileName: String): Boolean;  { RETIRADO DO TURBO HELP }
{ Boolean function that returns True if the file exists;otherwise,
 it returns False. Closes the file if it exists. }

procedure APAGATELA;
{ apaga toda tela }

function IFW(EXP : boolean;O1,O2 : word):word;
{se a expressao EXP for verdadeira, devolve Operando 1; senao, Operando 2}


   {----------- Objeto de lista de pointers ------------------}
   { permite uma lista com 65534 pointers !!!                 }
   { BASE : tabela de 256 ponteiros que apontam para tabelas com    }
   {        capacidade cada uma de outros 256 ponteiros, note que   }
   {        estas ultimas sao alocadas de acordo com a necessidade. }

type UTILPOINTER = record                { tabela de pointers }
                      PT:array [0..255] of pointer;   { ponteiros }
                      NUM:byte;                       { numero de ponteiros }
                   end;

type UTILPOINTERPTR = ^UTILPOINTER;      { pointer para tabela de pointers }

type LISTA_POINTER = object
                      BASE : array [0..255] of UTILPOINTERPTR;
      { BASE: tabela que aponta para tabelas de pointers uteis }
                      NUMP : word;
      { NUMP: numero de pointers na lista                      }

                      constructor INIT;
                      procedure INSERT(P:pointer);
                      { insere ponteiro P na lista }

                      procedure PUT(NUM:word;P:pointer);
                      { deposita pointer P na posicao NUM }

                      procedure KILL(NUM:word);
                      { deleta o iten NUM da lista }

                      procedure KILLALL;
                      { deleta todos os itens }

                      function GET(NUM:word):pointer;
                      { pega um ponteiro de indice NUM }

                      function GETNUM:word;
                      { retorna numero de elementos da lista }

                      destructor DONE;
                   { desaloca todas as tabelas de ponteiros realmente uteis }
                     end;


type STRINGPTR = ^string;

type LISTA_STRING = object(LISTA_POINTER)


                      procedure INSERTSTR(S:string);
                      { insere string }

                      function GETSTR(NUM:word):string;
                      { devolve string de indice NUM }

                      procedure DESALOCA;
                      { desaloca strings }
                    end;


{-------------------- IO de disco ---------------------------------------}
type IODiskBuffer = record
                      Buf : array[0..2047] of byte;{buffer propriamente dito}
                      NUM : word; {numero de bytes no buffer }
                      Modified : boolean;{ se o buffer foi modificado}
                      TAB : longint; { numero da tabela (pagina) }
                    end;

type IODISK = object
                F:file ;
                NOME:string;          { nome do arquivo   }
                BUFIN:IODiskBuffer;   { buffer de leitura }
                BUFOUT:IODiskBuffer;  { buffer de escrita }

                constructor Init(PNOME:string);
                { abre o arquivo }

                function Read(POS:longint):byte;
                { le um byte da posicao POS }

                procedure Write(POS:longint;INF:byte);
                { escreve um byte INF na posicao POS }

                function TAMANHO:longint;
                { devolve o tamanho do arquivo }

                procedure HARD;
                { gravacao fisica do buffer de saida }

                procedure RELOAD;
                { le os buffers novamente do disco }

                destructor Done;
                { fecha arquivo }
              end;

procedure MakeDirList(var DIR:LISTA_POINTER);
{ cria lista contendo diretorio }

procedure DisposeListPChar(var LIS:LISTA_POINTER);
{ Desaloca lista de PChars }

   procedure StrSet(var P : pchar; const S : string );
   { Seta uma uma nova string a um pchar }

    function strpnew(const s : string) : pchar;

    function MyStrPas(P:pchar):string;

                    IMPLEMENTATION

{-----------------------------NOVIDADES---------------------------}
    function strpnew(const s : string) : pchar;
      var
         p : pchar;
      begin
         getmem(p,length(s)+1);
         strpcopy(p,s);
         strpnew:=p;
      end;

   procedure StrSet(var P : pchar; const S : string );
   { Seta uma uma nova string a um pchar }
   begin
   if Assigned(P)
      then StrDispose(P);
   P:=StrPNew(S);
   end;

   function MyStrPas(P:pchar):string;
   begin
   if P<>nil
      then MyStrPas:=StrPas(P)
      else MyStrPas:='';
   end;

{--------------FIM DAS NOVIDADES----------------------------------}

function NEW_UTILPOINTER:pointer;
{ aloca tabela de ponteiros realmente uteis }
{ todos os pointers da nova tabela recebem nil }
var I:integer;
    UP:UTILPOINTERPTR;
begin
new(UP);
for I:=0 to 255 do UP^.PT[I]:=nil;
UP^.NUM:=0;
NEW_UTILPOINTER:=UP;
end;

constructor LISTA_POINTER.INIT;
{ Ponteiros de indice de arrays de ponteiros recebem NIL }
var I:integer;
begin
for I:=0 to 255 do BASE[I]:=nil;
NUMP:=0;
end;


procedure LISTA_POINTER.INSERT(P:pointer);
{ insere ponteiro P na lista }
var TABELA,POSICAO:byte;
    UP:UTILPOINTERPTR;
begin
inc(NUMP);
TABELA:=NUMP shr 8;           { pointer que aponta para tabela de pointers }
POSICAO:=NUMP and 255;        { posicao do pointer util }
if BASE[TABELA]=NIL           { tabela de pointers nao alocada ? }
   then begin
        BASE[TABELA]:=NEW_UTILPOINTER;   { aloca tabela }
        end;

UP:=BASE[TABELA];
if UP^.PT[POSICAO]=NIL
   then begin
        UP^.PT[POSICAO]:=P;         { Insere pointer }
        inc(UP^.NUM);
        end
   else begin
        UP^.PT[POSICAO]:=P;
        end;
end;

procedure LISTA_POINTER.PUT(NUM:word;P:pointer);
{ deposita pointer P na posicao NUM }
var TABELA,POSICAO:byte;
    UP:UTILPOINTERPTR;
begin
if NUM>NUMP then
   begin
   write('ERRO em PUT/LISTA_POINTER');
   halt;
   end
 else
   begin
   TABELA:=NUM shr 8;           { pointer que aponta para tabela de pointers }
   POSICAO:=NUM and 255;        { posicao do pointer util }
   UP:=BASE[TABELA];
   UP^.PT[POSICAO]:=P;
   end;
end;

function LISTA_POINTER.GETNUM:word;
{ retorna numero de elementos da lista }
begin
GETNUM:=NUMP;
end;

function LISTA_POINTER.GET(NUM:word):pointer;
{ pega um ponteiro de indice NUM }
var TABELA,POSICAO:byte;
    UP:UTILPOINTERPTR;
    RESULT:pointer;
begin
TABELA:=NUM shr 8;                { calcula posicao }
POSICAO:=NUM and 255;
if BASE[TABELA]=NIL               { tabela secundaria nao existe ? }
   then begin
        RESULT:=NIL;
        end
   else begin
        RESULT:=BASE[TABELA]^.PT[POSICAO];  { devolve conteudo }
        end;
GET:=RESULT;
end;

procedure LISTA_POINTER.KILL(NUM:word);
{ deleta o iten NUM da lista }
var COUNT:word;
    TABELA,POSICAO:byte;
    UP:UTILPOINTERPTR;

begin
for COUNT:=NUM to NUMP do     { shift na lista }
    PUT(COUNT,GET(succ(COUNT)));
TABELA:=NUMP shr 8;           { pointer que aponta para tabela de pointers }
POSICAO:=NUMP and 255;        { posicao do pointer util }
UP:=BASE[TABELA];
dec(UP^.NUM);
if UP^.NUM=0 then
   begin
   dispose(UP);
   BASE[TABELA]:=nil;        { desaloca tabela sem pointers }
   end;
dec(NUMP); { decrementa numero de pointers }
end;

procedure LISTA_POINTER.KILLALL;
{ deleta todos os itens }
var I:integer;
begin
NUMP:=0;
for I:=0 to 255 do
    begin
    if BASE[I]<>nil then
       begin
       DISPOSE(BASE[I]);
       BASE[I]:=nil;
       end;{ of if }
    end; { of for }
end; { of procedure }

destructor LISTA_POINTER.DONE;
{ desaloca todas as tabelas de ponteiros realmente uteis }
var I:integer;
begin
for I:=0 to 255 do
    begin
    if BASE[I]<>nil then
       DISPOSE(BASE[I]);
    end;
end;

procedure LISTA_STRING.INSERTSTR(S:string);
{ insere string }
var SPTR:STRINGPTR;
begin
new(SPTR);
SPTR^:=S;
INSERT(SPTR);
end;

function LISTA_STRING.GETSTR(NUM:word):string;
{ devolve string de indice NUM }
var SPTR:STRINGPTR;
begin
SPTR:=GET(NUM);
GETSTR:=SPTR^;
end;

procedure LISTA_STRING.DESALOCA;
{ desaloca strings }
var SPTR:STRINGPTR;
    W:word;
begin
for W:=1 to NUMP do
    begin
    SPTR:=GET(W);
    dispose(SPTR);
    end;
end;

{ ----------  Rotinas para permitir uso das variaveis PChar ----------------}
{---------------------------------------------------------------------------}
{ As funcoes e procedimentos, apesar de serem de uso absolutamente generico,}
{ forma desenvolvidas durante o Projeto de Editor de texto, ja que nao e    }
{ permitido o uso da Turbo Vision e qualquer biblioteca                     }

function PCHARLEN(PC:PChar):word;
{ devolve o tamanho de uma string apontada por PCHAR }
var COUNT:word;
begin
COUNT:=1;
while ord(PC[pred(count)]) <> 0 do
      inc(COUNT);
PCHARLEN := pred(COUNT);
end;

function GETPCHAR(TX:string):PChar;
{ Cria uma PCHAR com o counteudo passado como parametro em TX do tipo string }
var COUNT:word;
    PC:PChar;
begin
GetMem(PC,succ(ord(TX[0])));
for COUNT:=1 to ord(TX[0]) do
    PC[pred(COUNT)] := TX[COUNT];
PC[ord(TX[0])]:=chr(0);
GETPCHAR := PC;
end;

function GETSTRING(PC:PChar):string;
{ devolve uma string do tipo STRING armazenada como PCHAR }
var COUNT:word;
    TX:string;
begin
tx:='';
COUNT:=1;
while ( PC[pred(COUNT)] <> chr(0) ) and (COUNT<256) do
      begin
      TX[COUNT]:=PC[pred(COUNT)];
      inc(COUNT);
      end;
TX[0]:=chr(pred(COUNT));
GETSTRING:=TX;
end;

procedure PCHARDISPOSE(PC:PCHAR);
{ devolve o numero de caracteres da string apontada por PChar }
begin
if PC<>nil then
   FreeMem(PC,succ(PCHARLEN(PC)));
end;

procedure MakeDirList(var DIR:LISTA_POINTER);
{ cria lista contendo diretorio }
var
 DirInfo: SearchRec;
begin
 FindFirst('*.*', Archive, DirInfo);
while DosError = 0 do
 begin
   DIR.INSERT(GetPChar(DirInfo.Name));
   FindNext(DirInfo);
 end;
end;

procedure DisposeListPChar(var LIS:LISTA_POINTER);
{ Desaloca lista de PChars }
var COUNT:word;
    MAX:word;
begin
MAX:=LIS.GETNUM;
for COUNT:=1 to MAX do
    PCHARDISPOSE(LIS.GET(COUNT));
end;

function ASPOINTER(PT:pointer):pointer;
{ recebe pointer tipado e devolve pointer nao tipado }
begin
ASPOINTER:=PT;
end;

function FileExists(FileName: String): Boolean;  { RETIREDO DO TURBO HELP }
{ Boolean function that returns True if the file exists;otherwise,
 it returns False. Closes the file if it exists. }
var
 F: file;
begin
 {$I-}
 Assign(F, FileName);
 Reset(F);
 Close(F);
 {$I+}
 FileExists := (IOResult = 0) and (FileName <> '');
end;  { FileExists }


{ -------- Objeto de Entrada e saida de disco ------------------- }

constructor IODISK.Init(PNOME:string);
{ abre o arquivo }
begin
NOME:=PNOME;
assign(F,NOME);
if FileExists(NOME)
   then reset(F,1)
   else rewrite(F,1);
seek(F,0);

{ prepara buffer de entrada }
BUFIN.TAB:=0;
BUFIN.MODIFIED:=false;
blockread(F,BUFIN.BUF,2048,BUFIN.NUM);

{prepara arquivo de saida }
seek(F,0);
BUFOUT.TAB:=0;
BUFOUT.MODIFIED:=false;
blockread(F,BUFOUT.BUF,2048,BUFOUT.NUM);
end;

function IODISK.Read(POS:longint):byte;
{ le um byte da posicao POS }
var TAB:longint;    { tabela para alocar }
    POSONTAB:word;  { posicao na tabela  }
    RESULT:byte;
begin
TAB:=POS shr 11;
POSONTAB:= POS and 2047;
if BUFOUT.TAB=TAB then        { procura na tabela de escrita }
   begin
   RESULT:=BUFOUT.BUF[POSONTAB];
   end
 else
   begin
   if BUFIN.TAB=TAB then      { procaura na tabela de leitura }
      begin
      RESULT:=BUFIN.BUF[POSONTAB];
      end
    else
      begin                        { le outra tabela }
      seek(F,TAB shl 11);
      BUFIN.TAB:=TAB;
      BUFIN.MODIFIED:=false;
      blockread(F,BUFIN.BUF,2048,BUFIN.NUM);
      RESULT:=BUFIN.BUF[POSONTAB];
      end;
   end;
READ:=result;
end; { of function }


procedure IODISK.Write(POS:longint;INF:byte);
{ escreve um byte INF na posicao POS }
var TAB:longint;    { tabela para alocar }
    POSONTAB:word;  { posicao na tabela  }
begin
TAB:=POS shr 11;
POSONTAB:= POS and 2047;
if BUFIN.TAB=TAB then
   begin
   BUFIN.BUF[POSONTAB]:=INF;    { grava informacao no buffer de leitura }
   end;

if BUFOUT.TAB=TAB then
   begin
   BUFOUT.BUF[POSONTAB]:=INF;
   BUFOUT.MODIFIED:=true;
   end
 else
   begin
   if BUFOUT.MODIFIED then
      begin
      seek(F,BUFOUT.TAB shl 11);           { grava buffer antigo }
      blockwrite(F,BUFOUT.BUF,BUFOUT.NUM);
      BUFOUT.MODIFIED:=false;
      end;

   seek(F,TAB shl 11);
   BUFOUT.TAB:=TAB;
   blockread(F,BUFOUT.BUF,2048,BUFOUT.NUM);
   BUFOUT.BUF[POSONTAB]:=INF;
   BUFOUT.MODIFIED:=true;
   end;

if BUFOUT.NUM<succ(POSONTAB)
   then BUFOUT.NUM:=succ(POSONTAB); {GARANTE GRAVACAO DENTRO DO BUFFER}
end; { of procedure }

function IODISK.TAMANHO:longint;
{ devolve o tamanho do arquivo }
begin
TAMANHO:=filesize(F);
end;

procedure IODISK.HARD;
{ gravacao fisica do buffer de saida }
begin
if BUFOUT.MODIFIED then
   begin
   seek(F,BUFOUT.TAB shl 11);           { grava buffer antigo }
   blockwrite(F,BUFOUT.BUF,BUFOUT.NUM);
   BUFOUT.MODIFIED:=false;
   end;
end;

procedure IODISK.RELOAD;
{ le os buffers novamente do disco }
begin
{ prepara buffer de entrada }
BUFIN.MODIFIED:=false;
seek(F,BUFIN.TAB shl 11);
blockread(F,BUFIN.BUF,2048,BUFIN.NUM);

{prepara arquivo de saida }
seek(F,BUFOUT.TAB shl 11);
BUFOUT.MODIFIED:=false;
blockread(F,BUFOUT.BUF,2048,BUFOUT.NUM);
end;

destructor IODISK.Done;
{ fecha arquivo }
begin
HARD;
close(F);
end;

procedure APAGATELA;
{ apaga toda tela }
begin
textbackground(black);
window(1,1,80,25);
clrscr;
end;

function IFW(EXP : boolean;O1,O2 : word):word;
{se a expressao EXP for verdadeira devolve Operando 1 senao Operando 2}
begin
if EXP then IFW := O1
       else IFW := O2;
end;



end.