| // Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 |  | 
 | import 'dart:ffi'; | 
 |  | 
 | import 'package:ffi/ffi.dart'; | 
 | import 'package:expect/expect.dart'; | 
 |  | 
 | /// typedef struct { | 
 | ///     unsigned int bold      : 1; | 
 | ///     unsigned int underline : 2; | 
 | ///     unsigned int italic    : 1; | 
 | ///     unsigned int blink     : 1; | 
 | ///     unsigned int reverse   : 1; | 
 | ///     unsigned int strike    : 1; | 
 | ///     unsigned int font      : 4; | 
 | /// } ScreenCellAttrs; | 
 | final class ScreenCellAttrs extends Struct { | 
 |   @Int16() | 
 |   external int bits; | 
 |  | 
 |   int get bold => getBits(kBoldFieldOffset, kBoldFieldLength); | 
 |   void set bold(int value) => | 
 |       setBits(kBoldFieldOffset, kBoldFieldLength, value); | 
 |  | 
 |   int get underline => getBits(kUnderlineFieldOffset, kUnderlineFieldLength); | 
 |   void set underline(int value) => | 
 |       setBits(kUnderlineFieldOffset, kUnderlineFieldLength, value); | 
 |  | 
 |   int get italic => getBits(kItalicFieldOffset, kItalicFieldLength); | 
 |   void set italic(int value) => | 
 |       setBits(kItalicFieldOffset, kItalicFieldLength, value); | 
 |  | 
 |   int get blink => getBits(kBlinkFieldOffset, kBlinkFieldLength); | 
 |   void set blink(int value) => | 
 |       setBits(kBlinkFieldOffset, kBlinkFieldLength, value); | 
 |  | 
 |   int get reverse => getBits(kReverseFieldOffset, kReverseFieldLength); | 
 |   void set reverse(int value) => | 
 |       setBits(kReverseFieldOffset, kReverseFieldLength, value); | 
 |  | 
 |   int get strike => getBits(kStrikeFieldOffset, kStrikeFieldLength); | 
 |   void set strike(int value) => | 
 |       setBits(kStrikeFieldOffset, kStrikeFieldLength, value); | 
 |  | 
 |   int get font => getBits(kFontFieldOffset, kFontFieldLength); | 
 |   void set font(int value) => | 
 |       setBits(kFontFieldOffset, kFontFieldLength, value); | 
 |  | 
 |   int getBits(int offset, int length) => bits.getBits(offset, length); | 
 |  | 
 |   void setBits(int offset, int length, int value) { | 
 |     bits = bits.setBits(offset, length, value); | 
 |   } | 
 | } | 
 |  | 
 | const int kBoldFieldOffset = 0; | 
 | const int kBoldFieldLength = 1; | 
 | const int kUnderlineFieldOffset = kBoldFieldOffset + kBoldFieldLength; | 
 | const int kUnderlineFieldLength = 2; | 
 | const int kItalicFieldOffset = kUnderlineFieldOffset + kUnderlineFieldLength; | 
 | const int kItalicFieldLength = 1; | 
 | const int kBlinkFieldOffset = kItalicFieldOffset + kItalicFieldLength; | 
 | const int kBlinkFieldLength = 1; | 
 | const int kReverseFieldOffset = kBlinkFieldOffset + kBlinkFieldLength; | 
 | const int kReverseFieldLength = 1; | 
 | const int kStrikeFieldOffset = kReverseFieldOffset + kReverseFieldLength; | 
 | const int kStrikeFieldLength = 1; | 
 | const int kFontFieldOffset = kStrikeFieldOffset + kStrikeFieldLength; | 
 | const int kFontFieldLength = 4; | 
 |  | 
 | /// Extension to use a 64-bit integer as bit field. | 
 | extension IntBitField on int { | 
 |   static int _bitMask(int offset, int length) => ((1 << length) - 1) << offset; | 
 |  | 
 |   /// Read `length` bits at `offset`. | 
 |   /// | 
 |   /// Truncates everything. | 
 |   int getBits(int offset, int length) { | 
 |     final mask = _bitMask(offset, length); | 
 |     return (this & mask) >> offset; | 
 |   } | 
 |  | 
 |   /// Returns a new integer value in which `length` bits are overwritten at | 
 |   /// `offset`. | 
 |   /// | 
 |   /// Truncates everything. | 
 |   int setBits(int offset, int length, int value) { | 
 |     final mask = _bitMask(offset, length); | 
 |     return (this & ~mask) | ((value << offset) & mask); | 
 |   } | 
 | } | 
 |  | 
 | main() { | 
 |   final p = calloc<ScreenCellAttrs>(3); | 
 |  | 
 |   // Zeroes out all fields. | 
 |   p.ref.bits = 0; | 
 |  | 
 |   // Set individual fields. | 
 |   p.ref.blink = 0; | 
 |   p.ref.bold = 1; | 
 |   p.ref.font = 15; | 
 |   p.ref.italic = 1; | 
 |   p.ref.reverse = 0; | 
 |   p.ref.strike = 0; | 
 |   p.ref.underline = 2; | 
 |  | 
 |   // Read individual fields. | 
 |   print(p.ref.blink); | 
 |   print(p.ref.bold); | 
 |   print(p.ref.font); | 
 |   print(p.ref.italic); | 
 |   print(p.ref.reverse); | 
 |   print(p.ref.strike); | 
 |   print(p.ref.underline); | 
 |  | 
 |   // A check for automated testing. | 
 |   Expect.equals(1933, p.ref.bits); | 
 |  | 
 |   calloc.free(p); | 
 | } |