PageRenderTime 47ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/source/textio/machine-pc-freebsd/s-ntitco.adb

https://github.com/ytomino/drake
Ada | 315 lines | 284 code | 18 blank | 13 comment | 34 complexity | 5d787895cccf7c768a65182b2e4a2b12 MD5 | raw file
  1. -- reference:
  2. -- http://www.mudpedia.org/mediawiki/index.php/Xterm_256_colors
  3. with System.Address_To_Named_Access_Conversions;
  4. with System.Formatting;
  5. with System.Long_Long_Integer_Types;
  6. with System.Once;
  7. with C.stdlib;
  8. package body System.Native_Text_IO.Terminal_Colors is
  9. use type C.char_array;
  10. use type C.char_ptr;
  11. use type C.signed_int;
  12. use type C.size_t;
  13. subtype Word_Unsigned is Long_Long_Integer_Types.Word_Unsigned;
  14. function strlen (s : not null access constant C.char) return C.size_t
  15. with Import,
  16. Convention => Intrinsic, External_Name => "__builtin_strlen";
  17. package char_ptr_Conv is
  18. new Address_To_Named_Access_Conversions (C.char, C.char_ptr);
  19. TERM_Variable : constant C.char_array (0 .. 4) := "TERM" & C.char'Val (0);
  20. xterm_256color : constant String (1 .. 14) := "xterm-256color";
  21. Support_256_Color_Flag : aliased Once.Flag := 0;
  22. Support_256_Color : Boolean;
  23. procedure Support_256_Color_Init;
  24. procedure Support_256_Color_Init is
  25. TERM : C.char_ptr;
  26. begin
  27. TERM := C.stdlib.getenv (TERM_Variable (0)'Access);
  28. if TERM /= null
  29. and then strlen (TERM) = xterm_256color'Length
  30. then
  31. declare
  32. TERM_All : String (1 .. xterm_256color'Length);
  33. for TERM_All'Address use char_ptr_Conv.To_Address (TERM);
  34. begin
  35. Support_256_Color := TERM_All = xterm_256color;
  36. end;
  37. else
  38. Support_256_Color := False;
  39. end if;
  40. end Support_256_Color_Init;
  41. procedure Initialize;
  42. procedure Initialize is
  43. begin
  44. Once.Initialize (
  45. Support_256_Color_Flag'Access,
  46. Support_256_Color_Init'Access);
  47. end Initialize;
  48. function RGB_To_256_Color (Item : Ada.Colors.RGB) return Color;
  49. function RGB_To_256_Color (Item : Ada.Colors.RGB) return Color is
  50. subtype B is Ada.Colors.Brightness'Base;
  51. function Color_Scale (Item : B) return Color;
  52. function Color_Scale (Item : B) return Color is
  53. begin
  54. if Item < (0.0 + 16#5F.0#) / 2.0 / 255.0 then
  55. return 0;
  56. elsif Item < (16#5F.0# + 16#87.0#) / 2.0 / 255.0 then
  57. return 1;
  58. elsif Item < (16#87.0# + 16#AF.0#) / 2.0 / 255.0 then
  59. return 2;
  60. elsif Item < (16#AF.0# + 16#D7.0#) / 2.0 / 255.0 then
  61. return 3;
  62. elsif Item < (16#D7.0# + 16#FF.0#) / 2.0 / 255.0 then
  63. return 4;
  64. else
  65. return 5;
  66. end if;
  67. end Color_Scale;
  68. begin
  69. return 16
  70. + 36 * Color_Scale (Item.Red)
  71. + 6 * Color_Scale (Item.Green)
  72. + Color_Scale (Item.Blue);
  73. end RGB_To_256_Color;
  74. function Brightness_To_Grayscale_256_Color (Item : Ada.Colors.Brightness)
  75. return Color;
  76. function Brightness_To_Grayscale_256_Color (Item : Ada.Colors.Brightness)
  77. return Color
  78. is
  79. subtype B is Ada.Colors.Brightness'Base;
  80. Grayscale_Index : constant Integer :=
  81. (Integer (B'Floor (Item * B'Pred (250.0))) + 5) / 10 - 1 + 232;
  82. begin
  83. if Grayscale_Index < 232 then
  84. return 16; -- 16#00#
  85. elsif Grayscale_Index <= 255 then -- in 232 .. 255
  86. return Color (Grayscale_Index);
  87. else
  88. return 16 + 6#555#; -- 16#FF#
  89. end if;
  90. end Brightness_To_Grayscale_256_Color;
  91. function RGB_To_System_Color (Item : Ada.Colors.RGB) return Color;
  92. function RGB_To_System_Color (Item : Ada.Colors.RGB) return Color is
  93. subtype B is Ada.Colors.Brightness'Base;
  94. Result : Color;
  95. begin
  96. if Item.Red in 0.25 .. B'Pred (0.675)
  97. and then Item.Green in 0.25 .. B'Pred (0.675)
  98. and then Item.Blue in 0.25 .. B'Pred (0.675)
  99. then -- Dark_Gray = (16#80#, 16#80#, 16#80#)
  100. Result := 8;
  101. elsif Item.Red >= 0.875
  102. or else Item.Green >= 0.875
  103. or else Item.Blue >= 0.875
  104. then -- bright colors
  105. Result := 8;
  106. if Item.Red >= 0.875 then
  107. Result := Result or 1;
  108. end if;
  109. if Item.Green >= 0.875 then
  110. Result := Result or 2;
  111. end if;
  112. if Item.Blue >= 0.875 then
  113. Result := Result or 4;
  114. end if;
  115. else -- dark colors
  116. Result := 0;
  117. if Item.Red >= 0.375 then
  118. Result := Result or 1;
  119. end if;
  120. if Item.Green >= 0.375 then
  121. Result := Result or 2;
  122. end if;
  123. if Item.Blue >= 0.375 then
  124. Result := Result or 4;
  125. end if;
  126. end if;
  127. return Result;
  128. end RGB_To_System_Color;
  129. function Brightness_To_Grayscale_System_Color (Item : Ada.Colors.Brightness)
  130. return Color;
  131. function Brightness_To_Grayscale_System_Color (Item : Ada.Colors.Brightness)
  132. return Color is
  133. begin
  134. -- [0.000 .. 0.250) => 0
  135. -- [0.250 .. 0.625) => 16#80# = 8
  136. -- [0.625 .. 0.875) => 16#C0# = 7
  137. -- [0.875 .. 1.000] => 16#FF# = 15
  138. return RGB_To_System_Color ((Red => Item, Green => Item, Blue => Item));
  139. end Brightness_To_Grayscale_System_Color;
  140. -- implementation
  141. function RGB_To_Color (Item : Ada.Colors.RGB) return Color is
  142. begin
  143. Initialize;
  144. if Support_256_Color then
  145. return RGB_To_256_Color (Item);
  146. else
  147. return RGB_To_System_Color (Item);
  148. end if;
  149. end RGB_To_Color;
  150. function Brightness_To_Grayscale_Color (Item : Ada.Colors.Brightness)
  151. return Color is
  152. begin
  153. Initialize;
  154. if Support_256_Color then
  155. return Brightness_To_Grayscale_256_Color (Item);
  156. else
  157. return Brightness_To_Grayscale_System_Color (Item);
  158. end if;
  159. end Brightness_To_Grayscale_Color;
  160. procedure Set (
  161. Handle : Handle_Type;
  162. Reset : Boolean;
  163. Bold_Changing : Boolean;
  164. Bold : Boolean;
  165. Underline_Changing : Boolean;
  166. Underline : Boolean;
  167. Blink_Changing : Boolean;
  168. Blink : Boolean;
  169. Reversed_Changing : Boolean;
  170. Reversed : Boolean;
  171. Foreground_Changing : Boolean;
  172. Foreground : Color;
  173. Background_Changing : Boolean;
  174. Background : Color)
  175. is
  176. Seq : String (1 .. 256);
  177. Last : Natural;
  178. Error : Boolean;
  179. begin
  180. Seq (1) := Character'Val (16#1B#);
  181. Seq (2) := '[';
  182. Last := 2;
  183. -- changing
  184. if Reset then
  185. Last := Last + 1;
  186. Seq (Last) := '0';
  187. end if;
  188. if Bold_Changing and then Bold then
  189. if Last > 2 then
  190. Last := Last + 1;
  191. Seq (Last) := ';';
  192. end if;
  193. Last := Last + 1;
  194. Seq (Last) := '1';
  195. end if;
  196. if Underline_Changing and then Underline then
  197. if Last > 2 then
  198. Last := Last + 1;
  199. Seq (Last) := ';';
  200. end if;
  201. Last := Last + 1;
  202. Seq (Last) := '4';
  203. end if;
  204. if Blink_Changing and then Blink then
  205. if Last > 2 then
  206. Last := Last + 1;
  207. Seq (Last) := ';';
  208. end if;
  209. Last := Last + 1;
  210. Seq (Last) := '5';
  211. end if;
  212. if Reversed_Changing and then Reversed then
  213. if Last > 2 then
  214. Last := Last + 1;
  215. Seq (Last) := ';';
  216. end if;
  217. Last := Last + 1;
  218. Seq (Last) := '7';
  219. end if;
  220. if Foreground_Changing then
  221. if Last > 2 then
  222. Last := Last + 1;
  223. Seq (Last) := ';';
  224. end if;
  225. declare
  226. Color_Index : Word_Unsigned := Word_Unsigned (Foreground);
  227. begin
  228. if Foreground < 16#10# then
  229. -- system color
  230. if (Foreground and 8) = 0 then
  231. Last := Last + 1;
  232. Seq (Last) := '3';
  233. else
  234. Last := Last + 1;
  235. Seq (Last) := '9';
  236. Color_Index := Word_Unsigned (Foreground and 7);
  237. end if;
  238. else
  239. -- 256 color
  240. Seq (Last + 1 .. Last + 5) := "38;5;";
  241. Last := Last + 5;
  242. end if;
  243. Formatting.Image (
  244. Color_Index,
  245. Seq (Last + 1 .. Seq'Last),
  246. Last,
  247. Error => Error);
  248. end;
  249. end if;
  250. if Background_Changing then
  251. if Last > 2 then
  252. Last := Last + 1;
  253. Seq (Last) := ';';
  254. end if;
  255. declare
  256. Color_Index : Word_Unsigned := Word_Unsigned (Background);
  257. begin
  258. if Background < 16#10# then
  259. -- system color
  260. if (Background and 8) = 0 then
  261. Last := Last + 1;
  262. Seq (Last) := '4';
  263. else
  264. Last := Last + 1;
  265. Seq (Last) := '1';
  266. Last := Last + 1;
  267. Seq (Last) := '0';
  268. Color_Index := Word_Unsigned (Background and 7);
  269. end if;
  270. else
  271. -- 256 color
  272. Seq (Last + 1 .. Last + 5) := "48;5;";
  273. Last := Last + 5;
  274. end if;
  275. Formatting.Image (
  276. Color_Index,
  277. Seq (Last + 1 .. Seq'Last),
  278. Last,
  279. Error => Error);
  280. end;
  281. end if;
  282. -- setting
  283. if Last > 2 then
  284. Last := Last + 1;
  285. Seq (Last) := 'm';
  286. Write_Just (Handle, Seq (1 .. Last));
  287. end if;
  288. end Set;
  289. procedure Reset (
  290. Handle : Handle_Type)
  291. is
  292. Seq : constant String (1 .. 4) :=
  293. (Character'Val (16#1b#), '[', '0', 'm');
  294. begin
  295. Write_Just (Handle, Seq);
  296. end Reset;
  297. end System.Native_Text_IO.Terminal_Colors;