/*1* tkGet.c --2*3* This file contains a number of "Tk_GetXXX" procedures, which4* parse text strings into useful forms for Tk. This file has5* the simpler procedures, like Tk_GetDirection and Tk_GetUid.6* The more complex procedures like Tk_GetColor are in separate7* files.8*9* Copyright (c) 1991-1994 The Regents of the University of California.10* Copyright (c) 1994-1995 Sun Microsystems, Inc.11*12* See the file "license.terms" for information on usage and redistribution13* of this file, and for a DISCLAIMER OF ALL WARRANTIES.14*15* SCCS: @(#) tkGet.c 1.12 96/02/15 18:53:3316*/1718#include "tkInt.h"1920/*21* The hash table below is used to keep track of all the Tk_Uids created22* so far.23*/2425static Tcl_HashTable uidTable;26static int initialized = 0;2728/*29*--------------------------------------------------------------30*31* Tk_GetAnchor --32*33* Given a string, return the corresponding Tk_Anchor.34*35* Results:36* The return value is a standard Tcl return result. If37* TCL_OK is returned, then everything went well and the38* position is stored at *anchorPtr; otherwise TCL_ERROR39* is returned and an error message is left in40* interp->result.41*42* Side effects:43* None.44*45*--------------------------------------------------------------46*/4748int49Tk_GetAnchor(interp, string, anchorPtr)50Tcl_Interp *interp; /* Use this for error reporting. */51char *string; /* String describing a direction. */52Tk_Anchor *anchorPtr; /* Where to store Tk_Anchor corresponding53* to string. */54{55switch (string[0]) {56case 'n':57if (string[1] == 0) {58*anchorPtr = TK_ANCHOR_N;59return TCL_OK;60} else if ((string[1] == 'e') && (string[2] == 0)) {61*anchorPtr = TK_ANCHOR_NE;62return TCL_OK;63} else if ((string[1] == 'w') && (string[2] == 0)) {64*anchorPtr = TK_ANCHOR_NW;65return TCL_OK;66}67goto error;68case 's':69if (string[1] == 0) {70*anchorPtr = TK_ANCHOR_S;71return TCL_OK;72} else if ((string[1] == 'e') && (string[2] == 0)) {73*anchorPtr = TK_ANCHOR_SE;74return TCL_OK;75} else if ((string[1] == 'w') && (string[2] == 0)) {76*anchorPtr = TK_ANCHOR_SW;77return TCL_OK;78} else {79goto error;80}81case 'e':82if (string[1] == 0) {83*anchorPtr = TK_ANCHOR_E;84return TCL_OK;85}86goto error;87case 'w':88if (string[1] == 0) {89*anchorPtr = TK_ANCHOR_W;90return TCL_OK;91}92goto error;93case 'c':94if (strncmp(string, "center", strlen(string)) == 0) {95*anchorPtr = TK_ANCHOR_CENTER;96return TCL_OK;97}98goto error;99}100101error:102Tcl_AppendResult(interp, "bad anchor position \"", string,103"\": must be n, ne, e, se, s, sw, w, nw, or center",104(char *) NULL);105return TCL_ERROR;106}107108/*109*--------------------------------------------------------------110*111* Tk_NameOfAnchor --112*113* Given a Tk_Anchor, return the string that corresponds114* to it.115*116* Results:117* None.118*119* Side effects:120* None.121*122*--------------------------------------------------------------123*/124125char *126Tk_NameOfAnchor(anchor)127Tk_Anchor anchor; /* Anchor for which identifying string128* is desired. */129{130switch (anchor) {131case TK_ANCHOR_N: return "n";132case TK_ANCHOR_NE: return "ne";133case TK_ANCHOR_E: return "e";134case TK_ANCHOR_SE: return "se";135case TK_ANCHOR_S: return "s";136case TK_ANCHOR_SW: return "sw";137case TK_ANCHOR_W: return "w";138case TK_ANCHOR_NW: return "nw";139case TK_ANCHOR_CENTER: return "center";140}141return "unknown anchor position";142}143144/*145*--------------------------------------------------------------146*147* Tk_GetJoinStyle --148*149* Given a string, return the corresponding Tk_JoinStyle.150*151* Results:152* The return value is a standard Tcl return result. If153* TCL_OK is returned, then everything went well and the154* justification is stored at *joinPtr; otherwise155* TCL_ERROR is returned and an error message is left in156* interp->result.157*158* Side effects:159* None.160*161*--------------------------------------------------------------162*/163164int165Tk_GetJoinStyle(interp, string, joinPtr)166Tcl_Interp *interp; /* Use this for error reporting. */167char *string; /* String describing a justification style. */168int *joinPtr; /* Where to store join style corresponding169* to string. */170{171int c;172size_t length;173174c = string[0];175length = strlen(string);176177if ((c == 'b') && (strncmp(string, "bevel", length) == 0)) {178*joinPtr = JoinBevel;179return TCL_OK;180}181if ((c == 'm') && (strncmp(string, "miter", length) == 0)) {182*joinPtr = JoinMiter;183return TCL_OK;184}185if ((c == 'r') && (strncmp(string, "round", length) == 0)) {186*joinPtr = JoinRound;187return TCL_OK;188}189190Tcl_AppendResult(interp, "bad join style \"", string,191"\": must be bevel, miter, or round",192(char *) NULL);193return TCL_ERROR;194}195196/*197*--------------------------------------------------------------198*199* Tk_NameOfJoinStyle --200*201* Given a Tk_JoinStyle, return the string that corresponds202* to it.203*204* Results:205* None.206*207* Side effects:208* None.209*210*--------------------------------------------------------------211*/212213char *214Tk_NameOfJoinStyle(join)215int join; /* Join style for which identifying string216* is desired. */217{218switch (join) {219case JoinBevel: return "bevel";220case JoinMiter: return "miter";221case JoinRound: return "round";222}223return "unknown join style";224}225226/*227*--------------------------------------------------------------228*229* Tk_GetCapStyle --230*231* Given a string, return the corresponding Tk_CapStyle.232*233* Results:234* The return value is a standard Tcl return result. If235* TCL_OK is returned, then everything went well and the236* justification is stored at *capPtr; otherwise237* TCL_ERROR is returned and an error message is left in238* interp->result.239*240* Side effects:241* None.242*243*--------------------------------------------------------------244*/245246int247Tk_GetCapStyle(interp, string, capPtr)248Tcl_Interp *interp; /* Use this for error reporting. */249char *string; /* String describing a justification style. */250int *capPtr; /* Where to store cap style corresponding251* to string. */252{253int c;254size_t length;255256c = string[0];257length = strlen(string);258259if ((c == 'b') && (strncmp(string, "butt", length) == 0)) {260*capPtr = CapButt;261return TCL_OK;262}263if ((c == 'p') && (strncmp(string, "projecting", length) == 0)) {264*capPtr = CapProjecting;265return TCL_OK;266}267if ((c == 'r') && (strncmp(string, "round", length) == 0)) {268*capPtr = CapRound;269return TCL_OK;270}271272Tcl_AppendResult(interp, "bad cap style \"", string,273"\": must be butt, projecting, or round",274(char *) NULL);275return TCL_ERROR;276}277278/*279*--------------------------------------------------------------280*281* Tk_NameOfCapStyle --282*283* Given a Tk_CapStyle, return the string that corresponds284* to it.285*286* Results:287* None.288*289* Side effects:290* None.291*292*--------------------------------------------------------------293*/294295char *296Tk_NameOfCapStyle(cap)297int cap; /* Cap style for which identifying string298* is desired. */299{300switch (cap) {301case CapButt: return "butt";302case CapProjecting: return "projecting";303case CapRound: return "round";304}305return "unknown cap style";306}307308/*309*--------------------------------------------------------------310*311* Tk_GetJustify --312*313* Given a string, return the corresponding Tk_Justify.314*315* Results:316* The return value is a standard Tcl return result. If317* TCL_OK is returned, then everything went well and the318* justification is stored at *justifyPtr; otherwise319* TCL_ERROR is returned and an error message is left in320* interp->result.321*322* Side effects:323* None.324*325*--------------------------------------------------------------326*/327328int329Tk_GetJustify(interp, string, justifyPtr)330Tcl_Interp *interp; /* Use this for error reporting. */331char *string; /* String describing a justification style. */332Tk_Justify *justifyPtr; /* Where to store Tk_Justify corresponding333* to string. */334{335int c;336size_t length;337338c = string[0];339length = strlen(string);340341if ((c == 'l') && (strncmp(string, "left", length) == 0)) {342*justifyPtr = TK_JUSTIFY_LEFT;343return TCL_OK;344}345if ((c == 'r') && (strncmp(string, "right", length) == 0)) {346*justifyPtr = TK_JUSTIFY_RIGHT;347return TCL_OK;348}349if ((c == 'c') && (strncmp(string, "center", length) == 0)) {350*justifyPtr = TK_JUSTIFY_CENTER;351return TCL_OK;352}353354Tcl_AppendResult(interp, "bad justification \"", string,355"\": must be left, right, or center",356(char *) NULL);357return TCL_ERROR;358}359360/*361*--------------------------------------------------------------362*363* Tk_NameOfJustify --364*365* Given a Tk_Justify, return the string that corresponds366* to it.367*368* Results:369* None.370*371* Side effects:372* None.373*374*--------------------------------------------------------------375*/376377char *378Tk_NameOfJustify(justify)379Tk_Justify justify; /* Justification style for which380* identifying string is desired. */381{382switch (justify) {383case TK_JUSTIFY_LEFT: return "left";384case TK_JUSTIFY_RIGHT: return "right";385case TK_JUSTIFY_CENTER: return "center";386}387return "unknown justification style";388}389390/*391*----------------------------------------------------------------------392*393* Tk_GetUid --394*395* Given a string, this procedure returns a unique identifier396* for the string.397*398* Results:399* This procedure returns a Tk_Uid corresponding to the "string"400* argument. The Tk_Uid has a string value identical to string401* (strcmp will return 0), but it's guaranteed that any other402* calls to this procedure with a string equal to "string" will403* return exactly the same result (i.e. can compare Tk_Uid404* *values* directly, without having to call strcmp on what they405* point to).406*407* Side effects:408* New information may be entered into the identifier table.409*410*----------------------------------------------------------------------411*/412413Tk_Uid414Tk_GetUid(string)415char *string; /* String to convert. */416{417int dummy;418419if (!initialized) {420Tcl_InitHashTable(&uidTable, TCL_STRING_KEYS);421initialized = 1;422}423return (Tk_Uid) Tcl_GetHashKey(&uidTable,424Tcl_CreateHashEntry(&uidTable, string, &dummy));425}426427/*428*--------------------------------------------------------------429*430* Tk_GetScreenMM --431*432* Given a string, returns the number of screen millimeters433* corresponding to that string.434*435* Results:436* The return value is a standard Tcl return result. If437* TCL_OK is returned, then everything went well and the438* screen distance is stored at *doublePtr; otherwise439* TCL_ERROR is returned and an error message is left in440* interp->result.441*442* Side effects:443* None.444*445*--------------------------------------------------------------446*/447448int449Tk_GetScreenMM(interp, tkwin, string, doublePtr)450Tcl_Interp *interp; /* Use this for error reporting. */451Tk_Window tkwin; /* Window whose screen determines conversion452* from centimeters and other absolute453* units. */454char *string; /* String describing a screen distance. */455double *doublePtr; /* Place to store converted result. */456{457char *end;458double d;459460d = strtod(string, &end);461if (end == string) {462error:463Tcl_AppendResult(interp, "bad screen distance \"", string,464"\"", (char *) NULL);465return TCL_ERROR;466}467while ((*end != '\0') && isspace(UCHAR(*end))) {468end++;469}470switch (*end) {471case 0:472d /= WidthOfScreen(Tk_Screen(tkwin));473d *= WidthMMOfScreen(Tk_Screen(tkwin));474break;475case 'c':476d *= 10;477end++;478break;479case 'i':480d *= 25.4;481end++;482break;483case 'm':484end++;485break;486case 'p':487d *= 25.4/72.0;488end++;489break;490default:491goto error;492}493while ((*end != '\0') && isspace(UCHAR(*end))) {494end++;495}496if (*end != 0) {497goto error;498}499*doublePtr = d;500return TCL_OK;501}502503/*504*--------------------------------------------------------------505*506* Tk_GetPixels --507*508* Given a string, returns the number of pixels corresponding509* to that string.510*511* Results:512* The return value is a standard Tcl return result. If513* TCL_OK is returned, then everything went well and the514* rounded pixel distance is stored at *intPtr; otherwise515* TCL_ERROR is returned and an error message is left in516* interp->result.517*518* Side effects:519* None.520*521*--------------------------------------------------------------522*/523524int525Tk_GetPixels(interp, tkwin, string, intPtr)526Tcl_Interp *interp; /* Use this for error reporting. */527Tk_Window tkwin; /* Window whose screen determines conversion528* from centimeters and other absolute529* units. */530char *string; /* String describing a justification style. */531int *intPtr; /* Place to store converted result. */532{533char *end;534double d;535536d = strtod(string, &end);537if (end == string) {538error:539Tcl_AppendResult(interp, "bad screen distance \"", string,540"\"", (char *) NULL);541return TCL_ERROR;542}543while ((*end != '\0') && isspace(UCHAR(*end))) {544end++;545}546switch (*end) {547case 0:548break;549case 'c':550d *= 10*WidthOfScreen(Tk_Screen(tkwin));551d /= WidthMMOfScreen(Tk_Screen(tkwin));552end++;553break;554case 'i':555d *= 25.4*WidthOfScreen(Tk_Screen(tkwin));556d /= WidthMMOfScreen(Tk_Screen(tkwin));557end++;558break;559case 'm':560d *= WidthOfScreen(Tk_Screen(tkwin));561d /= WidthMMOfScreen(Tk_Screen(tkwin));562end++;563break;564case 'p':565d *= (25.4/72.0)*WidthOfScreen(Tk_Screen(tkwin));566d /= WidthMMOfScreen(Tk_Screen(tkwin));567end++;568break;569default:570goto error;571}572while ((*end != '\0') && isspace(UCHAR(*end))) {573end++;574}575if (*end != 0) {576goto error;577}578if (d < 0) {579*intPtr = (int) (d - 0.5);580} else {581*intPtr = (int) (d + 0.5);582}583return TCL_OK;584}585586587