PROGRAM LOCALIZA; {A+,S+,B-,E+,N+} {$M 16384, 000000, 50000} USES CRT,DOS; TYPE CADENA80 = STRING[80]; CADENA15 = STRING[15]; REGHORA = RECORD COMPHORA : WORD; { formato comprimido DOS } CADHORA : CADENA80; PM : BOOLEAN; HORAS,MINUTOS,SEGUNDOS,CENTESIMAS : INTEGER END; REGFECHA = RECORD FECHACOMP : WORD; CADENALARGAFECHA : CADENA80; CADENAFECHA : CADENA80; AGNO,MES,DIA : INTEGER; DIASEMANA : INTEGER END; PTRDIR = ^REGDIR; REGDIR = RECORD NOMBREFICHERO : CADENA15; ATRIB : BYTE; TAMFICHERO : LONGINT; HORA : REGHORA; FECHA : REGFECHA; ANTERIOR : PTRDIR; SIGUIENTE : PTRDIR; END; PTRDTA = ^SEARCHREC; VAR I,J : INTEGER; ESPECBUSQUEDA : CADENA80; DIRECTORIOINIC : CADENA80; BUFFERBUSQ : SEARCHREC; COLOR1 : BYTE; COLOR2 : BYTE; COLOR3 : BYTE; (**********************************************************) FUNCTION MODOVIDEOACTUAL : CHAR; VAR REGS : REGISTERS; BEGIN FILLCHAR(REGS,SIZEOF(REGS),0); REGS.AH:=$0F; INTR($10,REGS); CASE REGS.AL OF 1..6 : MODOVIDEOACTUAL := 'C'; {CGA} 7 : MODOVIDEOACTUAL := 'M'; {monocromo} 8..10 : MODOVIDEOACTUAL := 'P'; {PCjr} 13..16 : MODOVIDEOACTUAL := 'E' {EGA} END END; (**********************************************************) FUNCTION CALCDIASEMANA(AGNO,MES,DIA : INTEGER) : INTEGER; VAR SALVARFECHA,FECHATRABAJO : REGISTERS; NUMERODIA : INTEGER; BISIESTO : BOOLEAN; CONST DAYARRAY : ARRAY[1..12] OF INTEGER = (31,28,31,30,31,30,31,31,30,31,30,31); BEGIN BISIESTO := FALSE; IF (MES = 2) AND ((AGNO MOD 4)=0) AND (DIA = 29) THEN BISIESTO := TRUE; IF (NOT BISIESTO) AND (DIA > DAYARRAY[MES]) THEN CALCDIASEMANA := -1 ELSE BEGIN FECHATRABAJO.AH := $2B; SALVARFECHA.AH := $2A; { Salva la fecha en registros } MSDOS(SALVARFECHA); WITH FECHATRABAJO DO BEGIN CX := AGNO; { Hace el reloj igual a la fecha introducida } DH := MES; DL := DIA; MSDOS(FECHATRABAJO); AH := $2A; { Leer de nuevo la fecha para } MSDOS(FECHATRABAJO); { obtener el indicador de d¡a de la sem. } NUMERODIA := AL; { en AL. } IF BISIESTO THEN { Corregir para a¤os bisiesto } IF NUMERODIA = 0 THEN NUMERODIA := 6 ELSE NUMERODIA := PRED(NUMERODIA); CALCDIASEMANA := NUMERODIA END; SALVARFECHA.AH := $2B; { Reponer la fecha actual } MSDOS(SALVARFECHA); END END; (**********************************************************) PROCEDURE CALCFECHA(VAR FECHAACTUAL : REGFECHA); TYPE CADENA9 = STRING[9]; CONST MESES : ARRAY [1..12] OF CADENA9 = ('Enero','Febrero','Marzo','Abril','Mayo','Junio','Julio', 'Agosto','Septiembre','Octubre','Noviembre','Diciembre'); DIAS : ARRAY [0..6] OF CADENA9 = ('Domingo','Lunes','Martes','Mi‚rcoles', 'Jueves','Viernes','S bado'); VAR TEMP1 : CADENA80; BEGIN WITH FECHAACTUAL DO BEGIN DIASEMANA := CALCDIASEMANA(AGNO,MES,DIA); STR(MES,CADENAFECHA); STR(DIA,TEMP1); CADENAFECHA := CADENAFECHA + '/' + TEMP1; CADENALARGAFECHA := DIAS[DIASEMANA] + ', '; CADENALARGAFECHA := CADENALARGAFECHA + MESES[MES] + ' ' + TEMP1 + ', '; STR(AGNO,TEMP1); CADENALARGAFECHA := CADENALARGAFECHA + TEMP1; CADENAFECHA := CADENAFECHA + '/' + COPY(TEMP1,3,2); FECHACOMP := (AGNO - 1980) * 512 + (MES * 32) + DIA END END; (**********************************************************) PROCEDURE CALCHORA(VAR HORAACTUAL : REGHORA); TYPE CADENA5 = STRING[5]; VAR TEMP1,TEMP2 : CADENA5; AMPM : CHAR; I : INTEGER; BEGIN WITH HORAACTUAL DO BEGIN I := HORAS; IF HORAS = 0 THEN I := 12; { "0" horas = 12am } IF HORAS > 12 THEN I := HORAS - 12; IF HORAS > 11 THEN AMPM := 'p' ELSE AMPM := 'a'; STR(I:2,TEMP1); STR(MINUTOS,TEMP2); IF LENGTH(TEMP2) < 2 THEN TEMP2 := '0' + TEMP2; CADHORA := TEMP1 + ':' + TEMP2 + AMPM; COMPHORA := (HORAS SHL 11) OR (MINUTOS SHL 5) OR (SEGUNDOS SHR 1) END END; (**********************************************************) FUNCTION DIRACADENA(DIRENT : REGDIR) : STRING; CONST BLANCOS= ' '; VAR TEMP,CADTRABAJO : CADENA80; POSPUNTO : INTEGER; BEGIN WITH DIRENT DO BEGIN TEMP := ' '; {Si la entrada tiene atributo de directorio, formato diferente: } IF (ATRIB AND $10) <> 0 THEN { el bit 4 es el atrib. de direct. } BEGIN INSERT(NOMBREFICHERO,TEMP,1); { No hay extens. en nombres de subdir. } INSERT('',TEMP,14) { Decirle al mundo qu‚ es un subdir. } END ELSE { Esta sentencia compuesta separa el nombre del fichero y su } { extensi¢n, y convierte el tama¤o en una cadena. No se } { inserta una cifra de tama¤o en Temp para los subdirectorios. } BEGIN POSPUNTO := POS('.',NOMBREFICHERO); IF POSPUNTO > 0 THEN { El nombre del fichero tiene extensi¢n } CADTRABAJO := COPY(NOMBREFICHERO,1,POSPUNTO-1) + COPY(BLANCOS,1,9-POSPUNTO) + '.' + COPY(NOMBREFICHERO,POSPUNTO+1,LENGTH(NOMBREFICHERO)-POSPUNTO) ELSE CADTRABAJO := NOMBREFICHERO + COPY(BLANCOS,1,8-LENGTH(NOMBREFICHERO)) + '.'; INSERT(CADTRABAJO,TEMP,1); STR(TAMFICHERO:7,CADTRABAJO); INSERT(CADTRABAJO,TEMP,15) END; WITH FECHA DO BEGIN { Esta sentencia une las tres cifras independientes para } { el mes, el dia, y el a¤o, en una cadena.} IF MES < 10 THEN INSERT('0',CADENAFECHA,1); IF DIA < 10 THEN INSERT('0',CADENAFECHA,4); INSERT(CADENAFECHA,TEMP,24); END; INSERT(HORA.CADHORA,TEMP,34); { Finalmente, insertar la hora } END; DELETE(TEMP,42,LENGTH(TEMP)-42); DIRACADENA := TEMP END; (**********************************************************) PROCEDURE DTAADIR(VAR REGSALIDA : REGDIR); VAR DATODT : DATETIME; { Importado de la unidad DOS } I : INTEGER; REGINT : SEARCHREC; { Idem } REGCOMP : REGISTERS; { Idem } DTAACTUAL : PTRDTA; BEGIN REGCOMP.AX := $2F00; { Localizar posici¢n actual del DTA } MSDOS(REGCOMP); WITH REGCOMP DO DTAACTUAL := PTR(ES,BX); REGINT := DTAACTUAL^; UNPACKTIME(REGINT.TIME,DATODT); WITH REGSALIDA DO { Extraer y reformatear los datos } BEGIN NOMBREFICHERO:= REGINT.NAME; { Extraer nombre de fichero } ATRIB := REGINT.ATTR; { Extraer el campo de atributos } WITH HORA DO { Desarrollar la hora comprimida } BEGIN COMPHORA := REGINT.TIME SHR 16; HORAS := DATODT.HOUR; MINUTOS := DATODT.MIN; SEGUNDOS := DATODT.SEC; CENTESIMAS := 0; END; CALCHORA(HORA); { Llenar los otros campos } WITH FECHA DO { Desarrollar la fecha comprimida } BEGIN FECHACOMP := REGINT.TIME AND $0000FFFF; DIA := DATODT.DAY; MES := DATODT.MONTH; AGNO := DATODT.YEAR; END; CALCFECHA(FECHA); { Llenar los otros campos } TAMFICHERO := REGINT.SIZE; SIGUIENTE := NIL; { Inicializar el puntero "siguiente" } ANTERIOR := NIL { Inicializar el puntero "anterior" } END END; { DTAADIR } (**********************************************************) PROCEDURE BUSCARDIRECTORIO(DIRECTORIO,ESPECBUSQUEDA : STRING); VAR SIGUIENTEDIRECTORIO : STRING; DIRECTORIOTEMP : STRING; DTAACTUAL : SEARCHREC; DIRACTUAL : REGDIR; REGS : REGISTERS; {>>>>PresenDatos<<<<} { Presenta los datos del fichero y la v¡a de acceso completa } (*********************) PROCEDURE PRESENDATOS(DIRECTORIO : STRING; DIRACTUAL : REGDIR); VAR TEMP : STRING; BEGIN TEMP := DIRACADENA(DIRACTUAL); DELETE(TEMP,1,13); WRITE(TEMP,DIRECTORIO); IF DIRECTORIO <> '\' THEN WRITE('\'); WRITELN(DIRACTUAL.NOMBREFICHERO) END; BEGIN { En primer lugar buscamos subdirectorios. Si se encuentra alguno, } { hacemos una llamada recursiva para buscar en ‚l tambi‚n. } { Suprimir barras innecesarias si buscamos la ra¡z: } IF DIRECTORIO = '\' THEN DIRECTORIOTEMP := DIRECTORIO + '*.*' ELSE DIRECTORIOTEMP := DIRECTORIO + '\*.*'; { Hacer la llamada a FIND FIRST para los directorios: } FINDFIRST(DIRECTORIOTEMP,$10,DTAACTUAL); { Aqu¡ hay un peque¤o truco. Si tenemos alguna indicaci¢n de que } { hay al menos un subdirectorio m s adentro del directorio actual, } { (no aparecen los c¢digos de error 2 ¢ 18) debemos buscar en ‚l } { haciendo una llamada recursiva a BuscarDirectorio. Continuamos } { con esta estrategia hasta que ya no queden m s subdirectorios } { por explorar. } WHILE (DOSERROR <> 2) AND (DOSERROR <> 18) DO BEGIN IF ((DTAACTUAL.ATTR AND $10) = $10) { Si es un directorio } AND (DTAACTUAL.NAME[1] <> '.') THEN { y no '.' o '..' } BEGIN { A¤adimos una barra para separar las secciones de la v¡a } { de acceso si no estamos buscando en el directorio ra¡z: } IF DIRECTORIO <> '\' THEN SIGUIENTEDIRECTORIO := DIRECTORIO + '\' ELSE SIGUIENTEDIRECTORIO := DIRECTORIO; { Se comienza con el nombre del directorio actual, y se } { copia el nombre del directorio encotrado desde el DTA } { al final de la cadena del directorio actual. Luego se } { pasa la nueva v¡a de acceso a la siguiente llamada } { recursiva a BuscarDirectorio. } SIGUIENTEDIRECTORIO := SIGUIENTEDIRECTORIO + DTAACTUAL.NAME; { El procedimiento se llama a s¡ mismo. } BUSCARDIRECTORIO(SIGUIENTEDIRECTORIO,ESPECBUSQUEDA) END; FINDNEXT(DTAACTUAL) { Buscamos m s... } END; { Ahora podemos buscar ficheros, una vez que hemos acabado con } { los directorios. Esto es conceptualmente simple, ya que no } { involucra recursividad. Combinamos la v¡a acceso y el especi- } { ficador en una sola cadena y hacemos la llamada a FIND FIRST: } { Suprimir barras innecesarias para buscar en el directorio ra¡z: } IF DIRECTORIO <> '\' THEN DIRECTORIOTEMP := DIRECTORIO + '\' + ESPECBUSQUEDA ELSE DIRECTORIOTEMP := DIRECTORIO + ESPECBUSQUEDA; { Hacer la llamada a FIND FIRST: } FINDFIRST(DIRECTORIOTEMP,$07,DTAACTUAL); IF DOSERROR = 3 THEN { v¡a de acceso err¢nea } WRITELN('v¡a de acceso no encontrada; compruebe los datos.') { Si encontramos en el directorio actual algo que coincida con el espe- } { cificador, se a¤ade con el formato adecuado a una cadena y se presenta } ELSE IF (DOSERROR = 2) OR (DOSERROR = 18) THEN { Cadena nula: directorio vacio } ELSE BEGIN DTAADIR(DIRACTUAL); { Convertir a formato DIR.. } PRESENDATOS(DIRECTORIO,DIRACTUAL); { Presentar informaci¢n } IF DOSERROR <> 18 THEN { Existen m s ficheros... } REPEAT FINDNEXT(DTAACTUAL); IF DOSERROR <> 18 THEN { Existen m s entradas } BEGIN DTAADIR(DIRACTUAL); { Convertir a formato DIR } PRESENDATOS(DIRECTORIO,DIRACTUAL) { Presentar informaci¢n } END UNTIL (DOSERROR = 18) OR (DOSERROR = 2) { No hay m s ficheros } END END; (**********************************************************) BEGIN WINDOW(3,5,78,24); CLRSCR; {vemos el modo de v¡deo para tener en cuenta los colores} IF MODOVIDEOACTUAL='M' THEN BEGIN COLOR1:=WHITE; COLOR2:=WHITE; COLOR3:=WHITE END ELSE BEGIN COLOR1:=YELLOW; COLOR2:=LIGHTRED; COLOR3:=LIGHTGREEN END; TEXTBACKGROUND(LIGHTBLUE); TEXTCOLOR(COLOR1); IF PARAMCOUNT = 0 THEN BEGIN TEXTCOLOR(COLOR3); WRITELN(' EVALUACION V:1.00 "EMILIO SAHUQUILLO & JULIO MARTINEZ"'); TEXTCOLOR(COLOR1); WRITELN; WRITELN(' Esta opci¢n busca en el disco de trabajo todos los '); WRITELN(' ficheros que concuerdan con un determinado especificador,'); WRITELN(' examinando todos los subidirectorios necesarios.'); WRITELN(' Dado s¢lo el especificador, se presentar  la v¡a '); WRITELN(' de acceso completa de cualquier fichero que se considere'); WRITELN(' adecuado.'); TEXTCOLOR(COLOR2); WRITELN(' SINTAXIS DE LLAMADA:'); WRITELN(' '); TEXTCOLOR(COLOR1); WRITELN; TEXTCOLOR(COLOR2); WRITELN(' Por ejemplo : '); TEXTCOLOR(COLOR1); WRITELN(' para encontrar todos los ficheros de texto '); WRITELN(' (que terminan en .TXT) deberemos introducir:'); WRITELN; WRITELN(' *.TXT'); WRITELN; WRITELN(' y se mostrar  la v¡a de acceso completa de '); WRITELN(' cualquier fichero con la extensi¢n .TXT.') END ELSE BEGIN WRITELN; ESPECBUSQUEDA := PARAMSTR(1); { Si no se da especificador se buscar  en todo el disco: } IF POS('\',ESPECBUSQUEDA) = 0 THEN BUSCARDIRECTORIO('\',ESPECBUSQUEDA) ELSE BEGIN { Se separa el especificador de la v¡a de acceso: } I := LENGTH(ESPECBUSQUEDA); WHILE ESPECBUSQUEDA[I] <> '\' DO I := PRED(I); DIRECTORIOINIC := COPY(ESPECBUSQUEDA,1,I-1); DELETE(ESPECBUSQUEDA,1,I); BUSCARDIRECTORIO(DIRECTORIOINIC,ESPECBUSQUEDA) END END; TEXTBACKGROUND(BLACK); TEXTCOLOR(WHITE); LOWVIDEO END.