MEMOFUNC.MOD 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. IMPLEMENTATION MODULE MemoFunctions;
  2. (*
  3. * ModBase
  4. * Release 3.0
  5. * (c) Copyright 1986 - 1991 John McMonagle & Donald G. Fletcher
  6. * (c) Copyright 1986 - 1991 PMI
  7. * P.O. Box 8402
  8. * Green Bay Wi 53308
  9. * All Rights Reserved
  10. *)
  11. FROM SYSTEM IMPORT ADR,ADDRESS;
  12. (*Repertoire modules*)
  13. FROM HandleIO IMPORT BlockRead, BlockWrite,OpenFile,
  14. EndReached, SetFilePtr, GetFilePtr,FileOffSet;
  15. FROM StringIO IMPORT ErrorMessage, NoError, PartialRead, PrintMessage;
  16. FROM StrConv IMPORT StrToLongInteger, LongIntegerToStr;
  17. FROM StrEdit IMPORT Append;
  18. FROM M2Strings IMPORT Length,Pos;
  19. FROM LowLevel IMPORT Fill;
  20. FROM ErrorManager IMPORT WARN;
  21. FROM Numbers IMPORT Min;
  22. (*ModBase modules*)
  23. FROM ModBase3 IMPORT DBFile, GetField,MemoSize, Replace,OpenMemo,MemoHandle;
  24. FROM VStorage IMPORT
  25. DosAlloc, DosDealloc;
  26. PROCEDURE DEALLOCATE(VAR loc:ADDRESS;size:CARDINAL);
  27. BEGIN
  28. DosDealloc(loc,size);
  29. END DEALLOCATE;
  30. PROCEDURE ALLOCATE(VAR loc:ADDRESS;size:CARDINAL);
  31. BEGIN
  32. DosAlloc(loc,size);
  33. END ALLOCATE;
  34. CONST
  35. EndOfMemo = 32C;
  36. MemoBlockSize = 512;
  37. MaxMemoSize =4000;
  38. PROCEDURE PadFile( FileHandle: CARDINAL; TheChar: CHAR;
  39. HowMany: CARDINAL );
  40. VAR
  41. TmpBufPtr: POINTER TO CARDINAL;
  42. BEGIN
  43. ALLOCATE( TmpBufPtr, HowMany );
  44. Fill( TmpBufPtr, HowMany, TheChar );
  45. IF BlockWrite( FileHandle, TmpBufPtr, HowMany ) # NoError THEN
  46. HALT;
  47. END;
  48. DEALLOCATE( TmpBufPtr, HowMany );
  49. END PadFile;
  50. PROCEDURE GetMemoField(VAR alias: DBFile; fieldnum: CARDINAL; VAR
  51. memo: ARRAY OF CHAR);
  52. VAR
  53. FileError: ErrorMessage;
  54. memostr: ARRAY [0..9] OF CHAR;
  55. block: ARRAY[0..MemoSize-1] OF CHAR;
  56. memopos, memonum: LONGINT;
  57. handle,i: CARDINAL;
  58. fieldok: BOOLEAN;
  59. BEGIN
  60. IF NOT OpenMemo(alias)
  61. THEN
  62. WARN('Unable to open memo file')
  63. END;
  64. handle:=MemoHandle(alias);
  65. GetField(alias, fieldnum, memostr);
  66. (* First check to make sure there is a memo to read *)
  67. IF (StrToLongInteger(memostr,0, memonum))
  68. AND (memonum > VAL(LONGINT,0)) THEN
  69. memopos := VAL(LONGINT, MemoBlockSize) * memonum;
  70. SetFilePtr(handle, FromStart, memopos);
  71. memo[0] := 0C;
  72. block[0] := 0C;
  73. LOOP
  74. FileError := BlockRead(handle, ADR(block[0]), MemoSize);
  75. IF (FileError=NoError) OR (FileError=PartialRead) THEN
  76. i:=Pos(EndOfMemo,block);
  77. IF i<MemoSize THEN
  78. block[i]:=0C;
  79. Append(memo,block);
  80. EXIT;
  81. ELSE
  82. Append(memo,block);
  83. END;
  84. ELSE
  85. EXIT
  86. END;
  87. END;
  88. ELSE (* the memofield was empty *)
  89. memo[0] := 0C;
  90. END;
  91. END GetMemoField;
  92. PROCEDURE ReplaceM(VAR alias: DBFile; fieldnum: CARDINAL;VAR memo:
  93. ARRAY OF CHAR);
  94. VAR
  95. FileError: ErrorMessage;
  96. ptrstr: ARRAY [0..9] OF CHAR;
  97. blocknum, blockpos: LONGINT;
  98. OldMemo :POINTER TO ARRAY[0..MaxMemoSize]OF CHAR;
  99. handle:CARDINAL;
  100. (* seem a bit overkill but use of comparestr will use usualy 8K of stack *)
  101. PROCEDURE StrEqual(VAR str1,str2:ARRAY OF CHAR):BOOLEAN;
  102. VAR
  103. limit, count:CARDINAL;
  104. BEGIN
  105. limit:=Min(HIGH(str1),HIGH(str2));
  106. count:=0;
  107. WHILE count<limit
  108. DO
  109. IF str1[count]#str2[count]
  110. THEN
  111. RETURN FALSE;
  112. ELSIF str1[count]=0C
  113. THEN
  114. RETURN TRUE;
  115. END;
  116. INC(count);
  117. END (* while *);
  118. IF HIGH(str1)<HIGH(str2)
  119. THEN
  120. RETURN str2[count]=0C;
  121. ELSIF HIGH(str1)>HIGH(str2)
  122. THEN
  123. RETURN str1[count]=0C
  124. ELSE
  125. RETURN TRUE;
  126. END;
  127. END StrEqual;
  128. BEGIN
  129. IF NOT OpenMemo(alias)
  130. THEN
  131. WARN('Unable to open memo file')
  132. END;
  133. handle:=MemoHandle(alias);
  134. IF memo[0]#0C THEN (* Added to avoid writing a '' Memo !!!! *)
  135. (* check to see if memo changed *)
  136. NEW(OldMemo);
  137. GetMemoField(alias,fieldnum,OldMemo^);
  138. IF NOT StrEqual(OldMemo^,memo)
  139. THEN
  140. SetFilePtr(handle, FromStart, VAL(LONGINT,0));
  141. FileError := BlockRead(handle, ADR(blocknum), 4);
  142. blockpos := blocknum * VAL(LONGINT,MemoBlockSize);
  143. SetFilePtr(handle, FromStart, blockpos);
  144. FileError := BlockWrite(handle, ADR(memo), Length(memo));
  145. IF (Length(memo) MOD MemoBlockSize) # 0 THEN
  146. PadFile( handle, EndOfMemo, MemoBlockSize -
  147. (Length(memo) MOD MemoBlockSize) );
  148. END;
  149. LongIntegerToStr(blocknum, 10,ptrstr);
  150. Replace(alias, fieldnum, ptrstr);
  151. blockpos := GetFilePtr(handle);
  152. (* find what will be the next available block
  153. And write it to the first 4 bytes of the file *)
  154. blocknum := blockpos DIV VAL(LONGINT,MemoBlockSize);
  155. SetFilePtr(handle, FromStart, VAL(LONGINT,0));
  156. FileError := BlockWrite(handle, ADR(blocknum), 4);
  157. END;
  158. DISPOSE(OldMemo);
  159. ELSE
  160. Replace(alias, fieldnum,' ');
  161. END;
  162. END ReplaceM;
  163. BEGIN
  164. END MemoFunctions.