comptty.pas 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. {
  2. This file is part of the Free Pascal compiler.
  3. Copyright (c) 2020 by the Free Pascal development team
  4. This unit contains platform-specific code for checking TTY output
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit comptty;
  19. {$i fpcdefs.inc}
  20. interface
  21. function IsATTY(var t : text) : Boolean;
  22. const
  23. (* This allows compile-time removal of the colouring functionality under not supported platforms *)
  24. {$if defined(linux) or defined(MSWINDOWS) or defined(OS2) or defined(GO32V2) or defined(WATCOM) or defined(DARWIN)}
  25. TTYCheckSupported = true;
  26. {$else defined(linux) or defined(MSWINDOWS) or defined(OS2) or defined(GO32V2) or defined(WATCOM) or defined(DARWIN)}
  27. TTYCheckSupported = false;
  28. {$endif defined(linux) or defined(MSWINDOWS) or defined(OS2) or defined(GO32V2) or defined(WATCOM) or defined(DARWIN)}
  29. implementation
  30. {$if defined(linux) or defined(darwin)}
  31. uses
  32. termio;
  33. {$endif defined(linux) or defined(darwin)}
  34. {$ifdef mswindows}
  35. uses
  36. windows;
  37. {$endif mswindows}
  38. {$ifdef os2}
  39. uses
  40. doscalls;
  41. {$endif os2}
  42. {$if defined(GO32V2) or defined(WATCOM)}
  43. uses
  44. dos;
  45. {$endif defined(GO32V2) or defined(WATCOM)}
  46. const
  47. CachedIsATTY : Boolean = false;
  48. IsATTYValue : Boolean = false;
  49. {$if defined(linux) or defined(darwin)}
  50. function LinuxIsATTY(var t : text) : Boolean; inline;
  51. begin
  52. LinuxIsATTY:=termio.IsATTY(t)=1;
  53. end;
  54. {$endif defined(linux) or defined(darwin)}
  55. {$ifdef MSWINDOWS}
  56. const
  57. ENABLE_VIRTUAL_TERMINAL_PROCESSING = $0004;
  58. function WindowsIsATTY(var t : text) : Boolean; inline;
  59. const
  60. dwMode: dword = 0;
  61. begin
  62. WindowsIsATTY := false;
  63. if GetConsoleMode(TextRec(t).handle, dwMode) then
  64. begin
  65. dwMode := dwMode or ENABLE_VIRTUAL_TERMINAL_PROCESSING;
  66. if SetConsoleMode(TextRec(t).handle, dwMode) then
  67. WindowsIsATTY := true;
  68. end;
  69. end;
  70. {$endif MSWINDOWS}
  71. {$IFDEF OS2}
  72. function OS2IsATTY(var t : text) : Boolean; inline;
  73. var
  74. HT, Attr: cardinal;
  75. {$IFDEF EMX}
  76. OK: boolean;
  77. {$ENDIF EMX}
  78. const
  79. dhDevice = 1;
  80. begin
  81. {$IFDEF EMX}
  82. if os_mode = osOS2 then
  83. begin
  84. {$ENDIF EMX}
  85. OS2IsATTY := (DosQueryHType (TextRec (T).Handle, HT, Attr) = 0)
  86. and (HT = dhDevice);
  87. {$IFDEF EMX}
  88. end
  89. else
  90. begin
  91. OK := false;
  92. {$ASMMODE INTEL}
  93. asm
  94. mov ebx, TextRec (T).Handle
  95. mov eax, 4400h
  96. call syscall
  97. jc @IsDevEnd
  98. test edx, 80h { bit 7 is set if it is a device or a pipe }
  99. jz @IsDevEnd
  100. mov eax, 1A00h { Check ANSI.SYS availability }
  101. int 2Fh
  102. inc al { If it was FFh, then OK }
  103. jnz @IsDevEnd
  104. mov OK, true
  105. @IsDevEnd:
  106. end;
  107. OS2IsATTY := OK;
  108. end;
  109. {$ENDIF EMX}
  110. end;
  111. {$ENDIF OS2}
  112. {$if defined(GO32V2) or defined(WATCOM)}
  113. function DosIsATTY(var t : text) : Boolean; inline;
  114. var
  115. Regs: Registers;
  116. begin
  117. Regs.EBX := TextRec (T).Handle;
  118. Regs.EAX := $4400;
  119. MsDos (Regs);
  120. if (Regs.Flags and FCarry <> 0) or (Regs.EDX and $80 = 0) then
  121. { bit 7 is set if it is a device or a pipe }
  122. DosIsATTY := false
  123. else
  124. begin
  125. Regs.EAX := $1A00; { Check ANSI.SYS availability }
  126. Intr ($2F, Regs);
  127. DosIsATTY := Regs.AL = $FF; { If it was FFh, then OK }
  128. end;
  129. end;
  130. {$endif defined(GO32V2) or defined(WATCOM)}
  131. function IsATTY(var t : text) : Boolean;
  132. begin
  133. if not(CachedIsATTY) then
  134. begin
  135. (* If none of the supported values is defined, false is returned by default. *)
  136. {$if defined(linux) or defined(darwin)}
  137. IsATTYValue:=LinuxIsATTY(t);
  138. {$endif defined(linux) or defined(darwin)}
  139. {$ifdef MSWINDOWS}
  140. IsATTYValue:=WindowsIsATTY(t);
  141. {$endif MSWINDOWS}
  142. {$ifdef OS2}
  143. IsATTYValue:=OS2IsATTY(t);
  144. {$endif OS2}
  145. {$if defined(GO32V2) or defined(WATCOM)}
  146. IsATTYValue:=DosIsATTY(t);
  147. {$endif defined(GO32V2) or defined(WATCOM)}
  148. CachedIsATTY:=true;
  149. end;
  150. Result:=IsATTYValue;
  151. end;
  152. end.