home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / NOTEPAD2.ZIP / NPFONT.C < prev    next >
C/C++ Source or Header  |  1989-02-08  |  16KB  |  496 lines

  1. /***************************************************************************\
  2. * npfont.c - notepad font handling
  3. *
  4. * Created by Microsoft Corporation, 1989
  5. \***************************************************************************/
  6.  
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #define INCL_WIN
  10. #define INCL_GPI
  11. #include <os2.h>
  12. #include <opendlg.h>
  13. #include "notepad.h"
  14. #include "npcmd.h"
  15. #include "search.h"
  16.  
  17. typedef struct _NAMESTRUCT {
  18.         CHAR szFamilyName[FACESIZE];
  19.         CHAR szFaceName[FACESIZE];
  20. } NAMESTRUCT;
  21. typedef NAMESTRUCT FAR *PNAMESTRUCT;
  22.  
  23. typedef struct _FONTSTRUCT {
  24.         NAMESTRUCT nms;
  25.         SHORT sLastSize;
  26. } FONTSTRUCT;
  27. typedef FONTSTRUCT FAR *PFONTSTRUCT;
  28.  
  29. typedef struct _SIZESTRUCT {
  30.         SHORT sPoints;
  31.         LONG lMatch;
  32. } SIZESTRUCT;
  33. typedef SIZESTRUCT FAR *PSIZESTRUCT;
  34.  
  35. PFONTSTRUCT pfnts = NULL;
  36. PSIZESTRUCT psizes = NULL;
  37. USHORT cbsizes = 0;
  38. SHORT scsizes;
  39. SHORT sCurrFont = -1;
  40. SHORT sCurrSizeIndex = -1;
  41. SHORT sCurrSize;
  42. SHORT sScreenXRes, sScreenYRes;
  43. HWND hwndSizeMenu;
  44. HWND hwndFontMenu;
  45.  
  46. #define SYSFONTTEXT "System Font"
  47. VOID AutoSelectSize(VOID);
  48. VOID ClearSizeMenu(VOID);
  49. VOID DisableSizeMenu(VOID);
  50. int _CDECL CompareNMS(const void *, const void *);
  51.  
  52. PSZ CurrFaceName()
  53. {
  54.         return((pfnts+sCurrFont)->nms.szFaceName);
  55. }
  56.  
  57. SHORT CurrFaceSize()
  58. {
  59.         return((psizes+sCurrSizeIndex)->sPoints);
  60. }
  61.  
  62. /**********************************************************************
  63.  *
  64.  * GetWindowResolution
  65.  *
  66.  * determines the resolution (in x and y) that fonts on the screen should
  67.  * have.
  68.  **********************************************************************/
  69.  
  70. VOID GetWindowResolution(HWND hwnd)
  71. {
  72.         HDC hdcScreen;
  73.         LONG ldevcaps[2];
  74.         BOOL retcd;
  75.  
  76.  
  77.         hdcScreen = WinQueryWindowDC(hwnd);
  78.         retcd = DevQueryCaps(hdcScreen, CAPS_HORIZONTAL_FONT_RES, 2L, ldevcaps);
  79.         sScreenXRes = (SHORT)ldevcaps[0];
  80.         sScreenYRes = (SHORT)ldevcaps[1];
  81. }
  82.  
  83. static VOID AddFont(SHORT sIndex, PNAMESTRUCT pnms, MENUITEM FAR *mi)
  84. {
  85.     WinSendMsg(hwndFontMenu,MM_INSERTITEM,
  86.             MPFROMP(mi),
  87.             MPFROMP((pnms==NULL)?SYSFONTTEXT:(pnms->szFaceName)));
  88.     if (pnms == NULL) {
  89.         lstrcpy((pfnts+sIndex)->nms.szFamilyName, SYSFONTTEXT);
  90.         lstrcpy((pfnts+sIndex)->nms.szFaceName, SYSFONTTEXT);
  91.     } else {
  92.         lstrcpy((pfnts+sIndex)->nms.szFamilyName, pnms->szFamilyName);
  93.         lstrcpy((pfnts+sIndex)->nms.szFaceName, pnms->szFaceName);
  94.     }
  95.     (pfnts+sIndex)->sLastSize = 0;
  96. }
  97.  
  98. static VOID MakeFontMenu(LONG lFonts, PNAMESTRUCT pnms)
  99. {
  100.         MENUITEM mi;
  101.         SHORT i;
  102.  
  103.         pfnts = (PFONTSTRUCT)WinAllocMem(hhAppHeap,
  104.                     (USHORT) ((lFonts + 1) * sizeof(FONTSTRUCT)));
  105.  
  106.         mi.iPosition = MIT_END;
  107.         mi.afStyle = MIS_TEXT;
  108.         mi.afAttribute = 0;
  109.         mi.id = (SUB_FONTS | (0x01));
  110.         mi.hwndSubMenu = NULL;
  111.         mi.hItem = NULL;
  112.         AddFont(0,NULL,(MENUITEM FAR *)&mi);
  113.  
  114.         for (i = 0; i < (SHORT) lFonts; i++) {
  115.                 mi.iPosition = MIT_END;
  116.                 mi.afStyle = MIS_TEXT;
  117.                 mi.afAttribute = 0;
  118.                 mi.id = (SUB_FONTS | ((i+2) & 0xff));
  119.                 mi.hwndSubMenu = NULL;
  120.                 mi.hItem = NULL;
  121.                 AddFont(i+1,(pnms+i),(MENUITEM FAR *)&mi);
  122.         }
  123.         SelectFont(1);
  124. }
  125.  
  126. /**********************************************************************
  127.  *
  128.  * GetFontMetrics
  129.  *
  130.  *  Given a face name, get the table of font metrics; return as the
  131.  *  function value the number of entries in the font metrics table;
  132.  *  as a side effect set the pointer to the allocated table and update
  133.  *  the value passed by reference for the length of the table.  It is
  134.  *  the caller's responsibility to later WinFreeMem on the pointer
  135.  *  returned.
  136.  **********************************************************************/
  137.  
  138. SHORT GetFontMetrics(PSZ pszFaceName, PFONTMETRICS *pfms, PSHORT pcbytes)
  139. {
  140.         HPS hps;
  141.         LONG pcFonts;
  142.         LONG cRemFonts;
  143.  
  144.         hps = WinGetPS(hwndNPEdit);
  145.         pcFonts = 0;
  146.         cRemFonts = GpiQueryFonts(hps,
  147.                 QF_PUBLIC | QF_PRIVATE,
  148.                 pszFaceName,
  149.                 (PLONG) &pcFonts,
  150.                 (LONG) 0,
  151.                 NULL);
  152.         *pcbytes = (SHORT) (cRemFonts * sizeof(FONTMETRICS));
  153.         *pfms = (PFONTMETRICS)WinAllocMem(hhAppHeap,*pcbytes);
  154.         pcFonts = cRemFonts;
  155.         GpiQueryFonts(hps,
  156.                 QF_PUBLIC | QF_PRIVATE,
  157.                 pszFaceName,
  158.                 (PLONG) &pcFonts,
  159.                 (LONG) sizeof(FONTMETRICS),
  160.                 *pfms);
  161.         WinReleasePS(hps);
  162.         return((SHORT) cRemFonts);
  163. }
  164.  
  165. BOOL ExistsScrRes(PNAMESTRUCT pnms)
  166. {
  167.     SHORT i;
  168.     LONG cFonts;
  169.     PFONTMETRICS pfms;
  170.     SHORT cbytes;
  171.  
  172.     cFonts = GetFontMetrics(pnms->szFaceName, &pfms, &cbytes);
  173.     for (i = 0; i < (SHORT) cFonts; i++) {
  174.         if (((pfms+i)->sXDeviceRes == sScreenXRes) &&
  175.                 ((pfms+i)->sYDeviceRes == sScreenYRes)) {
  176.             WinFreeMem(hhAppHeap, (NPBYTE) OFFSETOF(pfms), (USHORT) cbytes);
  177.             return(TRUE);
  178.         }
  179.     }
  180.     WinFreeMem(hhAppHeap, (NPBYTE) OFFSETOF(pfms), (USHORT) cbytes);
  181.     return(FALSE);
  182. }
  183.  
  184. int _CDECL CompareNMS(const void *a, const void *b)
  185. {
  186.     return(lstrcmp((PSZ)((PNAMESTRUCT)a)->szFaceName,
  187.             (PSZ)((PNAMESTRUCT)b)->szFaceName));
  188. }
  189.  
  190. LONG EliminateDups(LONG cFonts, PNAMESTRUCT pnms)
  191. {
  192.     LONG i, cActual;
  193.  
  194.     cActual = 0;
  195.     for (i = 1; i < cFonts; i++) {
  196.         if (CompareNMS((void *) (pnms + cActual),
  197.                (void *) (pnms + i)) != 0) {
  198.             if (ExistsScrRes(pnms+i)) {
  199.                 cActual++;
  200.                 if (cActual != i)
  201.                   LCopyStruct((PCH)(pnms+i),(PCH)(pnms+cActual),sizeof(*pnms));
  202.             }
  203.         }
  204.     }
  205.     return(cActual + 1);
  206. }
  207.  
  208. VOID InitFonts()
  209. {
  210.         HPS hps;
  211.         LONG cRemFonts;
  212.         LONG pcFonts;
  213.         LONG cActualFonts;
  214.         PNAMESTRUCT pnms;
  215.         MENUITEM mi;
  216.  
  217.         if (!GpiLoadFonts(hab,"c:\\os2\\dll\\COURIER.dll"));
  218.         if (!GpiLoadFonts(hab,"c:\\os2\\dll\\TIMES.dll"));
  219.         if (!GpiLoadFonts(hab,"c:\\os2\\dll\\HELV.fon"));
  220.  
  221.         GetWindowResolution(hwndNPEdit);
  222.         WinSendMsg(hwndNPMenu,
  223.                         MM_QUERYITEM,
  224.                         MPFROM2SHORT(SUB_SIZES, FALSE),
  225.                         MPFROMP(&mi));
  226.         hwndSizeMenu = mi.hwndSubMenu;
  227.         WinSendMsg(hwndNPMenu,
  228.                         MM_QUERYITEM,
  229.                         MPFROM2SHORT(SUB_FONTS, FALSE),
  230.                         MPFROMP(&mi));
  231.         hwndFontMenu = mi.hwndSubMenu;
  232.  
  233.         hps = WinGetPS(hwndNPEdit);
  234.         pcFonts = 0;
  235.         cRemFonts = GpiQueryFonts(hps,
  236.                                 QF_PUBLIC | QF_PRIVATE,
  237.                                 NULL,
  238.                                 (PLONG) &pcFonts,
  239.                                 (LONG) 0,
  240.                                 NULL);
  241.         pnms = (PNAMESTRUCT) WinAllocMem(hhAppHeap,
  242.                 (USHORT) (cRemFonts*sizeof(NAMESTRUCT)));
  243.         pcFonts = cRemFonts;
  244.         GpiQueryFonts(hps,
  245.                         QF_PUBLIC | QF_PRIVATE,
  246.                         NULL,
  247.                         (PLONG) &pcFonts,
  248.                         (LONG) sizeof(NAMESTRUCT),
  249.                         (PFONTMETRICS)pnms);
  250.         WinReleasePS(hps);
  251.  
  252.         qsort((VOID *) OFFSETOF(pnms), (size_t) cRemFonts,
  253.         sizeof(*pnms), CompareNMS);
  254.         cActualFonts = EliminateDups(cRemFonts, pnms);
  255.  
  256.         MakeFontMenu(cActualFonts,pnms);
  257.  
  258. }
  259.  
  260. VOID ClearSizeMenu(VOID)
  261. {
  262.         SHORT i;
  263.  
  264.         sCurrSizeIndex = -1;
  265.         i = 1;
  266.         while (LONGFROMMR(WinSendMsg(hwndSizeMenu, MM_REMOVEITEM,
  267.                         MPFROMSHORT(SUB_SIZES | (i++ & 0xff)),
  268.                         NULL)))
  269.                 ;
  270. }
  271.  
  272. /**********************************************************************
  273.  *  DisableSizeMenu(VOID)
  274.  *
  275.  *  Called to destroy the existing size menu and replace it with a single
  276.  *  disabled entry "no sizes available" -- primarily for use with the
  277.  *  system font
  278.  **********************************************************************/
  279.  
  280. VOID DisableSizeMenu(VOID)
  281. {
  282.         MENUITEM mi;
  283.  
  284.         ClearSizeMenu();
  285.  
  286.         mi.iPosition = MIT_END;
  287.         mi.afStyle = MIS_TEXT;
  288.         mi.afAttribute = MIA_DISABLED;
  289.         mi.id = (SUB_SIZES | 0x01);
  290.         mi.hwndSubMenu = NULL;
  291.         mi.hItem = NULL;
  292.         WinSendMsg(hwndSizeMenu,MM_INSERTITEM,
  293.                 MPFROMP(&mi),
  294.                 MPFROMP("No Sizes Available"));
  295. }
  296.  
  297. VOID AddSize(SHORT sPointSize, SHORT sIndex)
  298. {
  299.  
  300.         MENUITEM mi;
  301.         CHAR buff[18];
  302.  
  303.         mi.iPosition = MIT_END;
  304.         mi.afStyle = MIS_TEXT;
  305.         mi.afAttribute = 0;
  306.         mi.id = (SUB_SIZES | ((sIndex+1) & 0xff));
  307.         mi.hwndSubMenu = NULL;
  308.         mi.hItem = NULL;
  309.         WinSendMsg(hwndSizeMenu,MM_INSERTITEM,
  310.                 MPFROMP(&mi),
  311.                 MPFROMP(itoa(sPointSize,buff,10)));
  312. }
  313.  
  314.  
  315. VOID BuildSizeTable(FONTMETRICS pfms[], LONG cFonts)
  316. {
  317.         SHORT i;
  318.         SHORT sMatches;
  319.  
  320.         if (psizes != NULL) {
  321.                 WinFreeMem(hhAppHeap, (NPBYTE) OFFSETOF(psizes),
  322.                 (USHORT) cbsizes);
  323.                 psizes = NULL;
  324.         }
  325.  
  326.         sMatches = 0;
  327.         for (i = 0; i < (SHORT) cFonts; i++) {
  328.                 if ((pfms[i].sXDeviceRes == sScreenXRes) &&
  329.                         (pfms[i].sYDeviceRes == sScreenYRes))
  330.                                 sMatches++;
  331.         }
  332.         cbsizes = sMatches * sizeof(SIZESTRUCT);
  333.         scsizes = sMatches;
  334.         if (scsizes == 0) {
  335.                 DisableSizeMenu();
  336.                 return;
  337.         }
  338.  
  339.         ClearSizeMenu();
  340.         psizes = (PSIZESTRUCT)WinAllocMem(hhAppHeap, cbsizes);
  341.         sMatches = 0;
  342.         for (i = 0; i < (SHORT) cFonts; i++) {
  343.                 if ((pfms[i].sXDeviceRes == sScreenXRes) &&
  344.                     (pfms[i].sYDeviceRes == sScreenYRes)) {
  345.                         (psizes+sMatches)->sPoints = pfms[i].sNominalPointSize;
  346.                         (psizes+sMatches)->lMatch = pfms[i].lMatch;
  347.                         AddSize((pfms[i].sNominalPointSize)/10,sMatches);
  348.  
  349.                         sMatches++;
  350.                 }
  351.         }
  352.  
  353. }
  354.  
  355. /**********************************************************************
  356.  *
  357.  * SelectSizeIndex
  358.  *
  359.  *  Given a 1-based index into the size table, do whatever's necessary
  360.  *  to set the current font to that size.
  361.  *  A value <0 will always select the system font/size.
  362.  **********************************************************************/
  363.  
  364. BOOL SelectSizeIndex(SHORT sIndex)
  365. {
  366.         FATTRS fattrs;
  367.  
  368.         if (sCurrSizeIndex >= 0) {
  369.                 WinSendMsg(hwndNPMenu,
  370.                         MM_SETITEMATTR,
  371.                         MPFROM2SHORT((SUB_SIZES|((sCurrSizeIndex+1)&0xff)),TRUE),
  372.                         MPFROM2SHORT(MIA_CHECKED,0));
  373.         }
  374.         sCurrSizeIndex = sIndex-1;
  375.         if ((sIndex < 0) || (sIndex>scsizes)) {
  376.                 sCurrSize = -1;
  377.         } else {
  378.                 sCurrSize = (psizes+sCurrSizeIndex)->sPoints;
  379.                 WinSendMsg(hwndNPMenu,
  380.                         MM_SETITEMATTR,
  381.                         MPFROM2SHORT((SUB_SIZES|((sIndex)&0xff)),TRUE),
  382.                         MPFROM2SHORT(MIA_CHECKED,MIA_CHECKED));
  383.         }
  384.         (pfnts+sCurrFont)->sLastSize = sCurrSize;
  385.  
  386.         if (sCurrSize < 0) {
  387.                 return((BOOL) LONGFROMMR(WinSendMsg(hwndNPEdit,
  388.                                 EM_SETFONT,
  389.                                 NULL,
  390.                                 0L)));
  391.         } else {
  392.                 fattrs.usRecordLength = sizeof(fattrs);
  393.                 fattrs.fsSelection = 0;
  394.                 fattrs.lMatch = (psizes+sIndex-1)->lMatch;
  395.                 lstrcpy(fattrs.szFacename, (pfnts+sCurrFont)->nms.szFaceName);
  396.                 fattrs.idRegistry = 0;
  397.                 fattrs.usCodePage = 0;
  398.                 fattrs.lMaxBaselineExt = 0;
  399.                 fattrs.lAveCharWidth = 0;
  400.                 fattrs.fsType = 0;
  401.                 fattrs.fsFontUse = 0;
  402.                 return((BOOL) LONGFROMMR(WinSendMsg(hwndNPEdit,
  403.                                 EM_SETFONT,
  404.                                 MPFROMP((PFATTRS)&fattrs),
  405.                                 0L)));
  406.         }
  407. }
  408.  
  409. /**********************************************************************
  410.  * SelectSize
  411.  *
  412.  *  Given a point size, selects the font of that size for the current face.
  413.  *  If no such size exists, returns FALSE.
  414.  *  A value <0 selects the system font/size.
  415.  **********************************************************************/
  416.  
  417. BOOL SelectSize(SHORT sPoints)
  418. {
  419.         SHORT i;
  420.  
  421.         if (sPoints == -1) {
  422.                 SelectSizeIndex(-1);
  423.                 return(TRUE);
  424.         }
  425.  
  426.         for (i=0; i<scsizes; i++) {
  427.                 if ((psizes+i)->sPoints == sPoints) {
  428.                         SelectSizeIndex(i+1);
  429.                         return(TRUE);
  430.                 }
  431.         }
  432.         return(FALSE);
  433. }
  434.  
  435. /**********************************************************************
  436.  *
  437.  *  AutoSelectSize
  438.  *
  439.  *  Tries to intelligently select the size when a new font is chosen.
  440.  *  Attempts, in order:
  441.  *  1.  The last size the font was used with
  442.  *  2.  The size used in the font just deselected
  443.  *  3.  The smallest size for that font.
  444.  **********************************************************************/
  445.  
  446. VOID AutoSelectSize(VOID)
  447. {
  448.         if ((pfnts+sCurrFont)->sLastSize > 0) {
  449.                 if (SelectSize((pfnts+sCurrFont)->sLastSize))
  450.                         return;
  451.         }
  452.         if (sCurrSize > 0)
  453.                 if (SelectSize(sCurrSize))
  454.                         return;
  455.         SelectSizeIndex(1);
  456. }
  457.  
  458. /**********************************************************************
  459.  *
  460.  *  SelectFont
  461.  *
  462.  *  Given a 1-based index into the Font table, sets the current font
  463.  *  to that font, and sets the size (and thus the font used in the
  464.  *  edit control) as needed.
  465.  *
  466.  **********************************************************************/
  467.  
  468. VOID SelectFont(SHORT sFontIndex)
  469. {
  470.         LONG cRemFonts;
  471.         PFONTMETRICS pfms;
  472.         SHORT cbytes;
  473.  
  474.         if (sCurrFont >= 0) {
  475.                 WinSendMsg(hwndNPMenu,
  476.                         MM_SETITEMATTR,
  477.                         MPFROM2SHORT((SUB_FONTS|((sCurrFont+1)&0xff)),TRUE),
  478.                         MPFROM2SHORT(MIA_CHECKED,0));
  479.         }
  480.         sCurrFont = sFontIndex-1;
  481.         WinSendMsg(hwndNPMenu,
  482.                 MM_SETITEMATTR,
  483.                 MPFROM2SHORT((SUB_FONTS|(sFontIndex&0xff)),TRUE),
  484.                 MPFROM2SHORT(MIA_CHECKED,MIA_CHECKED));
  485.         if (sCurrFont == 0) {
  486.                 DisableSizeMenu();
  487.                 SelectSize(-1);
  488.         } else {
  489.                 cRemFonts = GetFontMetrics((pfnts+sCurrFont)->nms.szFaceName,
  490.                                 &pfms, &cbytes);
  491.                 BuildSizeTable((FONTMETRICS near *) OFFSETOF(pfms), cRemFonts);
  492.                 AutoSelectSize();
  493.                 WinFreeMem(hhAppHeap, (NPBYTE) OFFSETOF(pfms), (USHORT) cbytes);
  494.         }
  495. }
  496.