Yay! They are actually providing the much needed improved printing abilities in IE7! Things like scale-to-fit, etc.
Now, the CSS zealots will still not be satisfied, stating that you should just use a separate CSS to layout your page when printed. I say that's crap--having the browser be able to scale down like Excel does is preferred by this developer, simply because I don't have time to fart around with separate stylesheets for every possible form of rendering... Let me layout for screen (keeping my horizontal scrolling to an absolute minimum), and have the printer follow suit.
Sunday, July 31, 2005
Yay! They are actually providing the much needed improved printing abilities in IE7! Things like scale-to-fit, etc.
Thursday, July 28, 2005
My wife and I stole a night away from the kids for ourselves. She's always wanted to go to Las Vegas (me too, for that matter), but there wasn't enough time. So, we did the next best thing: A Riverboat Casino in Southern Indiana.
Neither of us had ever gambled before. I can't say that I'm a big fan of it, having left $70 at the casino, and never being "ahead" at any time. We didn't approach it as a way to make money, but rather as a form of entertainment ("let's see what this game is like", etc). Still, it would have been nicer to walk away with even $75 in my wallet (i.e., +$5) instead of nothing...
Casinos have been lobbying Ohio for some time now to allow operations in the state. After my experience, I would actually be in favor of it. I mean, there's always going to be problem gamblers, but right now, they travel to Detroit, Windsor (Ontario, Canada), Indiana, or Las Vegas to get their fix. If we had a casino or two in Ohio, then that money would at least stay in our state. And, depending on Ohio's (or the local municipality's) cut of the take, it could go a long way to help better education, roads, or whatever that money gets spent on. Maybe it could even lead to no state sales tax!??!
Also, Hotel-Casinos hire A LOT of people. I was surprised at just how many staffers we saw, and that doesn't count the behind-the-scenes staff. That is a lot of jobs that could be created in our state.
Some observations about this casino:
1. It's the amusement park for disabled people. Think about it: Cedar Point doesn't make sense for Great-Grandma or cousin Jim who got in a wreck and is now paralyzed from the waist down. But, sitting in front of a slot machine is actually enjoyable to a lot of people. There were wheelchairs EVERYWHERE!
2. $10 blackjack sucks when you only want to spent $20 total playing blackjack and you're not that good in the first place. It doesn't help that the dealer was pressuring me to make decisions. I would have played $5 blackjack, but the only $5 table was full.
3. Cheapskates like me should plan on gambling in the morning--the minimum bets are lower until noon. The $5 roulette that we played the night before was only $2 in the morning.
4. Roulette is probably what I consider "my game" since there is only a slight advantage to the house (the 0 and 00), but other than that, it's completely random, requiring no skill. But, lots of money would certainly help. We saw one guy come in, get $150 in chips, put it all on black, and walked away with nothing. One spin, and he was out. Another lady came in, got $200 in chips, and played numbers, (i.e., put $100 worth on various numbers or inside splits) and tripled her chips in only a couple of spins.
5. Dedicated gamblers who require oxygen around the clock don't care about being in a smoky casino.
6. Craps must be a complicated game, because it requires 3-4 staffers to run it, even if only 1 player is using the table. (We watched a little, but never played).
8. There are actually people out there who will play $100 slot machines (that's $100 per pull...yeah, I couldn't believe it either). There's even people who win doing this (pictures litter the entrance of $16,000 winners, etc).
9. Speaking of slots, that's what casinos are. Huge rooms full of slot machines. You can't escape the noise (it's like being in an arcade!). Slots, more slots, video poker, and then more slots. 1-cent, 5-cent, 25-cent, 50-cent, $1, $5, $10, $25, $50, and $100 slots. And not just simple "spin and see what lines up", but more like "Pick 1-5 lines, place a wager per line, and then spin". Takes about 20 spins or so before the "1-5" lines start to make sense. Start with penny slots if you want to understand this phenomenon.
10. Soft drinks are free (self serve at either end of the casino). Alcohol might be too, if you're sitting at a table game, but we didn't take the chance (already gave enough to "the house"). Waitresses wore very skimpy outfits, but probably appropriate for the environment.
Seems like everywhere we went, I was staring at Chick McGee or Drew Hasting's face. There's a Friends of the Bob and Tom Show (more) on August 13th, and the promo poster was posted in multiple places.
Posted by Jason Follas at 7/28/2005 01:57:00 PM
Monday, July 25, 2005
Ah! For the first time in, well, a few years, I get to enjoy the ritual that we 'Mericans call "Vacation", which is sort of like Holiday for the rest of the English-speaking world, except there's generally less time involved because we 'Mericans are brainwashed into believing that we must work every possible hour of every possible day in order to get ahead.
It's the South Park 3-Phase plan to riches:
Phase I: Work your ass off and never take time off unless you're going to die, which would prevent you working, so better take care of that, but come right back when you're better.
Phase II: ???
Phase III: Profit.
Though, I'm finding that I don't know what to do with myself. I've been doing the same things that I normally do (surf the web, listen to DNR, read blogs, etc). There is more beer involved during the normal working hours than usual, so I've got that going for me... But, other than that, it's been uneventful so far.
I'm currently about 6-hours from where I live, so I won't be able to attend the local .NET users group tomorrow (Tuesday) in Toledo. Drew Robbins, the Microsoft Developer Evangelist for the Great Lakes Region, is presenting on VSTS. That's one demo that I would have liked to attend. Oh, well, ce la vie.
Posted by Jason Follas at 7/25/2005 02:28:00 PM
Thursday, July 21, 2005
I've worked on a lot of software in my 10+ year career. The vast majority has been the typical pull-data-out-of-a-database-and-show-it-on-the-web type of system. Extremely boring, and far from my roots in engineering and mathematics.
Thinking back to all of the systems that I had some kind of internal visibility to, the most exciting for me have been those involving creating optimal solutions to a problem. I mean, this is exactly why computers exist--not just composing a memo to tell your co-workers that there's going to be a potluck next week, or finding out how much tax you owe at the end of the year. I'm talking real problems that save companies money.
Like geocoding all of the stops that a delivery company needs to make within a city, figuring out the minimum number of trucks that are required for that day's manifest of freight, and exactly which routes the trucks should take through the city's streets in order to minimize delivery time and maximize fuel savings.
Or determining where to put freight on an aircraft in order to first ensure that the C/G is within the envelope (so the thing will fly), and then to optimize the fuel burn.
Or determining the cheapest blend of metal that results in an alloy with a specific set of properties.
These kinds of things are why I stay in this field (besides the fact that I could never cut it as a musician). The downside is that the resulting system no longer requires a knowledgeable person to operate it (downside for the Operator, that is). I mean, all of these things were done by somebody manually before using the same type of iterative processing. With an optimizer, immensely more possible solutions can be explored before determining the truly optimal solution, and as a result, you tend to get a better solution, which equates into bigger $avings.
Posted by Jason Follas at 7/21/2005 03:15:00 PM
Monday, July 18, 2005
This is interesting: The guys at MyGeneration Software (the 2-man collaborative effort with the great FREE code generator, O/R mapping tool, and architecture product) have a CodeSmith-to-MyGeneration Converter available (CodeSmith is a well-known code generation tool by Eric J. Smith et al, that sports an ASP-like syntax for its templates).
Posted by Jason Follas at 7/18/2005 02:21:00 PM
I was playing around with SQLCLR and found a scenario that confused me for a long time:
I created a small class library that contained two classes. One class instantiates the other class, which is marked as Serializable. A public method of the parent class serializes the child class using a BinaryFormatter, and returns the resulting byte array. Simple, right?
Well, I imported this class library as an assembly into my SQL Server, and was able to use the Safe permission set without a problem.
I then proceded to create a CLR Stored Procedure using Visual Studio.NET 2005 that would instantiate the parent class from my previous library, and invoke the method that would serialize the child class. I built the project, had VS deploy it to my SQL Server, and then I tested the stored proc in Management Studio.
It blew up with an error resembling the following (some names were changed to protect the innocent):
Msg 6522, Level 16, State 1, Procedure Z_Start, Line 0A .NET Framework error occurred during execution of user defined routine or aggregate 'Z_Start':
System.Security.SecurityException: Request for the permission of type 'System.Security.Permissions.SecurityPermission, mscorlib, Version=22.214.171.124, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.System.Security.SecurityException:
at System.Security.CodeAccessSecurityEngine.Check(PermissionToken permToken, CodeAccessPermission demand, StackCrawlMark& stackMark, Int32 checkFrames, Int32 unrestrictedOverride)
at System.Security.CodeAccessSecurityEngine.Check(CodeAccessPermission cap, StackCrawlMark& stackMark, PermissionType permType)
at System.Security.CodeAccessPermission.DemandInternal(PermissionType permissionType)
at System.Runtime.Serialization.Formatters.Binary.ObjectWriter..Serialize(Object graph, Header inHeaders, __BinaryWriter serWriter, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header headers, Boolean fCheck)
I played with everything that I could think of, changing the permission set of my first class library from SAFE to EXTERNAL_ACCESS to UNSAFE. Nothing worked. To me, it seemed like a bug (and I even filed a bug report).
Turns out to be a problem with this developer. Though I played around with the permission set of the one class library, I was totally forgetting that the stored procedure's assembly has its own permission set too. I was using VS to deploy the assembly, so I wasn't concerning myself, per se, with what VS was doing with it. Come to find out, that by default, VS marks SQLCLR projects as SAFE. In order to use Reflection (which the BinaryFormatter uses when serializing objects), you need at least EXTERNAL_ACCESS permissions on ALL assemblies in the call stack, not just one or the other.
A quick trip into the project's property page allowed me to change the stored procedure assembly to EXTERNAL_ACCESS, and then my test worked as expected. Credit to Erland Sommarskog (who reviewed my bug report and posted that EXTERNAL_ACCESS worked for him).
Now onto more playing around....
Posted by Jason Follas at 7/18/2005 09:56:00 AM
Sunday, July 17, 2005
I stopped in at the local Guitar Center this evening, and walked out with a Yamaha FG730S. I normally don't buy something without reviewing it in depth beforehand, but, this was different. This was impulsive. And, dammit, this sounds NICE! Especially compared to the no-name that I was previously plucking.
I see that it's a highly rated guitar, but I couldn't tell you anything about it for sure. All that I really know is that I walked out with a Yamaha. But, that's kind of like saying that I went to a car dealership and drove away in a Ford. Was it a Focus, Freestar, F-150, Mustang, or Crown Victoria? No clue, but it sure does drive nice!
My only real requirement that I told the sales guy was that I needed something easy to fret. He gave me this, and I loved it.... Though, I probably would have loved anything that he put into my hands at that moment. We'll see. It was only $300. I'll just eat PB&J for lunch this month.
Posted by Jason Follas at 7/17/2005 08:58:00 PM
Thursday, July 14, 2005
I'm still trying to figure out all of the ramifications of creating Assemblies in SQL 2005 that are marked Unsafe. Seems like the easiest way to get things done, but that's probably not the best way to think of the "Unsafe" permission set.
One of my libraries that I attempted to import today had some events in the object model, and SQL Server didn't like that (I was trying to mark it as a Safe Assembly) because the add_xxx method that the compiler tacks on for events is attributed as Synchronized, and apparently, explicit synchronization is bad, or otherwise unsafe, as far as SQL Server is concerned.
In my case, the events were simply part of an Observer pattern, and I was looking for a callback mechanism to alert the parent when something particular occurred in the child. I managed to get the code working using straight delegates (i.e., only 1 "event" handler would be allowed), and then SQL Server let me create the Assembly and mark it as Safe.
I'm probably making this more complicated than it needs to be, but I can't tell what's my fault and what is the fault of the beta software.
Posted by Jason Follas at 7/14/2005 11:46:00 PM
I had a lull in my assignments yesterday, which gave me a great opportunity to familiarize myself with SQLCLR (creating stored procedures, functions, triggers, and other SQL Server objects using .NET).
From the outside, the concept seems very cool (i.e., you can write everything in .NET code). But, a closer look shows that this is more similar to being a layer that just happens to run on the database to augment native database code instead of a full-fledged replacement for the database code.
Creating a CLR Stored Procedure is definitely a trick that you want to save for times when T-SQL just won't work, or would be overly complex. SQLCLR probably would not be appropriate for your everyday CRUD (Create, Read, Update, Delete) stored procs which are easily created using traditional methods. But, if you have some semi-complex processing, for example, where you need to do some looping (i.e., a for-loop or a while-loop), then a CLR Stored Procedure would definitely be appropriate.
Think about this:
The .NET code does not have native access to the database, like T-SQL does. As a result, the .NET code must still use ADO.NET to execute T-SQL in order to access data. So, since you never actually get away from T-SQL, you should probably plan to still create T-SQL stored procedures to access from your CLR stored procedures whenever possible (i.e., CRUD procs that your .NET code requires instead of building SQL in strings inside your code).
I also discovered a bug yesterday while trying to access CLR stored procedures from OSASPADO ("oh-SAS-pah-doh", or Old-School ASP/ADO), which was confirmed by Bob Beauchemin.
Don't misinterpret this post as thinking that SQLCLR is lackluster. It's an awesome addition to the SQL Server platform. But, it's very important to understand its limitations and design your systems around them.
Posted by Jason Follas at 7/14/2005 10:51:00 AM
Tuesday, July 12, 2005
Scott Hanselman posted today about FinePrint, which is an abstraction layer between the application and the printer driver. Your application renders the output to FinePrint's virtual printer driver, and then you can manipulate the results before they get sent to the actual printer (i.e., so that you can print multiple pages on one sheet of paper, play with margins, capture the printed output to the clipboard as a graphic, and other neat stuff).
I raised the question in the comments about whether or not a tool existed that would print web pages without the dreaded right-side clipping of text/graphics. Sure enough, there is!
Kent Chen posted this link, and he also has a blog entry describing it (which in turn, points to a blog entry, etc). Thanks for the heads-up, Kent!
IE Fitted-Width Printing: http://www.visiontech.ltd.uk/software/#IEPrint
But, the best news is that it appears that the IE7 team is working on adding this type of functionality right into Internet Explorer. AWESOME!
Posted by Jason Follas at 7/12/2005 11:24:00 PM
Every now and then, I'll launch a Virtual Machine using VirtualPC, and the screen will not change (does not refresh). I can move my mouse, but the VPC's pointer remains frozen. If I minimize the VPC window, and then restore it, the picture updates, but still remains static (so I know that the VPC is working, and it's just the screen that is not updating).
This problem seems to be related to power saving modes of my laptop. I almost never shut my laptop down, but rather just use the sleep function that kicks off when I close the display. If I leave a VPC running when the laptop sleeps, then I can almost guarantee that the screen problem will occur. However, sometimes, it occurs even when VPC (or the VPC console) is not running.
I found that when this occurs, that I can "fix" the problem by shutting down all VPC sessions (saving state, if appropriate) and then closing the VirtualPC Console. Next, start the VirtualPC Console again, and then start the VPC, and voila! Should be fixed.
This is a lot better than my old fix, which was a total system reboot.
Posted by Jason Follas at 7/12/2005 08:46:00 AM
Monday, July 11, 2005
With gasoline being a commodity, my brand loyalty is non-existent. Whichever station has the lowest price gets my dollar (or actually, as of this morning, my $2.34 per gallon). Oh, and the gas station MUST have pay-at-the-pump, else I don't patronize them.
One itsy-bitsy problem with bouncing between different gas stations and using pay-at-the-pump is that you have to figure out which direction to swipe your credit card in order for the pump to read it.
Sometimes, the stripe has to go to the left, sometimes to the right, and some pumps have cool readers that can read the card in either direction. I find that I always have to look at the little picture on the pump, turn my body (mentally) while holding the credit card so that my name is facing me, and then insert the card into the machine as indicated in the diagram.
Doing so this morning, I realized that this is very similar to the Endiness issue that exists with today's microprocessors. The credit card has one side that is the most significant (the side with the magnetic stripe). Inserting a card into the reader the wrong direction results in the card not being read.
Likewise, when a computer reads a value from its I/O, it expects the bits of the value to be arranged in a certain order. If the order is reversed, then a wrong value will be read in, which can have some pretty bad consequences. Some processors are "Big Endian" (i.e., Motorola), some are "Little Endian" (i.e., Intel), and some can be switched to handle either type of Endianess (i.e., ARM, PowerPC, etc). This is where I draw the parallel to the card readers at the gasoline pumps.
Posted by Jason Follas at 7/11/2005 09:22:00 AM
Saturday, July 09, 2005
As covered on Slashdot, here's a guy who took apart a self-heating coffee product to see how it works.
Interestingly, the source of heat comes from Calcium Oxide, which is also known as Quicklime. Basically, if you take some calcite limestone (Calcium Carbonate, that's the bedrock where I live) and heat it for a long time, it turns into Quicklime (and in the process, releases Carbon Dioxide). Add water to Quicklime, and I *think* that it turns into hydrated lime (Calcium Hydroxide?), but in the process, gets very hot.
The self heating coffee apparently has about 8oz of Quicklime powder packed into a chamber of the cup itself, and when activated, water is introduced into the Calcium Oxide, creating the chemical reaction.
In high school Chemistry class, we made Quicklime, and our teacher then instructed us to hold a small piece on our hand and add one drop of water. We learned "first hand" what an exothermic reaction was!
Posted by Jason Follas at 7/09/2005 11:26:00 PM
Friday, July 08, 2005
I pulled out a book today that I served as one of the Technical Reviewers for (Professional Visual Basic 6 - The 2003 Programmer's Resource published by Wrox Press ISBN 1-86100-818-X), and looked again at the credits page (just to see my name in print, if you have to know), there was Rocky's name under the category "Original Material" and also "Additional Material", whatever that means. He also wrote the book's Forward.
Now if only I knew who Rocky was back in 2002/2003...
Posted by Jason Follas at 7/08/2005 04:48:00 PM
Wednesday, July 06, 2005
I played around with the word wrap algorithm for a little bit, and came up with the following. I think it's better than my previous code, and simply inserts breaks into a string builder that already contains the text that needs to be split.
One challenge for my scenario is that my text might already have some line breaks in it, and I need to preserve those. Also, the text might have some indenting at the beginning of the line (i.e., spaces after the new line character), and it would be wrong to trim those out.
StringBuilder sb = new StringBuilder(text);
int lastBreak = -1;
int newBreaks = 0;
int lineStart = 0;
for (int i = 0; i < text.Length; i++)
if (text[i] == ' ')
lastBreak = i;
else if (text[i] == '\n')
lastBreak = i;
lineStart = i + 1;
if (i - lineStart + newBreaks >= m_width)
sb.Insert(newBreaks + lastBreak, "\n");
lineStart = newBreaks + lastBreak + 1;
Posted by Jason Follas at 7/06/2005 10:13:00 PM
Anyone know of a good Line Break/Word Wrap algorithm? Word Wrapping is something that I take for granted, since most Windows UI elements take care of it for me (i.e., textbox, web browser, etc).
I wanted my console application to wrap at 80 characters, but my 5 minutes of searching didn't return anything especially useful or simple.
I wrote the following, but I'm sure it can be done better somehow:
string blocks = text.Split("\n".ToCharArray());
for (int i = 0; i < blocks.Length - 1; i++)
if (blocks[i].Length < m_width)
int j = 0;
while (j < blocks[i].Length)
string tmp = blocks[i].Substring(j).TrimStart();
if (tmp.Length > m_width)
tmp = tmp.Substring(0, m_width);
int k = tmp.LastIndexOfAny(",.?!- ".ToCharArray()) + 1;
if (k == 0)
k = tmp.Length;
j += k;
By the way, there's an improved version at:
Posted by Jason Follas at 7/06/2005 04:19:00 PM
A peer of mine (Justin) from another branch of my company has written a kick-ass code generator along with another ex-employee of my company (and old MS employee, if I remember correctly).
MyGeneration continues to receive accolades and favorable reviews. The best part, is that it's Free!
Check it out!
Posted by Jason Follas at 7/06/2005 03:01:00 PM
Once again, I was given a "database" implemented using Excel that I now have to use as a regular import data source. Sigh.... And inevitably, users will start to insert columns into the already established spreadsheet layout, and I'll get the call when the import fails.
Rory has already covered this corporate-world trend in just about the funniest (and relevant) comic that I've ever read:
or all of his blog's comics:
Posted by Jason Follas at 7/06/2005 02:06:00 PM
Tuesday, July 05, 2005
My little project of writing the ZMachine interpreter class in C# continues. Let's just say that I'm able to play story files now! One step closer to my goal (why am I doing this labor of love? I'll explain at a later time, but let's just say that it should be a cool demo of something).
THE HITCHHIKER'S GUIDE TO THE GALAXY
Infocom interactive fiction - a science fiction story
Copyright (c) 1984 by Infocom, Inc. All rights reserved.
Release 59 / Serial number 851108
You wake up. The room is spinning very gently round your head. Or at least it would be if you could see it which you can't.
It is pitch black.
>turn on light
Good start to the day. Pity it's going to be the worst one of your life. The light is now on.
Bedroom, in the bed
The bedroom is a mess.
It is a small bedroom with a faded carpet and old wallpaper. There is a washbasin, a chair with a tatty dressing gown slung over it, and a window with the curtains drawn. Near the exit leading south is a phone.
There is a flathead screwdriver here. (outside the bed)
There is a toothbrush here. (outside the bed)
Very difficult, but you manage it. The room is still spinning. It dips and sways a little.
Luckily, this is large enough for you to get hold of. You notice something in the pocket.
You are now wearing your gown.
Opening your gown reveals a thing your aunt gave you which you don't know what it is, a buffered analgesic, and pocket fluff.
You swallow the tablet. After a few seconds the room begins to calm down and behave in an orderly manner. Your terrible headache goes.
telephone: You pick up the receiver. A moment later, the dialing tone is suddenly cut off. Glancing through the window you can't help but notice the large old oak tree of which you are particularly fond crashing down through the phone cable.
flathead screwdriver: Taken.
toothbrush: As you pick up the toothbrush a tree outside the window collapses. There is no causal relationship between these two events. Shouldn't you be taking more interest in events in the world around you? While you've got it...?
Posted by Jason Follas at 7/05/2005 09:38:00 PM
I just found a bug in my ZMachine interpreter that I've been trying to track down for the last 5 days or so. Not that it will mean anything to the casual reader here, but I coded the STOREW opcode to use address ARRAY + byte_index, when really it was ARRAY + (2 * byte_index). My LOADW was correctly coded.
So, as I ran HHGG.Z3, I would get to the first prompt just fine, but my "TURN ON LIGHT" would always result in "I don't understand that".
Now I can finish implementing the opcodes.....
Posted by Jason Follas at 7/05/2005 04:02:00 PM
I'm a consultant. I travel from client to client, gig to gig, solving their problems and writing software for them to use internally.
And you know what 80+% of that work turns out to be? Pulling data out of a database and displaying it on a web site. EVERYBODY needs this, and this is what every interactive system does.
At an abstract level, every client gets the same system that I previously wrote for a different client. It's their DSL (Domain Specific Language) and other nuances that makes templating the previous system somewhat of a challenge, and is what guarantees my continuing revenue.
I can't tell you how many times I've sat in elaborations where the client thinks this is some kind of novel approach to business, and they're so excited about getting started. But, to me, it's busy work. It's boring. It's been done before. It's old school.
Wanna know a secret? I have to invent new ways of doing things just to keep my mind from imploding on itself. Sometimes, they work, sometimes they don't. Luckily, in the latter category, I have previous successful implementations to recall when I'm in a time crunch.
So, the end result is that my customers are actually paying for innovation for my own selfish reasons, but think they're just getting a vanilla pull-data-from-a-database-and-display-on-a-website system.
Posted by Jason Follas at 7/05/2005 09:20:00 AM