git ssb

0+

cel / freecheck



Tree: 7f59fc06d2300c374b6d0ee81788ce84dd588c69

Files: 7f59fc06d2300c374b6d0ee81788ce84dd588c69 / freecheck

22658 bytesRaw
1#!/usr/bin/perl
2
3#---------------
4#
5# FreeCheck - a free check printing application released
6# under the GNU General Public Licene.
7#
8# Copyright (C) 2000 Eric Sandeen (eric_sandeen@bigfoot.com)
9#
10# This program is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation; either version 2 of the License, or
13# (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program; if not, write to the Free Software
22# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23#
24#---------------
25
26$version = "0.2";
27$ConfigFile = "freecheck.cfg";
28
29use Getopt::Long;
30
31# This tells us how to format the strings from the cfg file
32# so we can print it as a PostScript definition
33# The key read will replace "value" for each of these
34# Strings are enclosed in parentheses (String) (Foobar)
35# Fonts are preceded by a "/" /FontName /Arial
36# Digits are fine as they are Digit 123
37# Booleans are fine too Bool true
38# But to be safe, do digits and bools as subroutines:
39# Subroutines are in {} {subr} {3 mul}
40
41%Formats = qw(
42 # Globals
43 MICRFontName /value
44 MICRFontSize {value}
45 TransitSymbol (value)
46 OnUsSymbol (value)
47 AmountSymbol (value)
48 DashSymbol (value)
49 MICRVerTweak {value}
50 MICRHorTweak {value}
51 # Account
52 CheckNumber {value}
53 PrintCheckBody {value}
54 PrintMICRLine {value}
55 NumPages {value}
56 Name1 (value)
57 Name2 (value)
58 Address1 (value)
59 Address2 (value)
60 CityStateZip (value)
61 PhoneNumber (value)
62 BankName (value)
63 BankAddr1 (value)
64 BankAddr2 (value)
65 BankCityStateZip (value)
66 AuxOnUs (value)
67 Routing (value)
68 OnUs (value)
69 Fraction (value)
70 PrintVOID {value}
71 # Styles
72 StandardFontName /value
73 StandardFontSize {value}
74 CheckNumDigits {value}
75 CheckNumFont /value
76 CheckNumSize {value}
77 MemoLineHeight {value}
78 SignatureLineHeight {value}
79 BankInfoHeight {value}
80 AmountLineHeight {value}
81 PayeeLineHeight {value}
82 DateLineHeight {value}
83 # Check Blank Types
84 CheckHeight {value}
85 CheckWidth {value}
86 CheckHorOffset {value}
87 CheckVerOffset {value}
88 ChecksPerPage {value}
89 LeftMargin {value}
90 RightMargin {value}
91 TopMargin {value}
92 );
93
94# Parse command line options and deal with them:
95
96GetOptions ("account:s", # Account definition file
97 "checknum:i", # Check number optional (overrides acct file)
98 "pages:i", # Number of pages to print
99 "checkstyle:s", # Check style (defaults to "normal_style.ps"
100 "checktype:s", # Check blank definition
101 "nomicr", # Prevents MICR line from printing (body only)
102 "nobody", # Prevents body from printing (MICR line only)
103 "showaccounts", # Show available accounts
104 "showstyles", # Show available check styles
105 "showblanks", # Show available check blanks
106 "test", # Don't increment check n, and print VOID
107 "cgi:s", # Accept big string from CGI script (or similar)
108 "help")
109
110or Show_Usage();
111
112if ($opt_help) {
113 Show_Usage();
114}
115
116# Some defaults...
117if (!$opt_cgi) {
118 $opt_account = "sample";
119 $opt_checktype = "MVG3001";
120 $opt_checkstyle = "normal";
121}
122
123# Pull the config file into a string...
124$config_file = read_file($ConfigFile);
125
126# See what sections are available
127Get_Sections();
128
129# If we're missing the [Global] section, or if a requested section
130# cannot be found, die.
131if (!$global_found) {
132 die ("No [Global] section found in config file\n");
133}
134
135if ($accounts !~ /${opt_account}/i) {
136 die ("Account $opt_account not found in config file\n");
137}
138
139if ($checkblanks !~ /$opt_checktype/i) {
140 die ("Check type $opt_checktype not found in config file\n");
141}
142
143if ($checkstyles !~ /$opt_checkstyle/i) {
144 die ("Style $opt_checkstyle not found in config file\n");
145}
146
147# Show list of available sections, if requested
148if ($opt_showaccounts || $opt_showstyles || $opt_showblanks) {
149 print "\nFreeCheck v$version\n";
150 if ($opt_showaccounts) {
151 print "Accounts:\n";
152 foreach (split(/\s+/,$accounts)) {
153 print "\t$_\n";
154 }
155 }
156 if ($opt_showstyles) {
157 print "Check Styles:\n";
158 foreach (split(/\s+/,$checkstyles)) {
159 print "\t$_\n";
160 }
161 }
162 if ($opt_showblanks) {
163 print "Check Types:\n";
164 foreach (split(/\s+/,$checkblanks)) {
165 print "\t$_\n";
166 }
167 }
168 die("\n");
169}
170
171# Go through the config and fill up a hash with PostScript defines...
172Parse_Config($config_file);
173
174# Overwrite anything we got from the config file with what was on the
175# Command Line (if anything...)
176
177if ($opt_checknum) {
178 $Definitions{"CheckNumber"} = $opt_checknum;
179}
180
181if ($opt_pages) {
182 $Definitions{"NumPages"} = $opt_pages;
183}
184
185if ($opt_nomicr) {
186 $Definitions{"PrintMICRLine"} = "false";
187}
188
189if ($opt_nobody) {
190 $Definitions{"PrintCheckBody"} = "false";
191}
192
193# This probably isn't in the config file (although it might be...)
194# so cover both possibilites (true/false)
195if ($opt_test) {
196 $Definitions{"PrintVOID"} = "true";
197} else {
198 $Definitions{"PrintVOID"} = "false";
199}
200
201# the --cgi option lets us pass in name value pairs in a string.
202# This will overwrite anything we got from the config file, or
203# from the other command line options (--cgi has the last word)
204# Parse as follows:
205# name is the first word, everything following it is the value
206# each line contains one name/value pair.
207
208while ( $opt_cgi =~ /(^\w+)\s+?(.*$)/mcg ) {
209 $Definitions{$1} = $2;
210}
211
212##################
213# Error Checking #
214##################
215
216$error = "";
217
218# Make sure that MICR line is only numbers and symbols
219
220if ( $Definitions{"Routing"} !~ /^R[0-9]+R$/ ) {
221 $error = $error . "Error - Routing number must be numeric, with an \"R\" on each end\n";
222}
223
224if ( $Definitions{"AuxOnUs"} !~ /^[0-9\-CPS]*$/ ) {
225 $error = $error . "Error - Auxiliary On-Us field may only be numeric, with \"-\", and MICR symbols (C,P,S)\n";
226}
227
228if ( $Definitions{"OnUs"} !~ /^[0-9\-CPS]+$/ ) {
229 $error = $error . "Error - On-Us field may only be numeric, with \"-\", and MICR symbols (C,P,S)\n";
230}
231
232if ( $Definitions{"CheckNumber"} !~ /^[0-9]+$/ ) {
233 $error = $error . "Error - Check number must be numeric \n";
234}
235
236if ( $Definitions{"NumPages"} !~ /^[0-9]+$/ ) {
237 $error = $error . "Error - Number of pages must be numeric\n";
238}
239
240if ( $Definitions{"Fraction"} !~ /^[0-9]{2}\s*\-\s*[0-9]{1,4}\s*\/\s*[0-9]{3,4}$/ ) {
241 $error = $error . "Error - Routing fraction must be numeric, with a \"-\" in the numerator\n";
242}
243
244# Get routing symbol and institution number from routing number
245$RoutingSymbol = substr($Definitions{"Routing"},1,4);
246$Institution = substr($Definitions{"Routing"},5,4);
247
248# Strip any leading zeros...
249# Only should be one on routing...
250$RoutingSymbol =~ s/^0//;
251# One or more on institution
252$Institution =~ s/^0+//;
253
254# Fraction format:
255#
256# 2 digits, a "-", institution number (no leading zeros)
257# ------------------------------------------------------
258# routing number (no leading zeros)
259
260
261if ( $Definitions{"Fraction"} !~ /^[0-9]{2}\-${Institution}\/${RoutingSymbol}$/ ) {
262 $error = $error . "Error - Routing fraction does not match routing number\n";
263}
264
265
266# Test the MICR line for correctness
267if ( length ($Definitions{"Routing"}) != 11 ) {
268 $error = $error . "Error - Routing number must be exactly 9 digits long, with
269 an \"R\" on each end\n";
270}
271
272# Test the MICR checksum
273# Don't forget the real routing number is sandwiched between "Rs"
274
275unless ( ( $Definitions{"Routing"} !~ /^R[0-9]+R$/) || ( length ($Definitions{"Routing"}) != 11 ) ){
276
277 $CheckSum = 0;
278
279 @CheckSumMults = (3, 7, 1, 3, 7, 1, 3, 7);
280 for ($Digit = 1; $Digit < 9; $Digit++) {
281 $CheckSum = $CheckSum +
282 $CheckSumMults[$Digit-1] * substr($Definitions{"Routing"}, $Digit, 1);
283 }
284
285 $CheckSum = 10 - ($CheckSum % 10);
286
287 # Kludge alert...
288 if ($CheckSum == 10) {
289 $CheckSum = 0;
290 }
291
292 if ( $CheckSum ne substr($Definitions{"Routing"}, 9, 1) ) {
293 $error = $error . "Error - Routing Number Checksum Incorrect\n";
294 }
295}
296
297
298# die() if we got errors
299if ( $error && !$opt_test ) {
300 print $error;
301 die("Errors Encountered\n");
302}
303
304# Print PostScript
305
306# Initial stuff:
307
308print "%!\n";
309print "/inch {72 mul} def\n";
310
311# Go through $Definitions and print them out PostScript-Like
312Print_Defs();
313
314# Then print the main body
315Print_Body();
316
317# Update the config file with the new check number, if it's not just a test
318if (!$opt_test && !$opt_cgi) {
319 $next_check_number = $Definitions{"CheckNumber"}
320 + ($Definitions{"NumPages"} * $Definitions{"ChecksPerPage"});
321
322 $config_file = Replace_Val($config_file, "Account", $opt_account,
323 "CheckNumber", $next_check_number);
324 write_file ("freecheck.cfg", $config_file);
325}
326
327###############
328# Subroutines #
329###############
330
331# read_file and write_file shamelessly stolen from the File::Slurp module
332# Short enough, and I didn't want to require a non-standard module
333
334sub read_file
335{
336 my ($file) = @_;
337
338 local(*F);
339 my $r;
340 my (@r);
341
342 open(F, "<$file") || die "open $file: $!";
343 @r = <F>;
344 close(F);
345
346 return @r if wantarray;
347 return join("",@r);
348}
349
350sub write_file
351{
352 my ($f, @data) = @_;
353
354 local(*F);
355
356 open(F, ">$f") || die "open >$f: $!";
357 (print F @data) || die "write $f: $!";
358 close(F) || die "close $f: $!";
359 return 1;
360}
361
362# Wow, this is ugly! Anybody have a better suggestion?
363sub Parse_Config {
364 local ($config_file) = ($_[0]);
365 # Find each section we're looking for...
366 while ($config_file =~ /^\[\s*(
367 Global |
368 Account\s+${opt_account} |
369 Style\s+${opt_checkstyle} |
370 CheckBlank\s+${opt_checktype}
371 )\s*\]/xmgci) {
372 # and get the lines under it one by one
373 while ($config_file =~ /(^.+$)/mgc) {
374 $line = $+;
375 # If this line is a comment, skip it
376 if ($line =~ /^#/) {
377 next;
378 }
379 # If the line we just found is a new section..."[...]"
380 if ($line =~ /^\[.+\]/) {
381 # and it is another section we're looking for
382 # Grab the next line, and keep going
383 if ($line =~ /\[\s*(
384 Global |
385 Account\s+${opt_account} |
386 Style\s+${opt_checkstyle} |
387 CheckBlank\s+${opt_checktype}
388 )\s*]/xi) {
389 # Grab the next line, and keep going
390 next;
391 } else {
392 # Not a section we need, so break out
393 # of the loop
394 last;
395 }
396 }
397
398 ($key, $val) = split (/\s*=\s*/,$line);
399 # Need to strip trailing whitespace...
400 $val =~ s/\s*$//;
401 $Definitions{$key} = $val;
402 } # line-by-line while
403 } # section match conditional
404}
405
406sub Replace_Val {
407 local ($string, $section, $name, $key, $value) =
408 ($_[0], $_[1], $_[2], $_[3], $_[4]);
409 # We want to get "[section name] ... key = value" and replace it
410 # with the new value.
411
412 # s - "." matches ANYTHING including newline
413 # m - ^ and $ match after and before any newline
414 # in this case, ".+?" means the minimum number of <anything> i.e. end
415 # when we find the first instance of $key after [section name]
416 $string =~
417 s/(^\[\s*$section\s+$name\s*\].+?^${key}\s*=\s*).*?$/$+$value/smi;
418 $string;
419}
420# Given a section type, list all the section names of that type
421sub Get_Sections {
422 local $section;
423 while ($config_file =~ /^\[\s*(
424 Global |
425 Account.+ |
426 Style.+ |
427 CheckBlank.+
428 )\s*\]/xmgci) {
429 $section = $+;
430 if ( $section =~/CheckBlank\s+(.+)/i ) {
431 $checkblanks = "$+ $checkblanks";
432 } elsif ( $section =~/Style\s+(.+)/i ) {
433 $checkstyles = "$+ $checkstyles";
434 } elsif ( $section =~/Account\s+(.+)/i ) {
435 $accounts = "$+ $accounts";
436 } elsif ( $section =~/Global/i ) {
437 $global_found = "true";
438 }
439 }
440}
441
442sub Show_Usage {
443 print "\nFreeCheck v.$version - a Free Check printing Utility\n\n";
444 print "Usage: freecheck <options>:\n";
445 print "\n";
446 print "options:\n";
447 print " --account <filename> account to use (default \"$opt_account\")\n";
448 print " --checknum <integer> starting check number (overrides cfg)\n";
449 print " --pages <integer> number of pages to print (overrides cfg)\n";
450 print " --checkstyle <filename> check style to use (default \"$opt_checkstyle\")\n";
451 print " --checktype <filename> blank check type to use (default \"$opt_checktype\")\n";
452 print " --nomicr do not print MICR line\n";
453 print " --nobody do not print check body\n";
454 print " --showaccounts show all configured accounts\n";
455 print " --showstyles show all configured check styles\n";
456 print " --showblanks show all configured check blanks\n";
457 print " --help print this message\n";
458 print " --test print but don't increment check number\n";
459 print " and print VOID on the check\n";
460 print " --cgi accept string from CGI script (see docs)\n";
461 print "\nconfig file \"freecheck.cfg\" must be in the same directory,\n";
462 print "as the freecheck executable (this will change in the future...)\n";
463 die "\n";
464}
465
466sub Print_Defs {
467 # Go through each def in the hash table, and print according to the
468 # formatting hash
469 while ( ($key, $val) = each (%Definitions) ) {
470 print "/$key\t";
471 $_ = $Formats{$key};
472 s/value/$val/;
473 print;
474 print " def\n";
475 }
476}
477
478sub Print_Body {
479
480# This is the main body of the postscript file, that acts on all of the
481# definitions we got from the config file.
482
483print <<END_OF_POSTSCRIPT
484
485% Other Constants:
486
487% Size of the rectangular box for the amount (digits)
488/AmountBoxWidth {1 inch} def
489/AmountBoxHeight {0.25 inch} def
490
491/LineWidth {0.3} def
492
493% Max number of digits in check number, and allocate string
494/CheckNumDigits 4 def
495/CheckNumberString CheckNumber log floor 1 add cvi string def
496
497%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
498% Helpful Printing Routines %
499%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
500
501% Shows a line, then does a "carriage return / line feed"
502% But only if the string exists (more than 0 chars)
503% (How do we get the current font size (height)?)
504
505/ShowAndCR {
506 % A couple copies of the string (now 3 on stack)
507 dup dup
508 length 0 gt { % First copy
509 show % Second copy
510 stringwidth pop neg 0 rmoveto % Third copy & move back
511 neg 0 exch rmoveto % line down
512 } if
513} def
514
515% Fix up the MICR line components (replace placeholders with MICR
516% characters)
517% Argh... surely there's a better way - anyone? use "forall?"
518
519/FixMICR {
520
521 /CheckNumStart -1 def
522 /CheckNumEnd -1 def
523 /CheckNumInOnUs false def
524 /CheckNumInAuxOnUs false def
525
526 % Get starting and ending positions for check number in
527 % (Aux)OnUs field
528 % (This will break if check number is entered in both fields)
529
530 OnUs length 1 sub -1 0 {
531 dup % dups the index
532 OnUs exch get (C) 0 get eq {
533 /CheckNumInOnUs true def
534 % If end number not yet defined, define it
535 CheckNumEnd 0 lt {
536 /CheckNumEnd exch def
537 } {
538 /CheckNumStart exch def
539 } ifelse
540
541 } {
542 pop
543 } ifelse
544 } for
545
546 AuxOnUs length 1 sub -1 0 {
547 dup % dups the index
548 AuxOnUs exch get (C) 0 get eq {
549 /CheckNumInAuxOnUs true def
550 % If end number not yet defined, define it
551 CheckNumEnd 0 lt {
552 /CheckNumEnd exch def
553 } {
554 /CheckNumStart exch def
555 } ifelse
556
557 } {
558 pop
559 } ifelse
560 } for
561
562
563 % Replace "R" in routing number with actual transit number symbol
564 % That's it - should be no spaces, dashes, or anything but digits
565 Routing length 1 sub -1 0 {
566 dup % dups the index
567 Routing exch get (R) 0 get eq {
568 Routing exch TransitSymbol 0 get put
569 } {
570 pop
571 } ifelse
572 } for
573
574 % Replace "S" with space character in AuxOnUs
575 AuxOnUs length 1 sub -1 0 {
576 dup
577 AuxOnUs exch get (S) 0 get eq {
578 AuxOnUs exch ( ) 0 get put
579 } {
580 pop
581 } ifelse
582 } for
583
584 % Replace "-" with dash character in AuxOnUs
585 AuxOnUs length 1 sub -1 0 {
586 dup
587 AuxOnUs exch get (-) 0 get eq {
588 AuxOnUs exch DashSymbol 0 get put
589 } {
590 pop
591 } ifelse
592 } for
593
594 % Replace "P" with OnUs character in AuxOnUs
595 AuxOnUs length 1 sub -1 0 {
596 dup
597 OnUs exch get (P) 0 get eq {
598 OnUs exch OnUsSymbol 0 get put
599 } {
600 pop
601 } ifelse
602 } for
603
604 % Replace "S" with space character in OnUs
605 OnUs length 1 sub -1 0 {
606 dup
607 OnUs exch get (S) 0 get eq {
608 OnUs exch ( ) 0 get put
609 } {
610 pop
611 } ifelse
612 } for
613
614 % Replace "-" with dash character in OnUs
615 OnUs length 1 sub -1 0 {
616 dup
617 OnUs exch get (-) 0 get eq {
618 OnUs exch DashSymbol 0 get put
619 } {
620 pop
621 } ifelse
622 } for
623
624 % Replace "P" with OnUs character in OnUs
625 OnUs length 1 sub -1 0 {
626 dup
627 OnUs exch get (P) 0 get eq {
628 OnUs exch OnUsSymbol 0 get put
629 } {
630 pop
631 } ifelse
632 } for
633
634} def
635
636%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
637% Feature Printing Routines %
638%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
639
640/DrawMemoLine {
641 LeftMargin MemoLineHeight CheckHeight mul moveto
642 2.5 inch 0 inch rlineto
643 -2.5 inch 0 inch rmoveto
644 0 2 rmoveto
645 (for) show
646} def
647
648/DrawSignatureLine { % Expects height of signature line
649 % and right edge of check for
650 % beginning position
651
652 CheckWidth SignatureLineHeight CheckHeight mul moveto
653 RightMargin neg 0 rmoveto
654 -2.5 inch 0 rmoveto
655 2.5 inch 0 inch rlineto
656
657} def
658
659/DrawAmountLine {
660 CheckWidth AmountLineHeight CheckHeight mul moveto
661 RightMargin neg 0 rmoveto
662 (DOLLARS) stringwidth pop neg 0 rmoveto
663 (DOLLARS) show
664 (DOLLARS) stringwidth pop neg 0 rmoveto
665 -2 0 rmoveto
666 LeftMargin AmountLineHeight CheckHeight mul lineto
667} def
668
669/DrawAccountHolderInfo {
670 LeftMargin CheckHeight moveto
671 0 TopMargin neg rmoveto
672 0 StandardFontSize neg rmoveto
673
674 StandardFontSize Name1 ShowAndCR
675 StandardFontSize Name2 ShowAndCR
676
677 StandardFontName findfont
678 StandardFontSize 1 sub scalefont
679 setfont
680
681 StandardFontSize 1 sub Address1 ShowAndCR
682 StandardFontSize 1 sub Address2 ShowAndCR
683 StandardFontSize 1 sub CityStateZip ShowAndCR
684 StandardFontSize 1 sub PhoneNumber ShowAndCR
685
686 StandardFontName findfont
687 StandardFontSize 1 add scalefont
688 setfont
689} def
690
691/DrawDateLine {
692 0.6 CheckWidth mul DateLineHeight CheckHeight mul moveto
693 (Date) show
694 1 inch 0 rlineto
695} def
696
697/DrawBankInfo {
698 LeftMargin BankInfoHeight CheckHeight mul moveto
699
700 StandardFontSize BankName ShowAndCR
701
702 StandardFontName findfont
703 StandardFontSize 1 sub scalefont
704 setfont
705
706 StandardFontSize 1 sub BankAddr1 ShowAndCR
707 StandardFontSize 1 sub BankAddr2 ShowAndCR
708 StandardFontSize 1 sub BankCityStateZip ShowAndCR
709
710 StandardFontName findfont
711 StandardFontSize 1 add scalefont
712 setfont
713} def
714
715/DrawPayeeLine {
716
717 LeftMargin PayeeLineHeight CheckHeight mul moveto
718 (ORDER OF) show
719 (ORDER OF) stringwidth pop neg StandardFontSize rmoveto
720 (PAY TO THE) show
721 0 StandardFontSize neg rmoveto
722 4 0 rmoveto
723 currentpoint mark
724
725 CheckWidth PayeeLineHeight CheckHeight mul moveto
726 RightMargin neg 0 rmoveto
727 AmountBoxWidth neg 0 rmoveto
728
729 0 AmountBoxHeight rlineto
730 AmountBoxWidth 0 rlineto
731 0 AmountBoxHeight neg rlineto
732 AmountBoxWidth neg 0 rlineto
733
734 -4 0 rmoveto
735
736 /Helvetica-Bold findfont
737 14 scalefont
738 setfont
739
740 (\$) stringwidth pop neg 0 rmoveto
741 (\$) show
742 (\$) stringwidth pop neg 0 rmoveto
743
744 -4 0 rmoveto
745 cleartomark
746 lineto
747
748 StandardFontName findfont
749 StandardFontSize scalefont
750 setfont
751
752} def
753
754/DrawMICR {
755 % 0.25 high, 5.6875 from right edge should be in the middle
756 % of the tolerance band
757 CheckWidth 0.25 inch moveto
758 -5.6875 inch 0 inch rmoveto
759 MICRHorTweak MICRVerTweak rmoveto
760 % Now we're at the nominal start of the routing number
761
762 MICRFontName findfont
763 MICRFontSize scalefont
764 setfont
765
766 % Number of digits in the CheckNumberString
767 /CheckNumDigit CheckNumberString length 1 sub def
768
769 CheckNumInAuxOnUs {
770 CheckNumEnd -1 CheckNumStart {
771 CheckNumDigit 0 ge {
772 AuxOnUs exch CheckNumberString CheckNumDigit get put
773 /CheckNumDigit CheckNumDigit 1 sub def
774 } {
775 AuxOnUs exch (0) 0 get put
776 } ifelse
777 } for
778 } if
779
780
781 AuxOnUs stringwidth pop neg 0 rmoveto
782 AuxOnUs show
783
784 Routing show
785
786 CheckNumInOnUs {
787 CheckNumEnd -1 CheckNumStart {
788 CheckNumDigit 0 ge {
789 OnUs exch CheckNumberString CheckNumDigit get put
790 /CheckNumDigit CheckNumDigit 1 sub def
791 } {
792 OnUs exch (0) 0 get put
793 } ifelse
794 } for
795 } if
796
797 OnUs show
798
799 StandardFontName findfont
800 StandardFontSize scalefont
801 setfont
802} def
803
804/DrawCheckNumber {
805 CheckWidth CheckHeight moveto
806 RightMargin neg TopMargin neg rmoveto
807 CheckNumFont findfont
808 CheckNumSize scalefont
809 setfont
810
811 CheckNumberString stringwidth pop neg 0 rmoveto
812 0 -14 rmoveto
813 CheckNumberString show
814
815 StandardFontName findfont
816 StandardFontSize scalefont
817 setfont
818} def
819
820/DrawFraction {
821 0.6 CheckWidth mul CheckHeight moveto
822 0 TopMargin neg rmoveto
823 0 StandardFontSize neg rmoveto
824 Fraction show
825} def
826
827/DrawStub {
828 CheckHorOffset 2 inch ge {
829 save
830 newpath
831 CheckHorOffset neg 0 translate
832 StandardFontName findfont
833 StandardFontSize 1 sub scalefont
834 setfont
835 /StubSpacing {CheckHeight 6 div} def
836 CheckHorOffset 2 div StubSpacing 5 mul moveto
837 CheckNumberString show
838 0.3 inch StubSpacing 4 mul moveto
839 (Date ) show
840 CheckHorOffset 0.3 inch sub StubSpacing 4 mul lineto
841 0.3 inch StubSpacing 3 mul moveto
842 (Payee ) show
843 CheckHorOffset 0.3 inch sub StubSpacing 3 mul lineto
844 0.3 inch StubSpacing 2 mul moveto
845 (Amount ) show
846 CheckHorOffset 0.3 inch sub StubSpacing 2 mul lineto
847 0.3 inch StubSpacing 1 mul moveto
848 (Memo ) show
849 CheckHorOffset 0.3 inch sub StubSpacing 1 mul lineto
850 stroke
851 restore
852 } if
853} def
854
855/DrawVOID {
856 save
857 StandardFontName findfont
858 50 scalefont
859 setfont
860 newpath
861 CheckWidth 2 div 1 inch moveto
862 30 rotate
863 (V O I D) stringwidth pop 0 moveto
864 (V O I D) true charpath
865 stroke
866 restore
867} def
868
869/DrawCheck {
870
871 % Convert CheckNumber integer to a string
872 CheckNumber CheckNumberString cvs
873
874 PrintCheckBody {
875 DrawBankInfo
876 DrawAccountHolderInfo
877 DrawMemoLine
878 DrawSignatureLine
879 DrawAmountLine
880 DrawPayeeLine
881 DrawCheckNumber
882 DrawFraction
883 DrawDateLine
884 DrawStub
885 } if
886
887 PrintMICRLine {
888 DrawMICR
889 } if
890
891 PrintVOID {
892 % Draw border around check, and print "VOID" for testing
893 0 0 moveto
894 CheckWidth 0 lineto
895 CheckWidth CheckHeight lineto
896 0 CheckHeight lineto
897
898 0 0 lineto
899
900 DrawVOID
901 } if
902
903} def
904
905
906/CurrentPage 1 def
907
908% Replace symbol placeholders with actual glyphs
909% Also get starting and ending position for check number
910FixMICR
911
912NumPages -1 1 {
913 /CheckNumber CheckNumber ChecksPerPage add def
914 CheckHorOffset CheckVerOffset translate
915
916 StandardFontName findfont
917 StandardFontSize scalefont
918 setfont
919
920 LineWidth setlinewidth
921
922 % Loop through printing checks, starting with the bottom one
923
924 ChecksPerPage -1 1 {
925 /CheckNumber CheckNumber 1 sub def
926 newpath
927 DrawCheck
928 stroke
929 0 CheckHeight translate
930 } for
931
932 showpage
933 /CheckNumber CheckNumber ChecksPerPage add def
934 /CurrentPage CurrentPage 1 add def
935
936} for
937
938
939END_OF_POSTSCRIPT
940;
941
942}
943

Built with git-ssb-web