I've written label printing software (Windows, WPF, C#, .net 4.5) that happily prints barcodes with a Datamax H-Class printer, with one exception, when printing a barcode that starts with the character C
When I attempt this, the barcode is truncated up until the first numeric character within it.
Lower case c works fine, but as some of our model codes do start with C, I need to find a way to work around this.
I guess there must be some sort of escape character that would allow this? But I've not managed to find it via Google.
I'm not 100% sure it's a code128 issue either, could it be related to the Datamax H-Class printer, the Datamax Windows C# SDK or possibly the code128 font we're using on the printer?
Sorry the details are so vague, any help or advice on what to check next would be very much appreciated.
Update.
Just in case this is of any use (I doubt it though sadly) the code I'm using to send barcodes to the printer (successfully in the case of all barcode strings not starting with C ) is as follows:
ParametersDPL paramDPL = new ParametersDPL();
paramDPL.Align = ParametersDPL.Alignment.Left;
paramDPL.Rotate = ParametersDPL.Rotation.Rotate_270;
paramDPL.IsUnicode = false;
paramDPL.TextEncoding = Encoding.ASCII;
paramDPL.WideBarWidth = 7;
paramDPL.NarrowBarWidth = 4;
paramDPL.SymbolHeight = 60;
//if the stockCode starts with 'C' the barcode will be truncated
docDPL.WriteBarCode("E", String.Format("{0} {1}", stockCode, serialNumber), COL_1, ROW_5, paramDPL);
The ParametersDPL object is from the Datamax C# SDK. The only possible problem I could see with the code is perhaps the setting of the IsUnicode or TextEncoding properties, but I've experimented with them quite a bit to no effect. None of the other properties on the ParametersDPL seemed like likely culprits either.
I'm unfamiliar with Datamax PCL, but the symptoms suggest that the "C" is being used to select subalphabet "C" of code128. It might be useful to try a stock code starting "A" or "ZB" and see whether the "A" or "B" disappears. If it does, then the first character may be being used to select a subalphabet ("A" is caps-only ASCII, "B" is no-controls ASCII.)
You'd then need to look very closely at Datamax PCL format - it may be that there's a (possibly opional) formatting character there, which makes it leading-character-sensitive. Perhaps forcing in a leading "B" would cure the problem.
Related
I am trying to inject key combinations (like ALT+.) into a tty using the TIOCSTI in Python.
For some key combinations I have found the corresponding hex code for Bash shells using the following table which works good.
From this table I can see that for example CTRL+A is '\x01' etc.
import sys,os,Queue
import termios,fcntl
# replace xx with a tty num
tty_name = "/dev/pts/xx";
parent_fd = os.open(tty_name, os.O_RDWR)
special_char = "Ctrl_a"
if special_char == "Ctrl_a":
send_char = '\x01'
if special_char == "Ctrl_e":
send_char = '\x05'
if special_char == "Ctrl_c":
send_char = '\x03'
fcntl.ioctl(self.parent_fd, termios.TIOCSTI, send_char)
But how can I get the hex codes for other combinations such as
ALT+f etc. I need a full list or a way how to get this information for any possible combo as I want to implement most bash shortcuts for moving, manipulating the history etc. to inject.
Or is there any other way to inject key-combinations using TIOCSTI ?
As I can only send single chars to a tty I wonder if there is anything else possible.
Thank you very much for your help!
The usual working of "control codes" is that the "control" modifier substracts 64 from the character code.
"A" is ASCII character 65, so "Ctrl-A" is "65-64=1".
Is it enough for you to extend this scheme to your situation?
So, if you need the control code for, for example, "Device Control 4" (ASCII code 20), you'd add 64, to obtain "84", which is "T".
Therefore, the control-code for DC4 would be "Control+T".
In the reverse direction, the value for "Control+R" (history search in BASH) is R-64, so 82-64=18 (Device Control 2)
ASCIItable.com can help with a complete listing of all character codes in ASCII
Update: Since you were asking specifically for "alt+.":
The 'Control mean minus 64" doesn't apply to Alt, unfortunately; that seems to be handled completely differently, by the keyboard driver, by generating "key codes" (also called "scancodes", variably written with or without spaces) that don't necessarily map to ASCII. (Keycodes just happen to map to ASCII for 0-9 and A-Z, which leads to much confusion)
This page lists some more keycodes, including "155" for "alt+."
I am assigning to the lpszIcon member of the MSGBOXPARAMSW structure(notice the W). I want to use one of the predefined icons like IDI_APPLICATION or IDI_WARNING but they are all ASCII (defined as MAKEINTRESOURCE). I tried doing this:
MSGBOXPARAMSW mbp = { 0 };
mbp.lpszIcon = (LPCWSTR) IDI_ERROR;
but then no icon displayed at all. So how can I use the unicode versions of the IDI_ icons?
There is no ANSI or Unicode variant of a numeric resource ID. The code that you use to set lpszIcon is correct. It is idiomatic to use the MAKEINTRESOURCE macro rather than a cast, but the cast has identical meaning. Your problem lies in the other code, the code that we cannot see.
Reading between the lines, I think that you are targeting ANSI or MBCS. You tried to use MAKEINTRESOURCE but that expands to MAKEINTRESOURCEA. That's what led you to cast. You should have used MAKEINTRESOURCEW to match MSGBOXPARAMSW. That would have resolved the compilation error you encountered. You could equally have changed the project to target UNICODE.
But none of that explains why the icon does not appear in the dialog. There has to be a problem elsewhere. If the dialog appears then the most likely explanation is that you have set hInstance to a value other than NULL. But the code to set lpszIcon is correct, albeit not idiomatic.
How do i format something for another locale in Windows?
For example, in managed C# code, i would try to render a DateTime using en-US locale with:
String s = DateTime.Now.ToString(CultureInfo.CreateSpecificCulture("en-US"));
TextRenderer.DrawText(
e.Graphics, s, SystemFonts.IconTitleFont,
new Point(16, 16), SystemColors.ControlText);
And that works fine when my computer's locale is en-US:
It even works fine when my computer's locale is de-DE:
But it completely falls apart when my computer's locale is ps-AF:
Note: My sample code is in .NET, but can also be native.
Update: Attempting to set System.Threading.Thread.CurrentThread.CurrentCulture to en-US before calling DrawText:
var oldCulture = System.Threading.Thread.CurrentThread.CurrentCulture;
System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US");
try
{
// String s = DateTime.Now.ToString(CultureInfo.CreateSpecificCulture("en-US"));
String s = DateTime.Now.ToString();
TextRenderer.DrawText(e.Graphics, s, SystemFonts.IconTitleFont, new Point(16, 16), SystemColors.ControlText);
}
finally
{
System.Threading.Thread.CurrentThread.CurrentCulture = oldCulture;
}
No help.
Nine, no help
Jack, no help
Eight, possible straight
King, possible flush
Ace, no help
Six, possible straight
Dave of love for the dealer
Ace bets.
Update Two:
From Michael Kaplan's blog entry:
Sometimes, GDI respects users (even if no one else does!)
GDI doesn't give a crap about formatting or really anything related to locales, with one single exception:
Digit Substitution
Any time you go to render text it will grab those digit substitution settings in the user locale (including the user override information) and use the info to decide how to display numbers.
And there is no way to override those settings at the level where GDI uses them.
i wonder how Chrome manages it. When i write digits here, in the stackoverflow question, Chrome renders them using latin digits:
0123456789
See:
What you are seeing is due to the digit substitution that occurs when your system's locale is ps-AF.
I believe that's OK -- Users of such a locale are used to seeing digits presented this way.
Normally the way this is done is slightly different, see here for example, but I don't actually think this should make any difference:
String s = DateTime.Now.ToString(new CultureInfo("en-US"));
An alternative is to set Thread.CurrentCulture to your desired locale.
I.e. do this:
Thread.CurrentCulture = new CultureInfo("en-US");
And you can then replace the first line of your code with this:
String s = DateTime.Now.ToString();
I am not quite sure, but I believe that this would solve the digit substitution issue as DrawText would now be based on the en-US culture, rather than ps-AF
OK, I'm sure somebody, somewhere must have come up with an algorithm for this already, so I figured I'd ask before I go off to (re)invent it myself.
I have a list of arbitrary (user-entered) non-empty text strings. Each string can be any length (except 0), and they're all unique. I want to display them to the user, but I want to trim them to some fixed length that I decide, and replace part of them with an ellipsis (...). The catch is that I want all of the output strings to be unique.
For example, if I have the strings:
Microsoft Internet Explorer 6
Microsoft Internet Explorer 7
Microsoft Internet Explorer 8
Mozilla Firefox 3
Mozilla Firefox 4
Google Chrome 14
then I wouldn't want to trim the ends of the strings, because that's the unique part (don't want to display "Microsoft Internet ..." 3 times), but it's OK to cut out the middle part:
Microsoft...rer 6
Microsoft...rer 7
Microsoft...rer 8
Mozilla Firefox 3
Mozilla Firefox 4
Google Chrome 14
Other times, the middle part might be unique, and I'd want to trim the end:
Minutes of Company Meeting, 5/25/2010 -- Internal use only
Minutes of Company Meeting, 6/24/2010 -- Internal use only
Minutes of Company Meeting, 7/23/2010 -- Internal use only
could become:
Minutes of Company Meeting, 5/25/2010...
Minutes of Company Meeting, 6/24/2010...
Minutes of Company Meeting, 7/23/2010...
I guess it should probably never ellipsize the very beginning of the strings, even if that would otherwise be allowed, since that would look weird. And I guess it could ellipsize more than one place in the string, but within reason -- maybe 2 times would be OK, but 3 or more seems excessive. Or maybe the number of times isn't as important as the size of the chunks that remain: less than about 5 characters between ellipses would be rather pointless.
The inputs (both number and size) won't be terribly large, so performance is not a major concern (well, as long as the algorithm doesn't try something silly like enumerating all possible strings until it finds a set that works!).
I guess these requirements seem pretty specific, but I'm actually fairly lenient -- I'm just trying to describe what I have in mind.
Has something like this been done before? Is there some existing algorithm or library that does this? I've googled some but found nothing quite like this so far (but maybe I'm just bad at googling). I have to believe somebody somewhere has wanted to solve this problem already!
It sounds like an application of the longest common substring problem.
Replace the longest substring common to all strings with ellipsis. If the string is still too long and you are allowed to have another ellipsis, repeat.
You have to realize that you might not be able to "ellipsize" a given set of strings enough to meet length requirements.
Sort the strings. Keep the first X characters of each string. If this prefix is not unique to the string before and after, then advance until unique characters (compared to the string before and after) are found. (If no unique characters are found, the string has no unique part, see bottom of post) Add ellipses before and after those unique characters.
Note that this still might look funny:
Microsoft Office -> Micro...ffice
Microsoft Outlook -> Micro...utlook
I don't know what language you're looking to do this in, but here's a Python implementation.
def unique_index(before, current, after, size):
'''Returns the index of the first part of _current_ of length _size_ that is
unique to it, _before_, and _after_. If _current_ has no part unique to it,
_before_, and _after_, it returns the _size_ letters at the end of _current_'''
before_unique = False
after_unique = False
for i in range(len(current)-size):
#this will be incorrect in the case mentioned below
if i > len(before)-1 or before[i] != current[i]:
before_unique = True
if i > len(after)-1 or after[i] != current[i]:
after_unique = True
if before_unique and after_unique:
return i
return len(current)-size
def ellipsize(entries, prefix_size, max_string_length):
non_prefix_size = max_string_length - prefix_size #-len("...")? Post isn't clear about this.
#If you want to preserve order then make a copy and make a mapping from the copy to the original
entries.sort()
ellipsized = []
# you could probably remove all this indexing with something out of itertools
for i in range(len(entries)):
current = entries[i]
#entry is already short enough, don't need to truncate
if len(current) <= max_string_length:
ellipsized.append(current)
continue
#grab empty strings if there's no string before/after
if i == 0:
before = ''
else:
before = entries[i-1]
if i == len(entries)-1:
after = ''
else:
after = entries[i+1]
#Is the prefix unique? If so, we're done.
current_prefix = entries[i][:prefix_size]
if not before.startswith(current_prefix) and not after.startswith(current_prefix):
ellipsized.append(current[:max_string_length] + '...') #again, possibly -3
#Otherwise find the unique part after the prefix if it exists.
else:
index = prefix_size + unique_index(before[prefix_size:], current[prefix_size:], after[prefix_size:], non_prefix_size)
if index == prefix_size:
header = ''
else:
header = '...'
if index + non_prefix_size == len(current):
trailer = ''
else:
trailer = '...'
ellipsized.append(entries[i][:prefix_size] + header + entries[i][index:index+non_prefix_size] + trailer)
return ellipsized
Also, you mention the string themselves are unique, but do they all have unique parts? For example, "Microsoft" and "Microsoft Internet Explorer 7" are two different strings, but the first has no part that is unique from the second. If this is the case, then you'll have to add something to your spec as to what to do to make this case unambiguous. (If you add "Xicrosoft", "MXcrosoft", "MiXrosoft", etc. to the mix with these two strings, there is no unique string shorter than the original string to represent "Microsoft") (Another way to think about it: if you have all possible X letter strings you can't compress them all to X-1 or less strings. Just like no compression method can compress all inputs, as this is essentially a compression method.)
Results from original post:
>>> for entry in ellipsize(["Microsoft Internet Explorer 6", "Microsoft Internet Explorer 7", "Microsoft Internet Explorer 8", "Mozilla Firefox 3", "Mozilla Firefox 4", "Google Chrome 14"], 7, 20):
print entry
Google Chrome 14
Microso...et Explorer 6
Microso...et Explorer 7
Microso...et Explorer 8
Mozilla Firefox 3
Mozilla Firefox 4
>>> for entry in ellipsize(["Minutes of Company Meeting, 5/25/2010 -- Internal use only", "Minutes of Company Meeting, 6/24/2010 -- Internal use only", "Minutes of Company Meeting, 7/23/2010 -- Internal use only"], 15, 40):
print entry
Minutes of Comp...5/25/2010 -- Internal use...
Minutes of Comp...6/24/2010 -- Internal use...
Minutes of Comp...7/23/2010 -- Internal use...
Im pretty new to coding, heres my problem.
Results->Text = "G55 > Y" + System::Convert::ToString(destY);
"Results" is a System.Windows.Forms.Textbox "multiline btw", or so says VS.
That line works fine, but i need a "new line or CR" at the end, so that i can repeat that line with different Literals and a different var in ToString.
For days now ive tried different syntax's ive read about, and i cant get it to take any of them.
Or even a complete different way to input text into Results->Text that would allow for tidy multiline use.
Sidenote: since im using ->Text and System::Convert::ToString in VC, would this code be considered just c++ or .net or CLI? to tighten my searches.
Have you tried System::Environment::NewLine? This will give you CrLf on Windows and whatever is correct for Linux/OS X on those platforms.
Being completely unfamiliar with .NET, I could be completely wrong, but surely adding a + "\n" to the end of your line would do the job? Or failing that, a + "\r\n"?