home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / nicol / sti_dbas / sti_db1.pas next >
Encoding:
Pascal/Delphi Source File  |  1980-01-01  |  31.5 KB  |  1,100 lines

  1. program STI_DB1;
  2.  
  3. Uses Crt,Dos;
  4.  
  5.  
  6. Const
  7.   STI_DB_VLOB           =  1;               { field type for VLOBS          }
  8.   STI_DB_DATE           =  2;
  9.   STI_DB_TIME           =  3;
  10.   STI_DB_BYTE           =  4;
  11.   STI_DB_CHAR           =  5;
  12.   STI_DB_STRING         =  6;
  13.   STI_DB_INTEGER        =  7;
  14.   STI_DB_WORD           =  8;
  15.   STI_DB_REAL           =  9;
  16.   STI_DB_SOUND          =  10;
  17.   STI_DB_TEXT           =  11;
  18.   STI_DB_IMAGE          =  12;
  19.  
  20.  
  21.   VLOB_BLOCK_SIZE       =  128;             { very large object block       }
  22.   MAX_REC_LEN           =  5120;            { maximum record size           }
  23.   MAX_FIELDS            =  255;             { maximum number of fields      }
  24.   FIELD_DESC_LEN        =  10;              { length of field desciptor     }
  25.   MAX_HEAD_LEN          =  4000;            { maximum header length         }
  26.   MAX_FILES             =  5;               { maximum nuber of files        }
  27.  
  28.   STI_DB_NOT_OPEN       =  1;               { file states : unopened        }
  29.   STI_DB_NOT_UPDATED    =  2;               { opened : not updated          }
  30.   STI_DB_UPDATED        =  3;               { opened : updated              }
  31.   STI_DB_LOCKED         =  4;               { access is locked              }
  32.   STI_DB_ACCESS_OK      =  5;               { access is ok                  }
  33.  
  34.   STI_DB_ILLEGAL_FIELD  =  1;               { this is an illegal field      }
  35.   STI_NOT_STI_DB_FILE   =  2;               { this is not an STI file       }
  36.   STI_DB_ALREADY_OPEN   =  3;               { the file is already open      }
  37.   STI_DB_ILLEGAL_FILE   =  4;               { not a legal file number       }
  38.   STI_DB_BAD_FIELD_NUM  =  5;               { bot a legal field number      }
  39.   STI_DB_BAD_RECORD_NUM =  6;               { illegal record number         }
  40.  
  41.   ASCEND                =  1;
  42.   DESCEND               =  2;
  43.  
  44.  
  45. Type
  46.   STI_Sort = array[1..255] of byte;         { for sorting                   }
  47.   STI_BDat = array[1..3] of byte;           { for binary dates              }
  48.   STI_Ver  = array[1..2] of byte;           { for playing with version      }
  49.   STI_VLOB = array[1..VLOB_BLOCK_SIZE] of byte; { one VLOB block            }
  50.   STI_Rec  = array[1..MAX_REC_LEN] of char; { one record                    }
  51.   STI_Date = string[8];                     { type for date                 }
  52.   STIFDesc = string[FIELD_DESC_LEN];        { field descriptor              }
  53.  
  54.   STI_DBHead  =  record
  55.                    Version    : word;       { hi byte = major, lo  = minor  }
  56.                    With_VLOB  : boolean;    { does it have a VLOB field     }
  57.                    LastUpDate : STI_BDat;   { YY MM DD (YY = 1960 + 1..255  }
  58.                    RecNumber  : longint;    { 0..2147483647 records         }
  59.                    RecordLen  : word;       { 65535 bytes or 255 * 255      }
  60.                    FieldNum   : byte;       { 255 fields                    }
  61.                    HeaderLen  : word;       { size of header                }
  62.                  end;
  63.  
  64.    STI_DBField = record
  65.                    Descriptor : STIFDesc;   { field descriptor              }
  66.                    Length     : byte;       { 1..255 bytes in length        }
  67.                    FieldType  : byte;       { type of this field            }
  68.                    Offset     : word;       { offset in bytes in record     }
  69.                  end;
  70.  
  71.    STI_DBFArr  = array[1..MAX_FIELDS] of STI_DBField; { array of fields     }
  72.  
  73.    STI_DBFile  = record
  74.                    Name       : string;     { file name                     }
  75.                    DataFile   : file;       { the input file                }
  76.                    Header     : STI_DBHead; { the file header               }
  77.                    Status     : byte;       { the file status               }
  78.                    CurRecord  : longint;    { current record number         }
  79.                    Fields     : ^STI_DBFArr;{ the field and desciptors      }
  80.                    RecData    : ^STI_Rec;   { the current record            }
  81.                  end;
  82.    STI_DBFS = array[1..MAX_FILES] of STI_DBFile; { array of files           }
  83.  
  84. Var
  85.   STI_DB_Error    : byte;                   { error types                   }
  86.   STI_DB_IOStatus : integer;                { status of file IO             }
  87.   STI_OK          : boolean;                { error flag                    }
  88.  
  89.   STI_DBFiles     : STI_DBFS;               { files for access              }
  90.   STI_DBCurrent   : byte;                   { currently active file         }
  91.  
  92. {---------------------------------------------------------------------------}
  93. {                                                                           }
  94. {       ATOMIC PROCEDURES FOLLOW. BASIC I/O                                 }
  95. {                                                                           }
  96. {---------------------------------------------------------------------------}
  97.  
  98. procedure STI_DB_IOcheck(RecordNo : longint);
  99.  
  100. begin
  101.   if STI_DB_IOstatus <> 0 then
  102.     with STI_DBFiles[STI_DBCurrent] do
  103.       begin
  104.         Writeln;
  105.         Writeln('STI_DB I/O error ',STI_DB_IOstatus);
  106.         Write('File ');
  107.         Writeln(Name);
  108.         Writeln('- Record ',RecordNo);
  109.         Writeln('- Program aborted');
  110.         Halt;
  111.       end;
  112. end;
  113.  
  114. {---------------------------------------------------------------------------}
  115.  
  116. procedure STI_DB_ErrorCheck;
  117.  
  118. begin
  119.   if not(STI_OK) then
  120.     begin
  121.       WriteLn;
  122.       WriteLn('STI_DB Runtime Error ',STI_DB_Error);
  123.       WriteLn('File ',STI_DBFiles[STI_DBCurrent].Name);
  124.       WriteLn('- Record ',STI_DBFiles[STI_DBCurrent].CurRecord);
  125.       WriteLn('- Program aborted');
  126.       Halt;
  127.     end;
  128. end;
  129.  
  130. {---------------------------------------------------------------------------}
  131.  
  132. procedure STI_DBGetRec(RecordNo : longint);
  133.  
  134. begin
  135.   Seek(STI_DBFiles[STI_DBCurrent].DataFile,
  136.        STI_DBFiles[STI_DBCurrent].Header.HeaderLen+
  137.        (RecordNo*STI_DBFiles[STI_DBCurrent].Header.RecordLen));
  138.   STI_DB_IOstatus := IOresult;
  139.   STI_DB_IOcheck(RecordNo);
  140.   BlockRead(STI_DBFiles[STI_DBCurrent].DataFile,
  141.             STI_DBFiles[STI_DBCurrent].RecData^,
  142.             STI_DBFiles[STI_DBCurrent].Header.RecordLen);
  143.   STI_DB_IOstatus := IOresult;
  144.   STI_DB_IOcheck(RecordNo);
  145.   STI_DBFiles[STI_DBCurrent].CurRecord := RecordNo;
  146.   if STI_DBFiles[STI_DBCurrent].Header.RecNumber < RecordNo then
  147.     STI_DBFiles[STI_DBCurrent].Header.RecNumber := RecordNo;
  148. end;
  149.  
  150. {---------------------------------------------------------------------------}
  151.  
  152. procedure STI_DBPutRec(RecordNo : longint);
  153.  
  154. begin
  155.   Seek(STI_DBFiles[STI_DBCurrent].DataFile,
  156.        STI_DBFiles[STI_DBCurrent].Header.HeaderLen+
  157.        (RecordNo*STI_DBFiles[STI_DBCurrent].Header.RecordLen));
  158.   STI_DB_IOstatus := IOresult;
  159.   STI_DB_IOcheck(RecordNo);
  160.   BlockWrite(STI_DBFiles[STI_DBCurrent].DataFile,
  161.             STI_DBFiles[STI_DBCurrent].RecData^,
  162.             STI_DBFiles[STI_DBCurrent].Header.RecordLen);
  163.   STI_DB_IOstatus := IOresult;
  164.   STI_DB_IOcheck(RecordNo);
  165.   STI_DBFiles[STI_DBCurrent].CurRecord := RecordNo;
  166.   if STI_DBFiles[STI_DBCurrent].Header.RecNumber < RecordNo then
  167.     STI_DBFiles[STI_DBCurrent].Header.RecNumber := RecordNo;
  168. end;
  169.  
  170. {---------------------------------------------------------------------------}
  171.  
  172. procedure STI_DBPutRec2(RecordNo : longint; var Data; RecLen   : word);
  173.  
  174. begin
  175.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  176.     begin
  177.       STI_OK := FALSE;
  178.       STI_DB_Error := STI_DB_NOT_OPEN;
  179.     end;
  180.   STI_DB_ErrorCheck;
  181.   Move(Data,STI_DBFiles[STI_DBCurrent].RecData^[2],RecLen);
  182.   STI_DBPutRec(RecordNo);
  183. end;
  184.  
  185. {---------------------------------------------------------------------------}
  186.  
  187. procedure STI_DBGetRec2(RecordNo : longint; var Data; RecLen   : word);
  188.  
  189. begin
  190.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  191.     begin
  192.       STI_OK := FALSE;
  193.       STI_DB_Error := STI_DB_NOT_OPEN;
  194.     end;
  195.   STI_DB_ErrorCheck;
  196.   STI_DBGetRec(RecordNo);
  197.   Move(STI_DBFiles[STI_DBCurrent].RecData^[2],Data,RecLen);
  198. end;
  199.  
  200. {---------------------------------------------------------------------------}
  201.  
  202. procedure STI_DB_Check_Fields(Fields : STI_DBFArr; Num : byte);
  203.  
  204. Var
  205.   Loop : byte;
  206.  
  207. begin
  208.   for Loop := 1 to Num do
  209.     begin
  210.       if not(Fields[Loop].FieldType in[STI_DB_VLOB..STI_DB_IMAGE]) then
  211.         begin
  212.           STI_OK := FALSE;
  213.           STI_DB_Error := STI_DB_ILLEGAL_FIELD;
  214.         end;
  215.     end;
  216. end;
  217.  
  218. {---------------------------------------------------------------------------}
  219.  
  220. procedure STI_DBCreate(FileName : String; NumField : byte; Fields : STI_DBFArr);
  221.  
  222. Var
  223.   Count,
  224.   Loop,
  225.   YEAR,MONTH,
  226.   DAY,DOW      : word;
  227.   InFile       : STI_DBFile;
  228.  
  229. begin
  230.   if STI_DBFiles[STI_DBCurrent].Status <> STI_DB_NOT_OPEN then
  231.     begin
  232.       STI_OK := FALSE;
  233.       STI_DB_Error := STI_DB_ALREADY_OPEN;
  234.     end;
  235.   STI_DB_ErrorCheck;
  236.   Assign(InFile.DataFile,FileName);
  237.   STI_DB_IOstatus := IOresult;
  238.   STI_DB_IOcheck(0);
  239.   Rewrite(InFile.DataFile,1);
  240.   STI_DB_IOstatus := IOresult;
  241.   if STI_DB_IOstatus = $F1 then
  242.     STI_OK := FALSE
  243.   else
  244.     begin
  245.       GetDate(YEAR,MONTH,DAY,DOW);
  246.       STI_DB_IOcheck(0);
  247.       with InFile.Header do
  248.         begin
  249.           STI_Ver(Version)[1]  := 1;
  250.           STI_Ver(Version)[2]  := 0;
  251.           LastUpDate[1]        := YEAR-1980;
  252.           LastUpDate[2]        := MONTH;
  253.           LastUpDate[3]        := DAY;
  254.           RecNumber            := 0;
  255.           RecordLen := 0;
  256.           for Loop := 1 to NumField do
  257.             begin
  258.               Inc(RecordLen,Fields[Loop].Length);
  259.             end;
  260.           Inc(RecordLen);
  261.           FieldNum  := NumField;
  262.           HeaderLen := sizeof(STI_DBHead)+(sizeof(STI_DBField)*NumField);
  263.           With_VLOB := FALSE;
  264.           for Loop := 1 to NumField do
  265.             begin
  266.               if Fields[Loop].FieldType = STI_DB_VLOB then
  267.                 With_VLOB := TRUE;
  268.             end;
  269.         end;
  270.       BlockWrite(InFile.DataFile,InFile.Header,sizeof(STI_DBHead));
  271.       STI_OK := TRUE;
  272.       STI_DB_Check_Fields(Fields,NumField);
  273.       Count := 2;
  274.       for Loop := 1 to NumField do
  275.         begin
  276.           Fields[Loop].OffSet := Count;
  277.           BlockWrite(InFile.DataFile,Fields[Loop],sizeof(STI_DBField));
  278.           Inc(Count,Fields[Loop].Length);
  279.         end;
  280.       GetMem(InFile.Fields,NumField*sizeof(STI_DBField));
  281.       Move(Fields,InFile.Fields^,NumField*sizeof(STI_DBField));
  282.       GetMem(InFile.RecData,InFile.Header.RecordLen);
  283.       InFile.RecData^[1] := ' ';
  284.       InFile.Name       := FileName;
  285.       InFile.Status     := STI_DB_UPDATED;
  286.       InFile.CurRecord  := 1;
  287.    end;
  288.   STI_DB_ErrorCheck;
  289.   STI_DBFIles[STI_DBCurrent] := InFile;
  290. end;
  291.  
  292. {---------------------------------------------------------------------------}
  293.  
  294. procedure STI_DBOpen(FileName : string);
  295.  
  296. Var
  297.   Loop    : byte;
  298.   InFile  : STI_DBFile;
  299.  
  300. begin
  301.   if STI_DBFiles[STI_DBCurrent].Status <> STI_DB_NOT_OPEN then
  302.     begin
  303.       STI_OK := FALSE;
  304.       STI_DB_Error := STI_DB_ALREADY_OPEN;
  305.     end;
  306.   STI_DB_ErrorCheck;
  307.   Assign(InFile.DataFile,FileName);
  308.   STI_DB_IOstatus := IOresult;
  309.   STI_DB_IOcheck(0);
  310.   Reset(InFile.DataFile,1);
  311.   STI_DB_IOstatus := IOresult;
  312.   if STI_DB_IOstatus = 1 then
  313.     STI_OK := FALSE
  314.   else
  315.     begin
  316.       STI_DB_IOcheck(0);
  317.       BlockRead(InFile.DataFile,InFile.Header,sizeof(STI_DBHead));
  318.       STI_OK := TRUE;
  319.       GetMem(InFile.Fields,InFile.Header.FieldNum*sizeof(STI_DBField));
  320.       for Loop := 1 to InFile.Header.FieldNum do
  321.         begin
  322.           BlockRead(InFile.DataFile,InFile.Fields^[Loop],sizeof(STI_DBField));
  323.         end;
  324.       InFile.Name        := FileName;
  325.       InFile.CurRecord   := 1;
  326.       InFile.Status      := STI_DB_NOT_UPDATED;
  327.       GetMem(InFile.RecData,InFile.Header.RecordLen);
  328.       InFile.RecData^[1] := ' ';
  329.     end;
  330.   STI_DBFIles[STI_DBCurrent] := InFile;
  331. end;
  332.  
  333. {---------------------------------------------------------------------------}
  334.  
  335. procedure STI_DBClose;
  336.  
  337. Var
  338.   YEAR,MONTH,DAY,DOW : word;
  339.   InFile             : STI_DBFile;
  340.  
  341. begin
  342.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  343.     begin
  344.       STI_OK := FALSE;
  345.       STI_DB_Error := STI_DB_NOT_OPEN;
  346.     end;
  347.   STI_DB_ErrorCheck;
  348.   InFile := STI_DBFiles[STI_DBCurrent];
  349.   GetDate(YEAR,MONTH,DAY,DOW);
  350.   InFile.Header.LastUpDate[1]        := YEAR-1980;
  351.   InFile.Header.LastUpDate[2]        := MONTH;
  352.   InFile.Header.LastUpDate[3]        := DAY;
  353.   STI_DBPutRec(InFile.CurRecord);
  354.   Seek(InFile.DataFile,0);
  355.   BlockWrite(InFile.DataFile,InFile.Header,sizeof(STI_DBHead));
  356.   Close(InFile.DataFile);
  357.   FreeMem(InFile.Fields,InFile.Header.FieldNum*sizeof(STI_DBField));
  358.   FreeMem(InFile.RecData,InFile.Header.RecordLen);
  359.   STI_DB_IOStatus := IOResult;
  360.   InFile.Status := STI_DB_NOT_OPEN;
  361.   STI_DBFiles[STI_DBCurrent] := InFile;
  362. end;
  363.  
  364. {---------------------------------------------------------------------------}
  365. {                                                                           }
  366. {        HIGH LEVEL PROCEDURES AND FUNCTIONS FOLLOW                         }
  367. {                                                                           }
  368. {---------------------------------------------------------------------------}
  369.  
  370. function STI_DBFileExist(FileName : string) : boolean;
  371.  
  372. Var
  373.   FP : file;
  374.  
  375. begin
  376.   assign(FP,FileName);
  377.   reset(FP);
  378.   STI_DBFileExist := IOResult = 0;
  379. end;
  380.  
  381. {---------------------------------------------------------------------------}
  382.  
  383. procedure STI_DBSelect(FileNum : byte);
  384.  
  385. begin
  386.   if (FileNum = 0) or (FileNum > MAX_FILES) then
  387.     begin
  388.       STI_OK := FALSE;
  389.       STI_DB_Error := STI_DB_ILLEGAL_FILE;
  390.     end
  391.   else
  392.     begin
  393.       STI_OK := TRUE;
  394.       STI_DB_Error := 0;
  395.       STI_DBCurrent := FileNum;
  396.     end;
  397.   STI_DB_ErrorCheck;
  398. end;
  399.  
  400. {---------------------------------------------------------------------------}
  401.  
  402. procedure STI_DBGetFieldData(FieldNum : byte; Var Data);
  403.  
  404. Var
  405.   DBOffSet : word;
  406.   FLength  : byte;
  407.  
  408. begin
  409.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  410.     begin
  411.       STI_OK := FALSE;
  412.       STI_DB_Error := STI_DB_NOT_OPEN;
  413.       STI_DB_ErrorCheck;
  414.     end;
  415.   if (FieldNum < 1) or (FieldNum > STI_DBFiles[STI_DBCurrent].Header.FieldNum) then
  416.     begin
  417.       STI_OK := FALSE;
  418.       STI_DB_Error := STI_DB_BAD_FIELD_NUM;
  419.     end
  420.   else
  421.     begin
  422.       STI_OK := TRUE;
  423.       STI_DB_Error := 0;
  424.       DBOffset := STI_DBFiles[STI_DBCurrent].Fields^[FieldNum].OffSet;
  425.       Flength  := STI_DBFiles[STI_DBCurrent].Fields^[FieldNum].Length;
  426.       Move(STI_DBFiles[STI_DBCurrent].RecData^[DBOffset],Data,Flength);
  427.     end;
  428.   STI_DB_ErrorCheck;
  429. end;
  430.  
  431. {---------------------------------------------------------------------------}
  432.  
  433. procedure STI_DBPutFieldData(FieldNum : byte; Var Data);
  434.  
  435. Var
  436.   DBOffSet : word;
  437.   FLength  : byte;
  438.   Dummy    : string absolute Data;
  439.  
  440. begin
  441.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  442.     begin
  443.       STI_OK := FALSE;
  444.       STI_DB_Error := STI_DB_NOT_OPEN;
  445.       STI_DB_ErrorCheck;
  446.     end;
  447.   if (FieldNum < 1) or (FieldNum > STI_DBFiles[STI_DBCurrent].Header.FieldNum) then
  448.     begin
  449.       STI_OK := FALSE;
  450.       STI_DB_Error := STI_DB_BAD_FIELD_NUM;
  451.     end
  452.   else
  453.     begin
  454.       STI_OK := TRUE;
  455.       STI_DB_Error := 0;
  456.       DBOffset := STI_DBFiles[STI_DBCurrent].Fields^[FieldNum].OffSet;
  457.       Flength  := STI_DBFiles[STI_DBCurrent].Fields^[FieldNum].Length;
  458.       Move(Data,STI_DBFiles[STI_DBCurrent].RecData^[DBOffset],FLength);
  459.     end;
  460.   STI_DB_ErrorCheck;
  461. end;
  462.  
  463. {---------------------------------------------------------------------------}
  464.  
  465. procedure STI_DBGetFieldAttributes(FieldNum : byte; Var Field : STI_DBField);
  466.  
  467. begin
  468.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  469.     begin
  470.       STI_OK := FALSE;
  471.       STI_DB_Error := STI_DB_NOT_OPEN;
  472.       STI_DB_ErrorCheck;
  473.     end;
  474.   if (FieldNum < 1) or (FieldNum > STI_DBFiles[STI_DBCurrent].Header.FieldNum) then
  475.     begin
  476.       STI_OK := FALSE;
  477.       STI_DB_Error := STI_DB_BAD_FIELD_NUM;
  478.     end
  479.   else
  480.     begin
  481.       Field := STI_DBFiles[STI_DBCurrent].Fields^[FieldNum];
  482.     end;
  483.   STI_DB_ErrorCheck;
  484. end;
  485.  
  486. {---------------------------------------------------------------------------}
  487.  
  488. procedure STI_DBSetFieldAttributes(FieldNum : byte;     Field : STI_DBField);
  489.  
  490. begin
  491.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  492.     begin
  493.       STI_OK := FALSE;
  494.       STI_DB_Error := STI_DB_NOT_OPEN;
  495.       STI_DB_ErrorCheck;
  496.     end;
  497.   if (FieldNum < 1) or (FieldNum > STI_DBFiles[STI_DBCurrent].Header.FieldNum) then
  498.     begin
  499.       STI_OK := FALSE;
  500.       STI_DB_Error := STI_DB_BAD_FIELD_NUM;
  501.     end
  502.   else
  503.     begin
  504.       STI_DBFiles[STI_DBCurrent].Fields^[FieldNum] := Field;
  505.     end;
  506.   STI_DB_ErrorCheck;
  507. end;
  508.  
  509. {---------------------------------------------------------------------------}
  510.  
  511. function  STI_DBGetFieldName(FieldNum : byte) : string;
  512.  
  513. begin
  514.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  515.     begin
  516.       STI_OK := FALSE;
  517.       STI_DB_Error := STI_DB_NOT_OPEN;
  518.       STI_DB_ErrorCheck;
  519.     end;
  520.   if (FieldNum < 1) or (FieldNum > STI_DBFiles[STI_DBCurrent].Header.FieldNum) then
  521.     begin
  522.       STI_OK := FALSE;
  523.       STI_DB_Error := STI_DB_BAD_FIELD_NUM;
  524.     end
  525.   else
  526.     begin
  527.       STI_DBGetFieldName :=
  528.         STI_DBFiles[STI_DBCurrent].Fields^[FieldNum].Descriptor;
  529.     end;
  530.   STI_DB_ErrorCheck;
  531. end;
  532.  
  533. {---------------------------------------------------------------------------}
  534.  
  535. procedure STI_DBSetFieldName(FieldNum : byte; Name : string);
  536.  
  537. begin
  538.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  539.     begin
  540.       STI_OK := FALSE;
  541.       STI_DB_Error := STI_DB_NOT_OPEN;
  542.       STI_DB_ErrorCheck;
  543.     end;
  544.   if (FieldNum < 1) or (FieldNum > STI_DBFiles[STI_DBCurrent].Header.FieldNum) then
  545.     begin
  546.       STI_OK := FALSE;
  547.       STI_DB_Error := STI_DB_BAD_FIELD_NUM;
  548.     end
  549.   else
  550.     begin
  551.       STI_DBFiles[STI_DBCurrent].Fields^[FieldNum].Descriptor := Name;
  552.     end;
  553.   STI_DB_ErrorCheck;
  554. end;
  555.  
  556. {---------------------------------------------------------------------------}
  557.  
  558. function STI_DBNumRecs : longint;
  559.  
  560. begin
  561.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  562.     begin
  563.       STI_OK := FALSE;
  564.       STI_DB_Error := STI_DB_NOT_OPEN;
  565.     end;
  566.   STI_DBNumRecs := STI_DBFiles[STI_DBCurrent].Header.RecNumber;
  567.   STI_DB_ErrorCheck;
  568. end;
  569.  
  570. {---------------------------------------------------------------------------}
  571.  
  572. function STI_DBNumFields : byte;
  573.  
  574. begin
  575.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  576.     begin
  577.       STI_OK := FALSE;
  578.       STI_DB_Error := STI_DB_NOT_OPEN;
  579.     end;
  580.   STI_DBNumFields := STI_DBFiles[STI_DBCurrent].Header.FieldNum;
  581.   STI_DB_ErrorCheck;
  582. end;
  583.  
  584. {---------------------------------------------------------------------------}
  585.  
  586. function STI_DBCurrentRec : longint;
  587.  
  588. begin
  589.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  590.     begin
  591.       STI_OK := FALSE;
  592.       STI_DB_Error := STI_DB_NOT_OPEN;
  593.     end;
  594.   STI_DBCurrentRec := STI_DBFiles[STI_DBCurrent].CurRecord;
  595.   STI_DB_ErrorCheck;
  596. end;
  597.  
  598. {---------------------------------------------------------------------------}
  599.  
  600. function STI_DBEof : boolean;
  601.  
  602. begin
  603.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  604.     begin
  605.       STI_OK := FALSE;
  606.       STI_DB_Error := STI_DB_NOT_OPEN;
  607.     end;
  608.   STI_DBEof := STI_DBCurrentRec = STI_DBNumRecs;
  609.   STI_DB_ErrorCheck;
  610. end;
  611.  
  612. {---------------------------------------------------------------------------}
  613.  
  614. function STI_DBRecLen : word;
  615.  
  616. begin
  617.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  618.     begin
  619.       STI_OK := FALSE;
  620.       STI_DB_Error := STI_DB_NOT_OPEN;
  621.     end;
  622.   STI_DBRecLen := STI_DBFiles[STI_DBCurrent].Header.RecordLen;
  623.   STI_DB_ErrorCheck;
  624. end;
  625.  
  626. {---------------------------------------------------------------------------}
  627.  
  628. function STI_DBFieldLen(FieldNum : byte) : byte;
  629.  
  630. begin
  631.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  632.     begin
  633.       STI_OK := FALSE;
  634.       STI_DB_Error := STI_DB_NOT_OPEN;
  635.       STI_DB_ErrorCheck;
  636.     end;
  637.   if (FieldNum < 1) or (FieldNum > STI_DBFiles[STI_DBCurrent].Header.FieldNum) then
  638.     begin
  639.       STI_OK := FALSE;
  640.       STI_DB_Error := STI_DB_BAD_FIELD_NUM;
  641.     end
  642.   else
  643.     begin
  644.       STI_DBFieldLen := STI_DBFiles[STI_DBCurrent].Fields^[FieldNum].Length;
  645.     end;
  646.   STI_DB_ErrorCheck;
  647. end;
  648.  
  649. {---------------------------------------------------------------------------}
  650.  
  651. function STI_DBFieldType(FieldNum : byte) : byte;
  652.  
  653. begin
  654.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  655.     begin
  656.       STI_OK := FALSE;
  657.       STI_DB_Error := STI_DB_NOT_OPEN;
  658.       STI_DB_ErrorCheck;
  659.     end;
  660.   if (FieldNum < 1) or (FieldNum > STI_DBFiles[STI_DBCurrent].Header.FieldNum) then
  661.     begin
  662.       STI_OK := FALSE;
  663.       STI_DB_Error := STI_DB_BAD_FIELD_NUM;
  664.     end
  665.   else
  666.     begin
  667.       STI_DBFieldType := STI_DBFiles[STI_DBCurrent].Fields^[FieldNum].FieldType;
  668.     end;
  669.   STI_DB_ErrorCheck;
  670. end;
  671.  
  672. {---------------------------------------------------------------------------}
  673.  
  674. function STI_DBState : byte;
  675.  
  676. begin
  677.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  678.     begin
  679.       STI_OK := FALSE;
  680.       STI_DB_Error := STI_DB_NOT_OPEN;
  681.     end;
  682.   STI_DBState := STI_DBFiles[STI_DBCurrent].Status;
  683.   STI_DB_ErrorCheck;
  684. end;
  685.  
  686. {---------------------------------------------------------------------------}
  687.  
  688. function STI_DBFileName : string;
  689.  
  690. begin
  691.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  692.     begin
  693.       STI_OK := FALSE;
  694.       STI_DB_Error := STI_DB_NOT_OPEN;
  695.     end;
  696.   STI_DBFileName := STI_DBFiles[STI_DBCurrent].Name;
  697.   STI_DB_ErrorCheck;
  698. end;
  699.  
  700. {---------------------------------------------------------------------------}
  701.  
  702. function STI_DBLastUpDate : string;
  703.  
  704. Var
  705.   Year,Month,Day : string[10];
  706.  
  707. begin
  708.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  709.     begin
  710.       STI_OK := FALSE;
  711.       STI_DB_Error := STI_DB_NOT_OPEN;
  712.     end;
  713.   str(STI_DBFiles[STI_DBCurrent].Header.LastUpDate[1]+1980,Year);
  714.   str(STI_DBFiles[STI_DBCurrent].Header.LastUpDate[2],    Month);
  715.   str(STI_DBFiles[STI_DBCurrent].Header.LastUpDate[3],      Day);
  716.   STI_DBLastUpDate := Year+'/'+Month+'/'+Day;
  717.   STI_DB_ErrorCheck;
  718. end;
  719.  
  720. {---------------------------------------------------------------------------}
  721.  
  722. function STI_DBRecordDeleted(Rec : longint) : boolean;
  723.  
  724. begin
  725.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  726.     begin
  727.       STI_OK := FALSE;
  728.       STI_DB_Error := STI_DB_NOT_OPEN;
  729.     end;
  730.   if (STI_DBFiles[STI_DBCurrent].Header.RecNumber < Rec) or (Rec < 0) then
  731.     begin
  732.       STI_OK := FALSE;
  733.       STI_DB_Error := STI_DB_BAD_RECORD_NUM;
  734.     end
  735.   else
  736.     begin
  737.       STI_DBGetRec(Rec);
  738.       STI_DBRecordDeleted := STI_DBFiles[STI_DBCurrent].RecData^[1] = '*';
  739.       STI_DBPutRec(Rec);
  740.     end;
  741.   STI_DB_ErrorCheck;
  742. end;
  743.  
  744. {---------------------------------------------------------------------------}
  745.  
  746. procedure STI_DBSetCurrentRec(Rec : longint);
  747.  
  748. begin
  749.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  750.     begin
  751.       STI_OK := FALSE;
  752.       STI_DB_Error := STI_DB_NOT_OPEN;
  753.     end;
  754.   if (STI_DBFiles[STI_DBCurrent].Header.RecNumber < Rec) or (Rec < 0) then
  755.     begin
  756.       STI_OK := FALSE;
  757.       STI_DB_Error := STI_DB_BAD_RECORD_NUM;
  758.     end
  759.   else
  760.     begin
  761.       STI_DBFiles[STI_DBCurrent].CurRecord := Rec;
  762.       STI_DBGetRec(Rec);
  763.     end;
  764.   STI_DB_ErrorCheck;
  765. end;
  766.  
  767. {---------------------------------------------------------------------------}
  768.  
  769. procedure STI_DBDeleteRecord(Rec : longint);
  770.  
  771. begin
  772.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  773.     begin
  774.       STI_OK := FALSE;
  775.       STI_DB_Error := STI_DB_NOT_OPEN;
  776.     end;
  777.   if (STI_DBFiles[STI_DBCurrent].Header.RecNumber < Rec) or (Rec < 0) then
  778.     begin
  779.       STI_OK := FALSE;
  780.       STI_DB_Error := STI_DB_BAD_RECORD_NUM;
  781.     end
  782.   else
  783.     begin
  784.       STI_DBGetRec(Rec);
  785.       STI_DBFiles[STI_DBCurrent].RecData^[1] := '*';
  786.       STI_DBPutRec(Rec);
  787.     end;
  788.   STI_DB_ErrorCheck;
  789. end;
  790.  
  791. {---------------------------------------------------------------------------}
  792.  
  793. procedure STI_DBGoto(Rec : longint);
  794.  
  795. begin
  796.   STI_DBSetCurrentRec(Rec);
  797. end;
  798.  
  799. {---------------------------------------------------------------------------}
  800.  
  801. procedure STI_DBSKip(Rec : longint);
  802.  
  803. begin
  804.   STI_DBSetCurrentRec(Rec+STI_DBFiles[STI_DBCurrent].CurRecord);
  805. end;
  806.  
  807. {---------------------------------------------------------------------------}
  808.  
  809. procedure STI_DBAppend(Blank : boolean);
  810.  
  811. Var
  812.   Rec  : longint;
  813.  
  814. begin
  815.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  816.     begin
  817.       STI_OK := FALSE;
  818.       STI_DB_Error := STI_DB_NOT_OPEN;
  819.     end;
  820.   Rec := STI_DBFiles[STI_DBCurrent].Header.RecNumber + 1;
  821.   STI_DBFiles[STI_DBCurrent].CurRecord := Rec;
  822.   if Blank then
  823.     FillChar(STI_DBFiles[STI_DBCurrent].RecData,
  824.              STI_DBFiles[STI_DBCurrent].Header.RecordLen,#32);
  825.   STI_DBPutRec(Rec);
  826.   STI_DB_ErrorCheck;
  827. end;
  828.  
  829. {---------------------------------------------------------------------------}
  830.  
  831. procedure STI_DBSwapRecord(RecA,RecB : longint);
  832.  
  833. Var
  834.   Dummy1,
  835.   Dummy2 : array[1..MAX_REC_LEN] of byte;
  836.  
  837. begin
  838.   if STI_DBFiles[STI_DBCurrent].Status = STI_DB_NOT_OPEN then
  839.     begin
  840.       STI_OK := FALSE;
  841.       STI_DB_Error := STI_DB_NOT_OPEN;
  842.     end;
  843.   if (STI_DBFiles[STI_DBCurrent].Header.RecNumber < RecA) or (RecA < 0) then
  844.     begin
  845.       STI_OK := FALSE;
  846.       STI_DB_Error := STI_DB_BAD_RECORD_NUM;
  847.     end;
  848.   if (STI_DBFiles[STI_DBCurrent].Header.RecNumber < RecB) or (RecB < 0) then
  849.     begin
  850.       STI_OK := FALSE;
  851.       STI_DB_Error := STI_DB_BAD_RECORD_NUM;
  852.     end
  853.   else
  854.     begin
  855.       STI_DBGetRec2(RecA,Dummy1,STI_DBFiles[STI_DBCurrent].Header.RecordLen);
  856.       STI_DBGetRec2(RecB,Dummy2,STI_DBFiles[STI_DBCurrent].Header.RecordLen);
  857.       STI_DBPutRec2(RecB,Dummy1,STI_DBFiles[STI_DBCurrent].Header.RecordLen);
  858.       STI_DBPutRec2(RecA,Dummy2,STI_DBFiles[STI_DBCurrent].Header.RecordLen);
  859.     end;
  860.   STI_DB_ErrorCheck;
  861. end;
  862.  
  863. {---------------------------------------------------------------------------}
  864.  
  865. procedure STI_DBInit;
  866.  
  867. Var
  868.   Loop : byte;
  869.  
  870. begin
  871.   for Loop := 1 to MAX_FILES do
  872.     begin
  873.       STI_DBFiles[Loop].Name      := '';
  874.       STI_DBFiles[Loop].Status    := STI_DB_NOT_OPEN;
  875.       STI_DBFiles[Loop].CurRecord := 1;
  876.     end;
  877.   STI_DBCurrent    := 1;
  878.   STI_DB_Error     := 0;
  879.   STI_DB_IOStatus  := 0;
  880.   STI_OK           := TRUE;
  881. end;
  882.  
  883. {---------------------------------------------------------------------------}
  884.  
  885. function STI_DBPosSameData(Start : longint; Field : byte) : longint;
  886.  
  887. Var
  888.   Dummy1,
  889.   Dummy2 : string;
  890.   Count  : longint;
  891.  
  892. begin
  893.   Count := Start;
  894.   STI_DBGetRec(Start);
  895.   STI_DBGetFieldData(Field,Dummy1);
  896.   STI_DBGetRec(Count);
  897.   STI_DBGetFieldData(Field,Dummy2);
  898.   while (Dummy2 = Dummy1) and (Count < STI_DBFiles[STI_DBCurrent].Header.RecNumber) do
  899.     begin
  900.       Inc(Count);
  901.       STI_DBGetRec(Count);
  902.       STI_DBGetFieldData(Field,Dummy2);
  903.     end;
  904.   Dec(Count);
  905.   STI_DBPosSameData := Count;
  906. end;
  907.  
  908. {---------------------------------------------------------------------------}
  909.  
  910. procedure STI_DBMultiFieldInFileSort(Max : byte; Flds : STI_Sort; Mode : Byte);
  911.  
  912. var
  913.   loop      : byte;
  914.   beginrec,
  915.   lastrec   : longint;
  916.  
  917. procedure sort(l,r : longint; FNum : word);
  918.  
  919. var
  920.   i,j    : longint;
  921.   ai,aj,
  922.   x      : string;
  923.  
  924.  
  925. begin
  926.   i := l; j := r;
  927.   STI_DBGetRec((l+r) DIV 2);
  928.   STI_DBGetFieldData(FNum,x);
  929.   TextColor(White);
  930.   GotoXY(21,11);
  931.   Write('Mem   =',MemAvail:12);
  932.   GotoXY(21,12);
  933.   Write('Field =',FNum:12);
  934.   GotoXY(21,13);
  935.   Write('Left  =',i:12);
  936.   GotoXY(21,14);
  937.   Write('Right =',j:12);
  938.   repeat
  939.     STI_DBGetRec(i);
  940.     STI_DBGetFieldData(FNum,ai);
  941.     if Mode = ASCEND then
  942.       begin
  943.         while (ai < x) and (i <= STI_DBFiles[STI_DBCurrent].Header.RecNumber - 1) do
  944.           begin
  945.             i := i + 1;
  946.             GotoXY(21,13);
  947.             Write('Left  =',i:12);
  948.             STI_DBGetRec(i);
  949.             STI_DBGetFieldData(FNum,ai);
  950.           end;
  951.       end else
  952.       begin
  953.         while (ai > x) and (i <= STI_DBFiles[STI_DBCurrent].Header.RecNumber - 1) do
  954.           begin
  955.             i := i + 1;
  956.             GotoXY(21,13);
  957.             Write('Left  =',i:12);
  958.             STI_DBGetRec(i);
  959.             STI_DBGetFieldData(FNum,ai);
  960.           end;
  961.       end;
  962.     STI_DBGetRec(j);
  963.     STI_DBGetFieldData(FNum,aj);
  964.     if Mode = ASCEND then
  965.      begin
  966.        while (x < aj) and (j >= 1) do
  967.          begin
  968.            j := j - 1;
  969.            GotoXY(21,14);
  970.            Write('Right =',j:12);
  971.            STI_DBGetRec(j);
  972.            STI_DBGetFieldData(FNum,aj);
  973.          end;
  974.      end else
  975.      begin
  976.        while (x > aj) and (j >= 1) do
  977.          begin
  978.            j := j - 1;
  979.            GotoXY(21,14);
  980.            Write('Right =',j:12);
  981.            STI_DBGetRec(j);
  982.            STI_DBGetFieldData(FNum,aj);
  983.          end;
  984.      end;
  985.     if (i <= j) then
  986.       begin
  987.         STI_DBSwapRecord(j,i);
  988.         if i < STI_DBFiles[STI_DBCurrent].Header.RecNumber then i := i + 1;
  989.         if j >=          2 then j := j - 1;
  990.       end;
  991.   until i>j;
  992.   if l<j then sort(l,j,FNum);
  993.   if i<r then sort(i,r,FNum);
  994. end;
  995.  
  996.  
  997. begin {qsort}
  998.   Sort(1,STI_DBFiles[STI_DBCurrent].Header.RecNumber,flds[1]);
  999.   loop := 1;
  1000.   beginrec := 1;
  1001.   lastrec  := STI_DBPosSameData(beginrec,flds[1]);
  1002.  
  1003.   while loop < Max do
  1004.     begin
  1005.       while beginrec < STI_DBFiles[STI_DBCurrent].Header.RecNumber-1 do
  1006.         begin
  1007.           if (loop+1 <= max) then
  1008.             sort(beginrec,lastrec,flds[loop+1]);
  1009.           beginrec := lastrec+1;
  1010.           if beginrec < STI_DBFiles[STI_DBCurrent].Header.RecNumber-1 then
  1011.             lastrec := STI_DBPosSameData(beginrec,flds[loop]);
  1012.         end;
  1013.       inc(loop);
  1014.       beginrec := 1;
  1015.       lastrec  := STI_DBPosSameData(beginrec,flds[loop]);
  1016.     end;
  1017.  
  1018.   ClrScr;
  1019. end;
  1020.  
  1021. {---------------------------------------------------------------------------}
  1022.  
  1023. Type
  1024.   MyData  = record
  1025.               A : string[10];
  1026.               B : word;
  1027.               C : word;
  1028.               D : string[10];
  1029.             end;
  1030.  
  1031. Var
  1032.   DBFArr : STI_DBFArr;
  1033.   Dummy  : MyData;
  1034.   Loop   : word;
  1035.   OH,OM,OS,OSS,
  1036.   NH,NM,NS,NSS  : word;
  1037.   Test4,
  1038.   Test1   : string;
  1039.   Test3,
  1040.   Test2   : word;
  1041.   Flds    : STI_Sort;
  1042.  
  1043. begin
  1044.   ClrScr;
  1045.  
  1046.   DBFArr[1].Descriptor  := '##STRING##';
  1047.   DBFArr[1].Length      := 11;
  1048.   DBFArr[1].FieldType   := STI_DB_STRING;
  1049.   DBFArr[2].Descriptor  := '###WORD###';
  1050.   DBFArr[2].Length      := 2;
  1051.   DBFArr[2].FieldType   := STI_DB_WORD;
  1052.   DBFArr[3].Descriptor  := '###WORD###';
  1053.   DBFArr[3].Length      := 2;
  1054.   DBFArr[3].FieldType   := STI_DB_WORD;
  1055.   DBFArr[4].Descriptor  := '##STRING##';
  1056.   DBFArr[4].Length      := 11;
  1057.   DBFArr[4].FieldType   := STI_DB_STRING;
  1058.  
  1059.  
  1060.   STI_DBInit;
  1061.   STI_DBSelect(1);
  1062.   STI_DBCreate('A:TEST.SDB',4,DBFArr);
  1063.   STI_DBClose;
  1064.   STI_DBSelect(1);
  1065.   STI_DBOpen('A:TEST.SDB');
  1066.  
  1067.   GetTime(OH,OM,OS,OSS);
  1068.  
  1069.   for loop := 1 to 100 do
  1070.     begin
  1071.       str(random(500):10,Test1);
  1072.       Test2 := trunc(random(10));
  1073.       str(random(500):10,Test4);
  1074.       Test3 := trunc(random(10));
  1075.       STI_DBPutFieldData(1,Test1);
  1076.       STI_DBPutFieldData(2,Test2);
  1077.       STI_DBPutRec(Loop);
  1078.     end;
  1079.  
  1080.   for loop := 1 to 100 do
  1081.     begin
  1082.       STI_DBGetRec(Loop);
  1083.       STI_DBGetFieldData(1,Test1);
  1084.       STI_DBGetFieldData(2,Test2);
  1085.     end;
  1086.  
  1087.   GetTime(NH,NM,NS,NSS);
  1088.  
  1089.  
  1090.   Writeln(OH,':',OM,':',OS,':',OSS,'/',NH,':',NM,':',NS,':',NSS);
  1091.  
  1092.   STI_DBClose;
  1093. end.
  1094.  
  1095.  
  1096.  
  1097.  
  1098.  
  1099.  
  1100.