summaryrefslogtreecommitdiff
path: root/querycp.c
blob: 52fb42b313e607217d7284a4374dc3162bdcae5e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/* querycp.c is in the public domain */

#if (defined(__WATCOMC__) && defined(__NT__))
#  define _WIN32 1
#endif

#ifdef __DJGPP__

#include <dpmi.h>
#include <go32.h>
#include <stdio.h>

/*
 ----------------------------------------------------------------------
 Tuesday, May 5, 2009    1:40pm
 rugxulo _AT_ gmail _DOT_ com

 This file is (obviously?) not copyrighted, "nenies proprajxo" !!

 Tested successfully on DR-DOS 7.03, FreeDOS 1.0++, and MS-DOS 6.22.
 (Doesn't work on XP or Vista, though.)
 ----------------------------------------------------------------------

 unsigned short query_con_codepage(void);

 gets currently selected display CON codepage

 int 21h, 6601h ("chcp") needs NLSFUNC.EXE + COUNTRY.SYS, but many
    obscure codepages (e.g. FD's cp853 from EGA.CPX (CPIX.ZIP) or
    Kosta Kostis' cp913 from ISOLATIN.CPI (ISOCP101.ZIP) have no
    relevant data inside COUNTRY.SYS.

 int 21h, 440Ch 6Ah only works in MS-DOS and DR-DOS (not FreeDOS) because
    FreeDOS DISPLAY is an .EXE TSR, not a device driver, and hence doesn't
    fully support IOCTL, so they use the undocumented int 2Fh, 0AD02h
    (which doesn't work in DR-DOS!). But DR-DOS' DISPLAY doesn't respond
    to the typical install check i.d. anyways. FreeDOS currently only
    supports COUNTRY.SYS in their "unstable" kernel 2037, but at least
    their KEYB, "gxoje", supports cp853 too (thanks, Henrique!).

 P.S. For MS or DR: ren ega.cpx *.com ; upx -d ega.com ; ren ega.com *.cpi

 ADDENDUM (2011):
 Latest "stable" FreeDOS kernel is 2040, it now includes COUNTRY.SYS
 support by default, but NLSFUNC (CHCP) 'system code page' support is
 partially unimplemented (lacking some int 2Fh calls, yet Eduardo
 Casino didn't seem too worried, so I dunno, nag him if necessary,
 heh).
 ----------------------------------------------------------------------
*/

unsigned short query_con_codepage(void) {
   __dpmi_regs regs;

   unsigned short param_block[2] = { 0, 437 };

   regs.d.eax = 0x440C;                /* GENERIC IO FOR HANDLES */
   regs.d.ebx = 1;                     /* STDOUT */
   regs.d.ecx = 0x036A;                /* 3 = CON, 0x6A = QUERY SELECTED CP */
   regs.x.ds = __tb >> 4;              /* using transfer buffer for low mem. */
   regs.x.dx = __tb & 0x0F;            /* (suggested by DJGPP FAQ, hi Eli!) */
   regs.x.flags |= 1;                  /* preset carry for potential failure */
   __dpmi_int (0x21, &regs);

   if (!(regs.x.flags & 1))            /* if succeed (carry flag not set) */
     dosmemget( __tb, 4, param_block);
   else {                              /* (undocumented method) */
     regs.x.ax = 0xAD02;               /* 440C -> MS-DOS or DR-DOS only */
     regs.x.bx = 0xFFFE;               /* AD02 -> MS-DOS or FreeDOS only */
     regs.x.flags |= 1;
     __dpmi_int(0x2F, &regs);

     if ((!(regs.x.flags & 1)) && (regs.x.bx < 0xFFFE))
       param_block[1] = regs.x.bx;
   }

   return param_block[1];
}
#elif defined(__WATCOMC__) && defined(__I86__) /* Watcom C, 16 bit Intel */

/* rugxulo _AT_ gmail _DOT_ com */

#include <stdio.h>
#include <dos.h>
#include <i86.h>

unsigned short query_con_codepage(void) {
   union REGS regs;
   unsigned short param_block[2] = { 0, 437 };

   regs.x.ax = 0x440C;           /* GENERIC IO FOR HANDLES */
   regs.x.bx = 1;                /* STDOUT */
   regs.x.cx = 0x036A;           /* 3 = CON, 0x6A = QUERY SELECTED CP */
   regs.x.dx = (unsigned short)param_block;
   regs.x.cflag |= 1;            /* preset carry for potential failure */
   int86(0x21, &regs, &regs);

   if (regs.x.cflag)             /* if not succeed (carry flag set) */
   {
     regs.x.ax = 0xAD02;         /* 440C -> MS-DOS or DR-DOS only */
     regs.x.bx = 0xFFFE;         /* AD02 -> MS-DOS or FreeDOS only */
     regs.x.cflag |= 1;
     int86(0x2F, &regs, &regs);
   }

     if ((!(regs.x.cflag)) && (regs.x.bx < 0xFFFE))
       param_block[1] = regs.x.bx;

   return param_block[1];

}

#elif defined(__WATCOMC__) && defined(__DOS__) /* Watcom C, 32 bit DOS */

/* rugxulo _AT_ gmail _DOT_ com */

#include <stdio.h>
#include <dos.h>
#include <i86.h>

unsigned short query_con_codepage(void) {
   union REGS regs;
   unsigned short param_block[2] = { 0, 437 };

   regs.x.eax = 0x440C;           /* GENERIC IO FOR HANDLES */
   regs.x.ebx = 1;                /* STDOUT */
   regs.x.ecx = 0x036A;           /* 3 = CON, 0x6A = QUERY SELECTED CP */
   regs.x.edx = (unsigned short)param_block;
   regs.x.cflag |= 1;             /* preset carry for potential failure */
   int386(0x21, &regs, &regs);

   if (regs.x.cflag)              /* if not succeed (carry flag set) */
   {
     regs.x.eax = 0xAD02;         /* 440C -> MS-DOS or DR-DOS only */
     regs.x.ebx = 0xFFFE;         /* AD02 -> MS-DOS or FreeDOS only */
     regs.x.cflag |= 1;
     int386(0x2F, &regs, &regs);
   }

     if ((!(regs.x.cflag)) && (regs.x.ebx < 0xFFFE))
       param_block[1] = regs.x.ebx;

   return param_block[1];

}


#elif defined (_WIN32) && !defined(__CYGWIN__) /* Windows, not Cygwin */

/* Erwin Waterlander */

#include <windows.h>
unsigned short query_con_codepage(void) {

  /* Dos2unix is modelled after dos2unix under SunOS/Solaris.
   * The original dos2unix ISO mode on SunOS supported code
   * pages CP437, CP850, CP860, CP863, and CP865, which
   * are DOS code pages. Therefore we request here the DOS
   * code page of the Console. The DOS code page is used
   * by DOS programs, for instance text editor 'edit'.
   */

  /* Get the console's DOS code page */
   return((unsigned short)GetConsoleOutputCP());

   /* Get the system's ANSI code page */
   /* return((unsigned short)GetACP()); */

}

#elif defined (__OS2__) /* OS/2 Warp */

#define INCL_DOS
#include <os2.h>

unsigned short query_con_codepage(void) {
  ULONG cp[3];
  ULONG cplen;

  DosQueryCp(sizeof(cp), cp, &cplen);
  return((unsigned short)cp[0]);
}

#else  /* Unix, other */
unsigned short query_con_codepage(void) {
   return(0);
}
#endif

#ifdef TEST
int main() {
  printf("\nCP%u\n",query_con_codepage() );  /* should be same result as */
  return 0;                                  /*   "mode con cp /status" */
}
#endif